{"version":3,"file":"collection-config-builder.cjs","sources":["../../../../src/query/live/collection-config-builder.ts"],"sourcesContent":["import { D2, output, serializeValue } from '@tanstack/db-ivm'\nimport { INCLUDES_ROUTING, compileQuery } from '../compiler/index.js'\nimport { createCollection } from '../../collection/index.js'\nimport {\n  MissingAliasInputsError,\n  SetWindowRequiresOrderByError,\n} from '../../errors.js'\nimport { transactionScopedScheduler } from '../../scheduler.js'\nimport { getActiveTransaction } from '../../transactions.js'\nimport { CollectionSubscriber } from './collection-subscriber.js'\nimport { getCollectionBuilder } from './collection-registry.js'\nimport { LIVE_QUERY_INTERNAL } from './internal.js'\nimport {\n  buildQueryFromConfig,\n  extractCollectionAliases,\n  extractCollectionFromSource,\n  extractCollectionsFromQuery,\n} from './utils.js'\nimport type { LiveQueryInternalUtils } from './internal.js'\nimport type {\n  IncludesCompilationResult,\n  WindowOptions,\n} from '../compiler/index.js'\nimport type { SchedulerContextId } from '../../scheduler.js'\nimport type { CollectionSubscription } from '../../collection/subscription.js'\nimport type { RootStreamBuilder } from '@tanstack/db-ivm'\nimport type { OrderByOptimizationInfo } from '../compiler/order-by.js'\nimport type { Collection } from '../../collection/index.js'\nimport type {\n  ChangeMessage,\n  CollectionConfigSingleRowOption,\n  KeyedStream,\n  ResultStream,\n  StringCollationConfig,\n  SyncConfig,\n  UtilsRecord,\n} from '../../types.js'\nimport type { Context, GetResult } from '../builder/types.js'\nimport type {\n  BasicExpression,\n  IncludesMaterialization,\n  PropRef,\n  QueryIR,\n} from '../ir.js'\nimport type { LazyCollectionCallbacks } from '../compiler/joins.js'\nimport type {\n  Changes,\n  FullSyncState,\n  LiveQueryCollectionConfig,\n  SyncState,\n} from './types.js'\nimport type { AllCollectionEvents } from '../../collection/events.js'\n\nexport type LiveQueryCollectionUtils = UtilsRecord & {\n  getRunCount: () => number\n  /**\n   * Sets the offset and limit of an ordered query.\n   * Is a no-op if the query is not ordered.\n   *\n   * @returns `true` if no subset loading was triggered, or `Promise<void>` that resolves when the subset has been loaded\n   */\n  setWindow: (options: WindowOptions) => true | Promise<void>\n  /**\n   * Gets the current window (offset and limit) for an ordered query.\n   *\n   * @returns The current window settings, or `undefined` if the query is not windowed\n   */\n  getWindow: () => { offset: number; limit: number } | undefined\n  [LIVE_QUERY_INTERNAL]: LiveQueryInternalUtils\n}\n\ntype PendingGraphRun = {\n  loadCallbacks: Set<() => boolean>\n}\n\n// Global counter for auto-generated collection IDs\nlet liveQueryCollectionCounter = 0\n\ntype SyncMethods<TResult extends object> = Parameters<\n  SyncConfig<TResult>[`sync`]\n>[0]\n\nexport class CollectionConfigBuilder<\n  TContext extends Context,\n  TResult extends object = GetResult<TContext>,\n> {\n  private readonly id: string\n  readonly query: QueryIR\n  private readonly collections: Record<string, Collection<any, any, any>>\n  private readonly collectionByAlias: Record<string, Collection<any, any, any>>\n  // Populated during compilation with all aliases (including subquery inner aliases)\n  private compiledAliasToCollectionId: Record<string, string> = {}\n\n  // WeakMap to store the keys of the results\n  // so that we can retrieve them in the getKey function\n  private readonly resultKeys = new WeakMap<object, unknown>()\n\n  // WeakMap to store the orderBy index for each result\n  private readonly orderByIndices = new WeakMap<object, string>()\n\n  private readonly compare?: (val1: TResult, val2: TResult) => number\n  private readonly compareOptions?: StringCollationConfig\n\n  private isGraphRunning = false\n  private runCount = 0\n\n  // Current sync session state (set when sync starts, cleared when it stops)\n  // Public for testing purposes (CollectionConfigBuilder is internal, not public API)\n  public currentSyncConfig:\n    | Parameters<SyncConfig<TResult>[`sync`]>[0]\n    | undefined\n  public currentSyncState: FullSyncState | undefined\n\n  // Error state tracking\n  private isInErrorState = false\n\n  // Reference to the live query collection for error state transitions\n  public liveQueryCollection?: Collection<TResult, any, any>\n\n  private windowFn: ((options: WindowOptions) => void) | undefined\n  private currentWindow: WindowOptions | undefined\n\n  private maybeRunGraphFn: (() => void) | undefined\n\n  private readonly aliasDependencies: Record<\n    string,\n    Array<CollectionConfigBuilder<any, any>>\n  > = {}\n\n  private readonly builderDependencies = new Set<\n    CollectionConfigBuilder<any, any>\n  >()\n\n  // Pending graph runs per scheduler context (e.g., per transaction)\n  // The builder manages its own state; the scheduler just orchestrates execution order\n  // Only stores callbacks - if sync ends, pending jobs gracefully no-op\n  private readonly pendingGraphRuns = new Map<\n    SchedulerContextId,\n    PendingGraphRun\n  >()\n\n  // Unsubscribe function for scheduler's onClear listener\n  // Registered when sync starts, unregistered when sync stops\n  // Prevents memory leaks by releasing the scheduler's reference to this builder\n  private unsubscribeFromSchedulerClears?: () => void\n\n  private graphCache: D2 | undefined\n  private inputsCache: Record<string, RootStreamBuilder<unknown>> | undefined\n  private pipelineCache: ResultStream | undefined\n  public sourceWhereClausesCache:\n    | Map<string, BasicExpression<boolean>>\n    | undefined\n  private includesCache: Array<IncludesCompilationResult> | undefined\n\n  // Map of source alias to subscription\n  readonly subscriptions: Record<string, CollectionSubscription> = {}\n  // Map of source aliases to functions that load keys for that lazy source\n  lazySourcesCallbacks: Record<string, LazyCollectionCallbacks> = {}\n  // Set of source aliases that are lazy (don't load initial state)\n  readonly lazySources = new Set<string>()\n  // Set of collection IDs that include an optimizable ORDER BY clause\n  optimizableOrderByCollections: Record<string, OrderByOptimizationInfo> = {}\n\n  constructor(\n    private readonly config: LiveQueryCollectionConfig<TContext, TResult>,\n  ) {\n    // Generate a unique ID if not provided\n    this.id = config.id || `live-query-${++liveQueryCollectionCounter}`\n\n    this.query = buildQueryFromConfig({\n      query: config.query,\n      requireObjectResult: true,\n    })\n    this.collections = extractCollectionsFromQuery(this.query)\n    const collectionAliasesById = extractCollectionAliases(this.query)\n\n    // Build a reverse lookup map from alias to collection instance.\n    // This enables self-join support where the same collection can be referenced\n    // multiple times with different aliases (e.g., { employee: col, manager: col })\n    this.collectionByAlias = {}\n    for (const [collectionId, aliases] of collectionAliasesById.entries()) {\n      const collection = this.collections[collectionId]\n      if (!collection) continue\n      for (const alias of aliases) {\n        this.collectionByAlias[alias] = collection\n      }\n    }\n\n    // Create compare function for ordering if the query has orderBy\n    if (this.query.orderBy && this.query.orderBy.length > 0) {\n      this.compare = createOrderByComparator<TResult>(this.orderByIndices)\n    }\n\n    // Use explicitly provided compareOptions if available, otherwise inherit from FROM collection\n    this.compareOptions =\n      this.config.defaultStringCollation ??\n      extractCollectionFromSource(this.query).compareOptions\n\n    // Compile the base pipeline once initially\n    // This is done to ensure that any errors are thrown immediately and synchronously\n    this.compileBasePipeline()\n  }\n\n  /**\n   * Recursively checks if a query or any of its subqueries contains joins\n   */\n  private hasJoins(query: QueryIR): boolean {\n    // Check if this query has joins\n    if (query.join && query.join.length > 0) {\n      return true\n    }\n\n    // Recursively check subqueries in the from clause\n    if (query.from.type === `queryRef`) {\n      if (this.hasJoins(query.from.query)) {\n        return true\n      }\n    }\n\n    return false\n  }\n\n  getConfig(): CollectionConfigSingleRowOption<TResult> & {\n    utils: LiveQueryCollectionUtils\n  } {\n    return {\n      id: this.id,\n      getKey:\n        this.config.getKey ||\n        ((item: any) =>\n          (this.resultKeys.get(item) ?? item.$key) as string | number),\n      sync: this.getSyncConfig(),\n      compare: this.compare,\n      defaultStringCollation: this.compareOptions,\n      gcTime: this.config.gcTime || 5000, // 5 seconds by default for live queries\n      schema: this.config.schema,\n      onInsert: this.config.onInsert,\n      onUpdate: this.config.onUpdate,\n      onDelete: this.config.onDelete,\n      startSync: this.config.startSync,\n      singleResult: this.query.singleResult,\n      utils: {\n        getRunCount: this.getRunCount.bind(this),\n        setWindow: this.setWindow.bind(this),\n        getWindow: this.getWindow.bind(this),\n        [LIVE_QUERY_INTERNAL]: {\n          getBuilder: () => this,\n          hasCustomGetKey: !!this.config.getKey,\n          hasJoins: this.hasJoins(this.query),\n          hasDistinct: !!this.query.distinct,\n        },\n      },\n    }\n  }\n\n  setWindow(options: WindowOptions): true | Promise<void> {\n    if (!this.windowFn) {\n      throw new SetWindowRequiresOrderByError()\n    }\n\n    this.currentWindow = options\n    this.windowFn(options)\n    this.maybeRunGraphFn?.()\n\n    // Check if loading a subset was triggered\n    if (this.liveQueryCollection?.isLoadingSubset) {\n      // Loading was triggered, return a promise that resolves when it completes\n      return new Promise<void>((resolve) => {\n        const unsubscribe = this.liveQueryCollection!.on(\n          `loadingSubset:change`,\n          (event) => {\n            if (!event.isLoadingSubset) {\n              unsubscribe()\n              resolve()\n            }\n          },\n        )\n      })\n    }\n\n    // No loading was triggered\n    return true\n  }\n\n  getWindow(): { offset: number; limit: number } | undefined {\n    // Only return window if this is a windowed query (has orderBy and windowFn)\n    if (!this.windowFn || !this.currentWindow) {\n      return undefined\n    }\n    return {\n      offset: this.currentWindow.offset ?? 0,\n      limit: this.currentWindow.limit ?? 0,\n    }\n  }\n\n  /**\n   * Resolves a collection alias to its collection ID.\n   *\n   * Uses a two-tier lookup strategy:\n   * 1. First checks compiled aliases (includes subquery inner aliases)\n   * 2. Falls back to declared aliases from the query's from/join clauses\n   *\n   * @param alias - The alias to resolve (e.g., \"employee\", \"manager\")\n   * @returns The collection ID that the alias references\n   * @throws {Error} If the alias is not found in either lookup\n   */\n  getCollectionIdForAlias(alias: string): string {\n    const compiled = this.compiledAliasToCollectionId[alias]\n    if (compiled) {\n      return compiled\n    }\n    const collection = this.collectionByAlias[alias]\n    if (collection) {\n      return collection.id\n    }\n    throw new Error(`Unknown source alias \"${alias}\"`)\n  }\n\n  isLazyAlias(alias: string): boolean {\n    return this.lazySources.has(alias)\n  }\n\n  // The callback function is called after the graph has run.\n  // This gives the callback a chance to load more data if needed,\n  // that's used to optimize orderBy operators that set a limit,\n  // in order to load some more data if we still don't have enough rows after the pipeline has run.\n  // That can happen because even though we load N rows, the pipeline might filter some of these rows out\n  // causing the orderBy operator to receive less than N rows or even no rows at all.\n  // So this callback would notice that it doesn't have enough rows and load some more.\n  // The callback returns a boolean, when it's true it's done loading data and we can mark the collection as ready.\n  maybeRunGraph(callback?: () => boolean) {\n    if (this.isGraphRunning) {\n      // no nested runs of the graph\n      // which is possible if the `callback`\n      // would call `maybeRunGraph` e.g. after it has loaded some more data\n      return\n    }\n\n    // Should only be called when sync is active\n    if (!this.currentSyncConfig || !this.currentSyncState) {\n      throw new Error(\n        `maybeRunGraph called without active sync session. This should not happen.`,\n      )\n    }\n\n    this.isGraphRunning = true\n\n    try {\n      const { begin, commit } = this.currentSyncConfig\n      const syncState = this.currentSyncState\n\n      // Don't run if the live query is in an error state\n      if (this.isInErrorState) {\n        return\n      }\n\n      // Always run the graph if subscribed (eager execution)\n      if (syncState.subscribedToAllCollections) {\n        let callbackCalled = false\n        while (syncState.graph.pendingWork()) {\n          syncState.graph.run()\n          // Flush accumulated changes after each graph step to commit them as one transaction.\n          // This ensures intermediate join states (like null on one side) don't cause\n          // duplicate key errors when the full join result arrives in the same step.\n          syncState.flushPendingChanges?.()\n          callback?.()\n          callbackCalled = true\n        }\n\n        // Ensure the callback runs at least once even when the graph has no pending work.\n        // This handles lazy loading scenarios where setWindow() increases the limit or\n        // an async loadSubset completes and we need to re-check if more data is needed.\n        if (!callbackCalled) {\n          callback?.()\n        }\n\n        // On the initial run, we may need to do an empty commit to ensure that\n        // the collection is initialized\n        if (syncState.messagesCount === 0) {\n          begin()\n          commit()\n        }\n\n        // After graph processing completes, check if we should mark ready.\n        // This is the canonical place to transition to ready state because:\n        // 1. All data has been processed through the graph\n        // 2. All source collections have had a chance to send their initial data\n        // This prevents marking ready before data is processed (fixes isReady=true with empty data)\n        this.updateLiveQueryStatus(this.currentSyncConfig)\n      }\n    } finally {\n      this.isGraphRunning = false\n    }\n  }\n\n  /**\n   * Schedules a graph run with the transaction-scoped scheduler.\n   * Ensures each builder runs at most once per transaction, with automatic dependency tracking\n   * to run parent queries before child queries. Outside a transaction, runs immediately.\n   *\n   * Multiple calls during a transaction are coalesced into a single execution.\n   * Dependencies are auto-discovered from subscribed live queries, or can be overridden.\n   * Load callbacks are combined when entries merge.\n   *\n   * Uses the current sync session's config and syncState from instance properties.\n   *\n   * @param callback - Optional callback to load more data if needed (returns true when done)\n   * @param options - Optional scheduling configuration\n   * @param options.contextId - Transaction ID to group work; defaults to active transaction\n   * @param options.jobId - Unique identifier for this job; defaults to this builder instance\n   * @param options.alias - Source alias that triggered this schedule; adds alias-specific dependencies\n   * @param options.dependencies - Explicit dependency list; overrides auto-discovered dependencies\n   */\n  scheduleGraphRun(\n    callback?: () => boolean,\n    options?: {\n      contextId?: SchedulerContextId\n      jobId?: unknown\n      alias?: string\n      dependencies?: Array<CollectionConfigBuilder<any, any>>\n    },\n  ) {\n    const contextId = options?.contextId ?? getActiveTransaction()?.id\n    // Use the builder instance as the job ID for deduplication. This is memory-safe\n    // because the scheduler's context Map is deleted after flushing (no long-term retention).\n    const jobId = options?.jobId ?? this\n    const dependentBuilders = (() => {\n      if (options?.dependencies) {\n        return options.dependencies\n      }\n\n      const deps = new Set(this.builderDependencies)\n      if (options?.alias) {\n        const aliasDeps = this.aliasDependencies[options.alias]\n        if (aliasDeps) {\n          for (const dep of aliasDeps) {\n            deps.add(dep)\n          }\n        }\n      }\n\n      deps.delete(this)\n\n      return Array.from(deps)\n    })()\n\n    // Ensure dependent builders are actually scheduled in this context so that\n    // dependency edges always point to a real job (or a deduped no-op if already scheduled).\n    if (contextId) {\n      for (const dep of dependentBuilders) {\n        if (typeof dep.scheduleGraphRun === `function`) {\n          dep.scheduleGraphRun(undefined, { contextId })\n        }\n      }\n    }\n\n    // We intentionally scope deduplication to the builder instance. Each instance\n    // owns caches and compiled pipelines, so sharing work across instances that\n    // merely reuse the same string id would execute the wrong builder's graph.\n\n    if (!this.currentSyncConfig || !this.currentSyncState) {\n      throw new Error(\n        `scheduleGraphRun called without active sync session. This should not happen.`,\n      )\n    }\n\n    // Manage our own state - get or create pending callbacks for this context\n    let pending = contextId ? this.pendingGraphRuns.get(contextId) : undefined\n    if (!pending) {\n      pending = {\n        loadCallbacks: new Set(),\n      }\n      if (contextId) {\n        this.pendingGraphRuns.set(contextId, pending)\n      }\n    }\n\n    // Add callback if provided (this is what accumulates between schedules)\n    if (callback) {\n      pending.loadCallbacks.add(callback)\n    }\n\n    // Schedule execution (scheduler just orchestrates order, we manage state)\n    // For immediate execution (no contextId), pass pending directly since it won't be in the map\n    const pendingToPass = contextId ? undefined : pending\n    transactionScopedScheduler.schedule({\n      contextId,\n      jobId,\n      dependencies: dependentBuilders,\n      run: () => this.executeGraphRun(contextId, pendingToPass),\n    })\n  }\n\n  /**\n   * Clears pending graph run state for a specific context.\n   * Called when the scheduler clears a context (e.g., transaction rollback/abort).\n   */\n  clearPendingGraphRun(contextId: SchedulerContextId): void {\n    this.pendingGraphRuns.delete(contextId)\n  }\n\n  /**\n   * Returns true if this builder has a pending graph run for the given context.\n   */\n  hasPendingGraphRun(contextId: SchedulerContextId): boolean {\n    return this.pendingGraphRuns.has(contextId)\n  }\n\n  /**\n   * Executes a pending graph run. Called by the scheduler when dependencies are satisfied.\n   * Clears the pending state BEFORE execution so that any re-schedules during the run\n   * create fresh state and don't interfere with the current execution.\n   * Uses instance sync state - if sync has ended, gracefully returns without executing.\n   *\n   * @param contextId - Optional context ID to look up pending state\n   * @param pendingParam - For immediate execution (no context), pending state is passed directly\n   */\n  private executeGraphRun(\n    contextId?: SchedulerContextId,\n    pendingParam?: PendingGraphRun,\n  ): void {\n    // Get pending state: either from parameter (no context) or from map (with context)\n    // Remove from map BEFORE checking sync state to prevent leaking entries when sync ends\n    // before the transaction flushes (e.g., unsubscribe during in-flight transaction)\n    const pending =\n      pendingParam ??\n      (contextId ? this.pendingGraphRuns.get(contextId) : undefined)\n    if (contextId) {\n      this.pendingGraphRuns.delete(contextId)\n    }\n\n    // If no pending state, nothing to execute (context was cleared)\n    if (!pending) {\n      return\n    }\n\n    // If sync session has ended, don't execute (graph is finalized, subscriptions cleared)\n    if (!this.currentSyncConfig || !this.currentSyncState) {\n      return\n    }\n\n    this.incrementRunCount()\n\n    const combinedLoader = () => {\n      let allDone = true\n      let firstError: unknown\n      pending.loadCallbacks.forEach((loader) => {\n        try {\n          allDone = loader() && allDone\n        } catch (error) {\n          allDone = false\n          firstError ??= error\n        }\n      })\n      if (firstError) {\n        throw firstError\n      }\n      // Returning false signals that callers should schedule another pass.\n      return allDone\n    }\n\n    this.maybeRunGraph(combinedLoader)\n  }\n\n  private getSyncConfig(): SyncConfig<TResult> {\n    return {\n      rowUpdateMode: `full`,\n      sync: this.syncFn.bind(this),\n    }\n  }\n\n  incrementRunCount() {\n    this.runCount++\n  }\n\n  getRunCount() {\n    return this.runCount\n  }\n\n  private syncFn(config: SyncMethods<TResult>) {\n    // Store reference to the live query collection for error state transitions\n    this.liveQueryCollection = config.collection\n    // Store config and syncState as instance properties for the duration of this sync session\n    this.currentSyncConfig = config\n\n    const syncState: SyncState = {\n      messagesCount: 0,\n      subscribedToAllCollections: false,\n      unsubscribeCallbacks: new Set<() => void>(),\n    }\n\n    // Extend the pipeline such that it applies the incoming changes to the collection\n    const fullSyncState = this.extendPipelineWithChangeProcessing(\n      config,\n      syncState,\n    )\n    this.currentSyncState = fullSyncState\n\n    // Listen for scheduler context clears to clean up our pending state\n    // Re-register on each sync start so the listener is active for the sync session's lifetime\n    this.unsubscribeFromSchedulerClears = transactionScopedScheduler.onClear(\n      (contextId) => {\n        this.clearPendingGraphRun(contextId)\n      },\n    )\n\n    // Listen for loadingSubset changes on the live query collection BEFORE subscribing.\n    // This ensures we don't miss the event if subset loading completes synchronously.\n    // When isLoadingSubset becomes false, we may need to mark the collection as ready\n    // (if all source collections are already ready but we were waiting for subset load to complete)\n    const loadingSubsetUnsubscribe = config.collection.on(\n      `loadingSubset:change`,\n      (event) => {\n        if (!event.isLoadingSubset) {\n          // Subset loading finished, check if we can now mark ready\n          this.updateLiveQueryStatus(config)\n        }\n      },\n    )\n    syncState.unsubscribeCallbacks.add(loadingSubsetUnsubscribe)\n\n    const loadSubsetDataCallbacks = this.subscribeToAllCollections(\n      config,\n      fullSyncState,\n    )\n\n    this.maybeRunGraphFn = () => this.scheduleGraphRun(loadSubsetDataCallbacks)\n\n    // Initial run with callback to load more data if needed\n    this.scheduleGraphRun(loadSubsetDataCallbacks)\n\n    // Return the unsubscribe function\n    return () => {\n      syncState.unsubscribeCallbacks.forEach((unsubscribe) => unsubscribe())\n\n      // Clear current sync session state\n      this.currentSyncConfig = undefined\n      this.currentSyncState = undefined\n\n      // Clear all pending graph runs to prevent memory leaks from in-flight transactions\n      // that may flush after the sync session ends\n      this.pendingGraphRuns.clear()\n\n      // Reset caches so a fresh graph/pipeline is compiled on next start\n      // This avoids reusing a finalized D2 graph across GC restarts\n      this.graphCache = undefined\n      this.inputsCache = undefined\n      this.pipelineCache = undefined\n      this.sourceWhereClausesCache = undefined\n      this.includesCache = undefined\n\n      // Reset lazy source alias state\n      this.lazySources.clear()\n      this.optimizableOrderByCollections = {}\n      this.lazySourcesCallbacks = {}\n\n      // Clear subscription references to prevent memory leaks\n      // Note: Individual subscriptions are already unsubscribed via unsubscribeCallbacks\n      Object.keys(this.subscriptions).forEach(\n        (key) => delete this.subscriptions[key],\n      )\n      this.compiledAliasToCollectionId = {}\n\n      // Unregister from scheduler's onClear listener to prevent memory leaks\n      // The scheduler's listener Set would otherwise keep a strong reference to this builder\n      this.unsubscribeFromSchedulerClears?.()\n      this.unsubscribeFromSchedulerClears = undefined\n    }\n  }\n\n  /**\n   * Compiles the query pipeline with all declared aliases.\n   */\n  private compileBasePipeline() {\n    this.graphCache = new D2()\n    this.inputsCache = Object.fromEntries(\n      Object.keys(this.collectionByAlias).map((alias) => [\n        alias,\n        this.graphCache!.newInput<any>(),\n      ]),\n    )\n\n    const compilation = compileQuery(\n      this.query,\n      this.inputsCache as Record<string, KeyedStream>,\n      this.collections,\n      this.subscriptions,\n      this.lazySourcesCallbacks,\n      this.lazySources,\n      this.optimizableOrderByCollections,\n      (windowFn: (options: WindowOptions) => void) => {\n        this.windowFn = windowFn\n      },\n    )\n\n    this.pipelineCache = compilation.pipeline\n    this.sourceWhereClausesCache = compilation.sourceWhereClauses\n    this.compiledAliasToCollectionId = compilation.aliasToCollectionId\n    this.includesCache = compilation.includes\n\n    // Defensive check: verify all compiled aliases have corresponding inputs\n    // This should never happen since all aliases come from user declarations,\n    // but catch it early if the assumption is violated in the future.\n    const missingAliases = Object.keys(this.compiledAliasToCollectionId).filter(\n      (alias) => !Object.hasOwn(this.inputsCache!, alias),\n    )\n    if (missingAliases.length > 0) {\n      throw new MissingAliasInputsError(missingAliases)\n    }\n  }\n\n  private maybeCompileBasePipeline() {\n    if (!this.graphCache || !this.inputsCache || !this.pipelineCache) {\n      this.compileBasePipeline()\n    }\n    return {\n      graph: this.graphCache!,\n      inputs: this.inputsCache!,\n      pipeline: this.pipelineCache!,\n    }\n  }\n\n  private extendPipelineWithChangeProcessing(\n    config: SyncMethods<TResult>,\n    syncState: SyncState,\n  ): FullSyncState {\n    const { begin, commit } = config\n    const { graph, inputs, pipeline } = this.maybeCompileBasePipeline()\n\n    // Accumulator for changes across all output callbacks within a single graph run.\n    // This allows us to batch all changes from intermediate join states into a single\n    // transaction, avoiding duplicate key errors when joins produce multiple outputs\n    // for the same key (e.g., first output with null, then output with joined data).\n    let pendingChanges: Map<unknown, Changes<TResult>> = new Map()\n\n    pipeline.pipe(\n      output((data) => {\n        const messages = data.getInner()\n        syncState.messagesCount += messages.length\n\n        // Accumulate changes from this output callback into the pending changes map.\n        // Changes for the same key are merged (inserts/deletes are added together).\n        messages.reduce(accumulateChanges<TResult>, pendingChanges)\n      }),\n    )\n\n    // Set up includes output routing and child collection lifecycle\n    const includesState = this.setupIncludesOutput(\n      this.includesCache,\n      syncState,\n    )\n\n    // Flush pending changes and reset the accumulator.\n    // Called at the end of each graph run to commit all accumulated changes.\n    syncState.flushPendingChanges = () => {\n      const hasParentChanges = pendingChanges.size > 0\n      const hasChildChanges = hasPendingIncludesChanges(includesState)\n\n      if (!hasParentChanges && !hasChildChanges) {\n        return\n      }\n\n      let changesToApply = pendingChanges\n\n      // When a custom getKey is provided, multiple D2 internal keys may map\n      // to the same user-visible key. Re-accumulate by custom key so that a\n      // retract + insert for the same logical row merges into an UPDATE\n      // instead of a separate DELETE and INSERT that can race.\n      if (this.config.getKey) {\n        const merged = new Map<unknown, Changes<TResult>>()\n        for (const [, changes] of pendingChanges) {\n          const customKey = this.config.getKey(changes.value)\n          const existing = merged.get(customKey)\n          if (existing) {\n            existing.inserts += changes.inserts\n            existing.deletes += changes.deletes\n            // Keep the value from the insert side (the new value)\n            if (changes.inserts > 0) {\n              existing.value = changes.value\n              if (changes.orderByIndex !== undefined) {\n                existing.orderByIndex = changes.orderByIndex\n              }\n            }\n          } else {\n            merged.set(customKey, { ...changes })\n          }\n        }\n        changesToApply = merged\n      }\n\n      // 1. Flush parent changes\n      if (hasParentChanges) {\n        begin()\n        changesToApply.forEach(this.applyChanges.bind(this, config))\n        commit()\n      }\n      pendingChanges = new Map()\n\n      // 2. Process includes: create/dispose child Collections, route child changes\n      flushIncludesState(\n        includesState,\n        config.collection,\n        this.id,\n        hasParentChanges ? changesToApply : null,\n        config,\n      )\n    }\n\n    graph.finalize()\n\n    // Extend the sync state with the graph, inputs, and pipeline\n    syncState.graph = graph\n    syncState.inputs = inputs\n    syncState.pipeline = pipeline\n\n    return syncState as FullSyncState\n  }\n\n  /**\n   * Sets up output callbacks for includes child pipelines.\n   * Each includes entry gets its own output callback that accumulates child changes,\n   * and a child registry that maps correlation key → child Collection.\n   */\n  private setupIncludesOutput(\n    includesEntries: Array<IncludesCompilationResult> | undefined,\n    syncState: SyncState,\n  ): Array<IncludesOutputState> {\n    if (!includesEntries || includesEntries.length === 0) {\n      return []\n    }\n\n    return includesEntries.map((entry) => {\n      const state: IncludesOutputState = {\n        fieldName: entry.fieldName,\n        childCorrelationField: entry.childCorrelationField,\n        hasOrderBy: entry.hasOrderBy,\n        materialization: entry.materialization,\n        scalarField: entry.scalarField,\n        childRegistry: new Map(),\n        pendingChildChanges: new Map(),\n        correlationToParentKeys: new Map(),\n      }\n\n      // Attach output callback on the child pipeline\n      entry.pipeline.pipe(\n        output((data) => {\n          const messages = data.getInner()\n          syncState.messagesCount += messages.length\n\n          for (const [[childKey, tupleData], multiplicity] of messages) {\n            const [childResult, _orderByIndex, correlationKey, parentContext] =\n              tupleData as unknown as [\n                any,\n                string | undefined,\n                unknown,\n                Record<string, any> | null,\n              ]\n\n            const routingKey = computeRoutingKey(correlationKey, parentContext)\n\n            // Accumulate by [routingKey, childKey]\n            let byChild = state.pendingChildChanges.get(routingKey)\n            if (!byChild) {\n              byChild = new Map()\n              state.pendingChildChanges.set(routingKey, byChild)\n            }\n\n            const existing = byChild.get(childKey) || {\n              deletes: 0,\n              inserts: 0,\n              value: childResult,\n              orderByIndex: _orderByIndex,\n            }\n\n            if (multiplicity < 0) {\n              existing.deletes += Math.abs(multiplicity)\n            } else if (multiplicity > 0) {\n              existing.inserts += multiplicity\n              existing.value = childResult\n            }\n\n            byChild.set(childKey, existing)\n          }\n        }),\n      )\n\n      // Set up shared buffers for nested includes (e.g., comments inside issues)\n      if (entry.childCompilationResult.includes) {\n        state.nestedSetups = setupNestedPipelines(\n          entry.childCompilationResult.includes,\n          syncState,\n        )\n        state.nestedRoutingIndex = new Map()\n        state.nestedRoutingReverseIndex = new Map()\n      }\n\n      return state\n    })\n  }\n\n  private applyChanges(\n    config: SyncMethods<TResult>,\n    changes: {\n      deletes: number\n      inserts: number\n      value: TResult\n      orderByIndex: string | undefined\n    },\n    key: unknown,\n  ) {\n    const { write, collection } = config\n    const { deletes, inserts, value, orderByIndex } = changes\n\n    // Store the key of the result so that we can retrieve it in the\n    // getKey function\n    this.resultKeys.set(value, key)\n\n    // Store the orderBy index if it exists\n    if (orderByIndex !== undefined) {\n      this.orderByIndices.set(value, orderByIndex)\n    }\n\n    // Simple singular insert.\n    if (inserts && deletes === 0) {\n      write({\n        value,\n        type: `insert`,\n      })\n    } else if (\n      // Insert & update(s) (updates are a delete & insert)\n      inserts > deletes ||\n      // Just update(s) but the item is already in the collection (so\n      // was inserted previously).\n      (inserts === deletes && collection.has(collection.getKeyFromItem(value)))\n    ) {\n      write({\n        value,\n        type: `update`,\n      })\n      // Only delete is left as an option\n    } else if (deletes > 0) {\n      write({\n        value,\n        type: `delete`,\n      })\n    } else {\n      throw new Error(\n        `Could not apply changes: ${JSON.stringify(changes)}. This should never happen.`,\n      )\n    }\n  }\n\n  /**\n   * Handle status changes from source collections\n   */\n  private handleSourceStatusChange(\n    config: SyncMethods<TResult>,\n    collectionId: string,\n    event: AllCollectionEvents[`status:change`],\n  ) {\n    const { status } = event\n\n    // Handle error state - any source collection in error puts live query in error\n    if (status === `error`) {\n      this.transitionToError(\n        `Source collection '${collectionId}' entered error state`,\n      )\n      return\n    }\n\n    // Handle manual cleanup - this should not happen due to GC prevention,\n    // but could happen if user manually calls cleanup()\n    if (status === `cleaned-up`) {\n      this.transitionToError(\n        `Source collection '${collectionId}' was manually cleaned up while live query '${this.id}' depends on it. ` +\n          `Live queries prevent automatic GC, so this was likely a manual cleanup() call.`,\n      )\n      return\n    }\n\n    // Update ready status based on all source collections\n    this.updateLiveQueryStatus(config)\n  }\n\n  /**\n   * Update the live query status based on source collection statuses\n   */\n  private updateLiveQueryStatus(config: SyncMethods<TResult>) {\n    const { markReady } = config\n\n    // Don't update status if already in error\n    if (this.isInErrorState) {\n      return\n    }\n\n    const subscribedToAll = this.currentSyncState?.subscribedToAllCollections\n    const allReady = this.allCollectionsReady()\n    const isLoading = this.liveQueryCollection?.isLoadingSubset\n    // Mark ready when:\n    // 1. All subscriptions are set up (subscribedToAllCollections)\n    // 2. All source collections are ready\n    // 3. The live query collection is not loading subset data\n    // This prevents marking the live query ready before its data is processed\n    // (fixes issue where useLiveQuery returns isReady=true with empty data)\n    if (subscribedToAll && allReady && !isLoading) {\n      markReady()\n    }\n  }\n\n  /**\n   * Transition the live query to error state\n   */\n  private transitionToError(message: string) {\n    this.isInErrorState = true\n\n    // Log error to console for debugging\n    console.error(`[Live Query Error] ${message}`)\n\n    // Transition live query collection to error state\n    this.liveQueryCollection?._lifecycle.setStatus(`error`)\n  }\n\n  private allCollectionsReady() {\n    return Object.values(this.collections).every((collection) =>\n      collection.isReady(),\n    )\n  }\n\n  /**\n   * Creates per-alias subscriptions enabling self-join support.\n   * Each alias gets its own subscription with independent filters, even for the same collection.\n   * Example: `{ employee: col, manager: col }` creates two separate subscriptions.\n   */\n  private subscribeToAllCollections(\n    config: SyncMethods<TResult>,\n    syncState: FullSyncState,\n  ) {\n    // Use compiled aliases as the source of truth - these include all aliases from the query\n    // including those from subqueries, which may not be in collectionByAlias\n    const compiledAliases = Object.entries(this.compiledAliasToCollectionId)\n    if (compiledAliases.length === 0) {\n      throw new Error(\n        `Compiler returned no alias metadata for query '${this.id}'. This should not happen; please report.`,\n      )\n    }\n\n    // Create a separate subscription for each alias, enabling self-joins where the same\n    // collection can be used multiple times with different filters and subscriptions\n    const loaders = compiledAliases.map(([alias, collectionId]) => {\n      // Try collectionByAlias first (for declared aliases), fall back to collections (for subquery aliases)\n      const collection =\n        this.collectionByAlias[alias] ?? this.collections[collectionId]!\n\n      const dependencyBuilder = getCollectionBuilder(collection)\n      if (dependencyBuilder && dependencyBuilder !== this) {\n        this.aliasDependencies[alias] = [dependencyBuilder]\n        this.builderDependencies.add(dependencyBuilder)\n      } else {\n        this.aliasDependencies[alias] = []\n      }\n\n      // CollectionSubscriber handles the actual subscription to the source collection\n      // and feeds data into the D2 graph inputs for this specific alias\n      const collectionSubscriber = new CollectionSubscriber(\n        alias,\n        collectionId,\n        collection,\n        this,\n      )\n\n      // Subscribe to status changes for status flow\n      const statusUnsubscribe = collection.on(`status:change`, (event) => {\n        this.handleSourceStatusChange(config, collectionId, event)\n      })\n      syncState.unsubscribeCallbacks.add(statusUnsubscribe)\n\n      const subscription = collectionSubscriber.subscribe()\n      // Store subscription by alias (not collection ID) to support lazy loading\n      // which needs to look up subscriptions by their query alias\n      this.subscriptions[alias] = subscription\n\n      // Create a callback for loading more data if needed (used by OrderBy optimization)\n      const loadMore = collectionSubscriber.loadMoreIfNeeded.bind(\n        collectionSubscriber,\n        subscription,\n      )\n\n      return loadMore\n    })\n\n    // Combine all loaders into a single callback that initiates loading more data\n    // from any source that needs it. Returns true once all loaders have been called,\n    // but the actual async loading may still be in progress.\n    const loadSubsetDataCallbacks = () => {\n      loaders.map((loader) => loader())\n      return true\n    }\n\n    // Mark as subscribed so the graph can start running\n    // (graph only runs when all collections are subscribed)\n    syncState.subscribedToAllCollections = true\n\n    // Note: We intentionally don't call updateLiveQueryStatus() here.\n    // The graph hasn't run yet, so marking ready would be premature.\n    // The canonical place to mark ready is after the graph processes data\n    // in maybeRunGraph(), which ensures data has been processed first.\n\n    return loadSubsetDataCallbacks\n  }\n}\n\nfunction createOrderByComparator<T extends object>(\n  orderByIndices: WeakMap<object, string>,\n) {\n  return (val1: T, val2: T): number => {\n    // Use the orderBy index stored in the WeakMap\n    const index1 = orderByIndices.get(val1)\n    const index2 = orderByIndices.get(val2)\n\n    // Compare fractional indices lexicographically\n    if (index1 && index2) {\n      if (index1 < index2) {\n        return -1\n      } else if (index1 > index2) {\n        return 1\n      } else {\n        return 0\n      }\n    }\n\n    // Fallback to no ordering if indices are missing\n    return 0\n  }\n}\n\n/**\n * Shared buffer setup for a single nested includes level.\n * Pipeline output writes into the buffer; during flush the buffer is drained\n * into per-entry states via the routing index.\n */\ntype NestedIncludesSetup = {\n  compilationResult: IncludesCompilationResult\n  /** Shared buffer: nestedCorrelationKey → Map<childKey, Changes> */\n  buffer: Map<unknown, Map<unknown, Changes<any>>>\n  /** For 3+ levels of nesting */\n  nestedSetups?: Array<NestedIncludesSetup>\n}\n\n/**\n * State tracked per includes entry for output routing and child lifecycle\n */\ntype IncludesOutputState = {\n  fieldName: string\n  childCorrelationField: PropRef\n  /** Whether the child query has an ORDER BY clause */\n  hasOrderBy: boolean\n  /** How the child result is materialized on the parent row */\n  materialization: IncludesMaterialization\n  /** Internal field used to unwrap scalar child selects */\n  scalarField?: string\n  /** Maps correlation key value → child Collection entry */\n  childRegistry: Map<unknown, ChildCollectionEntry>\n  /** Pending child changes: correlationKey → Map<childKey, Changes> */\n  pendingChildChanges: Map<unknown, Map<unknown, Changes<any>>>\n  /** Reverse index: correlation key → Set of parent collection keys */\n  correlationToParentKeys: Map<unknown, Set<unknown>>\n  /** Shared nested pipeline setups (one per nested includes level) */\n  nestedSetups?: Array<NestedIncludesSetup>\n  /** nestedCorrelationKey → parentCorrelationKey */\n  nestedRoutingIndex?: Map<unknown, unknown>\n  /** parentCorrelationKey → Set<nestedCorrelationKeys> */\n  nestedRoutingReverseIndex?: Map<unknown, Set<unknown>>\n}\n\ntype ChildCollectionEntry = {\n  collection: Collection<any, any, any>\n  syncMethods: SyncMethods<any> | null\n  resultKeys: WeakMap<object, unknown>\n  orderByIndices: WeakMap<object, string> | null\n  /** Per-entry nested includes states (one per nested includes level) */\n  includesStates?: Array<IncludesOutputState>\n}\n\nfunction materializesInline(state: IncludesOutputState): boolean {\n  return state.materialization !== `collection`\n}\n\nfunction materializeIncludedValue(\n  state: IncludesOutputState,\n  entry: ChildCollectionEntry | undefined,\n): unknown {\n  if (!entry) {\n    if (state.materialization === `array`) {\n      return []\n    }\n    if (state.materialization === `concat`) {\n      return ``\n    }\n    return undefined\n  }\n\n  if (state.materialization === `collection`) {\n    return entry.collection\n  }\n\n  const rows = [...entry.collection.toArray]\n  const values = state.scalarField\n    ? rows.map((row) => row?.[state.scalarField!])\n    : rows\n\n  if (state.materialization === `array`) {\n    return values\n  }\n\n  return values.map((value) => String(value ?? ``)).join(``)\n}\n\n/**\n * Sets up shared buffers for nested includes pipelines.\n * Instead of writing directly into a single shared IncludesOutputState,\n * each nested pipeline writes into a buffer that is later drained per-entry.\n */\nfunction setupNestedPipelines(\n  includes: Array<IncludesCompilationResult>,\n  syncState: SyncState,\n): Array<NestedIncludesSetup> {\n  return includes.map((entry) => {\n    const buffer: Map<unknown, Map<unknown, Changes<any>>> = new Map()\n\n    // Attach output callback that writes into the shared buffer\n    entry.pipeline.pipe(\n      output((data) => {\n        const messages = data.getInner()\n        syncState.messagesCount += messages.length\n\n        for (const [[childKey, tupleData], multiplicity] of messages) {\n          const [childResult, _orderByIndex, correlationKey, parentContext] =\n            tupleData as unknown as [\n              any,\n              string | undefined,\n              unknown,\n              Record<string, any> | null,\n            ]\n\n          const routingKey = computeRoutingKey(correlationKey, parentContext)\n\n          let byChild = buffer.get(routingKey)\n          if (!byChild) {\n            byChild = new Map()\n            buffer.set(routingKey, byChild)\n          }\n\n          const existing = byChild.get(childKey) || {\n            deletes: 0,\n            inserts: 0,\n            value: childResult,\n            orderByIndex: _orderByIndex,\n          }\n\n          if (multiplicity < 0) {\n            existing.deletes += Math.abs(multiplicity)\n          } else if (multiplicity > 0) {\n            existing.inserts += multiplicity\n            existing.value = childResult\n          }\n\n          byChild.set(childKey, existing)\n        }\n      }),\n    )\n\n    const setup: NestedIncludesSetup = {\n      compilationResult: entry,\n      buffer,\n    }\n\n    // Recursively set up deeper levels\n    if (entry.childCompilationResult.includes) {\n      setup.nestedSetups = setupNestedPipelines(\n        entry.childCompilationResult.includes,\n        syncState,\n      )\n    }\n\n    return setup\n  })\n}\n\n/**\n * Creates fresh per-entry IncludesOutputState array from NestedIncludesSetup array.\n * Each entry gets its own isolated state for nested includes.\n */\nfunction createPerEntryIncludesStates(\n  setups: Array<NestedIncludesSetup>,\n): Array<IncludesOutputState> {\n  return setups.map((setup) => {\n    const state: IncludesOutputState = {\n      fieldName: setup.compilationResult.fieldName,\n      childCorrelationField: setup.compilationResult.childCorrelationField,\n      hasOrderBy: setup.compilationResult.hasOrderBy,\n      materialization: setup.compilationResult.materialization,\n      scalarField: setup.compilationResult.scalarField,\n      childRegistry: new Map(),\n      pendingChildChanges: new Map(),\n      correlationToParentKeys: new Map(),\n    }\n\n    if (setup.nestedSetups) {\n      state.nestedSetups = setup.nestedSetups\n      state.nestedRoutingIndex = new Map()\n      state.nestedRoutingReverseIndex = new Map()\n    }\n\n    return state\n  })\n}\n\n/**\n * Drains shared buffers into per-entry states using the routing index.\n * Returns the set of parent correlation keys that had changes routed to them.\n */\nfunction drainNestedBuffers(state: IncludesOutputState): Set<unknown> {\n  const dirtyCorrelationKeys = new Set<unknown>()\n\n  if (!state.nestedSetups) return dirtyCorrelationKeys\n\n  for (let i = 0; i < state.nestedSetups.length; i++) {\n    const setup = state.nestedSetups[i]!\n    const toDelete: Array<unknown> = []\n\n    for (const [nestedCorrelationKey, childChanges] of setup.buffer) {\n      const parentCorrelationKey =\n        state.nestedRoutingIndex!.get(nestedCorrelationKey)\n      if (parentCorrelationKey === undefined) {\n        // Unroutable — parent not yet seen; keep in buffer\n        continue\n      }\n\n      const entry = state.childRegistry.get(parentCorrelationKey)\n      if (!entry || !entry.includesStates) {\n        continue\n      }\n\n      // Route changes into this entry's per-entry state at position i\n      const entryState = entry.includesStates[i]!\n      for (const [childKey, changes] of childChanges) {\n        let byChild = entryState.pendingChildChanges.get(nestedCorrelationKey)\n        if (!byChild) {\n          byChild = new Map()\n          entryState.pendingChildChanges.set(nestedCorrelationKey, byChild)\n        }\n        const existing = byChild.get(childKey)\n        if (existing) {\n          existing.inserts += changes.inserts\n          existing.deletes += changes.deletes\n          if (changes.inserts > 0) {\n            existing.value = changes.value\n            if (changes.orderByIndex !== undefined) {\n              existing.orderByIndex = changes.orderByIndex\n            }\n          }\n        } else {\n          byChild.set(childKey, { ...changes })\n        }\n      }\n\n      dirtyCorrelationKeys.add(parentCorrelationKey)\n      toDelete.push(nestedCorrelationKey)\n    }\n\n    for (const key of toDelete) {\n      setup.buffer.delete(key)\n    }\n  }\n\n  return dirtyCorrelationKeys\n}\n\n/**\n * Updates the routing index after processing child changes.\n * Maps nested correlation keys to parent correlation keys so that\n * grandchild changes can be routed to the correct per-entry state.\n */\nfunction updateRoutingIndex(\n  state: IncludesOutputState,\n  correlationKey: unknown,\n  childChanges: Map<unknown, Changes<any>>,\n): void {\n  if (!state.nestedSetups) return\n\n  for (const setup of state.nestedSetups) {\n    for (const [, change] of childChanges) {\n      if (change.inserts > 0) {\n        // Read the nested routing key from the INCLUDES_ROUTING stamp.\n        // Must use the composite routing key (not raw correlationKey) to match\n        // how nested buffers are keyed by computeRoutingKey.\n        const nestedRouting =\n          change.value[INCLUDES_ROUTING]?.[setup.compilationResult.fieldName]\n        const nestedCorrelationKey = nestedRouting?.correlationKey\n        const nestedParentContext = nestedRouting?.parentContext ?? null\n        const nestedRoutingKey = computeRoutingKey(\n          nestedCorrelationKey,\n          nestedParentContext,\n        )\n\n        if (nestedCorrelationKey != null) {\n          state.nestedRoutingIndex!.set(nestedRoutingKey, correlationKey)\n          let reverseSet = state.nestedRoutingReverseIndex!.get(correlationKey)\n          if (!reverseSet) {\n            reverseSet = new Set()\n            state.nestedRoutingReverseIndex!.set(correlationKey, reverseSet)\n          }\n          reverseSet.add(nestedRoutingKey)\n        }\n      } else if (change.deletes > 0 && change.inserts === 0) {\n        // Remove from routing index\n        const nestedRouting2 =\n          change.value[INCLUDES_ROUTING]?.[setup.compilationResult.fieldName]\n        const nestedCorrelationKey = nestedRouting2?.correlationKey\n        const nestedParentContext2 = nestedRouting2?.parentContext ?? null\n        const nestedRoutingKey = computeRoutingKey(\n          nestedCorrelationKey,\n          nestedParentContext2,\n        )\n\n        if (nestedCorrelationKey != null) {\n          state.nestedRoutingIndex!.delete(nestedRoutingKey)\n          const reverseSet =\n            state.nestedRoutingReverseIndex!.get(correlationKey)\n          if (reverseSet) {\n            reverseSet.delete(nestedRoutingKey)\n            if (reverseSet.size === 0) {\n              state.nestedRoutingReverseIndex!.delete(correlationKey)\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\n/**\n * Cleans routing index entries when a parent is deleted.\n * Uses the reverse index to find and remove all nested routing entries.\n */\nfunction cleanRoutingIndexOnDelete(\n  state: IncludesOutputState,\n  correlationKey: unknown,\n): void {\n  if (!state.nestedRoutingReverseIndex) return\n\n  const nestedKeys = state.nestedRoutingReverseIndex.get(correlationKey)\n  if (nestedKeys) {\n    for (const nestedKey of nestedKeys) {\n      state.nestedRoutingIndex!.delete(nestedKey)\n    }\n    state.nestedRoutingReverseIndex.delete(correlationKey)\n  }\n}\n\n/**\n * Recursively checks whether any nested buffer has pending changes.\n */\nfunction hasNestedBufferChanges(setups: Array<NestedIncludesSetup>): boolean {\n  for (const setup of setups) {\n    if (setup.buffer.size > 0) return true\n    if (setup.nestedSetups && hasNestedBufferChanges(setup.nestedSetups))\n      return true\n  }\n  return false\n}\n\n/**\n * Computes a composite routing key from correlation key and parent context.\n * When parentContext is null (no parent filters), returns the raw correlationKey\n * for zero behavioral change on existing queries.\n */\nfunction computeRoutingKey(\n  correlationKey: unknown,\n  parentContext: Record<string, any> | null,\n): unknown {\n  if (parentContext == null) return correlationKey\n  return JSON.stringify([correlationKey, parentContext])\n}\n\n/**\n * Creates a child Collection entry for includes subqueries.\n * The child Collection is a full-fledged Collection instance that starts syncing immediately.\n */\nfunction createChildCollectionEntry(\n  parentId: string,\n  fieldName: string,\n  correlationKey: unknown,\n  hasOrderBy: boolean,\n  nestedSetups?: Array<NestedIncludesSetup>,\n): ChildCollectionEntry {\n  const resultKeys = new WeakMap<object, unknown>()\n  const orderByIndices = hasOrderBy ? new WeakMap<object, string>() : null\n  let syncMethods: SyncMethods<any> | null = null\n\n  const compare = orderByIndices\n    ? createOrderByComparator(orderByIndices)\n    : undefined\n\n  const collection = createCollection<any, string | number>({\n    id: `__child-collection:${parentId}-${fieldName}-${serializeValue(correlationKey)}`,\n    getKey: (item: any) => resultKeys.get(item) as string | number,\n    compare,\n    sync: {\n      rowUpdateMode: `full`,\n      sync: (methods) => {\n        syncMethods = methods\n        return () => {\n          syncMethods = null\n        }\n      },\n    },\n    startSync: true,\n    gcTime: 0,\n  })\n\n  const entry: ChildCollectionEntry = {\n    collection,\n    get syncMethods() {\n      return syncMethods\n    },\n    resultKeys,\n    orderByIndices,\n  }\n\n  if (nestedSetups) {\n    entry.includesStates = createPerEntryIncludesStates(nestedSetups)\n  }\n\n  return entry\n}\n\n/**\n * Flushes includes state using a bottom-up per-entry approach.\n * Five phases ensure correct ordering:\n *   1. Parent INSERTs — create child entries with per-entry nested states\n *   2. Child changes — apply to child Collections, update routing index\n *   3. Drain nested buffers — route buffered grandchild changes to per-entry states\n *   4. Flush per-entry states — recursively flush nested includes on each entry\n *   5. Parent DELETEs — clean up child entries and routing index\n */\nfunction flushIncludesState(\n  includesState: Array<IncludesOutputState>,\n  parentCollection: Collection<any, any, any>,\n  parentId: string,\n  parentChanges: Map<unknown, Changes<any>> | null,\n  parentSyncMethods: SyncMethods<any> | null,\n): void {\n  for (const state of includesState) {\n    // Phase 1: Parent INSERTs — ensure a child Collection exists for every parent\n    if (parentChanges) {\n      for (const [parentKey, changes] of parentChanges) {\n        if (changes.inserts > 0) {\n          const parentResult = changes.value\n          // Extract routing info from INCLUDES_ROUTING symbol (set by compiler)\n          const routing = parentResult[INCLUDES_ROUTING]?.[state.fieldName]\n          const correlationKey = routing?.correlationKey\n          const parentContext = routing?.parentContext ?? null\n          const routingKey = computeRoutingKey(correlationKey, parentContext)\n\n          if (correlationKey != null) {\n            // Ensure child Collection exists for this routing key\n            if (!state.childRegistry.has(routingKey)) {\n              const entry = createChildCollectionEntry(\n                parentId,\n                state.fieldName,\n                routingKey,\n                state.hasOrderBy,\n                state.nestedSetups,\n              )\n              state.childRegistry.set(routingKey, entry)\n            }\n            // Update reverse index: routing key → parent keys\n            let parentKeys = state.correlationToParentKeys.get(routingKey)\n            if (!parentKeys) {\n              parentKeys = new Set()\n              state.correlationToParentKeys.set(routingKey, parentKeys)\n            }\n            parentKeys.add(parentKey)\n\n            const childValue = materializeIncludedValue(\n              state,\n              state.childRegistry.get(routingKey),\n            )\n            parentResult[state.fieldName] = childValue\n\n            // Parent rows may already be materialized in the live collection by the\n            // time includes state is flushed, so update the stored row as well.\n            const storedParent = parentCollection.get(parentKey as any)\n            if (storedParent && storedParent !== parentResult) {\n              storedParent[state.fieldName] = childValue\n            }\n          }\n        }\n      }\n    }\n\n    // Track affected correlation keys for inline materializations before clearing child changes.\n    const affectedCorrelationKeys = materializesInline(state)\n      ? new Set<unknown>(state.pendingChildChanges.keys())\n      : null\n\n    // Phase 2: Child changes — apply to child Collections\n    // Track which entries had child changes and capture their childChanges maps\n    const entriesWithChildChanges = new Map<\n      unknown,\n      { entry: ChildCollectionEntry; childChanges: Map<unknown, Changes<any>> }\n    >()\n    if (state.pendingChildChanges.size > 0) {\n      for (const [correlationKey, childChanges] of state.pendingChildChanges) {\n        // Ensure child Collection exists for this correlation key\n        let entry = state.childRegistry.get(correlationKey)\n        if (!entry) {\n          entry = createChildCollectionEntry(\n            parentId,\n            state.fieldName,\n            correlationKey,\n            state.hasOrderBy,\n            state.nestedSetups,\n          )\n          state.childRegistry.set(correlationKey, entry)\n        }\n\n        if (state.materialization === `collection`) {\n          attachChildCollectionToParent(\n            parentCollection,\n            state.fieldName,\n            correlationKey,\n            state.correlationToParentKeys,\n            entry.collection,\n          )\n        }\n\n        // Apply child changes to the child Collection\n        if (entry.syncMethods) {\n          entry.syncMethods.begin()\n          for (const [childKey, change] of childChanges) {\n            entry.resultKeys.set(change.value, childKey)\n            if (entry.orderByIndices && change.orderByIndex !== undefined) {\n              entry.orderByIndices.set(change.value, change.orderByIndex)\n            }\n            if (change.inserts > 0 && change.deletes === 0) {\n              entry.syncMethods.write({ value: change.value, type: `insert` })\n            } else if (\n              change.inserts > change.deletes ||\n              (change.inserts === change.deletes &&\n                entry.syncMethods.collection.has(\n                  entry.syncMethods.collection.getKeyFromItem(change.value),\n                ))\n            ) {\n              entry.syncMethods.write({ value: change.value, type: `update` })\n            } else if (change.deletes > 0) {\n              entry.syncMethods.write({ value: change.value, type: `delete` })\n            }\n          }\n          entry.syncMethods.commit()\n        }\n\n        // Update routing index for nested includes\n        updateRoutingIndex(state, correlationKey, childChanges)\n\n        entriesWithChildChanges.set(correlationKey, { entry, childChanges })\n      }\n      state.pendingChildChanges.clear()\n    }\n\n    // Phase 3: Drain nested buffers — route buffered grandchild changes to per-entry states\n    const dirtyFromBuffers = drainNestedBuffers(state)\n\n    // Phase 4: Flush per-entry states\n    // First: entries that had child changes in Phase 2\n    for (const [, { entry, childChanges }] of entriesWithChildChanges) {\n      if (entry.includesStates) {\n        flushIncludesState(\n          entry.includesStates,\n          entry.collection,\n          entry.collection.id,\n          childChanges,\n          entry.syncMethods,\n        )\n      }\n    }\n    // Then: entries that only had buffer-routed changes (no child changes at this level)\n    for (const correlationKey of dirtyFromBuffers) {\n      if (entriesWithChildChanges.has(correlationKey)) continue\n      const entry = state.childRegistry.get(correlationKey)\n      if (entry?.includesStates) {\n        flushIncludesState(\n          entry.includesStates,\n          entry.collection,\n          entry.collection.id,\n          null,\n          entry.syncMethods,\n        )\n      }\n    }\n    // Finally: entries with deep nested buffer changes (grandchild-or-deeper buffers\n    // have pending data, but neither this level nor the immediate child level changed).\n    // Without this pass, changes at depth 3+ are stranded because drainNestedBuffers\n    // only drains one level and Phase 4 only flushes entries dirty from Phase 2/3.\n    const deepBufferDirty = new Set<unknown>()\n    if (state.nestedSetups) {\n      for (const [correlationKey, entry] of state.childRegistry) {\n        if (entriesWithChildChanges.has(correlationKey)) continue\n        if (dirtyFromBuffers.has(correlationKey)) continue\n        if (\n          entry.includesStates &&\n          hasPendingIncludesChanges(entry.includesStates)\n        ) {\n          flushIncludesState(\n            entry.includesStates,\n            entry.collection,\n            entry.collection.id,\n            null,\n            entry.syncMethods,\n          )\n          deepBufferDirty.add(correlationKey)\n        }\n      }\n    }\n\n    // For inline materializations: re-emit affected parents with updated snapshots.\n    // We mutate items in-place (so collection.get() reflects changes immediately)\n    // and emit UPDATE events directly. We bypass the sync methods because\n    // commitPendingTransactions compares previous vs new visible state using\n    // deepEquals, but in-place mutation means both sides reference the same\n    // object, so the comparison always returns true and suppresses the event.\n    const inlineReEmitKeys = materializesInline(state)\n      ? new Set([\n          ...(affectedCorrelationKeys || []),\n          ...dirtyFromBuffers,\n          ...deepBufferDirty,\n        ])\n      : null\n    if (parentSyncMethods && inlineReEmitKeys && inlineReEmitKeys.size > 0) {\n      const events: Array<ChangeMessage<any>> = []\n      for (const correlationKey of inlineReEmitKeys) {\n        const parentKeys = state.correlationToParentKeys.get(correlationKey)\n        if (!parentKeys) continue\n        const entry = state.childRegistry.get(correlationKey)\n        for (const parentKey of parentKeys) {\n          const item = parentCollection.get(parentKey as any)\n          if (item) {\n            const key = parentSyncMethods.collection.getKeyFromItem(item)\n            // Capture previous value before in-place mutation\n            const previousValue = { ...item }\n            item[state.fieldName] = materializeIncludedValue(state, entry)\n            events.push({\n              type: `update`,\n              key,\n              value: item,\n              previousValue,\n            })\n          }\n        }\n      }\n      if (events.length > 0) {\n        // Emit directly — the in-place mutation already updated the data in\n        // syncedData, so we only need to notify subscribers.\n        const changesManager = (parentCollection as any)._changes as {\n          emitEvents: (\n            changes: Array<ChangeMessage<any>>,\n            forceEmit?: boolean,\n          ) => void\n        }\n        changesManager.emitEvents(events, true)\n      }\n    }\n\n    // Phase 5: Parent DELETEs — dispose child Collections and clean up\n    if (parentChanges) {\n      for (const [parentKey, changes] of parentChanges) {\n        if (changes.deletes > 0 && changes.inserts === 0) {\n          const routing = changes.value[INCLUDES_ROUTING]?.[state.fieldName]\n          const correlationKey = routing?.correlationKey\n          const parentContext = routing?.parentContext ?? null\n          const routingKey = computeRoutingKey(correlationKey, parentContext)\n          if (correlationKey != null) {\n            // Clean up reverse index first, only delete child collection\n            // when the last parent referencing it is removed\n            const parentKeys = state.correlationToParentKeys.get(routingKey)\n            if (parentKeys) {\n              parentKeys.delete(parentKey)\n              if (parentKeys.size === 0) {\n                cleanRoutingIndexOnDelete(state, routingKey)\n                state.childRegistry.delete(routingKey)\n                state.correlationToParentKeys.delete(routingKey)\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  // Clean up the internal routing stamp from parent/child results\n  if (parentChanges) {\n    for (const [, changes] of parentChanges) {\n      delete changes.value[INCLUDES_ROUTING]\n    }\n  }\n}\n\n/**\n * Checks whether any includes state has pending changes that need to be flushed.\n * Checks direct pending child changes and shared nested buffers.\n */\nfunction hasPendingIncludesChanges(\n  states: Array<IncludesOutputState>,\n): boolean {\n  for (const state of states) {\n    if (state.pendingChildChanges.size > 0) return true\n    if (state.nestedSetups && hasNestedBufferChanges(state.nestedSetups))\n      return true\n  }\n  return false\n}\n\n/**\n * Attaches a child Collection to parent rows that match a given correlation key.\n * Uses the reverse index to look up parent keys directly instead of scanning.\n */\nfunction attachChildCollectionToParent(\n  parentCollection: Collection<any, any, any>,\n  fieldName: string,\n  correlationKey: unknown,\n  correlationToParentKeys: Map<unknown, Set<unknown>>,\n  childCollection: Collection<any, any, any>,\n): void {\n  const parentKeys = correlationToParentKeys.get(correlationKey)\n  if (!parentKeys) return\n\n  for (const parentKey of parentKeys) {\n    const item = parentCollection.get(parentKey as any)\n    if (item) {\n      item[fieldName] = childCollection\n    }\n  }\n}\n\nfunction accumulateChanges<T>(\n  acc: Map<unknown, Changes<T>>,\n  [[key, tupleData], multiplicity]: [\n    [unknown, [any, string | undefined]],\n    number,\n  ],\n) {\n  // All queries now consistently return [value, orderByIndex] format\n  // where orderByIndex is undefined for queries without ORDER BY\n  const [value, orderByIndex] = tupleData as [T, string | undefined]\n\n  const changes = acc.get(key) || {\n    deletes: 0,\n    inserts: 0,\n    value,\n    orderByIndex,\n  }\n  if (multiplicity < 0) {\n    changes.deletes += Math.abs(multiplicity)\n  } else if (multiplicity > 0) {\n    changes.inserts += multiplicity\n    // Update value to the latest version for this key\n    changes.value = value\n    if (orderByIndex !== undefined) {\n      changes.orderByIndex = orderByIndex\n    }\n  }\n  acc.set(key, changes)\n  return acc\n}\n"],"names":["buildQueryFromConfig","extractCollectionsFromQuery","extractCollectionAliases","extractCollectionFromSource","LIVE_QUERY_INTERNAL","SetWindowRequiresOrderByError","getActiveTransaction","transactionScopedScheduler","D2","compileQuery","MissingAliasInputsError","output","getCollectionBuilder","collectionSubscriber","CollectionSubscriber","INCLUDES_ROUTING","createCollection","serializeValue"],"mappings":"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"}