feat: 重构项目心跳数据结构并实现项目列表API
- 新增统一项目列表Redis键和迁移工具 - 实现GET /api/projects端点获取项目列表 - 实现POST /api/projects/migrate端点支持数据迁移 - 更新前端ProjectSelector组件使用真实项目数据 - 扩展projectStore状态管理 - 更新相关文档和OpenSpec规范 - 添加测试用例验证新功能
This commit is contained in:
53
src/backend/test/fakeRedis.js
Normal file
53
src/backend/test/fakeRedis.js
Normal file
@@ -0,0 +1,53 @@
|
||||
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());
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user