{"version":3,"file":"local-storage.cjs","sources":["../../src/local-storage.ts"],"sourcesContent":["import { safeRandomUUID } from './utils/uuid'\nimport { deepEquals } from './utils'\nimport { withCollectionConfigFactory } from './client.js'\nimport { collectionOptionsClaim } from './collection-options.js'\nimport { registerTransactionCommitWork } from './transaction-commit-work.js'\nimport {\n  InvalidStorageDataFormatError,\n  InvalidStorageObjectFormatError,\n  LocalStorageCollectionError,\n  SerializationError,\n  StorageKeyRequiredError,\n} from './errors'\nimport { codedMessage, codedWarning, devBuild } from './error-message.js'\nimport type {\n  BaseCollectionConfig,\n  CollectionConfig,\n  DeleteMutationFnParams,\n  InferSchemaOutput,\n  InsertMutationFnParams,\n  PendingMutation,\n  SyncConfig,\n  UpdateMutationFnParams,\n  UtilsRecord,\n} from './types'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\n\n/**\n * Storage API interface - subset of DOM Storage that we need\n */\nexport type StorageApi = Pick<Storage, `getItem` | `setItem` | `removeItem`>\n\n/**\n * Storage event API - subset of Window for 'storage' events only\n */\nexport type StorageEventApi = {\n  addEventListener: (\n    type: `storage`,\n    listener: (event: StorageEvent) => void,\n  ) => void\n  removeEventListener: (\n    type: `storage`,\n    listener: (event: StorageEvent) => void,\n  ) => void\n}\n\n// Browser storage events do not reach other Collections in the writing tab.\n// A sync run owns one listener for writes through the same Storage object/key.\nconst sameTabListeners = new WeakMap<StorageApi, Map<string, Set<() => void>>>()\n\nfunction subscribeToSameTabWrites(\n  storage: StorageApi,\n  key: string,\n  refresh: () => void,\n): () => void {\n  let byKey = sameTabListeners.get(storage)\n  if (!byKey) {\n    byKey = new Map()\n    sameTabListeners.set(storage, byKey)\n  }\n  let listeners = byKey.get(key)\n  if (!listeners) {\n    listeners = new Set()\n    byKey.set(key, listeners)\n  }\n  listeners.add(refresh)\n  return () => {\n    listeners.delete(refresh)\n    if (listeners.size === 0) byKey.delete(key)\n    if (byKey.size === 0) sameTabListeners.delete(storage)\n  }\n}\n\nfunction publishSameTabWrite(\n  storage: StorageApi,\n  key: string,\n  writer?: { listener: () => void; refresh: () => void },\n): void {\n  for (const refresh of [...(sameTabListeners.get(storage)?.get(key) ?? [])]) {\n    try {\n      if (refresh === writer?.listener) writer.refresh()\n      else refresh()\n    } catch (error) {\n      // A peer's parser or sync listener cannot revoke the writer's durable\n      // write or prevent another peer from observing it.\n      console.warn(\n        devBuild() && process.env.NODE_ENV !== `production`\n          ? `[LocalStorageCollection] Error refreshing a same-tab peer for storage key \"${key}\":`\n          : codedWarning(232, { storageKey: key }),\n        error,\n      )\n    }\n  }\n}\n\n/**\n * Internal storage format that includes version tracking\n */\ninterface StoredItem<T> {\n  versionKey: string\n  data: T\n}\n\nexport interface Parser {\n  parse: (data: string) => unknown\n  stringify: (data: unknown) => string\n}\n\n/**\n * Configuration interface for localStorage collection options\n * @template T - The type of items in the collection\n * @template TSchema - The schema type for validation\n * @template TKey - The type of the key returned by `getKey`\n */\nexport interface LocalStorageCollectionConfig<\n  T extends object = object,\n  TSchema extends StandardSchemaV1 = never,\n  TKey extends string | number = string | number,\n> extends BaseCollectionConfig<T, TKey, TSchema> {\n  /**\n   * The key to use for storing the collection data in localStorage/sessionStorage\n   */\n  storageKey: string\n\n  /**\n   * Storage API to use (defaults to window.localStorage)\n   * Can be any object that implements the Storage interface (e.g., sessionStorage)\n   */\n  storage?: StorageApi\n\n  /**\n   * Storage event API to use for cross-tab synchronization (defaults to window)\n   * Can be any object that implements addEventListener/removeEventListener for storage events\n   */\n  storageEventApi?: StorageEventApi\n\n  /**\n   * Parser to use for serializing and deserializing data to and from storage\n   * Defaults to JSON\n   */\n  parser?: Parser\n}\n\n/**\n * Type for the clear utility function\n */\nexport type ClearStorageFn = () => void\n\n/**\n * Type for the getStorageSize utility function\n */\nexport type GetStorageSizeFn = () => number\n\n/**\n * LocalStorage collection utilities type\n */\nexport interface LocalStorageCollectionUtils extends UtilsRecord {\n  clearStorage: ClearStorageFn\n  getStorageSize: GetStorageSizeFn\n  /**\n   * Accepts this Collection's manual mutations in write order and persists\n   * them to localStorage. Call it inside the transaction's mutationFn. The\n   * transaction's persistence receipt waits for this work even if the caller\n   * does not await the returned Promise. Await it when later mutationFn work\n   * depends on the storage write.\n   *\n   * @param transaction - The transaction containing mutations to accept\n   * @example\n   * const localSettings = createCollection(localStorageCollectionOptions({...}))\n   *\n   * const tx = createTransaction({\n   *   mutationFn: async ({ transaction }) => {\n   *     // Make API call first\n   *     await api.save(...)\n   *     // Then persist local-storage mutations after success\n   *     await localSettings.utils.acceptMutations(transaction)\n   *   }\n   * })\n   */\n  acceptMutations: (transaction: {\n    mutations: Array<PendingMutation<Record<string, unknown>>>\n  }) => Promise<void>\n}\n\n/**\n * Validates that a value can be JSON serialized\n * @param parser - The parser to use for serialization\n * @param value - The value to validate for JSON serialization\n * @param operation - The operation type being performed (for error messages)\n * @throws Error if the value cannot be JSON serialized\n */\nfunction validateJsonSerializable(\n  parser: Parser,\n  value: any,\n  operation: string,\n): void {\n  try {\n    parser.stringify(value)\n  } catch (error) {\n    throw new SerializationError(\n      operation,\n      error instanceof Error ? error.message : String(error),\n    )\n  }\n}\n\n/**\n * Generate a UUID for version tracking\n * @returns A unique identifier string for tracking data versions\n */\nfunction generateUuid(): string {\n  return safeRandomUUID()\n}\n\n/**\n * Encodes a key (string or number) into a storage-safe string format.\n * This prevents collisions between numeric and string keys by prefixing with type information.\n *\n * Examples:\n *   - number 1 → \"n:1\"\n *   - string \"1\" → \"s:1\"\n *   - string \"n:1\" → \"s:n:1\"\n *\n * @param key - The key to encode (string or number)\n * @returns Type-prefixed string that is safe for storage\n */\nfunction encodeStorageKey(key: string | number): string {\n  if (typeof key === `number`) {\n    return `n:${key}`\n  }\n  return `s:${key}`\n}\n\n/**\n * Decodes a storage key back to its original form.\n * This is the inverse of encodeStorageKey.\n *\n * @param encodedKey - The encoded key from storage\n * @returns The original key (string or number)\n */\nfunction decodeStorageKey(encodedKey: string): string | number {\n  if (encodedKey.startsWith(`n:`)) {\n    return Number(encodedKey.slice(2))\n  }\n  if (encodedKey.startsWith(`s:`)) {\n    return encodedKey.slice(2)\n  }\n  // Fallback for legacy data without encoding\n  return encodedKey\n}\n\nfunction sameStorageKey(\n  left: string | number,\n  right: string | number,\n): boolean {\n  return left === right || (Number.isNaN(left) && Number.isNaN(right))\n}\n\n/**\n * Creates an in-memory storage implementation that mimics the StorageApi interface\n * Used as a fallback when localStorage is not available (e.g., server-side rendering)\n * @returns An object implementing the StorageApi interface using an in-memory Map\n */\nfunction createInMemoryStorage(): StorageApi {\n  const storage = new Map<string, string>()\n\n  return {\n    getItem(key: string): string | null {\n      return storage.get(key) ?? null\n    },\n    setItem(key: string, value: string): void {\n      storage.set(key, value)\n    },\n    removeItem(key: string): void {\n      storage.delete(key)\n    },\n  }\n}\n\n/**\n * Creates a no-op storage event API for environments without window (e.g., server-side)\n * This provides the required interface but doesn't actually listen to any events\n * since cross-tab synchronization is not possible in server environments\n * @returns An object implementing the StorageEventApi interface with no-op methods\n */\nfunction createNoOpStorageEventApi(): StorageEventApi {\n  return {\n    addEventListener: () => {\n      // No-op: cannot listen to storage events without window\n    },\n    removeEventListener: () => {\n      // No-op: cannot remove listeners without window\n    },\n  }\n}\n\n/**\n * Creates localStorage collection options for use with a standard Collection\n *\n * This function creates a collection that persists data to localStorage/sessionStorage\n * and synchronizes changes across browser tabs using storage events. Active\n * Collections sharing this Storage object and storage key also synchronize\n * writes in the same tab, without waiting for a browser event.\n * Create fresh options for each direct `createCollection()` call. One options\n * object contains state owned by one Collection and cannot be reused.\n *\n * **Fallback Behavior:**\n *\n * When localStorage is not available (e.g., in server-side rendering environments),\n * this function automatically falls back to an in-memory storage implementation.\n * This prevents errors during module initialization and allows the collection to\n * work in any environment, though data will not persist across page reloads or\n * be shared across tabs when using the in-memory fallback.\n *\n * **Using with Manual Transactions:**\n *\n * For manual transactions, call `utils.acceptMutations()` in your transaction's `mutationFn`\n * to persist changes made during `tx.mutate()`. The transaction receipt waits for this work even\n * when the call is not awaited. Await it when later mutationFn work depends on the storage write.\n *\n * @template TExplicit - The explicit type of items in the collection (highest priority)\n * @template TSchema - The schema type for validation and type inference (second priority)\n * @template TFallback - The fallback type if no explicit or schema type is provided\n * @param config - Configuration options for the localStorage collection\n * @returns Collection options with utilities including clearStorage, getStorageSize, and acceptMutations\n *\n * @example\n * // Basic localStorage collection\n * const collection = createCollection(\n *   localStorageCollectionOptions({\n *     storageKey: 'todos',\n *     getKey: (item) => item.id,\n *   })\n * )\n *\n * @example\n * // localStorage collection with custom storage\n * const collection = createCollection(\n *   localStorageCollectionOptions({\n *     storageKey: 'todos',\n *     storage: window.sessionStorage, // Use sessionStorage instead\n *     getKey: (item) => item.id,\n *   })\n * )\n *\n * @example\n * // localStorage collection with mutation handlers\n * const collection = createCollection(\n *   localStorageCollectionOptions({\n *     storageKey: 'todos',\n *     getKey: (item) => item.id,\n *     onInsert: async ({ transaction }) => {\n *       console.log('Item inserted:', transaction.mutations[0].modified)\n *     },\n *   })\n * )\n *\n * @example\n * // Using with manual transactions\n * const localSettings = createCollection(\n *   localStorageCollectionOptions({\n *     storageKey: 'user-settings',\n *     getKey: (item) => item.id,\n *   })\n * )\n *\n * const tx = createTransaction({\n *   mutationFn: async ({ transaction }) => {\n *     // Use settings data in API call\n *     const settingsMutations = transaction.mutations.filter(m => m.collection === localSettings)\n *     await api.updateUserProfile({ settings: settingsMutations[0]?.modified })\n *\n *     // Persist local-storage mutations after API success\n *     await localSettings.utils.acceptMutations(transaction)\n *   }\n * })\n *\n * tx.mutate(() => {\n *   localSettings.insert({ id: 'theme', value: 'dark' })\n *   apiCollection.insert({ id: 2, data: 'profile data' })\n * })\n *\n * await tx.commit()\n */\n\n// Overload for when schema is provided\nexport function localStorageCollectionOptions<\n  T extends StandardSchemaV1,\n  TKey extends string | number = string | number,\n>(\n  config: LocalStorageCollectionConfig<InferSchemaOutput<T>, T, TKey> & {\n    schema: T\n  },\n): CollectionConfig<\n  InferSchemaOutput<T>,\n  TKey,\n  T,\n  LocalStorageCollectionUtils\n> & {\n  id: string\n  utils: LocalStorageCollectionUtils\n  schema: T\n}\n\n// Overload for when no schema is provided\n// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config\nexport function localStorageCollectionOptions<\n  T extends object,\n  TKey extends string | number = string | number,\n>(\n  config: LocalStorageCollectionConfig<T, never, TKey> & {\n    schema?: never // prohibit schema\n  },\n): CollectionConfig<T, TKey, never, LocalStorageCollectionUtils> & {\n  id: string\n  utils: LocalStorageCollectionUtils\n  schema?: never // no schema in the result\n}\n\nexport function localStorageCollectionOptions(\n  config: LocalStorageCollectionConfig<any, any, string | number>,\n): Omit<\n  CollectionConfig<any, string | number, any, LocalStorageCollectionUtils>,\n  `id`\n> & {\n  id: string\n  utils: LocalStorageCollectionUtils\n  schema?: StandardSchemaV1\n} {\n  // Validate required parameters\n  if (!config.storageKey) {\n    throw new StorageKeyRequiredError()\n  }\n\n  // Default to window.localStorage if no storage is provided\n  // Fall back to in-memory storage if localStorage is not available (e.g., server-side rendering)\n  const storage =\n    config.storage ||\n    (typeof window !== `undefined` ? window.localStorage : null) ||\n    createInMemoryStorage()\n\n  // Default to window for storage events if not provided\n  // Fall back to no-op storage event API if window is not available (e.g., server-side rendering)\n  const storageEventApi =\n    config.storageEventApi ||\n    (typeof window !== `undefined` ? window : null) ||\n    createNoOpStorageEventApi()\n\n  // Default to JSON parser if no parser is provided\n  const parser = config.parser || JSON\n\n  // Track the last known state to detect changes\n  const lastKnownData = new Map<string | number, StoredItem<any>>()\n\n  // Create the sync configuration\n  const sync = createLocalStorageSync<any>(\n    config.storageKey,\n    storage,\n    storageEventApi,\n    parser,\n    config.getKey,\n    lastKnownData,\n  )\n\n  /**\n   * Save data to storage\n   * @param dataMap - Map of items with version tracking to save to storage\n   */\n  const saveToStorage = (\n    dataMap: Map<string | number, StoredItem<any>>,\n    mutations: Array<PendingMutation<Record<string, unknown>>>,\n  ): {\n    serialized: string\n    persisted: Map<string | number, StoredItem<any>>\n  } => {\n    try {\n      // Convert Map to object format for storage\n      const objectData: Record<string, StoredItem<any>> = {}\n      dataMap.forEach((storedItem, key) => {\n        objectData[encodeStorageKey(key)] = storedItem\n      })\n      const serialized = parser.stringify(objectData)\n      // A custom parser may normalize rows while serializing. Validate and\n      // retain the exact snapshot before setItem makes the write durable.\n      const persisted =\n        parser === JSON\n          ? dataMap\n          : readFromStorage(\n              config.storageKey,\n              storage,\n              parser,\n              config.getKey,\n              serialized,\n            )\n      for (const mutation of mutations) {\n        const storedItem = persisted.get(mutation.key)\n        if (mutation.type === `delete` ? storedItem : !storedItem) {\n          throw new InvalidStorageDataFormatError(\n            config.storageKey,\n            encodeStorageKey(mutation.key),\n          )\n        }\n      }\n      storage.setItem(config.storageKey, serialized)\n      return { serialized, persisted }\n    } catch (error) {\n      console.error(\n        devBuild() && process.env.NODE_ENV !== `production`\n          ? `[LocalStorageCollection] Error saving data to storage key \"${config.storageKey}\":`\n          : codedMessage(218, { storageKey: config.storageKey }),\n        error,\n      )\n      throw error\n    }\n  }\n\n  /**\n   * Removes the stored snapshot and publishes removal of accepted synced rows.\n   * Pending optimistic mutations can still settle afterward.\n   */\n  const clearStorage: ClearStorageFn = (): void => {\n    storage.removeItem(config.storageKey)\n    publishSameTabWrite(storage, config.storageKey)\n  }\n\n  /**\n   * Get the size of the stored data in bytes (approximate)\n   * @returns The approximate size in bytes of the stored collection data\n   */\n  const getStorageSize: GetStorageSizeFn = (): number => {\n    const data = storage.getItem(config.storageKey)\n    return data ? new Blob([data]).size : 0\n  }\n\n  const persistMutations = (\n    mutations: Array<PendingMutation<Record<string, unknown>>>,\n  ): void => {\n    // A peer may have written after our last storage event. Start from the\n    // current durable snapshot so this write preserves untouched peer rows.\n    const staged = readFromStorage(\n      config.storageKey,\n      storage,\n      parser,\n      config.getKey,\n    )\n    for (const mutation of mutations) {\n      if (mutation.type === `delete`) staged.delete(mutation.key)\n      else {\n        if (parser === JSON) {\n          const restored = JSON.parse(JSON.stringify(mutation.modified))\n          if (!sameStorageKey(config.getKey(restored), mutation.key)) {\n            throw new InvalidStorageDataFormatError(\n              config.storageKey,\n              encodeStorageKey(mutation.key),\n            )\n          }\n        }\n        staged.set(mutation.key, {\n          versionKey: generateUuid(),\n          data: mutation.modified,\n        })\n      }\n    }\n    const { serialized: savedRaw, persisted } = saveToStorage(staged, mutations)\n    try {\n      for (const mutation of mutations) {\n        const storedItem = persisted.get(mutation.key)\n        if (storedItem) lastKnownData.set(mutation.key, storedItem)\n        else lastKnownData.delete(mutation.key)\n      }\n      sync.confirmOperationsSync(mutations, persisted)\n    } finally {\n      // Storage has already accepted this snapshot. A local confirmation\n      // error must not suppress publication to other active Collections.\n      const writerRefresh = sync.manualTrigger\n      publishSameTabWrite(\n        storage,\n        config.storageKey,\n        writerRefresh\n          ? {\n              listener: writerRefresh,\n              refresh: () =>\n                writerRefresh(\n                  storage.getItem(config.storageKey) === savedRaw\n                    ? persisted\n                    : undefined,\n                ),\n            }\n          : undefined,\n      )\n    }\n  }\n\n  // Reserve automatic and manual writes in acceptance order. A rejected\n  // handler releases only its storage slot after its predecessor, while its\n  // own transaction receipt can reject immediately.\n  let writeTail: Promise<void> | undefined\n  const reserveWrite = () => {\n    const previous = writeTail\n    let release!: () => void\n    const slot = new Promise<void>((resolve) => {\n      release = resolve\n    })\n    writeTail = slot\n    const retire = () => {\n      release()\n      if (writeTail === slot) writeTail = undefined\n    }\n    return { previous, retire }\n  }\n\n  const persistAutomatic = (\n    mutations: Array<PendingMutation<Record<string, unknown>>>,\n    handler?: () => unknown | Promise<unknown>,\n  ): Promise<unknown> => {\n    const { previous, retire } = reserveWrite()\n\n    // Native Storage writes synchronously. With no handler or earlier write,\n    // preserve that direct-mutation return boundary.\n    if (!handler && previous === undefined) {\n      try {\n        persistMutations(mutations)\n        return Promise.resolve({})\n      } catch (error) {\n        return Promise.reject(error)\n      } finally {\n        retire()\n      }\n    }\n\n    let result: unknown\n    try {\n      result = handler?.()\n    } catch (error) {\n      if (previous) void previous.then(retire)\n      else retire()\n      return Promise.reject(error)\n    }\n    return Promise.resolve(result).then(\n      async (value) => {\n        await previous\n        try {\n          persistMutations(mutations)\n          return value ?? {}\n        } finally {\n          retire()\n        }\n      },\n      (error: unknown) => {\n        // Rejection belongs to this transaction immediately. Only its empty\n        // storage slot must wait for the earlier accepted write to retire.\n        if (previous) void previous.then(retire)\n        else retire()\n        throw error\n      },\n    )\n  }\n\n  const persistManual = (\n    mutations: Array<PendingMutation<Record<string, unknown>>>,\n  ): Promise<void> => {\n    const { previous, retire } = reserveWrite()\n    if (previous === undefined) {\n      try {\n        persistMutations(mutations)\n        return Promise.resolve()\n      } finally {\n        retire()\n      }\n    }\n    return previous.then(() => {\n      try {\n        persistMutations(mutations)\n      } finally {\n        retire()\n      }\n    })\n  }\n\n  const wrappedOnInsert = (params: InsertMutationFnParams<any>) => {\n    params.transaction.mutations.forEach((mutation) => {\n      validateJsonSerializable(parser, mutation.modified, `insert`)\n    })\n    return persistAutomatic(\n      params.transaction.mutations,\n      config.onInsert ? () => config.onInsert!(params) : undefined,\n    )\n  }\n\n  const wrappedOnUpdate = (params: UpdateMutationFnParams<any>) => {\n    params.transaction.mutations.forEach((mutation) => {\n      validateJsonSerializable(parser, mutation.modified, `update`)\n    })\n    return persistAutomatic(\n      params.transaction.mutations,\n      config.onUpdate ? () => config.onUpdate!(params) : undefined,\n    )\n  }\n\n  const wrappedOnDelete = (params: DeleteMutationFnParams<any>) =>\n    persistAutomatic(\n      params.transaction.mutations,\n      config.onDelete ? () => config.onDelete!(params) : undefined,\n    )\n\n  // Extract standard Collection config properties\n  // Remove localStorage-specific properties so they don't leak into the CollectionConfig\n  const {\n    storageKey: _storageKey,\n    storage: _storage,\n    storageEventApi: _storageEventApi,\n    parser: _parser,\n    onInsert: _onInsert,\n    onUpdate: _onUpdate,\n    onDelete: _onDelete,\n    id,\n    ...restConfig\n  } = config\n\n  // Default id to a pattern based on storage key if not provided\n  const collectionId = id ?? `local-collection:${config.storageKey}`\n\n  /**\n   * Accepts this Collection's manual mutations in write order and resolves\n   * after their storage write. A mutationFn receipt tracks this work even\n   * when the caller does not await the returned Promise.\n   */\n  const persistAcceptedMutations = async (\n    transaction: {\n      mutations: Array<PendingMutation<Record<string, unknown>>>\n    },\n    owner: PendingMutation<Record<string, unknown>>[`collection`] | undefined,\n  ): Promise<void> => {\n    const collectionMutations = transaction.mutations.filter(\n      (mutation) => mutation.collection === owner,\n    )\n\n    if (collectionMutations.length === 0) {\n      return Promise.resolve()\n    }\n\n    // Validate all mutations can be serialized before modifying storage\n    for (const mutation of collectionMutations) {\n      switch (mutation.type) {\n        case `insert`:\n        case `update`:\n          validateJsonSerializable(parser, mutation.modified, mutation.type)\n          break\n        case `delete`:\n          validateJsonSerializable(parser, mutation.original, mutation.type)\n          break\n      }\n    }\n\n    await persistManual(collectionMutations)\n  }\n\n  const materializedAcceptors = new WeakSet<\n    LocalStorageCollectionUtils[`acceptMutations`]\n  >()\n  const acceptMutations = (transaction: {\n    mutations: Array<PendingMutation<Record<string, unknown>>>\n  }): Promise<void> => {\n    // A DbClient materializes module-level options into a fresh Collection.\n    // Route acceptance to that Collection's utility so its automatic and\n    // manual writes reserve slots in the same queue.\n    const candidates = new Set(\n      transaction.mutations\n        .filter((mutation) => mutation.collection.id === collectionId)\n        .map((mutation) => mutation.collection),\n    )\n    const owned = [...candidates].filter((candidate) => {\n      const candidateAccept = (candidate.utils as LocalStorageCollectionUtils)\n        .acceptMutations\n      return (\n        candidateAccept === acceptMutations ||\n        materializedAcceptors.has(candidateAccept)\n      )\n    })\n    if (owned.length > 1 || (candidates.size > 0 && owned.length === 0)) {\n      const work = Promise.reject(\n        new LocalStorageCollectionError(\n          devBuild() && process.env.NODE_ENV !== `production`\n            ? `LocalStorage manual acceptance belongs to a different Collection.`\n            : codedMessage(231),\n        ),\n      )\n      registerTransactionCommitWork(transaction, work)\n      return work\n    }\n    const owner = owned[0]\n    const ownerAccept = owner\n      ? (owner.utils as LocalStorageCollectionUtils).acceptMutations\n      : undefined\n    if (ownerAccept && ownerAccept !== acceptMutations)\n      return ownerAccept(transaction)\n    const work = persistAcceptedMutations(transaction, owner)\n    registerTransactionCommitWork(transaction, work)\n    return work\n  }\n\n  const options = {\n    ...restConfig,\n    id: collectionId,\n    sync,\n    onInsert: wrappedOnInsert,\n    onUpdate: wrappedOnUpdate,\n    onDelete: wrappedOnDelete,\n    utils: {\n      clearStorage,\n      getStorageSize,\n      acceptMutations,\n    },\n  }\n\n  let claimed = false\n  Object.defineProperty(options, collectionOptionsClaim, {\n    enumerable: true,\n    value: () => {\n      if (claimed)\n        throw new LocalStorageCollectionError(\n          devBuild() && process.env.NODE_ENV !== `production`\n            ? `LocalStorage options can create only one Collection. Create fresh options for each Collection.`\n            : codedMessage(230),\n        )\n      claimed = true\n    },\n  })\n\n  return withCollectionConfigFactory(options, () => {\n    const materialized = localStorageCollectionOptions({\n      ...config,\n      id: collectionId,\n    }) as unknown as typeof options\n    materializedAcceptors.add(materialized.utils.acceptMutations)\n    return materialized\n  })\n}\n\n/**\n * Read data from storage without treating a failed read as an empty snapshot.\n * @param parser - The parser to use for deserializing the data\n * @param storageKey - The key used to store data in the storage API\n * @param storage - The storage API to load from (localStorage, sessionStorage, etc.)\n * @returns Map of stored items with version tracking\n */\nfunction readFromStorage<T extends object>(\n  storageKey: string,\n  storage: StorageApi,\n  parser: Parser,\n  getKey: (item: T) => string | number,\n  knownRaw?: string,\n): Map<string | number, StoredItem<T>> {\n  const rawData = knownRaw ?? storage.getItem(storageKey)\n  if (rawData === null) {\n    return new Map()\n  }\n\n  const parsed = parser.parse(rawData)\n  const dataMap = new Map<string | number, StoredItem<T>>()\n\n  // Handle object format where keys map to StoredItem values\n  if (typeof parsed === `object` && parsed !== null && !Array.isArray(parsed)) {\n    Object.entries(parsed).forEach(([encodedKey, value]) => {\n      // Runtime check to ensure the value has the expected StoredItem structure\n      if (\n        value &&\n        typeof value === `object` &&\n        `versionKey` in value &&\n        typeof value.versionKey === `string` &&\n        `data` in value &&\n        value.data !== null &&\n        typeof value.data === `object`\n      ) {\n        const storedItem = value as StoredItem<T>\n        const decodedKey = decodeStorageKey(encodedKey)\n        if (\n          !sameStorageKey(getKey(storedItem.data), decodedKey) ||\n          dataMap.has(decodedKey)\n        ) {\n          throw new InvalidStorageDataFormatError(storageKey, encodedKey)\n        }\n        dataMap.set(decodedKey, storedItem)\n      } else {\n        throw new InvalidStorageDataFormatError(storageKey, encodedKey)\n      }\n    })\n  } else {\n    throw new InvalidStorageObjectFormatError(storageKey)\n  }\n\n  return dataMap\n}\n\n/**\n * Internal function to create localStorage sync configuration\n * Creates a sync configuration that handles localStorage persistence and cross-tab synchronization\n * @param storageKey - The key used for storing data in localStorage\n * @param storage - The storage API to use (localStorage, sessionStorage, etc.)\n * @param storageEventApi - The event API for listening to storage changes\n * @param getKey - Function to extract the key from an item\n * @param lastKnownData - Map tracking the last known state for change detection\n * @returns Sync configuration with manual trigger capability\n */\nfunction createLocalStorageSync<T extends object>(\n  storageKey: string,\n  storage: StorageApi,\n  storageEventApi: StorageEventApi,\n  parser: Parser,\n  getKey: (item: T) => string | number,\n  lastKnownData: Map<string | number, StoredItem<T>>,\n): SyncConfig<T> & {\n  manualTrigger?: (knownSnapshot?: Map<string | number, StoredItem<T>>) => void\n  collection: any\n  confirmOperationsSync: (\n    mutations: Array<any>,\n    persisted: Map<string | number, StoredItem<T>>,\n  ) => void\n} {\n  let syncParams: Parameters<SyncConfig<T>[`sync`]>[0] | null = null\n  let collection: any = null\n\n  /**\n   * Compare two Maps to find differences using version keys\n   * @param oldData - The previous state of stored items\n   * @param newData - The current state of stored items\n   * @returns Array of changes with type, key, and value information\n   */\n  const findChanges = (\n    oldData: Map<string | number, StoredItem<T>>,\n    newData: Map<string | number, StoredItem<T>>,\n    compareContent: boolean,\n  ): Array<{\n    type: `insert` | `update` | `delete`\n    key: string | number\n    value?: T\n  }> => {\n    const changes: Array<{\n      type: `insert` | `update` | `delete`\n      key: string | number\n      value?: T\n    }> = []\n\n    // Check for deletions and updates\n    oldData.forEach((oldStoredItem, key) => {\n      const newStoredItem = newData.get(key)\n      if (!newStoredItem) {\n        changes.push({ type: `delete`, key, value: oldStoredItem.data })\n      } else if (\n        oldStoredItem.versionKey !== newStoredItem.versionKey ||\n        (compareContent &&\n          !deepEquals(oldStoredItem.data, newStoredItem.data) &&\n          // A default-JSON writer may retain a native Date while the stored\n          // row contains its ISO string. A peer's unrelated write must not\n          // publish that representation change as an update.\n          (parser !== JSON ||\n            JSON.stringify(oldStoredItem.data) !==\n              JSON.stringify(newStoredItem.data)))\n      ) {\n        changes.push({ type: `update`, key, value: newStoredItem.data })\n      }\n    })\n\n    // Check for insertions\n    newData.forEach((newStoredItem, key) => {\n      if (!oldData.has(key)) {\n        changes.push({ type: `insert`, key, value: newStoredItem.data })\n      }\n    })\n\n    return changes\n  }\n\n  /**\n   * Process storage changes and update collection\n   * Loads new data from storage, compares with last known state, and applies changes\n   */\n  const processStorageChanges = (\n    knownSnapshot?: Map<string | number, StoredItem<T>>,\n  ) => {\n    if (!syncParams) return\n\n    const { begin, write, commit } = syncParams\n\n    // Load the new data\n    let newData: Map<string | number, StoredItem<T>>\n    try {\n      newData =\n        knownSnapshot ?? readFromStorage<T>(storageKey, storage, parser, getKey)\n    } catch (error) {\n      console.warn(\n        devBuild() && process.env.NODE_ENV !== `production`\n          ? `[LocalStorageCollection] Error loading data from storage key \"${storageKey}\":`\n          : codedWarning(219, { storageKey }),\n        error,\n      )\n      return\n    }\n\n    // Find the specific changes\n    // The default-JSON writer deliberately retains native authored values.\n    // Peers and storage events must compare content even under the same token.\n    const changes = findChanges(\n      lastKnownData,\n      newData,\n      knownSnapshot === undefined || parser !== JSON,\n    )\n\n    if (changes.length > 0) {\n      // Reject an invalid snapshot before opening a sync transaction. This\n      // leaves the previous mirror available for a later valid refresh.\n      changes.forEach(({ type, value }) => {\n        if (value) validateJsonSerializable(parser, value, type)\n      })\n      begin()\n      changes.forEach(({ type, value }) => {\n        if (value) {\n          write({ type, value })\n        }\n      })\n      // A commit can synchronously publish to a subscriber that writes again.\n      // The nested refresh must compare against this snapshot, not its parent.\n      lastKnownData.clear()\n      newData.forEach((storedItem, key) => {\n        lastKnownData.set(key, storedItem)\n      })\n      commit()\n    }\n  }\n\n  const syncConfig: SyncConfig<T> & {\n    manualTrigger?: (\n      knownSnapshot?: Map<string | number, StoredItem<T>>,\n    ) => void\n  } = {\n    rowUpdateMode: `full`,\n    sync: (params: Parameters<SyncConfig<T>[`sync`]>[0]) => {\n      const { begin, write, commit, markReady } = params\n\n      // A failed restore cannot establish an empty authoritative snapshot.\n      // Read before retaining this sync run's callbacks so startup failure\n      // leaves no stale adapter state.\n      const initialData = readFromStorage<T>(\n        storageKey,\n        storage,\n        parser,\n        getKey,\n      )\n      initialData.forEach((storedItem) => {\n        validateJsonSerializable(parser, storedItem.data, `load`)\n      })\n      syncParams = params\n      collection = params.collection\n      // Establish the mirror and same-tab listener before restore publishes\n      // callbacks, which can synchronously write through an already-ready peer.\n      lastKnownData.clear()\n      initialData.forEach((storedItem, key) => {\n        lastKnownData.set(key, storedItem)\n      })\n\n      // Listen for storage events from other tabs\n      const handleStorageEvent = (event: StorageEvent) => {\n        // Only respond to changes to our specific key and from our storage\n        if (event.key !== storageKey || event.storageArea !== storage) {\n          return\n        }\n\n        processStorageChanges()\n      }\n\n      const unsubscribeSameTab = subscribeToSameTabWrites(\n        storage,\n        storageKey,\n        processStorageChanges,\n      )\n      try {\n        if (initialData.size > 0) {\n          begin()\n          initialData.forEach((storedItem) => {\n            write({ type: `insert`, value: storedItem.data })\n          })\n          commit()\n        }\n        // Mark collection as ready after initial load, then listen for\n        // browser events from other tabs.\n        markReady()\n        storageEventApi.addEventListener(`storage`, handleStorageEvent)\n      } catch (error) {\n        unsubscribeSameTab()\n        if (syncParams === params) {\n          syncParams = null\n        }\n        throw error\n      }\n      return {\n        cleanup: () => {\n          storageEventApi.removeEventListener(`storage`, handleStorageEvent)\n          unsubscribeSameTab()\n          if (syncParams === params) {\n            syncParams = null\n          }\n        },\n      }\n    },\n\n    /**\n     * Get sync metadata - returns storage key information\n     * @returns Object containing storage key and storage type metadata\n     */\n    getSyncMetadata: () => ({\n      storageKey,\n      storageType:\n        storage === (typeof window !== `undefined` ? window.localStorage : null)\n          ? `localStorage`\n          : `custom`,\n    }),\n\n    // Manual trigger function for local updates\n    manualTrigger: processStorageChanges,\n  }\n\n  /**\n   * Confirms mutations by writing them through the sync interface\n   * This moves mutations from optimistic to synced state\n   * @param mutations - Array of mutation objects to confirm\n   */\n  const confirmOperationsSync = (\n    mutations: Array<any>,\n    persisted: Map<string | number, StoredItem<T>>,\n  ) => {\n    if (!syncParams) {\n      // Sync not initialized yet, mutations will be handled on next sync\n      return\n    }\n\n    const { begin, write, commit } = syncParams\n\n    // Write the mutations through sync to confirm them\n    begin()\n    mutations.forEach((mutation: any) => {\n      write({\n        // A peer may have inserted the same key while this local mutation\n        // was pending. Full-row update confirms the accepted stored value in\n        // either case without a duplicate insert.\n        type: mutation.type === `delete` ? `delete` : `update`,\n        value:\n          mutation.type === `delete`\n            ? mutation.original\n            : persisted.get(mutation.key)!.data,\n      })\n    })\n    commit()\n  }\n\n  return {\n    ...syncConfig,\n    get collection() {\n      return collection\n    },\n    confirmOperationsSync,\n  }\n}\n"],"names":["devBuild","codedWarning","SerializationError","safeRandomUUID","StorageKeyRequiredError","InvalidStorageDataFormatError","codedMessage","work","LocalStorageCollectionError","registerTransactionCommitWork","collectionOptionsClaim","withCollectionConfigFactory","InvalidStorageObjectFormatError","deepEquals"],"mappings":"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"}