{"version":3,"file":"lifecycle.cjs","sources":["../../../src/collection/lifecycle.ts"],"sourcesContent":["import {\n  CollectionInErrorStateError,\n  CollectionStateError,\n  InvalidCollectionStatusTransitionError,\n} from '../errors'\nimport {\n  safeCancelIdleCallback,\n  safeRequestIdleCallback,\n} from '../utils/browser-polyfills'\nimport { runAllCallbacks } from '../utils/callbacks'\nimport { createDeferred } from '../deferred'\nimport { CleanupQueue } from './cleanup-queue'\nimport type { IdleCallbackDeadline } from '../utils/browser-polyfills'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { CollectionConfig, CollectionStatus } from '../types'\nimport type { CollectionEventsManager } from './events'\nimport type { CollectionIndexesManager } from './indexes'\nimport type { CollectionChangesManager } from './changes'\nimport type { CollectionSyncManager } from './sync'\nimport type { CollectionStateManager } from './state'\n\n/**\n * Floor applied to the GC delay of a collection that started syncing before\n * anything subscribed. Adapters build their live query while rendering and\n * subscribe when that render commits. This grace period reduces cleanup\n * during that gap; a later subscriber can still restart sync. Adapters pass\n * a near-zero `gcTime` to make teardown on unmount immediate. Does not apply\n * to the timer armed when the last subscriber leaves, which still honours\n * `gcTime` exactly.\n */\nconst UNSUBSCRIBED_GC_FLOOR_MS = 50\n\nexport class CollectionLifecycleManager<\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 config: CollectionConfig<TOutput, TKey, TSchema, any>\n  private id: string\n  private indexes!: CollectionIndexesManager<TOutput, TKey, TSchema, TInput>\n  private events!: CollectionEventsManager\n  private changes!: CollectionChangesManager<TOutput, TKey, TSchema, TInput>\n  private sync!: CollectionSyncManager<TOutput, TKey, TSchema, TInput>\n  private state!: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n\n  public status: CollectionStatus = `idle`\n  public hasBeenReady = false\n  public hasReceivedFirstCommit = false\n  public onFirstReadyCallbacks: Array<() => void> = []\n  private idleCallbackId: number | null = null\n  private syncError: unknown\n  private cleanupConfig: () => void\n  private statusRevision = 0\n  private cleaningUp = false\n  private cleanupPromise: Promise<void> | null = null\n  private readonly cleanupStartCallbacks = new Set<() => void>()\n\n  /**\n   * Creates a new CollectionLifecycleManager instance\n   */\n  constructor(\n    config: CollectionConfig<TOutput, TKey, TSchema, any>,\n    id: string,\n    cleanupConfig: () => void = () => {},\n  ) {\n    this.config = config\n    this.id = id\n    this.cleanupConfig = cleanupConfig\n  }\n\n  setDeps(deps: {\n    indexes: CollectionIndexesManager<TOutput, TKey, TSchema, TInput>\n    events: CollectionEventsManager\n    changes: CollectionChangesManager<TOutput, TKey, TSchema, TInput>\n    sync: CollectionSyncManager<TOutput, TKey, TSchema, TInput>\n    state: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n  }) {\n    this.indexes = deps.indexes\n    this.events = deps.events\n    this.changes = deps.changes\n    this.sync = deps.sync\n    this.state = deps.state\n  }\n\n  /**\n   * Validates state transitions to prevent invalid status changes\n   */\n  public validateStatusTransition(\n    from: CollectionStatus,\n    to: CollectionStatus,\n  ): void {\n    if (from === to) {\n      // Allow same state transitions\n      return\n    }\n    const validTransitions: Record<\n      CollectionStatus,\n      Array<CollectionStatus>\n    > = {\n      idle: [`loading`, `error`, `cleaned-up`],\n      loading: [`ready`, `error`, `cleaned-up`],\n      ready: [`cleaned-up`, `error`],\n      error: [`ready`, `cleaned-up`, `idle`],\n      'cleaned-up': [`loading`, `error`],\n    }\n\n    if (!validTransitions[from].includes(to)) {\n      throw new InvalidCollectionStatusTransitionError(from, to, this.id)\n    }\n  }\n\n  /**\n   * Safely update the collection status with validation\n   * @private\n   */\n  public setStatus(\n    newStatus: CollectionStatus,\n    allowReady: boolean = false,\n  ): void {\n    if (newStatus === `ready` && !allowReady) {\n      // setStatus('ready') is an internal method that should not be called directly\n      // Instead, use markReady to transition to ready triggering the necessary events\n      // and side effects.\n      throw new CollectionStateError(\n        `You can't directly call \"setStatus('ready'). You must use markReady instead.`,\n      )\n    }\n    this.validateStatusTransition(this.status, newStatus)\n    const revision = ++this.statusRevision\n    const previousStatus = this.status\n    this.status = newStatus\n\n    // Emit event\n    this.events.emitStatusChange(\n      newStatus,\n      previousStatus,\n      () => this.statusRevision === revision,\n    )\n  }\n\n  /**\n   * Validates that the collection is in a usable state for data operations\n   * @private\n   */\n  public validateCollectionUsable(operation: string): void {\n    switch (this.status) {\n      case `error`:\n        throw new CollectionInErrorStateError(operation, this.id)\n      case `cleaned-up`:\n        // Automatically restart the collection when operations are called on cleaned-up collections\n        this.sync.startSync()\n        break\n    }\n  }\n\n  /**\n   * Mark the collection as ready for use\n   * This is called by sync implementations to explicitly signal that the collection is ready,\n   * providing a more intuitive alternative to using commits for readiness signaling\n   * @private - Should only be called by sync implementations\n   */\n  public markReady(): void {\n    const failure = this.applyReadyTransition()\n    if (failure) throw failure.error\n  }\n\n  /** @internal Capture ready-effect failures while the sync entry completes. */\n  public markReadyDuringSyncStart(): { error: unknown } | undefined {\n    return this.applyReadyTransition()\n  }\n\n  private applyReadyTransition(): { error: unknown } | undefined {\n    this.validateStatusTransition(this.status, `ready`)\n    // A successful initial sync or recovery establishes a ready snapshot.\n    if (this.status === `loading` || this.status === `error`) {\n      this.syncError = undefined\n      const readyRevision = this.statusRevision + 1\n      this.setStatus(`ready`, true)\n\n      // A status listener can synchronously supersede this transition, even\n      // when it restarts the Collection back to ready before returning.\n      if (\n        (this.status as CollectionStatus) !== `ready` ||\n        this.statusRevision !== readyRevision\n      ) {\n        return undefined\n      }\n\n      const readyEffects: Array<() => void> = []\n\n      // Call any registered first ready callbacks (only on first time becoming ready)\n      if (!this.hasBeenReady) {\n        this.hasBeenReady = true\n\n        // Also mark as having received first commit for backwards compatibility\n        if (!this.hasReceivedFirstCommit) {\n          this.hasReceivedFirstCommit = true\n        }\n\n        readyEffects.push(...this.onFirstReadyCallbacks)\n        this.onFirstReadyCallbacks = []\n      }\n      // Notify dependents when markReady is called, after status is set\n      // This ensures live queries get notified when their dependencies become ready\n      readyEffects.push(() => this.changes.emitEmptyReadyEvent())\n      try {\n        runAllCallbacks(readyEffects)\n      } catch (error) {\n        return { error }\n      }\n    }\n    return undefined\n  }\n\n  /** Mark an asynchronous sync failure after sync has started. */\n  public markError(error?: unknown): void {\n    this.validateStatusTransition(this.status, `error`)\n    this.syncError = error\n    this.setStatus(`error`)\n  }\n\n  /** Return the cause supplied by the current sync run, if any. */\n  public getSyncError(): unknown {\n    return this.syncError\n  }\n\n  public assertCanStartSync(): void {\n    if (this.cleaningUp) {\n      throw new CollectionStateError(\n        `Cannot start collection \"${this.id}\" during cleanup. Restart after cleanup() completes.`,\n      )\n    }\n    // A synchronously finished retirement retains its public promise until\n    // settlement. Starting a new sync run assigns later cleanup to that run.\n    this.cleanupPromise = null\n  }\n\n  /**\n   * Observe the synchronous start of cleanup without treating it as terminal\n   * resource settlement. Internal dependents use this to retire work before\n   * an asynchronous adapter cleanup publishes `cleaned-up`.\n   */\n  public onCleanupStart(callback: () => void): () => void {\n    this.cleanupStartCallbacks.add(callback)\n    if (this.cleaningUp) {\n      try {\n        callback()\n      } catch (error) {\n        // Registration did not return its ownership handle. Do not retain an\n        // observer that its caller has no way to unsubscribe.\n        this.cleanupStartCallbacks.delete(callback)\n        throw error\n      }\n    }\n    return () => this.cleanupStartCallbacks.delete(callback)\n  }\n\n  /**\n   * Start the garbage collection timer for a collection with no subscribers\n   * Called when sync starts outside a subscription\n   */\n  public startGCTimerIfUnsubscribed(): void {\n    this.startGCTimer(UNSUBSCRIBED_GC_FLOOR_MS)\n  }\n\n  private canGarbageCollect(): boolean {\n    return (\n      !this.cleaningUp &&\n      this.changes.activeSubscribersCount === 0 &&\n      !this.sync.hasPendingPreload\n    )\n  }\n\n  /**\n   * Start the garbage collection timer\n   * Called when the collection becomes inactive (no subscribers)\n   */\n  public startGCTimer(minDelay = 0): void {\n    if (!this.canGarbageCollect()) return\n\n    const gcTime = this.config.gcTime ?? 300000 // 5 minutes default\n\n    // If gcTime is 0, negative, or non-finite (Infinity, -Infinity, NaN), GC is disabled.\n    // Note: setTimeout with Infinity coerces to 0 via ToInt32, causing immediate GC,\n    // so we must explicitly check for non-finite values here.\n    if (gcTime <= 0 || !Number.isFinite(gcTime)) {\n      return\n    }\n\n    CleanupQueue.getInstance().schedule(\n      this,\n      Math.max(gcTime, minDelay),\n      () => {\n        if (this.canGarbageCollect()) {\n          // Schedule cleanup during idle time to avoid blocking the UI thread\n          this.scheduleIdleCleanup()\n        }\n      },\n    )\n  }\n\n  /**\n   * Cancel the garbage collection timer\n   * Called when the collection becomes active again\n   */\n  public cancelGCTimer(): void {\n    CleanupQueue.getInstance().cancel(this)\n    // Also cancel any pending idle cleanup\n    if (this.idleCallbackId !== null) {\n      safeCancelIdleCallback(this.idleCallbackId)\n      this.idleCallbackId = null\n    }\n  }\n\n  /**\n   * Schedule cleanup to run during browser idle time\n   * This prevents blocking the UI thread during cleanup operations\n   */\n  private scheduleIdleCleanup(): void {\n    // Cancel any existing idle callback\n    if (this.idleCallbackId !== null) {\n      safeCancelIdleCallback(this.idleCallbackId)\n    }\n\n    // Schedule cleanup with a timeout of 1 second\n    // This ensures cleanup happens even if the browser is busy\n    this.idleCallbackId = safeRequestIdleCallback(\n      (deadline) => {\n        // Perform cleanup if we still have no subscribers\n        if (this.canGarbageCollect()) {\n          const cleanupCompleted = this.performCleanup(deadline)\n          // Only clear the callback ID if cleanup actually completed\n          if (cleanupCompleted) {\n            this.idleCallbackId = null\n          }\n        } else {\n          // No need to cleanup, clear the callback ID\n          this.idleCallbackId = null\n        }\n      },\n      { timeout: 1000 },\n    )\n  }\n\n  /**\n   * Perform cleanup operations, optionally in chunks during idle time\n   * @returns true if cleanup was completed, false if it was rescheduled\n   */\n  private performCleanup(deadline?: IdleCallbackDeadline): boolean {\n    // Nested cleanup belongs to this retirement, not a new lifecycle turn.\n    if (this.cleaningUp) return true\n    // If we have a deadline, we can potentially split cleanup into chunks\n    // For now, we'll do all cleanup at once but check if we have time\n    const hasTime =\n      !deadline || deadline.timeRemaining() > 0 || deadline.didTimeout\n\n    if (hasTime) {\n      const cleanup = this.beginCleanup()\n      // Automatic GC has no caller to receive cleanup rejection. Core still\n      // finalizes the lifecycle; adapter diagnostics remain observable through\n      // the returned promise for explicit cleanup.\n      void cleanup.catch(() => undefined)\n\n      return true\n    } else {\n      // If we don't have time, reschedule for the next idle period\n      this.scheduleIdleCleanup()\n      return false\n    }\n  }\n\n  private beginCleanup(): Promise<void> {\n    if (this.cleanupPromise) return this.cleanupPromise\n\n    const completion = createDeferred<void>()\n    this.cleanupPromise = completion.promise\n    this.cleaningUp = true\n    const localFailures: Array<unknown> = []\n    let synchronousSyncFailure: { error: unknown } | undefined\n    let syncCleanupComplete = true\n    let finished = false\n\n    const attempt = (callback: () => void): void => {\n      try {\n        callback()\n      } catch (error) {\n        localFailures.push(error)\n      }\n    }\n\n    // Dependents must stop using the discarded sync run immediately, while\n    // the public status and cleanup promise still wait for adapter settlement.\n    for (const callback of [...this.cleanupStartCallbacks]) {\n      attempt(callback)\n    }\n\n    const finish = (syncFailure?: { error: unknown }) => {\n      if (finished) return\n      finished = true\n      this.cleaningUp = false\n      attempt(() => this.setStatus(`cleaned-up`))\n\n      // Active collection subscriptions still depend on lifecycle events.\n      // Once the last subscriber leaves, its GC cleanup clears the handlers.\n      if (this.changes.activeSubscribersCount === 0) {\n        attempt(() => this.events.cleanup())\n      }\n\n      // Keep cleanup observably asynchronous even when every release is\n      // synchronous. Existing callers may use this turn to let optimistic\n      // settlement finish before starting the next operation.\n      let failure: { error: unknown } | undefined\n      if (syncFailure && localFailures.length > 0) {\n        failure = {\n          error: new AggregateError(\n            [syncFailure.error, ...localFailures],\n            `Adapter cleanup and local teardown both failed`,\n            { cause: syncFailure.error },\n          ),\n        }\n      } else if (syncFailure) {\n        failure = syncFailure\n      } else if (localFailures.length === 1) {\n        failure = { error: localFailures[0] }\n      } else if (localFailures.length > 1) {\n        failure = {\n          error: new AggregateError(\n            localFailures,\n            `Multiple local teardown steps failed`,\n            { cause: localFailures[0] },\n          ),\n        }\n      }\n      void Promise.resolve()\n        .then(() => Promise.resolve())\n        .then(() => {\n          if (this.cleanupPromise === completion.promise) {\n            this.cleanupPromise = null\n          }\n          if (failure) completion.reject(failure.error)\n          else completion.resolve()\n        })\n    }\n\n    // Sync cleanup invalidates the sync run before invoking the adapter. The\n    // remaining managers retire their local state synchronously while the\n    // adapter's resource-release promise is pending.\n    attempt(() => this.cleanupConfig())\n    try {\n      syncCleanupComplete = this.sync.cleanup(finish)\n    } catch (error) {\n      synchronousSyncFailure = { error }\n    }\n\n    attempt(() => this.state.cleanup())\n    attempt(() => this.changes.cleanup())\n    attempt(() => this.indexes.cleanup())\n    CleanupQueue.getInstance().cancel(this)\n\n    this.hasBeenReady = false\n    this.syncError = undefined\n    // Cleanup is not readiness. Sync cleanup rejects pending preload callers;\n    // first-ready listeners belong to the discarded run.\n    this.onFirstReadyCallbacks = []\n\n    if (syncCleanupComplete) finish(synchronousSyncFailure)\n    return completion.promise\n  }\n\n  /**\n   * Register a callback to be executed when the collection first becomes ready\n   * Useful for preloading collections\n   * @param callback Function to call when the collection first becomes ready\n   */\n  public onFirstReady(callback: () => void): () => void {\n    // If already ready, call immediately\n    if (this.hasBeenReady) {\n      callback()\n      return () => {}\n    }\n\n    this.onFirstReadyCallbacks.push(callback)\n    return () => {\n      const index = this.onFirstReadyCallbacks.indexOf(callback)\n      if (index !== -1) {\n        this.onFirstReadyCallbacks.splice(index, 1)\n      }\n    }\n  }\n\n  public cleanup(): Promise<void> {\n    // Cancel any pending idle cleanup\n    if (this.idleCallbackId !== null) {\n      safeCancelIdleCallback(this.idleCallbackId)\n      this.idleCallbackId = null\n    }\n\n    // Return this exact retirement operation even if an event listener starts\n    // a replacement run and cleanup while the first promise is still pending.\n    return this.beginCleanup()\n  }\n}\n"],"names":["InvalidCollectionStatusTransitionError","CollectionStateError","CollectionInErrorStateError","runAllCallbacks","CleanupQueue","safeCancelIdleCallback","safeRequestIdleCallback","createDeferred"],"mappings":"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"}