{"version":3,"file":"transactions.cjs","sources":["../../src/transactions.ts"],"sourcesContent":["import { createDeferred } from './deferred'\nimport { safeRandomUUID } from './utils/uuid'\nimport './duplicate-instance-check'\nimport {\n  MissingMutationFunctionError,\n  TransactionAlreadyCompletedRollbackError,\n  TransactionNotPendingCommitError,\n  TransactionNotPendingMutateError,\n} from './errors'\nimport { transactionScopedScheduler } from './scheduler.js'\nimport type { Deferred } from './deferred'\nimport type {\n  MutationFn,\n  PendingMutation,\n  TransactionConfig,\n  TransactionState,\n  TransactionWithMutations,\n} from './types'\n\nexport class TransactionScope {\n  private transactions: Array<Transaction<any>> = []\n  private transactionStack: Array<Transaction<any>> = []\n  private sequenceNumber = 0\n\n  createTransaction<T extends object = Record<string, unknown>>(\n    config: TransactionConfig<T>,\n  ): Transaction<T> {\n    const transaction = new Transaction<T>(config, this, this.sequenceNumber++)\n    this.transactions.push(transaction)\n    return transaction\n  }\n\n  getActiveTransaction(): Transaction | undefined {\n    return this.transactionStack.at(-1)\n  }\n\n  getActiveTransactionForCollection(): Transaction | undefined {\n    const activeTransaction = this.getActiveTransaction()\n    if (activeTransaction) {\n      return activeTransaction\n    }\n\n    if (this === defaultTransactionScope) {\n      return undefined\n    }\n\n    return defaultTransactionScope.claimActiveTransaction(this)\n  }\n\n  private claimActiveTransaction(\n    targetScope: TransactionScope,\n  ): Transaction | undefined {\n    const transaction = this.getActiveTransaction()\n    if (!transaction) {\n      return undefined\n    }\n\n    const owner = getTransactionScope(transaction)\n    if (owner === targetScope) {\n      return transaction\n    }\n    if (owner !== this) {\n      throw new Error(\n        `A transaction created with createTransaction() cannot mutate collections from multiple DbClient instances. Use dbClient.createTransaction() for explicit client scope.`,\n      )\n    }\n\n    this.removeTransaction(transaction)\n    targetScope.transactions.push(transaction)\n    targetScope.transactionStack.push(transaction)\n    transaction.sequenceNumber = targetScope.sequenceNumber++\n    transactionScopes.set(transaction, targetScope)\n    return transaction\n  }\n\n  registerTransaction(transaction: Transaction<any>): void {\n    // Clear stale work left by an aborted mutate scope before reusing the id.\n    transactionScopedScheduler.clear(transaction.id)\n    this.transactionStack.push(transaction)\n  }\n\n  unregisterTransaction(transaction: Transaction<any>): void {\n    try {\n      transactionScopedScheduler.flush(transaction.id)\n    } finally {\n      this.transactionStack = this.transactionStack.filter(\n        (candidate) => candidate.id !== transaction.id,\n      )\n    }\n  }\n\n  removeTransaction(transaction: Transaction<any>): void {\n    const index = this.transactions.findIndex(\n      (candidate) => candidate.id === transaction.id,\n    )\n    if (index !== -1) {\n      this.transactions.splice(index, 1)\n    }\n  }\n\n  rollbackConflictingTransactions(\n    transaction: Transaction<any>,\n    mutationIds: Set<string>,\n  ): void {\n    for (const candidate of [...this.transactions]) {\n      if (\n        candidate !== transaction &&\n        candidate.state === `pending` &&\n        candidate.mutations.some((mutation) =>\n          mutationIds.has(mutation.globalKey),\n        )\n      ) {\n        candidate.rollback({ isSecondaryRollback: true })\n      }\n    }\n  }\n\n  clear(): void {\n    const transactionIds = new Set([\n      ...this.transactions.map((transaction) => transaction.id),\n      ...this.transactionStack.map((transaction) => transaction.id),\n    ])\n    for (const transactionId of transactionIds) {\n      transactionScopedScheduler.clear(transactionId)\n    }\n    this.transactions = []\n    this.transactionStack = []\n  }\n}\n\nconst defaultTransactionScope = new TransactionScope()\nconst transactionScopes = new WeakMap<object, TransactionScope>()\nconst transactionAmbientScopes = new WeakMap<object, TransactionScope>()\n\nfunction getTransactionScope(transaction: object): TransactionScope {\n  const scope = transactionScopes.get(transaction)\n  if (!scope) {\n    throw new Error(`Transaction is not associated with a TransactionScope.`)\n  }\n  return scope\n}\n\nfunction getTransactionAmbientScope(transaction: object): TransactionScope {\n  const scope = transactionAmbientScopes.get(transaction)\n  if (!scope) {\n    throw new Error(`Transaction is not associated with an ambient scope.`)\n  }\n  return scope\n}\n\n/**\n * Merges two pending mutations for the same item within a transaction\n *\n * Merge behavior truth table:\n * - (insert, update) → insert (merge changes, keep empty original)\n * - (insert, delete) → null (cancel both mutations)\n * - (update, delete) → delete (delete dominates)\n * - (update, update) → update (replace with latest, union changes)\n * - (delete, delete) → delete (replace with latest)\n * - (insert, insert) → insert (replace with latest)\n *\n * Note: (delete, update) and (delete, insert) should never occur as the collection\n * layer prevents operations on deleted items within the same transaction.\n *\n * @param existing - The existing mutation in the transaction\n * @param incoming - The new mutation being applied\n * @returns The merged mutation, or null if both should be removed\n */\nfunction mergePendingMutations<T extends object>(\n  existing: PendingMutation<T>,\n  incoming: PendingMutation<T>,\n): PendingMutation<T> | null {\n  // Truth table implementation\n  switch (`${existing.type}-${incoming.type}` as const) {\n    case `insert-update`: {\n      // Update after insert: keep as insert but merge changes\n      // For insert-update, the key should remain the same since collections don't allow key changes\n      return {\n        ...existing,\n        type: `insert` as const,\n        original: {},\n        modified: incoming.modified,\n        changes: { ...existing.changes, ...incoming.changes },\n        // Keep existing keys (key changes not allowed in updates)\n        key: existing.key,\n        globalKey: existing.globalKey,\n        // Merge metadata (last-write-wins)\n        metadata: incoming.metadata ?? existing.metadata,\n        syncMetadata: { ...existing.syncMetadata, ...incoming.syncMetadata },\n        // Update tracking info\n        mutationId: incoming.mutationId,\n        updatedAt: incoming.updatedAt,\n      }\n    }\n\n    case `insert-delete`:\n      // Delete after insert: cancel both mutations\n      return null\n\n    case `update-delete`:\n      // Delete after update: delete dominates\n      return incoming\n\n    case `update-update`: {\n      // Update after update: replace with latest, union changes\n      return {\n        ...incoming,\n        // Keep original from first update\n        original: existing.original,\n        // Union the changes from both updates\n        changes: { ...existing.changes, ...incoming.changes },\n        // Merge metadata\n        metadata: incoming.metadata ?? existing.metadata,\n        syncMetadata: { ...existing.syncMetadata, ...incoming.syncMetadata },\n      }\n    }\n\n    case `delete-delete`:\n    case `insert-insert`:\n      // Same type: replace with latest\n      return incoming\n\n    default: {\n      // Exhaustiveness check\n      const _exhaustive: never = `${existing.type}-${incoming.type}` as never\n      throw new Error(`Unhandled mutation combination: ${_exhaustive}`)\n    }\n  }\n}\n\n/**\n * Creates a new transaction for grouping multiple collection operations\n * @param config - Transaction configuration with mutation function\n * @returns A new Transaction instance\n * @example\n * // Basic transaction usage\n * const tx = createTransaction({\n *   mutationFn: async ({ transaction }) => {\n *     // Send all mutations to API\n *     await api.saveChanges(transaction.mutations)\n *   }\n * })\n *\n * tx.mutate(() => {\n *   collection.insert({ id: \"1\", text: \"Buy milk\" })\n *   collection.update(\"2\", draft => { draft.completed = true })\n * })\n *\n * await tx.isPersisted.promise\n *\n * @example\n * // Handle transaction errors\n * try {\n *   const tx = createTransaction({\n *     mutationFn: async () => { throw new Error(\"API failed\") }\n *   })\n *\n *   tx.mutate(() => {\n *     collection.insert({ id: \"1\", text: \"New item\" })\n *   })\n *\n *   await tx.isPersisted.promise\n * } catch (error) {\n *   console.log('Transaction failed:', error)\n * }\n *\n * @example\n * // Manual commit control\n * const tx = createTransaction({\n *   autoCommit: false,\n *   mutationFn: async () => {\n *     // API call\n *   }\n * })\n *\n * tx.mutate(() => {\n *   collection.insert({ id: \"1\", text: \"Item\" })\n * })\n *\n * // Commit later\n * await tx.commit()\n */\nexport function createTransaction<T extends object = Record<string, unknown>>(\n  config: TransactionConfig<T>,\n): Transaction<T> {\n  return defaultTransactionScope.createTransaction(config)\n}\n\n/**\n * Gets the currently active ambient transaction, if any\n * Used internally by collection operations to join existing transactions\n * @returns The active transaction or undefined if none is active\n * @example\n * // Check if operations will join an ambient transaction\n * const ambientTx = getActiveTransaction()\n * if (ambientTx) {\n *   console.log('Operations will join transaction:', ambientTx.id)\n * }\n */\nexport function getActiveTransaction(): Transaction | undefined {\n  return defaultTransactionScope.getActiveTransaction()\n}\n\nclass Transaction<T extends object = Record<string, unknown>> {\n  public id: string\n  public state: TransactionState\n  public mutationFn: MutationFn<T>\n  public mutations: Array<PendingMutation<T>>\n  /**\n   * Deferred that settles when this transaction settles.\n   *\n   * Await `isPersisted.promise`, not `isPersisted` itself. The promise resolves\n   * when the transaction completes successfully and rejects if the transaction\n   * fails or is rolled back.\n   *\n   * For non-empty commits, the mutation function is the normal settlement\n   * boundary. This does not inherently prove that a backend has uploaded,\n   * confirmed, or read back the write unless the mutation function waits for\n   * that backend observation before returning.\n   */\n  public isPersisted: Deferred<Transaction<T>>\n  public autoCommit: boolean\n  public createdAt: Date\n  public sequenceNumber: number\n  public metadata: Record<string, unknown>\n  public error?: {\n    message: string\n    error: Error\n  }\n\n  constructor(\n    config: TransactionConfig<T>,\n    scope: TransactionScope,\n    sequenceNumber: number,\n  ) {\n    if (typeof config.mutationFn === `undefined`) {\n      throw new MissingMutationFunctionError()\n    }\n    this.id = config.id ?? safeRandomUUID()\n    this.mutationFn = config.mutationFn\n    this.state = `pending`\n    this.mutations = []\n    this.isPersisted = createDeferred<Transaction<T>>()\n    this.autoCommit = config.autoCommit ?? true\n    this.createdAt = new Date()\n    this.sequenceNumber = sequenceNumber\n    this.metadata = config.metadata ?? {}\n    transactionScopes.set(this, scope)\n    transactionAmbientScopes.set(this, scope)\n  }\n\n  setState(newState: TransactionState) {\n    this.state = newState\n\n    if (newState === `completed` || newState === `failed`) {\n      getTransactionScope(this).removeTransaction(this)\n    }\n  }\n\n  /**\n   * Execute collection operations within this transaction\n   * @param callback - Synchronous function containing collection operations to group together.\n   * The transaction context is active only for the synchronous duration of this callback.\n   * Async work should happen in `mutationFn`; collection operations after `await` boundaries\n   * inside this callback will not be part of this transaction. For manual transactions, call\n   * `mutate` multiple times before committing to add more synchronous operations to the same\n   * transaction.\n   * @returns This transaction for chaining\n   * @example\n   * // Group multiple operations\n   * const tx = createTransaction({ mutationFn: async () => {\n   *   // Send to API\n   * }})\n   *\n   * tx.mutate(() => {\n   *   collection.insert({ id: \"1\", text: \"Buy milk\" })\n   *   collection.update(\"2\", draft => { draft.completed = true })\n   *   collection.delete(\"3\")\n   * })\n   *\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Handle mutate errors\n   * try {\n   *   tx.mutate(() => {\n   *     collection.insert({ id: \"invalid\" }) // This might throw\n   *   })\n   * } catch (error) {\n   *   console.log('Mutation failed:', error)\n   * }\n   *\n   * @example\n   * // Manual commit control\n   * const tx = createTransaction({ autoCommit: false, mutationFn: async () => {} })\n   *\n   * tx.mutate(() => {\n   *   collection.insert({ id: \"1\", text: \"Item\" })\n   * })\n   *\n   * // Add more synchronous mutations to the same transaction\n   * tx.mutate(() => {\n   *   collection.update(\"1\", draft => { draft.text = \"Updated item\" })\n   * })\n   *\n   * // Commit later when ready\n   * await tx.commit()\n   */\n  mutate(callback: () => void): Transaction<T> {\n    if (this.state !== `pending`) {\n      throw new TransactionNotPendingMutateError()\n    }\n\n    const initialScope = getTransactionScope(this)\n    const registeredScopes = new Set([\n      initialScope,\n      getTransactionAmbientScope(this),\n    ])\n    for (const scope of registeredScopes) {\n      scope.registerTransaction(this)\n    }\n\n    try {\n      callback()\n    } finally {\n      registeredScopes.add(getTransactionScope(this))\n      for (const scope of registeredScopes) {\n        scope.unregisterTransaction(this)\n      }\n    }\n\n    if (this.autoCommit) {\n      this.commit().catch(() => {\n        // Errors from autoCommit are handled via isPersisted.promise\n        // This catch prevents unhandled promise rejections\n      })\n    }\n\n    return this\n  }\n\n  /**\n   * Apply new mutations to this transaction, intelligently merging with existing mutations\n   *\n   * When mutations operate on the same item (same globalKey), they are merged according to\n   * the following rules:\n   *\n   * - **insert + update** → insert (merge changes, keep empty original)\n   * - **insert + delete** → removed (mutations cancel each other out)\n   * - **update + delete** → delete (delete dominates)\n   * - **update + update** → update (union changes, keep first original)\n   * - **same type** → replace with latest\n   *\n   * This merging reduces over-the-wire churn and keeps the optimistic local view\n   * aligned with user intent.\n   *\n   * @param mutations - Array of new mutations to apply\n   */\n  applyMutations(mutations: Array<PendingMutation<any>>): void {\n    // Merge via a globalKey-keyed map rather than a findIndex scan per\n    // mutation, which is O(n²) for bulk operations (e.g. inserting many rows\n    // in one call). Map preserves insertion order, matching the previous\n    // replace-in-place / remove / append semantics.\n    const merged = new Map<string, PendingMutation<any>>()\n    for (const mutation of this.mutations) {\n      merged.set(mutation.globalKey, mutation)\n    }\n\n    for (const newMutation of mutations) {\n      const existingMutation = merged.get(newMutation.globalKey)\n\n      if (existingMutation) {\n        const mergeResult = mergePendingMutations(existingMutation, newMutation)\n\n        if (mergeResult === null) {\n          // Remove the mutation (e.g., delete after insert cancels both)\n          merged.delete(newMutation.globalKey)\n        } else {\n          // Replace with merged mutation\n          merged.set(newMutation.globalKey, mergeResult)\n        }\n      } else {\n        // Insert new mutation\n        merged.set(newMutation.globalKey, newMutation)\n      }\n    }\n\n    // Rebuild in place to preserve the array's identity for external holders\n    this.mutations.length = 0\n    for (const mutation of merged.values()) {\n      this.mutations.push(mutation)\n    }\n  }\n\n  /**\n   * Rollback the transaction and any conflicting transactions\n   * @param config - Configuration for rollback behavior\n   * @returns This transaction for chaining\n   * @example\n   * // Manual rollback\n   * const tx = createTransaction({ mutationFn: async () => {\n   *   // Send to API\n   * }})\n   *\n   * tx.mutate(() => {\n   *   collection.insert({ id: \"1\", text: \"Buy milk\" })\n   * })\n   *\n   * // Rollback if needed\n   * if (shouldCancel) {\n   *   tx.rollback()\n   * }\n   *\n   * @example\n   * // Handle rollback cascade (automatic)\n   * const tx1 = createTransaction({ mutationFn: async () => {} })\n   * const tx2 = createTransaction({ mutationFn: async () => {} })\n   *\n   * tx1.mutate(() => collection.update(\"1\", draft => { draft.value = \"A\" }))\n   * tx2.mutate(() => collection.update(\"1\", draft => { draft.value = \"B\" })) // Same item\n   *\n   * tx1.rollback() // This will also rollback tx2 due to conflict\n   *\n   * @example\n   * // Handle rollback in error scenarios\n   * try {\n   *   await tx.isPersisted.promise\n   * } catch (error) {\n   *   console.log('Transaction was rolled back:', error)\n   *   // Transaction automatically rolled back on mutation function failure\n   * }\n   */\n  rollback(config?: { isSecondaryRollback?: boolean }): Transaction<T> {\n    const isSecondaryRollback = config?.isSecondaryRollback ?? false\n    if (this.state === `completed`) {\n      throw new TransactionAlreadyCompletedRollbackError()\n    }\n\n    this.setState(`failed`)\n\n    // See if there's any other transactions w/ mutations on the same ids\n    // and roll them back as well.\n    if (!isSecondaryRollback) {\n      const mutationIds = new Set(\n        this.mutations.map((mutation) => mutation.globalKey),\n      )\n      getTransactionScope(this).rollbackConflictingTransactions(\n        this,\n        mutationIds,\n      )\n    }\n\n    // Reject the promise\n    this.isPersisted.reject(this.error?.error)\n    this.touchCollection()\n\n    return this\n  }\n\n  // Tell collection that something has changed with the transaction\n  touchCollection(): void {\n    const hasCalled = new Set()\n    for (const mutation of this.mutations) {\n      if (!hasCalled.has(mutation.collection.id)) {\n        mutation.collection._state.onTransactionStateChange()\n\n        // Only call commitPendingTransactions if there are pending sync transactions\n        if (mutation.collection._state.pendingSyncedTransactions.length > 0) {\n          mutation.collection._state.commitPendingTransactions()\n        }\n\n        hasCalled.add(mutation.collection.id)\n      }\n    }\n  }\n\n  /**\n   * Commit the transaction and execute the mutation function\n   * @returns Promise that resolves to this transaction when complete\n   * @example\n   * // Manual commit (when autoCommit is false)\n   * const tx = createTransaction({\n   *   autoCommit: false,\n   *   mutationFn: async ({ transaction }) => {\n   *     await api.saveChanges(transaction.mutations)\n   *   }\n   * })\n   *\n   * tx.mutate(() => {\n   *   collection.insert({ id: \"1\", text: \"Buy milk\" })\n   * })\n   *\n   * await tx.commit() // Manually commit\n   *\n   * @example\n   * // Handle commit errors\n   * try {\n   *   const tx = createTransaction({\n   *     mutationFn: async () => { throw new Error(\"API failed\") }\n   *   })\n   *\n   *   tx.mutate(() => {\n   *     collection.insert({ id: \"1\", text: \"Item\" })\n   *   })\n   *\n   *   await tx.commit()\n   * } catch (error) {\n   *   console.log('Commit failed, transaction rolled back:', error)\n   * }\n   *\n   * @example\n   * // Check transaction state after commit\n   * await tx.commit()\n   * console.log(tx.state) // \"completed\" or \"failed\"\n   */\n  async commit(): Promise<Transaction<T>> {\n    if (this.state !== `pending`) {\n      throw new TransactionNotPendingCommitError()\n    }\n\n    this.setState(`persisting`)\n\n    if (this.mutations.length === 0) {\n      this.setState(`completed`)\n      this.isPersisted.resolve(this)\n\n      return this\n    }\n\n    // Run mutationFn\n    try {\n      // At this point we know there's at least one mutation\n      // We've already verified mutations is non-empty, so this cast is safe\n      // Use a direct type assertion instead of object spreading to preserve the original type\n      await this.mutationFn({\n        transaction: this as unknown as TransactionWithMutations<T>,\n      })\n\n      this.setState(`completed`)\n      this.touchCollection()\n\n      this.isPersisted.resolve(this)\n    } catch (error) {\n      // Preserve the original error for rethrowing\n      const originalError =\n        error instanceof Error ? error : new Error(String(error))\n\n      // Update transaction with error information\n      this.error = {\n        message: originalError.message,\n        error: originalError,\n      }\n\n      // rollback the transaction\n      this.rollback()\n\n      // Re-throw the original error to preserve identity and stack\n      throw originalError\n    }\n\n    return this\n  }\n\n  /**\n   * Compare two transactions by their createdAt time and sequence number in order\n   * to sort them in the order they were created.\n   * @param other - The other transaction to compare to\n   * @returns -1 if this transaction was created before the other, 1 if it was created after, 0 if they were created at the same time\n   */\n  compareCreatedAt(other: Transaction<any>): number {\n    const createdAtComparison =\n      this.createdAt.getTime() - other.createdAt.getTime()\n    if (createdAtComparison !== 0) {\n      return createdAtComparison\n    }\n    return this.sequenceNumber - other.sequenceNumber\n  }\n}\n\nexport type { Transaction }\n"],"names":["transactionScopedScheduler","MissingMutationFunctionError","safeRandomUUID","createDeferred","TransactionNotPendingMutateError","TransactionAlreadyCompletedRollbackError","TransactionNotPendingCommitError"],"mappings":"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"}