type Entry = { value: T; expires: number }; const store = new Map>(); export function memo(key: string, ttlMs: number, fn: () => T): T { const now = Date.now(); const hit = store.get(key) as Entry | undefined; if (hit && hit.expires > now) return hit.value; const value = fn(); store.set(key, { value, expires: now + ttlMs }); return value; } export async function memoAsync( key: string, ttlMs: number, fn: () => Promise ): Promise { const now = Date.now(); const hit = store.get(key) as Entry | undefined; if (hit && hit.expires > now) return hit.value; const value = await fn(); store.set(key, { value, expires: now + ttlMs }); return value; } export function invalidate(prefix: string): void { for (const k of store.keys()) if (k.startsWith(prefix)) store.delete(k); }