返回 DeepSeek-Reasonix
mockReadSnapshot.ts
根目录 / desktop / frontend / src / lib / mockReadSnapshot.ts
1 // Browser mock uses the same immutable-page contract as the host. The cache
2 // contains fixture data only and is bounded across all mock list entry points.
3 const snapshots = new Map<string, { binding: string; rows: unknown[]; expires: number }>();
4 let sequence = 0;
5
6 export function releaseMockReadSnapshot(id: string): void { snapshots.delete(id); }
7
8 export function mockReadSnapshotPage<T>(kind: string, query: unknown, cursor: string | undefined, limit: number | undefined, currentRows: T[]) {
9 const binding = JSON.stringify([kind, query]);
10 let id: string;
11 let offset = 0;
12 if (cursor) {
13 const match = /^mock-read-(\d+):(\d+)$/.exec(cursor);
14 if (!match) throw Object.assign(new Error("Read snapshot expired"), { code: "stale_cursor" });
15 id = `mock-read-${match[1]}`; offset = Number(match[2]);
16 } else {
17 for (const [key, value] of snapshots) if (value.expires <= Date.now()) snapshots.delete(key);
18 if (snapshots.size >= 64) snapshots.delete(snapshots.keys().next().value!);
19 id = `mock-read-${++sequence}`;
20 snapshots.set(id, { binding, rows: structuredClone(currentRows), expires: Date.now() + 30 * 60_000 });
21 }
22 const snapshot = snapshots.get(id);
23 if (!snapshot || snapshot.binding !== binding || snapshot.expires <= Date.now() || offset > snapshot.rows.length) throw Object.assign(new Error("Read snapshot expired"), { code: "stale_cursor" });
24 const end = Math.min(snapshot.rows.length, offset + Math.min(200, Math.max(1, limit || 50)));
25 return { items: structuredClone(snapshot.rows.slice(offset, end)) as T[], nextCursor: end < snapshot.rows.length ? `${id}:${end}` : "", snapshotId: id, snapshotExpiresAt: snapshot.expires };
26 }
27
27 lines TYPESCRIPT