// Lightweight TTL cache backed by localStorage so resolved Nostr data (author // profiles, long-form events) survives page reloads and navigation instead of // being re-queried from relays every visit. No-ops on the server and degrades // silently on quota/parse errors so it can never break rendering. const PREFIX = "bbe:nostr:"; interface Entry { v: T; t: number; // stored-at epoch ms } export function readCache(key: string, ttlMs: number): T | null { if (typeof window === "undefined") return null; try { const raw = window.localStorage.getItem(PREFIX + key); if (!raw) return null; const entry = JSON.parse(raw) as Entry; if (Date.now() - entry.t > ttlMs) { window.localStorage.removeItem(PREFIX + key); return null; } return entry.v; } catch { return null; } } export function writeCache(key: string, value: T): void { if (typeof window === "undefined") return; const payload = JSON.stringify({ v: value, t: Date.now() } satisfies Entry); try { window.localStorage.setItem(PREFIX + key, payload); } catch { // Quota exceeded (or similar): evict our namespace and retry once. try { pruneNamespace(); window.localStorage.setItem(PREFIX + key, payload); } catch { // Give up silently — caching is best-effort. } } } // Removes every entry written by this cache to recover space when localStorage // is full. Only touches our own namespace. function pruneNamespace(): void { for (let i = window.localStorage.length - 1; i >= 0; i--) { const k = window.localStorage.key(i); if (k && k.startsWith(PREFIX)) window.localStorage.removeItem(k); } }