{"version":3,"file":"OfflineExecutor.cjs","sources":["../../src/OfflineExecutor.ts"],"sourcesContent":["// Storage adapters\nimport { createOptimisticAction, createTransaction } from '@tanstack/db'\nimport { IndexedDBAdapter } from './storage/IndexedDBAdapter'\nimport { LocalStorageAdapter } from './storage/LocalStorageAdapter'\n\n// Core components\nimport { OutboxManager } from './outbox/OutboxManager'\nimport { KeyScheduler } from './executor/KeyScheduler'\nimport { TransactionExecutor } from './executor/TransactionExecutor'\n\n// Coordination\nimport { WebLocksLeader } from './coordination/WebLocksLeader'\nimport { BroadcastChannelLeader } from './coordination/BroadcastChannelLeader'\n\n// Connectivity\nimport { WebOnlineDetector } from './connectivity/OnlineDetector'\n\n// API\nimport { OfflineTransaction as OfflineTransactionAPI } from './api/OfflineTransaction'\nimport { createOfflineAction } from './api/OfflineAction'\n\n// TanStack DB primitives\n\n// Replay\nimport { withNestedSpan, withSpan } from './telemetry/tracer'\nimport type {\n  CreateOfflineActionOptions,\n  CreateOfflineTransactionOptions,\n  LeaderElection,\n  OfflineConfig,\n  OfflineMode,\n  OfflineTransaction,\n  OnlineDetector,\n  StorageAdapter,\n  StorageDiagnostic,\n} from './types'\nimport type { Transaction } from '@tanstack/db'\n\nexport class OfflineExecutor {\n  private config: OfflineConfig\n\n  // @ts-expect-error - Set during async initialization in initialize()\n  private storage: StorageAdapter | null\n  private outbox: OutboxManager | null\n  private scheduler: KeyScheduler\n  private executor: TransactionExecutor | null\n  private leaderElection: LeaderElection | null\n  private onlineDetector: OnlineDetector\n  private isLeaderState = false\n  private unsubscribeOnline: (() => void) | null = null\n  private unsubscribeLeadership: (() => void) | null = null\n\n  // Public diagnostic properties\n  public readonly mode: OfflineMode\n  public readonly storageDiagnostic: StorageDiagnostic\n\n  // Track initialization completion\n  private initPromise: Promise<void>\n  private initResolve!: () => void\n  private initReject!: (error: Error) => void\n\n  // Coordination mechanism for blocking transactions\n  private pendingTransactionPromises: Map<\n    string,\n    {\n      promise: Promise<any>\n      resolve: (result: any) => void\n      reject: (error: Error) => void\n    }\n  > = new Map()\n\n  // Track restoration transactions for cleanup when offline transactions complete\n  private restorationTransactions: Map<string, Transaction> = new Map()\n\n  constructor(config: OfflineConfig) {\n    this.config = config\n    this.scheduler = new KeyScheduler()\n    this.onlineDetector = config.onlineDetector ?? new WebOnlineDetector()\n\n    // Initialize as pending - will be set by async initialization\n    this.storage = null\n    this.outbox = null\n    this.executor = null\n    this.leaderElection = null\n\n    // Temporary diagnostic - will be updated by async initialization\n    this.mode = `offline`\n    this.storageDiagnostic = {\n      code: `STORAGE_AVAILABLE`,\n      mode: `offline`,\n      message: `Initializing storage...`,\n    }\n\n    // Create initialization promise\n    this.initPromise = new Promise((resolve, reject) => {\n      this.initResolve = resolve\n      this.initReject = reject\n    })\n\n    this.initialize()\n  }\n\n  /**\n   * Probe storage availability and create appropriate adapter.\n   * Returns null if no storage is available (online-only mode).\n   */\n  private async createStorage(): Promise<{\n    storage: StorageAdapter | null\n    diagnostic: StorageDiagnostic\n  }> {\n    // If user provided custom storage, use it without probing\n    if (this.config.storage) {\n      return {\n        storage: this.config.storage,\n        diagnostic: {\n          code: `STORAGE_AVAILABLE`,\n          mode: `offline`,\n          message: `Using custom storage adapter`,\n        },\n      }\n    }\n\n    // Probe IndexedDB first\n    const idbProbe = await IndexedDBAdapter.probe()\n    if (idbProbe.available) {\n      return {\n        storage: new IndexedDBAdapter(),\n        diagnostic: {\n          code: `STORAGE_AVAILABLE`,\n          mode: `offline`,\n          message: `Using IndexedDB for offline storage`,\n        },\n      }\n    }\n\n    // IndexedDB failed, try localStorage\n    const lsProbe = LocalStorageAdapter.probe()\n    if (lsProbe.available) {\n      return {\n        storage: new LocalStorageAdapter(),\n        diagnostic: {\n          code: `INDEXEDDB_UNAVAILABLE`,\n          mode: `offline`,\n          message: `IndexedDB unavailable, using localStorage fallback`,\n          error: idbProbe.error,\n        },\n      }\n    }\n\n    // Both failed - determine the diagnostic code\n    const isSecurityError =\n      idbProbe.error?.name === `SecurityError` ||\n      lsProbe.error?.name === `SecurityError`\n    const isQuotaError =\n      idbProbe.error?.name === `QuotaExceededError` ||\n      lsProbe.error?.name === `QuotaExceededError`\n\n    let code: StorageDiagnostic[`code`]\n    let message: string\n\n    if (isSecurityError) {\n      code = `STORAGE_BLOCKED`\n      message = `Storage blocked (private mode or security restrictions). Running in online-only mode.`\n    } else if (isQuotaError) {\n      code = `QUOTA_EXCEEDED`\n      message = `Storage quota exceeded. Running in online-only mode.`\n    } else {\n      code = `UNKNOWN_ERROR`\n      message = `Storage unavailable due to unknown error. Running in online-only mode.`\n    }\n\n    return {\n      storage: null,\n      diagnostic: {\n        code,\n        mode: `online-only`,\n        message,\n        error: idbProbe.error || lsProbe.error,\n      },\n    }\n  }\n\n  private createLeaderElection(): LeaderElection {\n    if (this.config.leaderElection) {\n      return this.config.leaderElection\n    }\n\n    if (WebLocksLeader.isSupported()) {\n      return new WebLocksLeader()\n    } else if (BroadcastChannelLeader.isSupported()) {\n      return new BroadcastChannelLeader()\n    } else {\n      // Fallback: always be leader in environments without multi-tab support\n      return {\n        requestLeadership: () => Promise.resolve(true),\n        releaseLeadership: () => {},\n        isLeader: () => true,\n        onLeadershipChange: () => () => {},\n      }\n    }\n  }\n\n  private setupEventListeners(): void {\n    // Only set up leader election listeners if we have storage\n    if (this.leaderElection) {\n      this.unsubscribeLeadership = this.leaderElection.onLeadershipChange(\n        (isLeader) => {\n          this.isLeaderState = isLeader\n\n          if (this.config.onLeadershipChange) {\n            this.config.onLeadershipChange(isLeader)\n          }\n\n          if (isLeader) {\n            this.loadAndReplayTransactions()\n          }\n        },\n      )\n    }\n\n    this.unsubscribeOnline = this.onlineDetector.subscribe(() => {\n      if (this.isOfflineEnabled && this.executor) {\n        this.executor.resetRetryDelays()\n\n        if (this.scheduler.getPendingCount() > 0) {\n          const barrierPromise = this.executor.executeAll()\n\n          for (const collection of Object.values(this.config.collections)) {\n            collection.deferDataRefresh = barrierPromise\n          }\n\n          barrierPromise\n            .catch((error) => {\n              console.warn(\n                `Failed to execute transactions on connectivity change:`,\n                error,\n              )\n            })\n            .finally(() => {\n              for (const collection of Object.values(this.config.collections)) {\n                if (collection.deferDataRefresh === barrierPromise) {\n                  collection.deferDataRefresh = null\n                }\n              }\n            })\n        } else {\n          this.executor.executeAll().catch((error) => {\n            console.warn(\n              `Failed to execute transactions on connectivity change:`,\n              error,\n            )\n          })\n        }\n      }\n    })\n  }\n\n  private async initialize(): Promise<void> {\n    return withSpan(`executor.initialize`, {}, async (span) => {\n      try {\n        // Probe storage and create adapter\n        const { storage, diagnostic } = await this.createStorage()\n\n        // Cast to writable to set readonly properties\n        ;(this as any).storage = storage\n        ;(this as any).storageDiagnostic = diagnostic\n        ;(this as any).mode = diagnostic.mode\n\n        span.setAttribute(`storage.mode`, diagnostic.mode)\n        span.setAttribute(`storage.code`, diagnostic.code)\n\n        if (!storage) {\n          // Online-only mode - notify callback and skip offline setup\n          if (this.config.onStorageFailure) {\n            this.config.onStorageFailure(diagnostic)\n          }\n          span.setAttribute(`result`, `online-only`)\n          this.initResolve()\n          return\n        }\n\n        // Storage available - set up offline components\n        this.outbox = new OutboxManager(storage, this.config.collections)\n        this.executor = new TransactionExecutor(\n          this.scheduler,\n          this.outbox,\n          this.config,\n          this,\n        )\n        this.leaderElection = this.createLeaderElection()\n\n        // Request leadership first\n        const isLeader = await this.leaderElection.requestLeadership()\n        this.isLeaderState = isLeader\n        span.setAttribute(`isLeader`, isLeader)\n\n        // Set up event listeners after leadership is established\n        // This prevents the callback from being called multiple times\n        this.setupEventListeners()\n\n        // Notify initial leadership state\n        if (this.config.onLeadershipChange) {\n          this.config.onLeadershipChange(isLeader)\n        }\n\n        if (isLeader) {\n          await this.loadAndReplayTransactions()\n        }\n        span.setAttribute(`result`, `offline-enabled`)\n        this.initResolve()\n      } catch (error) {\n        console.warn(`Failed to initialize offline executor:`, error)\n        span.setAttribute(`result`, `failed`)\n        this.initReject(\n          error instanceof Error ? error : new Error(String(error)),\n        )\n      }\n    })\n  }\n\n  private async loadAndReplayTransactions(): Promise<void> {\n    if (!this.executor) {\n      return\n    }\n\n    try {\n      // Load pending transactions and restore optimistic state\n      await this.executor.loadPendingTransactions()\n\n      // Start execution in the background - don't await to avoid blocking initialization\n      // The transactions will execute and complete asynchronously\n      this.executor.executeAll().catch((error) => {\n        console.warn(`Failed to execute transactions:`, error)\n      })\n    } catch (error) {\n      console.warn(`Failed to load and replay transactions:`, error)\n    }\n  }\n\n  get isOfflineEnabled(): boolean {\n    return this.mode === `offline` && this.isLeaderState\n  }\n\n  /**\n   * Wait for the executor to fully initialize.\n   * This ensures that pending transactions are loaded and optimistic state is restored.\n   */\n  async waitForInit(): Promise<void> {\n    return this.initPromise\n  }\n\n  createOfflineTransaction(\n    options: CreateOfflineTransactionOptions,\n  ): Transaction | OfflineTransactionAPI {\n    const mutationFn = this.config.mutationFns[options.mutationFnName]\n\n    if (!mutationFn) {\n      throw new Error(`Unknown mutation function: ${options.mutationFnName}`)\n    }\n\n    // Check leadership immediately and use the appropriate primitive\n    if (!this.isOfflineEnabled) {\n      // Non-leader: use createTransaction directly with the resolved mutation function\n      // We need to wrap it to add the idempotency key\n      return createTransaction({\n        autoCommit: options.autoCommit ?? true,\n        mutationFn: (params) =>\n          mutationFn({\n            ...params,\n            idempotencyKey: options.idempotencyKey || crypto.randomUUID(),\n          }),\n        metadata: options.metadata,\n      })\n    }\n\n    // Leader: use OfflineTransaction wrapper for offline persistence\n    return new OfflineTransactionAPI(\n      options,\n      mutationFn,\n      this.persistTransaction.bind(this),\n      this,\n    )\n  }\n\n  createOfflineAction<T>(options: CreateOfflineActionOptions<T>) {\n    const mutationFn = this.config.mutationFns[options.mutationFnName]\n\n    if (!mutationFn) {\n      throw new Error(`Unknown mutation function: ${options.mutationFnName}`)\n    }\n\n    // Return a wrapper that checks leadership status at call time\n    return (variables: T) => {\n      // Check leadership when action is called, not when it's created\n      if (!this.isOfflineEnabled) {\n        // Non-leader: use createOptimisticAction directly\n        const action = createOptimisticAction({\n          mutationFn: (vars, params) =>\n            mutationFn({\n              ...vars,\n              ...params,\n              idempotencyKey: crypto.randomUUID(),\n            }),\n          onMutate: options.onMutate,\n        })\n        return action(variables)\n      }\n\n      // Leader: use the offline action wrapper\n      const action = createOfflineAction(\n        options,\n        mutationFn,\n        this.persistTransaction.bind(this),\n        this,\n      )\n      return action(variables)\n    }\n  }\n\n  private async persistTransaction(\n    transaction: OfflineTransaction,\n  ): Promise<void> {\n    // Wait for initialization to complete\n    await this.initPromise\n\n    return withNestedSpan(\n      `executor.persistTransaction`,\n      {\n        'transaction.id': transaction.id,\n        'transaction.mutationFnName': transaction.mutationFnName,\n      },\n      async (span) => {\n        if (!this.isOfflineEnabled || !this.outbox || !this.executor) {\n          span.setAttribute(`result`, `skipped_not_leader`)\n          this.resolveTransaction(transaction.id, undefined)\n          return\n        }\n\n        try {\n          await this.outbox.add(transaction)\n          await this.executor.execute(transaction)\n          span.setAttribute(`result`, `persisted`)\n        } catch (error) {\n          console.error(\n            `Failed to persist offline transaction ${transaction.id}:`,\n            error,\n          )\n          span.setAttribute(`result`, `failed`)\n          throw error\n        }\n      },\n    )\n  }\n\n  // Method for OfflineTransaction to wait for completion\n  async waitForTransactionCompletion(transactionId: string): Promise<any> {\n    const existing = this.pendingTransactionPromises.get(transactionId)\n    if (existing) {\n      return existing.promise\n    }\n\n    const deferred: {\n      promise: Promise<any>\n      resolve: (result: any) => void\n      reject: (error: Error) => void\n    } = {} as any\n\n    deferred.promise = new Promise((resolve, reject) => {\n      deferred.resolve = resolve\n      deferred.reject = reject\n    })\n\n    this.pendingTransactionPromises.set(transactionId, deferred)\n    return deferred.promise\n  }\n\n  // Method for TransactionExecutor to signal completion\n  resolveTransaction(transactionId: string, result: any): void {\n    const deferred = this.pendingTransactionPromises.get(transactionId)\n    if (deferred) {\n      deferred.resolve(result)\n      this.pendingTransactionPromises.delete(transactionId)\n    }\n\n    // Clean up the restoration transaction - the sync will provide authoritative data\n    this.cleanupRestorationTransaction(transactionId)\n  }\n\n  // Method for TransactionExecutor to signal failure\n  rejectTransaction(transactionId: string, error: Error): void {\n    const deferred = this.pendingTransactionPromises.get(transactionId)\n    if (deferred) {\n      deferred.reject(error)\n      this.pendingTransactionPromises.delete(transactionId)\n    }\n\n    // Clean up the restoration transaction and rollback optimistic state\n    this.cleanupRestorationTransaction(transactionId, true)\n  }\n\n  // Method for TransactionExecutor to register restoration transactions\n  registerRestorationTransaction(\n    offlineTransactionId: string,\n    restorationTransaction: Transaction,\n  ): void {\n    this.restorationTransactions.set(\n      offlineTransactionId,\n      restorationTransaction,\n    )\n  }\n\n  private cleanupRestorationTransaction(\n    transactionId: string,\n    shouldRollback = false,\n  ): void {\n    const restorationTx = this.restorationTransactions.get(transactionId)\n    if (!restorationTx) {\n      return\n    }\n\n    this.restorationTransactions.delete(transactionId)\n\n    if (shouldRollback) {\n      restorationTx.rollback()\n      return\n    }\n\n    // Mark as completed so recomputeOptimisticState removes it from consideration.\n    // The actual data will come from the sync.\n    restorationTx.setState(`completed`)\n\n    // Remove from each collection's transaction map and recompute\n    const touchedCollections = new Set<string>()\n    for (const mutation of restorationTx.mutations) {\n      // Defensive check for corrupted deserialized data\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      if (!mutation.collection) {\n        continue\n      }\n      const collectionId = mutation.collection.id\n      if (touchedCollections.has(collectionId)) {\n        continue\n      }\n      touchedCollections.add(collectionId)\n      mutation.collection._state.transactions.delete(restorationTx.id)\n      mutation.collection._state.recomputeOptimisticState(false)\n    }\n  }\n\n  async removeFromOutbox(id: string): Promise<void> {\n    if (!this.outbox) {\n      return\n    }\n    await this.outbox.remove(id)\n  }\n\n  async peekOutbox(): Promise<Array<OfflineTransaction>> {\n    if (!this.outbox) {\n      return []\n    }\n    return this.outbox.getAll()\n  }\n\n  async clearOutbox(): Promise<void> {\n    if (!this.outbox || !this.executor) {\n      return\n    }\n    await this.outbox.clear()\n    this.executor.clear()\n  }\n\n  getPendingCount(): number {\n    if (!this.executor) {\n      return 0\n    }\n    return this.executor.getPendingCount()\n  }\n\n  getRunningCount(): number {\n    if (!this.executor) {\n      return 0\n    }\n    return this.executor.getRunningCount()\n  }\n\n  getOnlineDetector(): OnlineDetector {\n    return this.onlineDetector\n  }\n\n  isOnline(): boolean {\n    return this.onlineDetector.isOnline()\n  }\n\n  dispose(): void {\n    for (const collection of Object.values(this.config.collections)) {\n      collection.deferDataRefresh = null\n    }\n\n    if (this.unsubscribeOnline) {\n      this.unsubscribeOnline()\n      this.unsubscribeOnline = null\n    }\n\n    if (this.unsubscribeLeadership) {\n      this.unsubscribeLeadership()\n      this.unsubscribeLeadership = null\n    }\n\n    if (this.leaderElection) {\n      this.leaderElection.releaseLeadership()\n\n      if (`dispose` in this.leaderElection) {\n        ;(this.leaderElection as any).dispose()\n      }\n    }\n\n    this.onlineDetector.dispose()\n  }\n}\n\nexport function startOfflineExecutor(config: OfflineConfig): OfflineExecutor {\n  return new OfflineExecutor(config)\n}\n"],"names":["KeyScheduler","WebOnlineDetector","IndexedDBAdapter","LocalStorageAdapter","WebLocksLeader","BroadcastChannelLeader","withSpan","OutboxManager","TransactionExecutor","createTransaction","OfflineTransactionAPI","action","createOptimisticAction","createOfflineAction","withNestedSpan","OfflineExecutor"],"mappings":"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"}