import type { Layer } from "./layer"; import type { LayerKey } from "./types"; import { keySignature } from "./utils"; export interface LayerGcCacheOptions { /** Read at store time; `<= 0` disables caching. */ gcTime: () => number; onBeforeStore?: (layer: Layer) => void; /** Runs for expiry and same-key displacement, but not restoration. */ onEvict?: (layer: Layer) => void; } export interface LayerGcCache { maybeStore(layer: Layer): void; take(key: LayerKey): Layer | undefined; } /** * Retains dismissed layer data for same-key restoration without reloading. * Only the last dismissed layer for each key is retained. */ export function createLayerGcCache( opts: LayerGcCacheOptions, ): LayerGcCache { const entries = new Map< string, { layer: Layer; timer: ReturnType } >(); const evict = (sig: string): void => { const entry = entries.get(sig); if (!entry) { return; } clearTimeout(entry.timer); entries.delete(sig); opts.onEvict?.(entry.layer); }; return { maybeStore(layer) { const gcTime = opts.gcTime(); if (gcTime <= 0 || layer.state.data === undefined) { return; } opts.onBeforeStore?.(layer); const sig = keySignature(layer.key); evict(sig); const timer = setTimeout(() => evict(sig), gcTime); entries.set(sig, { layer, timer }); }, take(key) { const sig = keySignature(key); const entry = entries.get(sig); if (!entry) { return undefined; } clearTimeout(entry.timer); entries.delete(sig); // Restoration transfers ownership without eviction cleanup. return entry.layer; }, }; }