Files
Web_BLS_ProjectConsole/src/backend/test/fakeRedis.js
XuJiacheng 282f7268ed feat: 重构项目心跳数据结构并实现项目列表API
- 新增统一项目列表Redis键和迁移工具
- 实现GET /api/projects端点获取项目列表
- 实现POST /api/projects/migrate端点支持数据迁移
- 更新前端ProjectSelector组件使用真实项目数据
- 扩展projectStore状态管理
- 更新相关文档和OpenSpec规范
- 添加测试用例验证新功能
2026-01-13 19:45:05 +08:00

54 lines
1.2 KiB
JavaScript

function escapeRegex(input) {
return String(input).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function globToRegex(glob) {
const parts = String(glob).split('*').map(escapeRegex);
const regex = `^${parts.join('.*')}$`;
return new RegExp(regex);
}
export function createFakeRedis(initial = {}) {
const kv = new Map(Object.entries(initial));
return {
isReady: true,
async get(key) {
return kv.has(key) ? kv.get(key) : null;
},
async set(key, value) {
kv.set(key, String(value));
return 'OK';
},
async del(key) {
const existed = kv.delete(key);
return existed ? 1 : 0;
},
async keys(pattern) {
const re = globToRegex(pattern);
return Array.from(kv.keys()).filter((k) => re.test(k));
},
// optional: used by logs route
async lRange(key, start, stop) {
const raw = kv.get(key);
const list = Array.isArray(raw) ? raw : [];
const normalizeIndex = (idx) => (idx < 0 ? list.length + idx : idx);
const s = normalizeIndex(start);
const e = normalizeIndex(stop);
return list.slice(Math.max(0, s), Math.min(list.length, e + 1));
},
// helper for tests
_dump() {
return Object.fromEntries(kv.entries());
},
};
}