export interface QueryCacheOptions { ttlMs: number; maxEntries: number; now?: () => number; } export function createQueryCache(options: QueryCacheOptions) { const now = options.now ?? Date.now; const entries = new Map(); async function cached(key: string, fn: () => Promise): Promise { const hit = entries.get(key); if (hit && now() - hit.ts < options.ttlMs) { return hit.data as T; } const data = await fn(); entries.set(key, { data, ts: now() }); while (entries.size > options.maxEntries) { const oldestKey = entries.keys().next().value; if (oldestKey === undefined) break; entries.delete(oldestKey); } return data; } function clear() { entries.clear(); } return { cached, clear }; } export const queryCache = createQueryCache({ ttlMs: 120_000, maxEntries: 500, });