{"version":3,"sources":["../src/client-cache.ts"],"sourcesContent":["/// <reference lib=\"es2021.weakref\" />\nimport { createRouteDataCacheKey, type RouteDataCacheKey } from \"./cache\";\nimport { subscribeFarmCacheInvalidation } from \"./cache-invalidation\";\n\nexport type FarmClientCacheKey = RouteDataCacheKey;\n\nexport type FarmClientCacheStatus = \"idle\" | \"pending\" | \"success\" | \"error\";\n\nexport type FarmClientCacheEntry<TData = unknown> = {\n  data: TData;\n  updatedAt: number;\n  staleAt: number;\n  gcAt?: number;\n  invalidatedAt?: number;\n  status?: FarmClientCacheStatus;\n  error?: Error | null;\n  fetching?: boolean;\n  /** Marks an entry the persistence layer may write to its adapter. */\n  persist?: boolean;\n};\n\n/** @internal Observation seam for the client cache persistence engine. */\nexport type FarmClientCachePersistenceSink = {\n  onSet(key: string, entry: FarmClientCacheEntry): void;\n  onDelete(key: string): void;\n  onClear(): void;\n};\n\ntype FarmClientCacheListener = (event?: \"invalidate\") => void;\n\nconst invalidationTrackers = new WeakMap<FarmClientDataCache, Set<Set<string>>>();\n\n/** Internal request-lifetime tracking, including keys learned only from a response. */\nexport function trackFarmClientCacheInvalidations(cache: FarmClientDataCache) {\n  let trackers = invalidationTrackers.get(cache);\n  if (!trackers) {\n    trackers = new Set();\n    invalidationTrackers.set(cache, trackers);\n  }\n  const keys = new Set<string>();\n  trackers.add(keys);\n  return {\n    has(key: string) {\n      const resolved = cache.resolveKey(key);\n      for (const invalidated of keys) {\n        if (cache.resolveKey(invalidated) === resolved) return true;\n      }\n      return false;\n    },\n    dispose() {\n      if (!trackers.delete(keys)) return;\n      keys.clear();\n      if (trackers.size === 0) invalidationTrackers.delete(cache);\n    },\n  };\n}\n\nconst cacheFinalizer =\n  typeof FinalizationRegistry === \"function\"\n    ? new FinalizationRegistry<() => void>((unsubscribe) => unsubscribe())\n    : undefined;\n\n// This closure must only capture a weak reference, never the cache itself.\nfunction subscribeWeakCache(reference: WeakRef<FarmClientDataCache>): () => void {\n  const unsubscribe = subscribeFarmCacheInvalidation((key) => {\n    const cache = reference.deref();\n    if (cache) cache.invalidate(key);\n    else dispose();\n  });\n  function dispose() {\n    unsubscribe();\n    cacheFinalizer?.unregister(reference);\n  }\n  return dispose;\n}\n\nconst DEFAULT_GC_SWEEP_INTERVAL_MS = 30_000;\n\nexport class FarmClientDataCache {\n  private entries = new Map<string, FarmClientCacheEntry>();\n  private aliases = new Map<string, string>();\n  private invalidatedAt = new Map<string, number>();\n  private listeners = new Map<string, Set<FarmClientCacheListener>>();\n  private inflight = new Map<string, Promise<unknown>>();\n  private unsubscribeInvalidation: (() => void) | undefined;\n  private gcTimer: ReturnType<typeof setTimeout> | undefined;\n  private readonly gcSweepIntervalMs: number | false;\n  private persistence: FarmClientCachePersistenceSink | undefined;\n\n  constructor(\n    options: { subscribeToInvalidation?: boolean; gcSweepIntervalMs?: number | false } = {},\n  ) {\n    this.gcSweepIntervalMs = options.gcSweepIntervalMs ?? DEFAULT_GC_SWEEP_INTERVAL_MS;\n    if (options.subscribeToInvalidation !== false) {\n      if (typeof WeakRef === \"function\") {\n        const reference = new WeakRef(this);\n        const unsubscribe = subscribeWeakCache(reference);\n        cacheFinalizer?.register(this, unsubscribe, reference);\n        this.unsubscribeInvalidation = unsubscribe;\n      } else {\n        // Keep invalidation working on older runtimes without weak references.\n        this.unsubscribeInvalidation = subscribeFarmCacheInvalidation((key) =>\n          this.invalidate(key),\n        );\n      }\n    }\n  }\n\n  get size(): number {\n    return this.entries.size;\n  }\n\n  /** @internal Attach or detach the persistence engine's observation sink. */\n  attachPersistence(sink: FarmClientCachePersistenceSink | undefined): void {\n    this.persistence = sink;\n  }\n\n  resolveKey(key: string): string {\n    let resolved = key;\n    const seen = new Set<string>();\n\n    while (this.aliases.has(resolved) && !seen.has(resolved)) {\n      seen.add(resolved);\n      resolved = this.aliases.get(resolved)!;\n    }\n\n    return resolved;\n  }\n\n  get<TData = unknown>(key: string, now = Date.now()): FarmClientCacheEntry<TData> | undefined {\n    const resolved = this.resolveKey(key);\n    const entry = this.entries.get(resolved) as FarmClientCacheEntry<TData> | undefined;\n    if (!entry) return undefined;\n\n    if (entry.gcAt !== undefined && now >= entry.gcAt) {\n      this.entries.delete(resolved);\n      this.persistence?.onDelete(resolved);\n      this.emit(resolved);\n      return undefined;\n    }\n\n    return entry;\n  }\n\n  set<TData>(key: string, entry: FarmClientCacheEntry<TData>): this {\n    const resolved = this.resolveKey(key);\n    const invalidatedAt = this.invalidatedAt.get(resolved);\n    const nextEntry =\n      invalidatedAt !== undefined && invalidatedAt > entry.updatedAt\n        ? { ...entry, staleAt: 0, invalidatedAt }\n        : { ...entry, invalidatedAt: undefined };\n\n    if (invalidatedAt === undefined || entry.updatedAt >= invalidatedAt) {\n      this.invalidatedAt.delete(resolved);\n    }\n\n    this.entries.set(resolved, nextEntry);\n    if (nextEntry.gcAt !== undefined) this.scheduleGcSweep();\n    this.persistence?.onSet(resolved, nextEntry);\n    this.emit(resolved);\n    return this;\n  }\n\n  delete(key: string): boolean {\n    const resolved = this.resolveKey(key);\n    const deleted = this.entries.delete(resolved);\n    this.inflight.delete(resolved);\n    if (deleted) this.persistence?.onDelete(resolved);\n    this.emit(resolved);\n    return deleted;\n  }\n\n  clear(): void {\n    const keys = new Set([...this.entries.keys(), ...this.listeners.keys()]);\n    this.entries.clear();\n    this.aliases.clear();\n    this.invalidatedAt.clear();\n    this.inflight.clear();\n    this.persistence?.onClear();\n    for (const key of keys) this.emit(key);\n  }\n\n  dispose(): void {\n    this.unsubscribeInvalidation?.();\n    this.unsubscribeInvalidation = undefined;\n    if (this.gcTimer !== undefined) {\n      clearTimeout(this.gcTimer);\n      this.gcTimer = undefined;\n    }\n    this.clear();\n  }\n\n  isStale(key: string, now = Date.now()): boolean {\n    const entry = this.get(key, now);\n    return !entry || entry.invalidatedAt !== undefined || now >= entry.staleAt;\n  }\n\n  invalidate(key: string, now = Date.now()): void {\n    const resolved = this.resolveKey(key);\n    for (const keys of invalidationTrackers.get(this) ?? []) keys.add(resolved);\n    this.invalidatedAt.set(resolved, now);\n\n    const entry = this.entries.get(resolved);\n    if (entry) {\n      this.entries.set(resolved, {\n        ...entry,\n        staleAt: 0,\n        invalidatedAt: now,\n      });\n    }\n\n    this.emit(resolved, \"invalidate\");\n  }\n\n  alias(alias: string, key: string): void {\n    const resolved = this.resolveKey(key);\n    if (alias === resolved) return;\n\n    const aliasEntry = this.entries.get(alias);\n    const aliasInvalidatedAt = this.invalidatedAt.get(alias) ?? aliasEntry?.invalidatedAt;\n    const resolvedInvalidatedAt = this.invalidatedAt.get(resolved);\n    if (aliasEntry && !this.entries.has(resolved)) {\n      this.entries.set(resolved, aliasEntry);\n      this.persistence?.onSet(resolved, aliasEntry);\n    }\n\n    if (this.entries.delete(alias)) this.persistence?.onDelete(alias);\n    this.invalidatedAt.delete(alias);\n    const invalidatedAt = [aliasInvalidatedAt, resolvedInvalidatedAt].reduce<number | undefined>(\n      (latest, value) =>\n        value === undefined ? latest : latest === undefined ? value : Math.max(latest, value),\n      undefined,\n    );\n    const resolvedEntry = this.entries.get(resolved);\n    if (\n      invalidatedAt !== undefined &&\n      (!resolvedEntry || invalidatedAt > resolvedEntry.updatedAt)\n    ) {\n      this.invalidatedAt.set(resolved, invalidatedAt);\n      if (resolvedEntry) {\n        this.entries.set(resolved, {\n          ...resolvedEntry,\n          staleAt: 0,\n          invalidatedAt,\n        });\n      }\n    } else if (invalidatedAt !== undefined) {\n      this.invalidatedAt.delete(resolved);\n      if (resolvedEntry?.invalidatedAt !== undefined) {\n        this.entries.set(resolved, { ...resolvedEntry, invalidatedAt: undefined });\n      }\n    }\n\n    const aliasInflight = this.inflight.get(alias);\n    if (aliasInflight && !this.inflight.has(resolved)) {\n      this.inflight.set(resolved, aliasInflight);\n    }\n    this.inflight.delete(alias);\n    this.aliases.set(alias, resolved);\n    this.emit(alias);\n    this.emit(resolved, this.invalidatedAt.has(resolved) ? \"invalidate\" : undefined);\n  }\n\n  subscribe(key: string, listener: FarmClientCacheListener): () => void {\n    let listeners = this.listeners.get(key);\n    if (!listeners) {\n      listeners = new Set();\n      this.listeners.set(key, listeners);\n    }\n\n    listeners.add(listener);\n    return () => {\n      listeners!.delete(listener);\n      // Only drop the map entry if it still holds this exact set. A repeated or\n      // stale unsubscribe (called after the key was drained and resubscribed)\n      // must not evict a newer subscriber's live listener set.\n      if (listeners!.size === 0 && this.listeners.get(key) === listeners) {\n        this.listeners.delete(key);\n      }\n    };\n  }\n\n  getInflight<TData>(key: string): Promise<TData> | undefined {\n    return this.inflight.get(this.resolveKey(key)) as Promise<TData> | undefined;\n  }\n\n  setInflight<TData>(key: string, promise: Promise<TData>): void {\n    this.inflight.set(this.resolveKey(key), promise);\n  }\n\n  deleteInflight(key: string): void {\n    this.inflight.delete(this.resolveKey(key));\n  }\n\n  private scheduleGcSweep(): void {\n    if (this.gcSweepIntervalMs === false || this.gcTimer !== undefined) return;\n    const timer = setTimeout(() => {\n      this.gcTimer = undefined;\n      this.sweepExpiredEntries();\n    }, this.gcSweepIntervalMs);\n    // Cache cleanup must never keep a Node.js process (SSR, tests) alive.\n    (timer as unknown as { unref?: () => void }).unref?.();\n    this.gcTimer = timer;\n  }\n\n  private sweepExpiredEntries(now = Date.now()): void {\n    const watched = new Set<string>();\n    for (const key of this.listeners.keys()) watched.add(this.resolveKey(key));\n\n    let remaining = false;\n    const swept = new Set<string>();\n    for (const [key, entry] of this.entries) {\n      if (entry.gcAt === undefined) continue;\n      if (now < entry.gcAt || entry.fetching || this.inflight.has(key) || watched.has(key)) {\n        remaining = true;\n        continue;\n      }\n      // Only unwatched entries are swept, so eviction is unobservable: a read\n      // of this key would already evict it lazily before returning data.\n      this.entries.delete(key);\n      this.persistence?.onDelete(key);\n      swept.add(key);\n    }\n\n    if (swept.size > 0) this.sweepEntryMetadata(swept);\n    if (remaining) this.scheduleGcSweep();\n  }\n\n  /**\n   * Entry eviction alone leaves the per-key metadata behind. `invalidatedAt`\n   * marks and provisional aliases are created per query invocation, so with\n   * dynamic keys they accumulate for the lifetime of the page even though the\n   * entries they describe are long gone.\n   */\n  private sweepEntryMetadata(swept: Set<string>): void {\n    for (const key of swept) this.invalidatedAt.delete(key);\n\n    for (const [alias, target] of this.aliases) {\n      // Keep any alias that is still addressable: one that has its own entry,\n      // that something is subscribed to, or whose target is still live.\n      if (this.entries.has(alias) || this.listeners.has(alias)) continue;\n      const resolved = this.resolveKey(target);\n      if (!swept.has(resolved)) continue;\n      if (this.entries.has(resolved) || this.listeners.has(resolved)) continue;\n      this.aliases.delete(alias);\n      this.invalidatedAt.delete(alias);\n    }\n  }\n\n  private emit(key: string, event?: \"invalidate\"): void {\n    this.notifyListeners(key, event);\n    for (const [alias, target] of this.aliases) {\n      if (this.resolveKey(target) === key) {\n        this.notifyListeners(alias, event);\n      }\n    }\n  }\n\n  private notifyListeners(key: string, event?: \"invalidate\"): void {\n    for (const listener of this.listeners.get(key) ?? []) {\n      // One subscriber must not be able to break the others, or to make an\n      // ordinary cache write or invalidation throw in its caller. This matches\n      // the isolation the global invalidation bus already provides.\n      try {\n        listener(event);\n      } catch (error) {\n        const detail = error instanceof Error ? (error.stack ?? error.message) : String(error);\n        console.warn(`[farm:client-cache] cache listener failed: ${detail}`);\n      }\n    }\n  }\n}\n\nconst FARM_CLIENT_DATA_CACHE = Symbol.for(\"farm.clientDataCache\");\nconst clientCacheGlobal = globalThis as typeof globalThis & {\n  [FARM_CLIENT_DATA_CACHE]?: FarmClientDataCache;\n};\nconst sharedFarmClientDataCache = (clientCacheGlobal[FARM_CLIENT_DATA_CACHE] ??=\n  new FarmClientDataCache());\n\nexport function getFarmClientDataCache(): FarmClientDataCache {\n  return sharedFarmClientDataCache;\n}\n\nexport function normalizeFarmClientCacheKey(key: FarmClientCacheKey): string {\n  return typeof key === \"string\" ? key : createRouteDataCacheKey(key);\n}\n"],"mappings":"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","names":[]}