{"version":3,"file":"live-query-observer.cjs","sources":["../../src/live-query-observer.ts"],"sourcesContent":["import { LiveQueryObserverDisposedError } from './errors.js'\nimport {\n  getLiveQueryStatusFlags,\n  isSingleResultCollection,\n} from './live-query-adapter.js'\nimport { getBuilderFromConfig } from './query/live/collection-registry.js'\nimport type { Collection } from './collection/index.js'\nimport type { DbClient, DehydratedLiveQueryResult } from './client.js'\nimport type { ChangeMessage, CollectionStatus } from './types.js'\n\n/**\n * The canonical, adapter-agnostic view of a live query at a point in time.\n *\n * `getSnapshot()` returns a stable object identity that only changes when the\n * query changes, so `useSyncExternalStore`-style consumers can compare by\n * reference. Each snapshot owns a captured view of `state`/`data`, so reading\n * an older snapshot cannot expose rows from a later revision.\n */\nexport interface LiveQuerySnapshot<\n  T extends object,\n  TKey extends string | number,\n> {\n  /** Keyed results, or `undefined` for a disabled query. */\n  state: ReadonlyMap<TKey, T> | undefined\n  /** Ordered results (single row for `findOne`), or `undefined` when disabled. */\n  data: T | ReadonlyArray<T> | undefined\n  /** The underlying collection, or `undefined` when disabled. */\n  collection: Collection<T, TKey, any> | undefined\n  /**\n   * Monotonic counter bumped whenever the visible layout (the ordered key\n   * sequence) changes — membership, ordering, or an order-only move. Lets\n   * consumers detect a reorder that changed no row value (which `data`/`state`\n   * identity alone can't express once row values are structurally shared).\n   *\n   * It is NOT in lockstep with snapshot identity: a value-only update produces a\n   * new snapshot while `layoutRevision` stays put. A `layoutRevision` change\n   * always accompanies a new snapshot, but not vice versa.\n   */\n  layoutRevision: number\n  status: CollectionStatus | `disabled`\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: boolean\n}\n\n/**\n * Listener payload: changes, `[]` for an internal layout-only publication, or\n * `undefined` for a synthetic status/ready notification.\n */\nexport type LiveQueryObserverListener<\n  T extends object,\n  TKey extends string | number,\n> = (changes: Array<ChangeMessage<T, TKey>> | undefined) => void\n\n/**\n * Wraps a resolved live-query `Collection` (or `null` for a disabled query) with\n * the shared lifecycle every framework adapter needs: start sync on first\n * subscribe, subscribe to changes and status transitions, expose a stable\n * snapshot for wholesale consumers, and deliver the raw change set for\n * granular consumers.\n *\n * Input resolution (query fn / config / collection / disabled) stays in the\n * adapter — it is framework-reactive. The observer owns everything after the\n * input is resolved to a concrete collection.\n *\n * @internal Unstable contract for TanStack DB's official framework adapters —\n * not a public extension point yet; may change in any release.\n */\nexport interface LiveQueryObserver<\n  T extends object,\n  TKey extends string | number,\n> {\n  /** Stable per-revision snapshot for wholesale materialization. */\n  getSnapshot: () => LiveQuerySnapshot<T, TKey>\n  /** Stable server snapshot used by useSyncExternalStore-style adapters. */\n  getServerSnapshot: () => LiveQuerySnapshot<T, TKey>\n  /**\n   * Subscribe to changes. The listener receives the change set (or `undefined`\n   * for the synthetic notify a ready collection emits on attach). Granular\n   * adapters apply the changes; wholesale adapters can ignore them and re-read\n   * `getSnapshot()`. Returns an unsubscribe function.\n   */\n  subscribe: (listener: LiveQueryObserverListener<T, TKey>) => () => void\n  /** Resolve once the collection has loaded its first data. */\n  preload: () => Promise<void>\n  /** The transport or preload error for this query, if it has not produced data. */\n  getError: () => unknown\n  /** Capture the ordered query result without serializing its source collections. */\n  dehydrate: () => DehydratedLiveQueryResult<T, TKey>\n  /** Idempotent teardown. */\n  dispose: () => void\n}\n\n/**\n * One logical subscription. Records — not raw callbacks — identify\n * subscriptions, so the same listener function can be subscribed twice and\n * each subscription tears down independently.\n */\ninterface SubscriptionRecord<T extends object, TKey extends string | number> {\n  listener: LiveQueryObserverListener<T, TKey>\n  active: boolean\n}\n\ninterface Publication<T extends object, TKey extends string | number> {\n  changes: Array<ChangeMessage<T, TKey>> | undefined\n  targets: Array<SubscriptionRecord<T, TKey>>\n  entries?: Array<[TKey, T]>\n  status: CollectionStatus\n  collectionRevision?: number\n  collectionLayoutRevision?: number\n  layoutChanged: boolean\n}\n\nconst DISABLED_SNAPSHOT: LiveQuerySnapshot<any, any> = {\n  state: undefined,\n  data: undefined,\n  collection: undefined,\n  layoutRevision: 0,\n  status: `disabled`,\n  isLoading: false,\n  isReady: true,\n  isIdle: false,\n  isError: false,\n  isCleanedUp: false,\n  isEnabled: false,\n}\n\nclass LiveQueryObserverImpl<\n  T extends object,\n  TKey extends string | number,\n> implements LiveQueryObserver<T, TKey> {\n  private readonly collection: Collection<T, TKey, any> | null\n  private readonly wholesale: boolean\n  private readonly client: DbClient | undefined\n  private readonly queryHash: string | undefined\n  private readonly onPreload: (() => void) | undefined\n  private visibleStatus: CollectionStatus | undefined\n  private cachedEntries: Array<[TKey, T]> | undefined\n  private cachedCollectionRevision: number | undefined\n  private cachedCollectionLayoutRevision: number | undefined\n  private snapshotDirty = true\n  private cachedSnapshot: LiveQuerySnapshot<T, TKey> = DISABLED_SNAPSHOT\n  private layoutRevision = 0\n  private lastLayoutKeys: Array<TKey> | undefined\n  private deliveredLayoutRevision: number | undefined\n  private readonly subscriptions = new Set<SubscriptionRecord<T, TKey>>()\n  // Publications are dispatched FIFO: an emit that happens while another\n  // publication is being delivered (a listener mutating the collection\n  // synchronously) is queued, never delivered reentrantly.\n  private readonly publicationQueue: Array<Publication<T, TKey>> = []\n  private dispatching = false\n  private blockDelivery = false\n  private attached = false\n  private collectionUnsub: (() => void) | null = null\n  private unregisterClientResource: (() => void) | undefined\n  private hydrationSeed:\n    | {\n        dehydratedAt: number\n        entries: Array<[TKey, T]>\n      }\n    | undefined\n  private hydrationError: unknown\n  private hasHydrationError = false\n  private liveResultIsAuthoritative = false\n  private handoffScheduled = false\n  private preloadPromise: Promise<void> | undefined\n  private disposed = false\n\n  // Sync activation belongs to the first subscription (attach), so building\n  // an observer cannot activate collection resources on its own. Server\n  // request clients still record ownership here because React may render an\n  // observer without ever subscribing to it.\n  constructor(\n    collection: Collection<T, TKey, any> | null,\n    wholesale: boolean,\n    client: DbClient | undefined,\n    queryHash: string | undefined,\n    onPreload: (() => void) | undefined,\n  ) {\n    this.collection = collection\n    this.wholesale = wholesale\n    this.client = client\n    this.queryHash = queryHash\n    this.onPreload = onPreload\n    this.registerClientResource()\n  }\n\n  getSnapshot(): LiveQuerySnapshot<T, TKey> {\n    const collection = this.collection\n    if (!collection) return DISABLED_SNAPSHOT\n\n    this.syncHydrationState()\n    if (!this.attached) this.refreshDetachedState(collection)\n\n    if (this.snapshotDirty) {\n      const entries = this.getVisibleEntries(collection)\n      const state = new Map(entries)\n      const data = entries.map(([, value]) => value)\n      const singleResult = isSingleResultCollection(collection)\n      const liveStatus = this.visibleStatus ?? collection.status\n      const status =\n        this.hasHydrationError || liveStatus === `error`\n          ? (`error` as const)\n          : this.hasHydrationSeed()\n            ? (`ready` as const)\n            : liveStatus\n\n      // Bump the layout revision when the ordered key sequence changes\n      // (membership, ordering, or an order-only move). Compare the key sequence\n      // directly rather than via a serialized signature: a joined-with-separator\n      // signature can collide when a key value equals the concatenation of\n      // neighboring keys around the separator. Comparing keys also avoids\n      // materializing a large string on every rebuild; a new key array is only\n      // allocated when the layout actually moved.\n      const prevKeys = this.lastLayoutKeys\n      let layoutChanged =\n        prevKeys === undefined || prevKeys.length !== entries.length\n      if (!layoutChanged) {\n        for (let i = 0; i < entries.length; i++) {\n          if (prevKeys![i] !== entries[i]![0]) {\n            layoutChanged = true\n            break\n          }\n        }\n      }\n      if (layoutChanged) {\n        this.lastLayoutKeys = entries.map(([key]) => key)\n        this.layoutRevision++\n      }\n\n      this.cachedSnapshot = {\n        state,\n        data: singleResult ? data[0] : data,\n        collection,\n        layoutRevision: this.layoutRevision,\n        status,\n        ...getLiveQueryStatusFlags(status),\n        isEnabled: true,\n      }\n      this.snapshotDirty = false\n    }\n    return this.cachedSnapshot\n  }\n\n  getServerSnapshot(): LiveQuerySnapshot<T, TKey> {\n    return this.getSnapshot()\n  }\n\n  getError(): unknown {\n    this.syncHydrationState()\n    return this.hasHydrationError ? this.hydrationError : undefined\n  }\n\n  dehydrate(): DehydratedLiveQueryResult<T, TKey> {\n    const collection = this.collection\n    if (!collection) return { rows: [] }\n\n    const entries = this.hasHydrationSeed()\n      ? this.hydrationSeed!.entries\n      : this.readEntries(collection).entries\n\n    return {\n      rows: entries.map(([key, value]) => ({\n        key,\n        value,\n      })),\n    }\n  }\n\n  private hasHydrationSeed(): boolean {\n    return this.hydrationSeed !== undefined && !this.liveResultIsAuthoritative\n  }\n\n  private getVisibleEntries(\n    collection: Collection<T, TKey, any>,\n  ): Array<[TKey, T]> {\n    if (this.hasHydrationSeed()) return this.hydrationSeed!.entries\n    return this.cachedEntries ?? this.captureEntries(collection).entries\n  }\n\n  private syncHydrationState(): boolean {\n    if (!this.client || !this.queryHash || this.liveResultIsAuthoritative) {\n      return false\n    }\n\n    const query = this.client._getLiveQuery(this.queryHash)\n    if (!query) return false\n\n    if (\n      this.attached &&\n      !this.hydrationSeed &&\n      this.collection?.status === `ready` &&\n      !this.collection.isLoadingSubset\n    ) {\n      return this.markLiveResultAuthoritative(query.dehydratedAt)\n    }\n\n    if (query.status === `error`) {\n      const changed =\n        !this.hasHydrationError || this.hydrationError !== query.error\n      this.hydrationError = query.error\n      this.hasHydrationError = true\n      if (changed) this.snapshotDirty = true\n      return changed\n    }\n\n    if (\n      query.status !== `success` ||\n      !query.snapshot ||\n      (this.hydrationSeed &&\n        this.hydrationSeed.dehydratedAt >= query.dehydratedAt)\n    ) {\n      return false\n    }\n\n    this.hydrationSeed = {\n      dehydratedAt: query.dehydratedAt,\n      entries: query.snapshot.rows.map((row) => [\n        row.key as TKey,\n        row.value as T,\n      ]),\n    }\n    this.hydrationError = undefined\n    this.hasHydrationError = false\n    this.snapshotDirty = true\n    return true\n  }\n\n  private diffEntries(\n    previous: Array<[TKey, T]>,\n    next: Array<[TKey, T]>,\n  ): Array<ChangeMessage<T, TKey>> {\n    const previousByKey = new Map(previous)\n    const nextByKey = new Map(next)\n    const changes: Array<ChangeMessage<T, TKey>> = []\n\n    for (const [key, value] of previous) {\n      if (!nextByKey.has(key)) changes.push({ type: `delete`, key, value })\n    }\n    for (const [key, value] of next) {\n      const previousValue = previousByKey.get(key)\n      if (previousValue === undefined) {\n        changes.push({ type: `insert`, key, value })\n      } else if (previousValue !== value) {\n        changes.push({\n          type: `update`,\n          key,\n          value,\n          previousValue,\n        })\n      }\n    }\n\n    return changes\n  }\n\n  private handoffHydrationSeed(collection: Collection<T, TKey, any>): {\n    changes: Array<ChangeMessage<T, TKey>>\n    entries: Array<[TKey, T]>\n    revision?: number\n  } {\n    const previous = this.hydrationSeed?.entries ?? []\n    const dehydratedAt = this.hydrationSeed?.dehydratedAt\n    const { entries, revision } = this.readEntries(collection)\n    this.hydrationSeed = undefined\n    this.markLiveResultAuthoritative(dehydratedAt)\n    this.updateCachedEntries(entries, revision)\n    this.snapshotDirty = true\n    return {\n      changes: this.diffEntries(previous, entries),\n      entries,\n      revision,\n    }\n  }\n\n  private markLiveResultAuthoritative(dehydratedAt?: number): boolean {\n    const changed = this.hasHydrationError\n    this.hydrationError = undefined\n    this.hasHydrationError = false\n    this.liveResultIsAuthoritative = true\n    if (dehydratedAt !== undefined && this.queryHash) {\n      this.client?._consumeLiveQueryResult(this.queryHash, dehydratedAt)\n    }\n    if (changed) this.snapshotDirty = true\n    return changed\n  }\n\n  private scheduleHydrationHandoff(): void {\n    if (this.handoffScheduled) return\n    this.handoffScheduled = true\n\n    queueMicrotask(() => {\n      this.handoffScheduled = false\n      const collection = this.collection\n      if (\n        this.disposed ||\n        !this.attached ||\n        !collection ||\n        !this.hasHydrationSeed() ||\n        collection.status !== `ready` ||\n        collection.isLoadingSubset\n      ) {\n        return\n      }\n\n      const handoff = this.handoffHydrationSeed(collection)\n      this.emit(\n        this.wholesale ? undefined : handoff.changes,\n        undefined,\n        handoff.entries,\n        collection.status,\n        handoff.revision,\n        this.getCollectionLayoutRevision(collection),\n        true,\n      )\n    })\n  }\n\n  private getCollectionRevision(\n    collection: Collection<T, TKey, any>,\n  ): number | undefined {\n    const revision = (collection as { _stateRevision?: unknown })._stateRevision\n    return typeof revision === `number` ? revision : undefined\n  }\n\n  private getCollectionLayoutRevision(\n    collection: Collection<T, TKey, any>,\n  ): number | undefined {\n    const revision = (collection as { _layoutRevision?: unknown })\n      ._layoutRevision\n    return typeof revision === `number` ? revision : undefined\n  }\n\n  private readEntries(collection: Collection<T, TKey, any>): {\n    entries: Array<[TKey, T]>\n    revision?: number\n  } {\n    const entries = Array.from(collection.entries()) as Array<[TKey, T]>\n    const revision = this.getCollectionRevision(collection)\n    return { entries, revision }\n  }\n\n  private captureEntries(collection: Collection<T, TKey, any>): {\n    entries: Array<[TKey, T]>\n    revision?: number\n  } {\n    const { entries, revision } = this.readEntries(collection)\n    this.updateCachedEntries(entries, revision)\n    return { entries, revision }\n  }\n\n  private updateCachedEntries(\n    entries: Array<[TKey, T]>,\n    revision: number | undefined,\n  ): void {\n    const changed =\n      revision !== undefined\n        ? this.cachedEntries === undefined ||\n          revision !== this.cachedCollectionRevision\n        : !this.entriesEqual(this.cachedEntries, entries)\n\n    this.cachedEntries = entries\n    this.cachedCollectionRevision = revision\n    if (changed) this.snapshotDirty = true\n  }\n\n  private entriesEqual(\n    left: Array<[TKey, T]> | undefined,\n    right: Array<[TKey, T]>,\n  ): boolean {\n    if (!left || left.length !== right.length) return false\n    return left.every(\n      ([key, value], index) =>\n        right[index]![0] === key && right[index]![1] === value,\n    )\n  }\n\n  /**\n   * While detached there is no delivered-publication clock, so fall back to\n   * the collection revision. Compatible cross-copy collections that predate\n   * `_stateRevision` are compared structurally instead.\n   */\n  private refreshDetachedState(collection: Collection<T, TKey, any>): void {\n    const status = collection.status\n    const revision = this.getCollectionRevision(collection)\n    const layoutRevision = this.getCollectionLayoutRevision(collection)\n\n    if (revision !== undefined) {\n      if (\n        this.cachedEntries === undefined ||\n        revision !== this.cachedCollectionRevision ||\n        layoutRevision !== this.cachedCollectionLayoutRevision\n      ) {\n        this.captureEntries(collection)\n        this.cachedCollectionLayoutRevision = layoutRevision\n        this.snapshotDirty = true\n      }\n    } else {\n      const entries = Array.from(collection.entries()) as Array<[TKey, T]>\n      this.updateCachedEntries(entries, undefined)\n    }\n\n    if (this.visibleStatus !== status) {\n      this.visibleStatus = status\n      this.snapshotDirty = true\n    }\n  }\n\n  subscribe(listener: LiveQueryObserverListener<T, TKey>): () => void {\n    if (this.disposed) throw new LiveQueryObserverDisposedError()\n\n    const record: SubscriptionRecord<T, TKey> = { listener, active: true }\n    this.subscriptions.add(record)\n    if (this.subscriptions.size === 1) {\n      this.attach()\n    } else {\n      // The initial-state replay only happens on attach, so a granular\n      // subscriber that arrives while already attached is seeded with the\n      // current rows — delivered to this subscription alone, without advancing\n      // the observer's revision (the collection state did not change).\n      // Wholesale consumers read getSnapshot() instead and need no seed.\n      if (!this.wholesale) this.seed(record)\n    }\n\n    return () => {\n      if (!record.active) return\n      record.active = false\n      this.subscriptions.delete(record)\n      if (this.subscriptions.size === 0) this.detach()\n    }\n  }\n\n  /** Deliver the collection's current rows to one late subscription as inserts. */\n  private seed(record: SubscriptionRecord<T, TKey>): void {\n    const collection = this.collection\n    if (!collection) return\n\n    const seedChanges: Array<ChangeMessage<T, TKey>> = []\n    for (const [key, value] of this.getVisibleEntries(collection)) {\n      seedChanges.push({ type: `insert`, key, value })\n    }\n    if (seedChanges.length === 0) return\n\n    this.emit(seedChanges, [record])\n  }\n\n  private attach(): void {\n    const collection = this.collection\n    if (!collection || this.disposed) return\n    this.registerClientResource()\n    this.syncHydrationState()\n    this.refreshDetachedState(collection)\n    this.attached = true\n    this.visibleStatus ??= collection.status\n    this.deliveredLayoutRevision = this.getCollectionLayoutRevision(collection)\n    const attachedWithHydrationSeed = this.hasHydrationSeed()\n    this.blockDelivery = this.wholesale || attachedWithHydrationSeed\n\n    // Sync activation happens inside subscribeChanges (addSubscriber starts\n    // an idle/cleaned-up collection) — the same startSync path the old\n    // constructor-time startSyncImmediate() took, but now owned by the first\n    // committed subscription and observed by the status listener below.\n\n    // Granular consumers subscribe with initial state so they receive the\n    // current rows as inserts followed by deltas through one consistent\n    // channel (the collection's per-subscriber change stream requires this to\n    // align deltas). Wholesale consumers subscribe WITHOUT initial state —\n    // preserving their pre-observer loading policy: no snapshot request means\n    // no unfiltered loadSubset({ where: undefined }) against on-demand\n    // collections. The explicit `false` marks all state as seen so deletes\n    // still flow through as notifies.\n    const notify = (\n      changes: Array<ChangeMessage<T, TKey>> | undefined,\n      status: CollectionStatus = collection.status,\n      explicitLayoutChange = false,\n    ) => {\n      if (this.disposed || this.subscriptions.size === 0) return\n\n      if (this.hasHydrationSeed()) {\n        if (status === `ready`) this.scheduleHydrationHandoff()\n        if (status !== `error`) return\n      }\n\n      if (\n        status === `ready` &&\n        !collection.isLoadingSubset &&\n        !this.liveResultIsAuthoritative &&\n        this.client &&\n        this.queryHash\n      ) {\n        const query = this.client._getLiveQuery(this.queryHash)\n        this.markLiveResultAuthoritative(query?.dehydratedAt)\n      }\n\n      const layoutRevision = this.getCollectionLayoutRevision(collection)\n      let layoutChanged = explicitLayoutChange\n      if (\n        !explicitLayoutChange &&\n        changes !== undefined &&\n        changes.length === 0\n      ) {\n        // Empty ready events predate the explicit layout signal and share its\n        // empty-array payload. Only forward an empty batch when the collection\n        // confirms that a new layout-only publication occurred.\n        if (\n          layoutRevision === undefined ||\n          layoutRevision === this.deliveredLayoutRevision\n        ) {\n          return\n        }\n        layoutChanged = true\n      }\n      if (changes !== undefined && layoutRevision !== undefined) {\n        this.deliveredLayoutRevision = layoutRevision\n      }\n      const captured =\n        changes !== undefined\n          ? this.readEntries(collection)\n          : status === `cleaned-up`\n            ? this.readEntries(collection)\n            : undefined\n      this.emit(\n        changes,\n        undefined,\n        captured?.entries,\n        status,\n        captured?.revision,\n        layoutRevision,\n        layoutChanged,\n      )\n    }\n\n    // Status transitions that carry no change events (loading→ready with no\n    // rows, error, cleaned-up) are part of the canonical publication path:\n    // any status change publishes a synthetic notify so consumers re-read the\n    // snapshot. Unlike onFirstReady, `on` returns a real unsubscribe, so a\n    // detached attachment leaves nothing behind.\n    const statusUnsub = collection.on(`status:change`, ({ status }) =>\n      notify(undefined, status),\n    )\n    const subscribeLayoutChanges = (\n      collection as Collection<T, TKey, any> & {\n        _subscribeLayoutChanges?: (listener: () => void) => () => void\n      }\n    )._subscribeLayoutChanges\n    const layoutUnsub =\n      typeof subscribeLayoutChanges === `function`\n        ? subscribeLayoutChanges.call(collection, () =>\n            notify([], collection.status, true),\n          )\n        : () => {}\n\n    // `subscribeChanges` delivers the initial state synchronously, so a\n    // listener can dispose the observer while the collection subscription is\n    // still being created. Register the release hook up front; if detach()\n    // ran during that replay (collectionUnsub no longer points at our hook),\n    // undo the subscription as soon as the call returns.\n    let subscription: { unsubscribe: () => void } | null = null\n    const clientUnsub =\n      this.client && this.queryHash\n        ? this.client.subscribe((event) => {\n            if (\n              event.type === `liveQueryStreamError` ||\n              event.query.queryHash !== this.queryHash\n            ) {\n              return\n            }\n\n            const previousEntries = this.getVisibleEntries(collection)\n            if (!this.syncHydrationState()) return\n            const nextEntries = this.getVisibleEntries(collection)\n            this.emit(\n              this.wholesale\n                ? undefined\n                : this.diffEntries(previousEntries, nextEntries),\n            )\n          })\n        : () => {}\n    const release = () => {\n      clientUnsub()\n      statusUnsub()\n      layoutUnsub()\n      subscription?.unsubscribe()\n    }\n    this.collectionUnsub = release\n    subscription = collection.subscribeChanges(\n      (changes) => notify(changes as Array<ChangeMessage<T, TKey>>),\n      { includeInitialState: !this.wholesale && !attachedWithHydrationSeed },\n    )\n    this.blockDelivery = false\n    if (this.collectionUnsub !== release) {\n      subscription.unsubscribe()\n      return\n    }\n    if (this.wholesale || attachedWithHydrationSeed) {\n      // Publications raised while subscribeChanges starts sync are part of the\n      // subscribe handshake. Apply their final snapshot state now, but suppress\n      // listener delivery: useSyncExternalStore performs its consistency read\n      // immediately after subscribe returns.\n      this.flushPublications(!this.wholesale)\n      const { entries, revision } = this.readEntries(collection)\n      this.updateCachedEntries(entries, revision)\n    }\n    if (this.hasHydrationSeed()) {\n      if (!this.wholesale) this.seed(Array.from(this.subscriptions)[0]!)\n      if (collection.status === `ready`) this.scheduleHydrationHandoff()\n    }\n  }\n\n  private detach(): void {\n    this.collectionUnsub?.()\n    this.collectionUnsub = null\n    this.attached = false\n    this.blockDelivery = false\n    this.publicationQueue.length = 0\n    this.unregisterClientResource?.()\n    this.unregisterClientResource = undefined\n  }\n\n  private registerClientResource(): void {\n    if (\n      this.unregisterClientResource ||\n      !this.client?._isSsrServerCleanupEnabled() ||\n      !this.collection ||\n      !getBuilderFromConfig(this.collection.config)\n    ) {\n      return\n    }\n\n    this.unregisterClientResource = this.client._registerLiveQueryResource(\n      this,\n      async () => {\n        const collection = this.collection\n        this.dispose()\n        await collection?.cleanup()\n      },\n    )\n  }\n\n  private emit(\n    changes: Array<ChangeMessage<T, TKey>> | undefined,\n    targets = Array.from(this.subscriptions),\n    entries?: Array<[TKey, T]>,\n    status = this.collection?.status ?? `cleaned-up`,\n    collectionRevision?: number,\n    collectionLayoutRevision?: number,\n    layoutChanged = false,\n  ): void {\n    this.publicationQueue.push({\n      changes,\n      targets,\n      entries,\n      status,\n      collectionRevision,\n      collectionLayoutRevision,\n      layoutChanged,\n    })\n    if (this.dispatching || this.blockDelivery) return\n\n    this.flushPublications()\n  }\n\n  private flushPublications(deliver = true): void {\n    if (this.dispatching) return\n\n    this.dispatching = true\n    try {\n      // A dispose() during dispatch empties the queue, ending this loop.\n      while (this.publicationQueue.length > 0) {\n        const publication = this.publicationQueue.shift()!\n        if (publication.entries) {\n          this.updateCachedEntries(\n            publication.entries,\n            publication.collectionRevision,\n          )\n        }\n        if (publication.collectionLayoutRevision !== undefined) {\n          this.cachedCollectionLayoutRevision =\n            publication.collectionLayoutRevision\n        }\n        if (publication.layoutChanged) {\n          this.snapshotDirty = true\n        }\n        if (this.visibleStatus !== publication.status) {\n          this.visibleStatus = publication.status\n          this.snapshotDirty = true\n        }\n        // Targets are captured when the publication is queued: a subscription\n        // removed mid-delivery still receives the in-flight publication, and\n        // one added later does not. Late-subscriber seeds use the same queue.\n        if (deliver) {\n          for (const subRecord of publication.targets) {\n            if (this.disposed) return\n            subRecord.listener(publication.changes)\n          }\n        }\n      }\n    } finally {\n      this.dispatching = false\n    }\n  }\n\n  preload(): Promise<void> {\n    if (this.preloadPromise) return this.preloadPromise\n\n    if (this.client && this.queryHash) {\n      const query = this.client._getLiveQuery(this.queryHash)\n      if (query?.status === `pending`) return query.promise\n      if (query?.status === `success`) return Promise.resolve()\n    }\n\n    this.registerClientResource()\n    this.onPreload?.()\n    const collectionPromise = this.collection?.preload() ?? Promise.resolve()\n    const preloadPromise =\n      this.client?._isSsrStreamingEnabled() && this.queryHash\n        ? this.client._registerLiveQuery(\n            this.queryHash,\n            collectionPromise.then(() => this.dehydrate()),\n          )\n        : collectionPromise\n    this.preloadPromise = preloadPromise\n    const clearPreload = () => {\n      if (this.preloadPromise === preloadPromise) {\n        this.preloadPromise = undefined\n      }\n    }\n    void preloadPromise.then(clearPreload, clearPreload)\n    return preloadPromise\n  }\n\n  dispose(): void {\n    if (this.disposed) return\n    this.disposed = true\n    this.detach()\n    for (const subRecord of this.subscriptions) subRecord.active = false\n    this.subscriptions.clear()\n    this.publicationQueue.length = 0\n  }\n}\n\nexport interface CreateLiveQueryObserverOptions {\n  /**\n   * How subscribers consume the observer:\n   *\n   * - `granular` (default): subscribers apply the delivered `ChangeMessage[]`\n   *   deltas to their own keyed state (Vue/Svelte/Solid). The observer\n   *   subscribes with initial state and seeds late subscribers, so every\n   *   subscriber converges from deltas alone.\n   * - `wholesale`: subscribers treat notifications as a wake-up and re-read\n   *   `getSnapshot()` (React/Angular). The observer subscribes WITHOUT initial\n   *   state, preserving those adapters' loading policy — no snapshot request,\n   *   so no unfiltered `loadSubset` against on-demand collections. Nothing is\n   *   delivered synchronously during `subscribe`, which keeps\n   *   `useSyncExternalStore`-style consumers safe by construction.\n   */\n  mode?: `granular` | `wholesale`\n  /** DbClient cache that owns SSR snapshots for this query identity. */\n  client?: DbClient\n  /** Stable live-query identity used for dehydration and hydration. */\n  queryHash?: string\n  /** Resume framework-deferred query sources before a server preload. */\n  onPreload?: () => void\n}\n\n/**\n * Create a {@link LiveQueryObserver} for a resolved live-query collection, or a\n * disabled observer when `collection` is `null`/`undefined`.\n *\n * @internal This is an unstable contract shared by TanStack DB's official\n * framework adapters. It is exported so the adapter packages can use it, but\n * it is not a public extension point yet: its API may change in any release\n * without a semver major.\n */\nexport function createLiveQueryObserver<\n  T extends object,\n  TKey extends string | number,\n>(\n  collection: Collection<T, TKey, any> | null | undefined,\n  options: CreateLiveQueryObserverOptions = {},\n): LiveQueryObserver<T, TKey> {\n  return new LiveQueryObserverImpl<T, TKey>(\n    collection ?? null,\n    options.mode === `wholesale`,\n    options.client,\n    options.queryHash,\n    options.onPreload,\n  )\n}\n"],"names":["isSingleResultCollection","getLiveQueryStatusFlags","LiveQueryObserverDisposedError","getBuilderFromConfig"],"mappings":"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"}