{"version":3,"file":"index.cjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Ctx, ReadSignal } from '@kontsedal/olas-core'\nimport { signal } from '@kontsedal/olas-core'\n\nexport type StorageAdapter = {\n  get(key: string): string | null | Promise<string | null>\n  set(key: string, value: string): void | Promise<void>\n  delete(key: string): void | Promise<void>\n  onChange?(handler: (key: string, value: string | null) => void): () => void\n  /**\n   * Optional — list every key currently in storage. Consumers that need to\n   * enumerate keys (e.g. `@kontsedal/olas-mutation-queue` replaying the\n   * pending queue on init) require this extension; consumers that only\n   * `get` / `set` known keys (the typical `usePersisted` shape) don't need\n   * it. Both built-in adapters (`localStorageAdapter`, `indexedDbAdapter`)\n   * implement it.\n   */\n  keys?(): Iterable<string> | Promise<Iterable<string>>\n}\n\n/**\n * Where a `PersistOptions.onError` fired. Distinguishes the failing operation\n * for routing (e.g. quota-exceeded vs schema-migration-failed vs\n * deserialization-corrupted).\n */\nexport type PersistErrorOp =\n  | 'load'\n  | 'deserialize'\n  | 'serialize'\n  | 'write'\n  | 'migrate'\n  | 'remoteChange'\n\nexport type PersistOptions<T> = {\n  /**\n   * Storage backend. When omitted *or explicitly `undefined`* (handy for app\n   * code that forwards a deps slot like `ctx.deps.storage`), the browser\n   * `localStorageAdapter` is used. SSR-safe — `localStorageAdapter` no-ops\n   * when `localStorage` isn't defined.\n   */\n  storage?: StorageAdapter | undefined\n  serialize?: (value: T) => string\n  deserialize?: (raw: string) => T\n  crossTab?: boolean\n  /**\n   * Schema version. When the value loaded from storage carries a different\n   * `version`, `migrate(raw, fromVersion)` is invoked to bring it forward;\n   * the migrated value is written back atomically. When omitted, no version\n   * gate runs — payloads are read and written raw (current default).\n   *\n   * The on-disk shape with versioning enabled is `{\"v\": N, \"d\": <serialized>}`\n   * — `usePersisted` wraps every write and reads both shapes (legacy raw and\n   * versioned). Versioned writes only happen once `version` is set.\n   */\n  version?: number\n  /**\n   * Migrate a raw payload of a prior version. Receives the pre-deserialize\n   * string and the version number it was written with (or `undefined` if no\n   * version stamp existed, i.e. the legacy raw shape). Return the migrated\n   * payload AS A `T` value (post-deserialize); `usePersisted` re-serializes\n   * it before writing. Return `undefined` to drop the entry (the source\n   * keeps its current value).\n   */\n  migrate?: (raw: string, fromVersion: number | undefined) => T | undefined | Promise<T | undefined>\n  /**\n   * Debounce writes by `throttleMs` milliseconds. Useful for high-frequency\n   * sources (cursor position, scroll, every-keystroke field) where the\n   * default \"write on every change\" is too chatty. Defaults to `0` (no\n   * debounce). On `ctx.onDispose`, any pending write is flushed.\n   */\n  throttleMs?: number\n  /**\n   * Routed errors from every fallible op: storage `get`/`set` (quota,\n   * security, version-conflict), `deserialize`/`serialize` (corrupt JSON,\n   * non-serializable T), `migrate` (user-thrown), and `onChange` callbacks\n   * (cross-tab payload corruption). Without this, errors are swallowed —\n   * matches the historical behavior, but production apps want at least a\n   * sentry/console hook.\n   */\n  onError?: (err: unknown, op: PersistErrorOp, key: string) => void\n}\n\nexport type Persisted = {\n  ready: ReadSignal<boolean>\n}\n\nexport type PersistableSource<T> = {\n  readonly value: T\n  set(value: T): void\n  subscribe(handler: (value: T) => void): () => void\n}\n\n/**\n * Configuration for `indexedDbAdapter`. All fields optional; sane defaults\n * picked for typical app use.\n */\nexport type IndexedDbAdapterOptions = {\n  /** Database name. Defaults to `'olas-persist'`. */\n  databaseName?: string\n  /** Object store inside the database. Defaults to `'kv'`. */\n  storeName?: string\n  /**\n   * `BroadcastChannel` name used to notify other tabs of writes through this\n   * adapter (so `onChange` works cross-tab — IDB itself has no built-in\n   * change event). Defaults to `'olas-persist:' + databaseName + '/' +\n   * storeName`. Set to `null` to disable cross-tab notifications.\n   */\n  channelName?: string | null\n  /**\n   * Override the `IDBFactory` — defaults to `globalThis.indexedDB`. Useful\n   * for testing (inject a fake) or runtimes that ship their own IDB\n   * implementation. When undefined and no global `indexedDB`, the adapter\n   * no-ops (SSR-safe).\n   */\n  indexedDB?: IDBFactory\n  /**\n   * Override the `BroadcastChannel` constructor. Defaults to\n   * `globalThis.BroadcastChannel`. When undefined and no global, `onChange`\n   * subscriptions still register but never fire.\n   */\n  broadcastChannel?: typeof BroadcastChannel\n}\n\n/**\n * IndexedDB-backed `StorageAdapter`. Async on every operation; cross-tab\n * change notifications layered via `BroadcastChannel` (IDB has no native\n * change event, so external IDB writes by code that doesn't go through\n * this adapter are *not* observed). When no `IDBFactory` is available\n * (SSR, restricted environments), every method resolves to a no-op.\n *\n * Storage is a single key/value object store inside a single database;\n * fine for the persisted-signal use case `usePersisted` is built around.\n * For larger or schema-shaped data, write a custom adapter against your\n * own IDB layout.\n */\nexport function indexedDbAdapter(options?: IndexedDbAdapterOptions): StorageAdapter {\n  const dbName = options?.databaseName ?? 'olas-persist'\n  const storeName = options?.storeName ?? 'kv'\n  const idbFactory = options?.indexedDB ?? getGlobalIndexedDb()\n  const bcCtor = options?.broadcastChannel ?? getGlobalBroadcastChannel()\n  const channelName =\n    options?.channelName === null\n      ? null\n      : (options?.channelName ?? `olas-persist:${dbName}/${storeName}`)\n\n  let dbPromise: Promise<IDBDatabase> | null = null\n  let channel: BroadcastChannel | null = null\n\n  const ensureChannel = (): BroadcastChannel | null => {\n    if (channel !== null) return channel\n    if (bcCtor === undefined || channelName === null) return null\n    try {\n      channel = new bcCtor(channelName)\n      return channel\n    } catch {\n      return null\n    }\n  }\n\n  const openDb = (): Promise<IDBDatabase> | null => {\n    if (idbFactory === undefined) return null\n    if (dbPromise !== null) return dbPromise\n    dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n      const req = idbFactory.open(dbName, 1)\n      req.onupgradeneeded = () => {\n        const db = req.result\n        if (!db.objectStoreNames.contains(storeName)) {\n          db.createObjectStore(storeName)\n        }\n      }\n      req.onsuccess = () => {\n        const db = req.result\n        // Without this, holding the connection open BLOCKS another tab that\n        // wants to upgrade or `deleteDatabase` — a permanent silent stall.\n        // Close ours and drop the cached promise so the next op re-opens; a\n        // failed re-open then REJECTS and routes through the caller's onError\n        // instead of no-oping forever (T6.1).\n        db.onversionchange = () => {\n          db.close()\n          dbPromise = null\n        }\n        resolve(db)\n      }\n      req.onerror = () => reject(req.error ?? new Error('[olas-persist] IDB open failed'))\n    })\n    // Lazy connection — if the open fails, future calls retry rather than\n    // staying stuck on a poisoned promise.\n    dbPromise.catch(() => {\n      dbPromise = null\n    })\n    return dbPromise\n  }\n\n  const runRequest = async <T>(\n    mode: IDBTransactionMode,\n    build: (store: IDBObjectStore) => IDBRequest<T>,\n  ): Promise<T | undefined> => {\n    const db = await openDb()\n    if (db === null) return undefined\n    return new Promise<T | undefined>((resolve, reject) => {\n      let settled = false\n      const fail = (err: unknown): void => {\n        if (settled) return\n        settled = true\n        reject(err ?? new Error('[olas-persist] IDB request failed'))\n      }\n      const tx = db.transaction(storeName, mode)\n      const store = tx.objectStore(storeName)\n      const req = build(store)\n      let result: T | undefined\n      // Capture the request's result on success, but resolve on the\n      // TRANSACTION's commit — a write's `req.onsuccess` fires before the data\n      // is durably committed, so quota / disk failures only surface as a\n      // `tx.onabort` at commit time. Resolving on `req.onsuccess` (the old\n      // behavior) acked writes that never landed (T6.1).\n      req.onsuccess = () => {\n        result = req.result\n      }\n      req.onerror = () => fail(req.error)\n      tx.oncomplete = () => {\n        if (settled) return\n        settled = true\n        resolve(result)\n      }\n      tx.onabort = () => fail(tx.error)\n      tx.onerror = () => fail(tx.error)\n    })\n  }\n\n  return {\n    async get(key: string): Promise<string | null> {\n      if (idbFactory === undefined) return null\n      // A real read error (db closed, corrupt store) REJECTS so the caller's\n      // error routing runs (`usePersisted` → `onError('load')`). A missing key\n      // is not an error — `req.result` is `undefined`, so we return null.\n      const result = await runRequest<unknown>('readonly', (s) => s.get(key))\n      return typeof result === 'string' ? result : null\n    },\n    async set(key: string, value: string): Promise<void> {\n      if (idbFactory === undefined) return\n      // Do NOT swallow — a rejected write (quota, closed db, aborted commit)\n      // propagates so `usePersisted`'s `onError('write')` fires (T6.1). The\n      // cross-tab broadcast only runs once the commit actually lands.\n      await runRequest('readwrite', (s) => s.put(value, key))\n      ensureChannel()?.postMessage({ key, value })\n    },\n    async delete(key: string): Promise<void> {\n      if (idbFactory === undefined) return\n      await runRequest('readwrite', (s) => s.delete(key))\n      ensureChannel()?.postMessage({ key, value: null })\n    },\n    onChange(handler: (key: string, value: string | null) => void): () => void {\n      const ch = ensureChannel()\n      if (ch === null) return () => {}\n      const listener = (event: MessageEvent<{ key: string; value: string | null }>) => {\n        try {\n          handler(event.data.key, event.data.value)\n        } catch {\n          /* swallow — onChange handlers shouldn't take down the adapter */\n        }\n      }\n      ch.addEventListener('message', listener)\n      return () => ch.removeEventListener('message', listener)\n    },\n    async keys(): Promise<string[]> {\n      if (idbFactory === undefined) return []\n      try {\n        const result = await runRequest<IDBValidKey[]>('readonly', (s) => s.getAllKeys())\n        if (!Array.isArray(result)) return []\n        return result.filter((k): k is string => typeof k === 'string')\n      } catch {\n        return []\n      }\n    },\n  }\n}\n\nfunction getGlobalIndexedDb(): IDBFactory | undefined {\n  return typeof indexedDB === 'undefined' ? undefined : indexedDB\n}\n\nfunction getGlobalBroadcastChannel(): typeof BroadcastChannel | undefined {\n  return typeof BroadcastChannel === 'undefined' ? undefined : BroadcastChannel\n}\n\n/** Default localStorage adapter — only viable in the browser. */\nexport const localStorageAdapter: StorageAdapter = {\n  get(key: string): string | null {\n    if (typeof localStorage === 'undefined') return null\n    return localStorage.getItem(key)\n  },\n  set(key: string, value: string): void {\n    if (typeof localStorage === 'undefined') return\n    localStorage.setItem(key, value)\n  },\n  delete(key: string): void {\n    if (typeof localStorage === 'undefined') return\n    localStorage.removeItem(key)\n  },\n  onChange(handler) {\n    if (typeof window === 'undefined') return () => {}\n    const listener = (event: StorageEvent) => {\n      if (event.key === null) return\n      handler(event.key, event.newValue)\n    }\n    window.addEventListener('storage', listener)\n    return () => window.removeEventListener('storage', listener)\n  },\n  keys(): string[] {\n    if (typeof localStorage === 'undefined') return []\n    const out: string[] = []\n    for (let i = 0; i < localStorage.length; i++) {\n      const k = localStorage.key(i)\n      if (k !== null) out.push(k)\n    }\n    return out\n  },\n}\n\n/**\n * Persist a signal-like source under `key`. Loads the stored value on\n * construction (sync for localStorage, async for any storage that returns a\n * promise). Subsequent writes to the source are mirrored to storage.\n *\n * Cleanup (unsubscribe + cross-tab listener removal) is bound to `ctx`.\n */\nexport function usePersisted<T>(\n  ctx: Ctx,\n  key: string,\n  source: PersistableSource<T>,\n  options?: PersistOptions<T>,\n): Persisted {\n  const storage = options?.storage ?? localStorageAdapter\n  const serialize = options?.serialize ?? JSON.stringify\n  const deserialize = options?.deserialize ?? JSON.parse\n  const crossTab = options?.crossTab ?? false\n  const version = options?.version\n  const migrate = options?.migrate\n  const throttleMs = options?.throttleMs ?? 0\n  const onError = options?.onError\n\n  const reportError = (err: unknown, op: PersistErrorOp): void => {\n    if (onError === undefined) return\n    try {\n      onError(err, op, key)\n    } catch {\n      /* an onError handler that itself throws is its own problem. */\n    }\n  }\n\n  const ready$ = signal(false)\n  let writingFromLoad = false\n  // Ready-gate race bookkeeping (T6.1). A source write or a cross-tab change\n  // that lands BEFORE the initial async load settles must not be lost or\n  // clobbered by `applyLoaded`. We remember the latest of each and reconcile\n  // once ready flips true (a local user write wins over both stored + remote).\n  let userWroteBeforeReady = false\n  let pendingUserValueBeforeReady: T | undefined\n  let hasPendingRemote = false\n  let pendingRemoteRaw: string | null = null\n\n  /**\n   * On-disk envelope when `version` is set: `{\"v\": N, \"d\": \"<serializedT>\"}`.\n   * Without `version`, we read/write raw (legacy shape). Migration takes the\n   * raw inner string + the parsed `v` (or `undefined` for legacy) so the\n   * consumer's migrator can replay arbitrary historical formats.\n   */\n  type Envelope = { v: number; d: string }\n  const isEnvelope = (raw: unknown): raw is Envelope =>\n    typeof raw === 'object' &&\n    raw !== null &&\n    typeof (raw as { v?: unknown }).v === 'number' &&\n    typeof (raw as { d?: unknown }).d === 'string'\n\n  const encodeForStorage = (value: T): string => {\n    const inner = serialize(value)\n    if (version === undefined) return inner\n    return JSON.stringify({ v: version, d: inner })\n  }\n\n  // Apply a cross-tab raw value to the source (a null → `undefined` delete;\n  // otherwise parse/deserialize, honoring the version envelope). Shared by the\n  // live `onChange` path and the buffered-until-ready replay (T6.1).\n  const applyRemote = (rawValue: string | null): void => {\n    if (rawValue == null) {\n      writingFromLoad = true\n      try {\n        source.set(undefined as T)\n      } finally {\n        writingFromLoad = false\n      }\n      return\n    }\n    try {\n      let parsed: unknown\n      try {\n        parsed = JSON.parse(rawValue)\n      } catch {\n        parsed = undefined\n      }\n      let value: T\n      if (version !== undefined && isEnvelope(parsed)) {\n        if (parsed.v !== version) return // peer on a different schema; ignore.\n        value = deserialize(parsed.d) as T\n      } else {\n        value = deserialize(rawValue) as T\n      }\n      writingFromLoad = true\n      try {\n        source.set(value)\n      } finally {\n        writingFromLoad = false\n      }\n    } catch (err) {\n      reportError(err, 'remoteChange')\n    }\n  }\n\n  // Flip `ready` and reconcile anything that raced the initial load: a local\n  // user write wins outright (and is flushed to storage); otherwise a buffered\n  // cross-tab change (the freshest one) is applied. `scheduleWrite` is only\n  // reached in the async-load path, where it is already defined below.\n  const settleReady = (): void => {\n    ready$.set(true)\n    if (userWroteBeforeReady) {\n      userWroteBeforeReady = false\n      hasPendingRemote = false\n      scheduleWrite(pendingUserValueBeforeReady as T)\n      return\n    }\n    if (hasPendingRemote) {\n      hasPendingRemote = false\n      applyRemote(pendingRemoteRaw)\n    }\n  }\n\n  // Load initial value.\n  const loaded = storage.get(key)\n  const applyLoaded = async (raw: string | null): Promise<void> => {\n    // A local write already raced the load — it wins; don't apply storage.\n    // `settleReady` flushes the user's value.\n    if (userWroteBeforeReady) {\n      settleReady()\n      return\n    }\n    if (raw == null) {\n      settleReady()\n      return\n    }\n    let value: T | undefined\n    let needsRewrite = false\n    try {\n      // Try the envelope shape first (for version-aware reads). If it isn't\n      // an envelope, treat the raw string as a legacy v=undefined payload.\n      let parsedEnvelope: unknown\n      try {\n        parsedEnvelope = JSON.parse(raw)\n      } catch {\n        parsedEnvelope = undefined\n      }\n      if (version !== undefined && isEnvelope(parsedEnvelope)) {\n        if (parsedEnvelope.v === version) {\n          value = deserialize(parsedEnvelope.d) as T\n        } else if (migrate !== undefined) {\n          try {\n            const migrated = await migrate(parsedEnvelope.d, parsedEnvelope.v)\n            if (migrated === undefined) {\n              settleReady()\n              return\n            }\n            value = migrated\n            needsRewrite = true\n          } catch (err) {\n            reportError(err, 'migrate')\n            settleReady()\n            return\n          }\n        } else {\n          // Version mismatch with no migrator — discard.\n          settleReady()\n          return\n        }\n      } else if (version !== undefined && migrate !== undefined) {\n        // Legacy raw payload but we now require versioning — invoke migrator\n        // with `fromVersion: undefined`.\n        try {\n          const migrated = await migrate(raw, undefined)\n          if (migrated === undefined) {\n            settleReady()\n            return\n          }\n          value = migrated\n          needsRewrite = true\n        } catch (err) {\n          reportError(err, 'migrate')\n          settleReady()\n          return\n        }\n      } else {\n        value = deserialize(raw) as T\n      }\n    } catch (err) {\n      reportError(err, 'deserialize')\n      settleReady()\n      return\n    }\n    // A write may have landed while we awaited an async migrate — it wins.\n    if (userWroteBeforeReady) {\n      settleReady()\n      return\n    }\n    writingFromLoad = true\n    try {\n      source.set(value as T)\n    } finally {\n      writingFromLoad = false\n    }\n    settleReady()\n    if (needsRewrite) {\n      // Persist the migrated value so the next load doesn't re-migrate. Split\n      // serialize vs write so a storage-quota throw isn't mislabeled (T6.1).\n      let encoded: string\n      try {\n        encoded = encodeForStorage(value as T)\n      } catch (err) {\n        reportError(err, 'serialize')\n        return\n      }\n      try {\n        const writeResult = storage.set(key, encoded)\n        if (writeResult instanceof Promise) writeResult.catch((e) => reportError(e, 'write'))\n      } catch (err) {\n        reportError(err, 'write')\n      }\n    }\n  }\n\n  if (loaded instanceof Promise) {\n    loaded.then(\n      (raw) => applyLoaded(raw),\n      (err) => {\n        reportError(err, 'load')\n        settleReady()\n      },\n    )\n  } else {\n    applyLoaded(loaded)\n  }\n\n  // Optional throttled writer. State is captured per-`usePersisted` call so\n  // multiple persisted signals in the same controller don't interfere.\n  let pendingWriteValue: T | undefined\n  let hasPendingWrite = false\n  let writeTimer: ReturnType<typeof setTimeout> | null = null\n\n  const flushWrite = (): void => {\n    if (!hasPendingWrite) return\n    const value = pendingWriteValue as T\n    hasPendingWrite = false\n    pendingWriteValue = undefined\n    writeTimer = null\n    // Encode and write are separate failure domains: encoding is a 'serialize'\n    // error; `storage.set` (sync for localStorage — quota throws here) is a\n    // 'write' error. The old single try mislabeled every write throw as\n    // 'serialize' (T6.1).\n    let raw: string\n    try {\n      raw = encodeForStorage(value)\n    } catch (err) {\n      reportError(err, 'serialize')\n      return\n    }\n    try {\n      const writeResult = storage.set(key, raw)\n      if (writeResult instanceof Promise) writeResult.catch((e) => reportError(e, 'write'))\n    } catch (err) {\n      reportError(err, 'write')\n    }\n  }\n\n  const scheduleWrite = (value: T): void => {\n    if (throttleMs <= 0) {\n      pendingWriteValue = value\n      hasPendingWrite = true\n      flushWrite()\n      return\n    }\n    pendingWriteValue = value\n    hasPendingWrite = true\n    if (writeTimer === null) {\n      writeTimer = setTimeout(flushWrite, throttleMs)\n    }\n  }\n\n  // Persist on every CHANGE. The signal's subscribe fires immediately with\n  // the current value — skip that initial call so we don't write back what\n  // we just loaded (or the source's default before load).\n  let skipFirstDelivery = true\n  const unsub = source.subscribe((value) => {\n    if (skipFirstDelivery) {\n      skipFirstDelivery = false\n      return\n    }\n    if (writingFromLoad) return\n    if (!ready$.peek()) {\n      // A real user write before the initial load settled — remember it so\n      // `settleReady` flushes it and `applyLoaded` doesn't clobber the source.\n      // The old code dropped it, then the load overwrote what the user typed\n      // (T6.1).\n      userWroteBeforeReady = true\n      pendingUserValueBeforeReady = value\n      return\n    }\n    scheduleWrite(value)\n  })\n\n  // Cross-tab sync.\n  let unsubChange: (() => void) | null = null\n  if (crossTab && storage.onChange) {\n    unsubChange = storage.onChange((changedKey, rawValue) => {\n      if (changedKey !== key) return\n      if (!ready$.peek()) {\n        // Buffer the freshest cross-tab change until the initial load settles;\n        // applying it now would race the load and get clobbered by\n        // `applyLoaded` (T6.1). A local user write still takes precedence in\n        // `settleReady`.\n        hasPendingRemote = true\n        pendingRemoteRaw = rawValue\n        return\n      }\n      // A null value is a cross-tab delete (`localStorage.removeItem`) — mirror\n      // it locally as `undefined`; see `applyRemote`.\n      applyRemote(rawValue)\n    })\n  }\n\n  ctx.onDispose(() => {\n    // Flush any pending throttled write before tearing down so we never lose\n    // the last value the user produced. Synchronous in localStorage; the\n    // Promise return from IDB resolves shortly after dispose returns.\n    if (hasPendingWrite) {\n      if (writeTimer !== null) clearTimeout(writeTimer)\n      flushWrite()\n    }\n    unsub()\n    unsubChange?.()\n  })\n\n  return { ready: ready$ }\n}\n\n/**\n * Clear every key under a `prefix` (default: clear all). Useful for \"log out\"\n * flows that want to drop persisted state without enumerating consumers.\n * Errors are routed through the optional `onError` (e.g. quota or security\n * exceptions on `delete`).\n */\nexport async function clearPersisted(\n  storage: StorageAdapter = localStorageAdapter,\n  prefix?: string,\n  onError?: (err: unknown, key: string) => void,\n): Promise<void> {\n  if (storage.keys === undefined) return\n  let keys: Iterable<string>\n  try {\n    const result = storage.keys()\n    keys = result instanceof Promise ? await result : result\n  } catch (err) {\n    onError?.(err, '<keys>')\n    return\n  }\n  for (const key of keys) {\n    if (prefix !== undefined && !key.startsWith(prefix)) continue\n    try {\n      const r = storage.delete(key)\n      if (r instanceof Promise) await r\n    } catch (err) {\n      onError?.(err, key)\n    }\n  }\n}\n"],"mappings":"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"}