{"version":3,"file":"sync.cjs","sources":["../../../src/collection/sync.ts"],"sourcesContent":["import {\n  CollectionConfigurationError,\n  CollectionIsInErrorStateError,\n  DuplicateKeySyncError,\n  NoPendingSyncTransactionCommitError,\n  NoPendingSyncTransactionWriteError,\n  SyncCleanupError,\n  SyncTransactionAlreadyCommittedError,\n  SyncTransactionAlreadyCommittedWriteError,\n} from '../errors'\nimport { deepEquals } from '../utils'\nimport { LIVE_QUERY_INTERNAL } from '../query/live/internal.js'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type {\n  ChangeMessageOrDeleteKeyMessage,\n  CleanupFn,\n  CollectionConfig,\n  LoadSubsetOptions,\n  OptimisticChangeMessage,\n  SyncConfigRes,\n  SyncMetadataApi,\n} from '../types'\nimport type { CollectionImpl } from './index.js'\nimport type { CollectionStateManager } from './state'\nimport type { CollectionLifecycleManager } from './lifecycle'\nimport type { CollectionEventsManager } from './events.js'\nimport type { LiveQueryCollectionUtils } from '../query/live/collection-config-builder.js'\n\nexport class CollectionSyncManager<\n  TOutput extends object = Record<string, unknown>,\n  TKey extends string | number = string | number,\n  TSchema extends StandardSchemaV1 = StandardSchemaV1,\n  TInput extends object = TOutput,\n> {\n  private collection!: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n  private state!: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n  private lifecycle!: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n  private _events!: CollectionEventsManager\n  private config!: CollectionConfig<TOutput, TKey, TSchema>\n  private id: string\n  private syncMode: `eager` | `on-demand`\n\n  public preloadPromise: Promise<void> | null = null\n  public syncCleanupFn: (() => void) | null = null\n  public syncLoadSubsetFn:\n    | ((options: LoadSubsetOptions) => true | Promise<void>)\n    | null = null\n  public syncUnloadSubsetFn: ((options: LoadSubsetOptions) => void) | null =\n    null\n\n  private pendingLoadSubsetPromises: Set<Promise<void>> = new Set()\n\n  /**\n   * Creates a new CollectionSyncManager instance\n   */\n  constructor(config: CollectionConfig<TOutput, TKey, TSchema>, id: string) {\n    this.config = config\n    this.id = id\n    this.syncMode = config.syncMode ?? `eager`\n  }\n\n  setDeps(deps: {\n    collection: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n    state: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n    lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n    events: CollectionEventsManager\n  }) {\n    this.collection = deps.collection\n    this.state = deps.state\n    this.lifecycle = deps.lifecycle\n    this._events = deps.events\n  }\n\n  /**\n   * Start the sync process for this collection\n   * This is called when the collection is first accessed or preloaded\n   */\n  public startSync(): void {\n    if (\n      this.lifecycle.status !== `idle` &&\n      this.lifecycle.status !== `cleaned-up`\n    ) {\n      return // Already started or in progress\n    }\n\n    this.lifecycle.setStatus(`loading`)\n\n    try {\n      const syncRes = normalizeSyncFnResult(\n        this.config.sync.sync({\n          collection: this.collection,\n          begin: (options?: { immediate?: boolean }) => {\n            this.state.pendingSyncedTransactions.push({\n              committed: false,\n              operations: [],\n              deletedKeys: new Set(),\n              rowMetadataWrites: new Map(),\n              collectionMetadataWrites: new Map(),\n              immediate: options?.immediate,\n            })\n          },\n          write: (\n            messageWithOptionalKey: ChangeMessageOrDeleteKeyMessage<\n              TOutput,\n              TKey\n            >,\n          ) => {\n            const pendingTransaction =\n              this.state.pendingSyncedTransactions[\n                this.state.pendingSyncedTransactions.length - 1\n              ]\n            if (!pendingTransaction) {\n              throw new NoPendingSyncTransactionWriteError()\n            }\n            if (pendingTransaction.committed) {\n              throw new SyncTransactionAlreadyCommittedWriteError()\n            }\n\n            let key: TKey | undefined = undefined\n            if (`key` in messageWithOptionalKey) {\n              key = messageWithOptionalKey.key\n            } else {\n              key = this.config.getKey(messageWithOptionalKey.value)\n            }\n\n            if (this.state.pendingLocalChanges.has(key)) {\n              this.state.pendingLocalOrigins.add(key)\n            }\n\n            let messageType = messageWithOptionalKey.type\n\n            // Check if an item with this key already exists when inserting\n            if (messageWithOptionalKey.type === `insert`) {\n              const insertingIntoExistingSynced = this.state.syncedData.has(key)\n              const hasPendingDeleteForKey =\n                pendingTransaction.deletedKeys.has(key)\n              const isTruncateTransaction = pendingTransaction.truncate === true\n              // Allow insert after truncate in the same transaction even if it existed in syncedData\n              if (\n                insertingIntoExistingSynced &&\n                !hasPendingDeleteForKey &&\n                !isTruncateTransaction\n              ) {\n                const existingValue = this.state.syncedData.get(key)\n                const valuesEqual =\n                  existingValue !== undefined &&\n                  deepEquals(existingValue, messageWithOptionalKey.value)\n                if (valuesEqual) {\n                  // The \"insert\" is an echo of a value we already have locally.\n                  // Treat it as an update so we preserve optimistic intent without\n                  // throwing a duplicate-key error during reconciliation.\n                  messageType = `update`\n                } else {\n                  const utils = this.config\n                    .utils as Partial<LiveQueryCollectionUtils>\n                  const internal = utils[LIVE_QUERY_INTERNAL]\n                  throw new DuplicateKeySyncError(key, this.id, {\n                    hasCustomGetKey: internal?.hasCustomGetKey ?? false,\n                    hasJoins: internal?.hasJoins ?? false,\n                    hasDistinct: internal?.hasDistinct ?? false,\n                  })\n                }\n              }\n            }\n\n            const message = {\n              ...messageWithOptionalKey,\n              type: messageType,\n              key,\n            } as OptimisticChangeMessage<TOutput, TKey>\n            pendingTransaction.operations.push(message)\n\n            if (messageType === `delete`) {\n              pendingTransaction.deletedKeys.add(key)\n              pendingTransaction.rowMetadataWrites.set(key, { type: `delete` })\n            } else if (messageType === `insert`) {\n              if (message.metadata !== undefined) {\n                pendingTransaction.rowMetadataWrites.set(key, {\n                  type: `set`,\n                  value: message.metadata,\n                })\n              } else {\n                pendingTransaction.rowMetadataWrites.set(key, {\n                  type: `delete`,\n                })\n              }\n            } else if (message.metadata !== undefined) {\n              pendingTransaction.rowMetadataWrites.set(key, {\n                type: `set`,\n                value: message.metadata,\n              })\n            }\n          },\n          commit: () => {\n            const pendingTransaction =\n              this.state.pendingSyncedTransactions[\n                this.state.pendingSyncedTransactions.length - 1\n              ]\n            if (!pendingTransaction) {\n              throw new NoPendingSyncTransactionCommitError()\n            }\n            if (pendingTransaction.committed) {\n              throw new SyncTransactionAlreadyCommittedError()\n            }\n\n            pendingTransaction.committed = true\n\n            this.state.commitPendingTransactions()\n          },\n          markReady: () => {\n            this.lifecycle.markReady()\n          },\n          truncate: () => {\n            const pendingTransaction =\n              this.state.pendingSyncedTransactions[\n                this.state.pendingSyncedTransactions.length - 1\n              ]\n            if (!pendingTransaction) {\n              throw new NoPendingSyncTransactionWriteError()\n            }\n            if (pendingTransaction.committed) {\n              throw new SyncTransactionAlreadyCommittedWriteError()\n            }\n\n            // Clear all operations from the current transaction\n            pendingTransaction.operations = []\n            pendingTransaction.deletedKeys.clear()\n            pendingTransaction.rowMetadataWrites.clear()\n            // Intentionally preserve collectionMetadataWrites across truncate.\n            // Collection-scoped metadata (for example persisted resume/reset\n            // state) can be staged before truncate and should commit atomically\n            // with the truncate transaction.\n\n            // Mark the transaction as a truncate operation. During commit, this triggers:\n            // - Delete events for all previously synced keys (excluding optimistic-deleted keys)\n            // - Clearing of syncedData/syncedMetadata\n            // - Subsequent synced ops applied on the fresh base\n            // - Finally, optimistic mutations re-applied on top (single batch)\n            pendingTransaction.truncate = true\n\n            // Capture optimistic state NOW to preserve it even if transactions complete\n            // before this truncate transaction is committed\n            pendingTransaction.optimisticSnapshot = {\n              upserts: new Map(this.state.optimisticUpserts),\n              deletes: new Set(this.state.optimisticDeletes),\n            }\n          },\n          metadata: this.createSyncMetadataApi(),\n        }),\n      )\n\n      // Store cleanup function if provided\n      this.syncCleanupFn = syncRes?.cleanup ?? null\n\n      // Store loadSubset function if provided\n      this.syncLoadSubsetFn = syncRes?.loadSubset ?? null\n\n      // Store unloadSubset function if provided\n      this.syncUnloadSubsetFn = syncRes?.unloadSubset ?? null\n\n      // Validate: on-demand mode requires a loadSubset function\n      if (this.syncMode === `on-demand` && !this.syncLoadSubsetFn) {\n        throw new CollectionConfigurationError(\n          `Collection \"${this.id}\" is configured with syncMode \"on-demand\" but the sync function did not return a loadSubset handler. ` +\n            `Either provide a loadSubset handler or use syncMode \"eager\".`,\n        )\n      }\n    } catch (error) {\n      this.lifecycle.setStatus(`error`)\n      throw error\n    }\n  }\n\n  private getActivePendingSyncTransaction() {\n    const pendingTransaction =\n      this.state.pendingSyncedTransactions[\n        this.state.pendingSyncedTransactions.length - 1\n      ]\n\n    if (!pendingTransaction) {\n      throw new NoPendingSyncTransactionWriteError()\n    }\n    if (pendingTransaction.committed) {\n      throw new SyncTransactionAlreadyCommittedWriteError()\n    }\n\n    return pendingTransaction\n  }\n\n  private createSyncMetadataApi(): SyncMetadataApi<TKey> {\n    return {\n      row: {\n        get: (key) => {\n          const pendingTransaction =\n            this.state.pendingSyncedTransactions[\n              this.state.pendingSyncedTransactions.length - 1\n            ]\n          const pendingWrite = pendingTransaction?.rowMetadataWrites.get(key)\n          if (pendingWrite) {\n            return pendingWrite.type === `delete`\n              ? undefined\n              : pendingWrite.value\n          }\n          if (pendingTransaction?.truncate) {\n            return undefined\n          }\n          return this.state.syncedMetadata.get(key)\n        },\n        set: (key, metadata) => {\n          const pendingTransaction = this.getActivePendingSyncTransaction()\n          pendingTransaction.rowMetadataWrites.set(key, {\n            type: `set`,\n            value: metadata,\n          })\n        },\n        delete: (key) => {\n          const pendingTransaction = this.getActivePendingSyncTransaction()\n          pendingTransaction.rowMetadataWrites.set(key, {\n            type: `delete`,\n          })\n        },\n      },\n      collection: {\n        get: (key) => {\n          const pendingTransaction =\n            this.state.pendingSyncedTransactions[\n              this.state.pendingSyncedTransactions.length - 1\n            ]\n          const pendingWrite =\n            pendingTransaction?.collectionMetadataWrites.get(key)\n          if (pendingWrite) {\n            return pendingWrite.type === `delete`\n              ? undefined\n              : pendingWrite.value\n          }\n          return this.state.syncedCollectionMetadata.get(key)\n        },\n        set: (key, value) => {\n          const pendingTransaction = this.getActivePendingSyncTransaction()\n          pendingTransaction.collectionMetadataWrites.set(key, {\n            type: `set`,\n            value,\n          })\n        },\n        delete: (key) => {\n          const pendingTransaction = this.getActivePendingSyncTransaction()\n          pendingTransaction.collectionMetadataWrites.set(key, {\n            type: `delete`,\n          })\n        },\n        list: (prefix) => {\n          const merged = new Map(this.state.syncedCollectionMetadata)\n          const pendingTransaction =\n            this.state.pendingSyncedTransactions[\n              this.state.pendingSyncedTransactions.length - 1\n            ]\n          if (pendingTransaction) {\n            for (const [\n              key,\n              pendingWrite,\n            ] of pendingTransaction.collectionMetadataWrites) {\n              if (pendingWrite.type === `delete`) {\n                merged.delete(key)\n              } else {\n                merged.set(key, pendingWrite.value)\n              }\n            }\n          }\n\n          return Array.from(merged.entries())\n            .filter(([key]) => (prefix ? key.startsWith(prefix) : true))\n            .map(([key, value]) => ({\n              key,\n              value,\n            }))\n        },\n      },\n    }\n  }\n\n  /**\n   * Preload the collection data by starting sync if not already started\n   * Multiple concurrent calls will share the same promise\n   */\n  public preload(): Promise<void> {\n    if (this.preloadPromise) {\n      return this.preloadPromise\n    }\n\n    // Warn when calling preload on an on-demand collection\n    if (this.syncMode === `on-demand`) {\n      console.warn(\n        `${this.id ? `[${this.id}] ` : ``}Calling .preload() on a collection with syncMode \"on-demand\" is a no-op. ` +\n          `In on-demand mode, data is only loaded when queries request it. ` +\n          `Instead, create a live query and call .preload() on that to load the specific data you need. ` +\n          `See https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync for more details.`,\n      )\n    }\n\n    this.preloadPromise = new Promise<void>((resolve, reject) => {\n      if (this.lifecycle.status === `ready`) {\n        resolve()\n        return\n      }\n\n      if (this.lifecycle.status === `error`) {\n        reject(new CollectionIsInErrorStateError())\n        return\n      }\n\n      // Register callback BEFORE starting sync to avoid race condition\n      this.lifecycle.onFirstReady(() => {\n        resolve()\n      })\n\n      // Start sync if collection hasn't started yet or was cleaned up\n      if (\n        this.lifecycle.status === `idle` ||\n        this.lifecycle.status === `cleaned-up`\n      ) {\n        try {\n          this.startSync()\n        } catch (error) {\n          reject(error)\n          return\n        }\n      }\n    })\n\n    return this.preloadPromise\n  }\n\n  /**\n   * Gets whether the collection is currently loading more data\n   */\n  public get isLoadingSubset(): boolean {\n    return this.pendingLoadSubsetPromises.size > 0\n  }\n\n  /**\n   * Tracks a load promise for isLoadingSubset state.\n   * @internal This is for internal coordination (e.g., live-query glue code), not for general use.\n   */\n  public trackLoadPromise(promise: Promise<void>): void {\n    const loadingStarting = !this.isLoadingSubset\n    this.pendingLoadSubsetPromises.add(promise)\n\n    if (loadingStarting) {\n      this._events.emit(`loadingSubset:change`, {\n        type: `loadingSubset:change`,\n        collection: this.collection,\n        isLoadingSubset: true,\n        previousIsLoadingSubset: false,\n        loadingSubsetTransition: `start`,\n      })\n    }\n\n    promise.finally(() => {\n      const loadingEnding =\n        this.pendingLoadSubsetPromises.size === 1 &&\n        this.pendingLoadSubsetPromises.has(promise)\n      this.pendingLoadSubsetPromises.delete(promise)\n\n      if (loadingEnding) {\n        this._events.emit(`loadingSubset:change`, {\n          type: `loadingSubset:change`,\n          collection: this.collection,\n          isLoadingSubset: false,\n          previousIsLoadingSubset: true,\n          loadingSubsetTransition: `end`,\n        })\n      }\n    })\n  }\n\n  /**\n   * Requests the sync layer to load more data.\n   * @param options Options to control what data is being loaded\n   * @returns If data loading is asynchronous, this method returns a promise that resolves when the data is loaded.\n   *          Returns true if no sync function is configured, if syncMode is 'eager', or if there is no work to do.\n   */\n  public loadSubset(options: LoadSubsetOptions): Promise<void> | true {\n    // Bypass loadSubset when syncMode is 'eager'\n    if (this.syncMode === `eager`) {\n      return true\n    }\n\n    if (this.syncLoadSubsetFn) {\n      const result = this.syncLoadSubsetFn(options)\n      // If the result is a promise, track it\n      if (result instanceof Promise) {\n        this.trackLoadPromise(result)\n        return result\n      }\n    }\n\n    return true\n  }\n\n  /**\n   * Notifies the sync layer that a subset is no longer needed.\n   * @param options Options that identify what data is being unloaded\n   */\n  public unloadSubset(options: LoadSubsetOptions): void {\n    if (this.syncUnloadSubsetFn) {\n      this.syncUnloadSubsetFn(options)\n    }\n  }\n\n  public cleanup(): void {\n    try {\n      if (this.syncCleanupFn) {\n        this.syncCleanupFn()\n        this.syncCleanupFn = null\n      }\n    } catch (error) {\n      // Re-throw in a microtask to surface the error after cleanup completes\n      queueMicrotask(() => {\n        if (error instanceof Error) {\n          // Preserve the original error and stack trace\n          const wrappedError = new SyncCleanupError(this.id, error)\n          wrappedError.cause = error\n          wrappedError.stack = error.stack\n          throw wrappedError\n        } else {\n          throw new SyncCleanupError(this.id, error as Error | string)\n        }\n      })\n    }\n    this.preloadPromise = null\n  }\n}\n\nfunction normalizeSyncFnResult(result: void | CleanupFn | SyncConfigRes) {\n  if (typeof result === `function`) {\n    return { cleanup: result }\n  }\n\n  if (typeof result === `object`) {\n    return result\n  }\n\n  return undefined\n}\n"],"names":["NoPendingSyncTransactionWriteError","SyncTransactionAlreadyCommittedWriteError","deepEquals","utils","internal","LIVE_QUERY_INTERNAL","DuplicateKeySyncError","NoPendingSyncTransactionCommitError","SyncTransactionAlreadyCommittedError","CollectionConfigurationError","CollectionIsInErrorStateError","SyncCleanupError"],"mappings":"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"}