import { LIVE_QUERY_INTERNAL, LiveQueryInternalUtils } from './internal.js';
import { WindowOptions } from '../compiler/index.js';
import { SchedulerContextId } from '../../scheduler.js';
import { CollectionSubscription } from '../../collection/subscription.js';
import { OrderByOptimizationInfo } from '../compiler/order-by.js';
import { Collection } from '../../collection/index.js';
import { HealthSource } from '../../collection/health-tree.js';
import { CollectionConfigSingleRowOption, CollectionDependent, StringCollationConfig, SyncConfig, UtilsRecord } from '../../types.js';
import { Context, GetResult } from '../builder/types.js';
import { BasicExpression, QueryIR } from '../ir.js';
import { LazyCollectionCallbacks } from '../compiler/joins.js';
import { FullSyncState, LiveQueryCollectionConfig } from './types.js';
export type LiveQueryCollectionUtils = UtilsRecord & {
    /** Most recent subset-load failure observed by this live query. */
    readonly lastSubsetError: unknown | undefined;
    /**
     * Sets the offset and limit of the query's window, its ordered view. A
     * windowed query has an `orderBy`. A `findOne` keeps its compiled limit (1,
     * or 0 for `.limit(0).findOne()`); an ordered `findOne` has a movable window,
     * and an unordered one is a fixed one-row result that accepts only its
     * compiled limit at offset 0.
     *
     * @throws `SetWindowRequiresOrderByError` if the query is neither windowed
     * nor a `findOne`, or an unordered `findOne` would move its offset.
     * @throws `SetWindowFindOneLimitError` if a `findOne` would change its limit.
     * @returns `true` if no subset loading was triggered, or `Promise<void>` that resolves when the subset has been loaded
     */
    setWindow: (options: WindowOptions) => true | Promise<void>;
    /**
     * Gets the current window (offset and limit) for an ordered query.
     *
     * @returns The current window settings, or `undefined` if the query is not windowed
     */
    getWindow: () => {
        offset: number;
        limit: number;
    } | undefined;
    [LIVE_QUERY_INTERNAL]: LiveQueryInternalUtils;
};
export declare class CollectionConfigBuilder<TContext extends Context, TResult extends object = GetResult<TContext>> {
    private readonly config;
    private readonly id;
    readonly query: QueryIR;
    private readonly collections;
    private readonly collectionSources;
    private readonly resultKeys;
    private readonly orderByIndices;
    private readonly compare?;
    private readonly compareOptions;
    readonly queryCompareOptions: StringCollationConfig;
    private isGraphRunning;
    private graphInputRevision;
    currentSyncConfig: Parameters<SyncConfig<TResult>[`sync`]>[0] | undefined;
    currentSyncState: FullSyncState | undefined;
    private fatalQueryError;
    private lastSubsetError;
    private reloadSnapshotPending;
    liveQueryCollection?: Collection<TResult, any, any>;
    private dependentEntry;
    /**
     * Reload each source with an error anywhere in its tree, then this query if
     * its own node shows an error. A nested live query passes the reload down the
     * same way. A source's reload keeps this query's status until it commits.
     * A query that is not running starts once its sources reloaded, as any
     * Collection's reload starts one; `query` is the live-query Collection,
     * which a query that never started has not given this builder yet.
     */
    reload(query?: Collection<any, any, any> | undefined): Promise<void>;
    /** This live query as its sources' `subscribers` list it. */
    dependent(): CollectionDependent | undefined;
    /**
     * Whether this live-query Collection had a subscriber or a preload in its
     * current sync run. Until then it reads its source Collections without
     * starting provider work.
     */
    hasSubscriberOrPreload(): boolean;
    private windowFn;
    private readonly initialWindow;
    private currentWindow;
    private settledWindow;
    private activeWindowOperation;
    private maybeRunGraphFn;
    private loadMoreFn;
    private readonly builderDependencies;
    private graphCache;
    private inputsCache;
    private pipelineCache;
    sourceWhereClausesCache: Map<string, BasicExpression<boolean>> | undefined;
    private includesRuntimeCache;
    private bucketFacadesCache;
    private readonly includeSourceIds;
    readonly subscriptions: Record<string, CollectionSubscription>;
    lazySourcesCallbacks: Record<string, LazyCollectionCallbacks>;
    readonly lazySources: Set<string>;
    private readonly activeDemands;
    private demandGeneration;
    private readonly pendingOrderedLoads;
    private orderedLoadFailed;
    private windowFailed;
    private syncRunGeneration;
    private windowOperationGeneration;
    private windowRequestGeneration;
    private latestWindowRequest;
    optimizableOrderByCollections: Record<string, OrderByOptimizationInfo>;
    constructor(config: LiveQueryCollectionConfig<TContext, TResult>);
    /** Direct lexical source Collections, including joins, unions, and includes. */
    getSourceCollections(): ReadonlyArray<Collection<any, any, any>>;
    /**
     * Recursively checks if a query or any of its subqueries contains joins
     */
    private hasJoins;
    getConfig(): CollectionConfigSingleRowOption<TResult> & {
        utils: LiveQueryCollectionUtils;
    };
    setWindow(options: WindowOptions): true | Promise<void>;
    getWindow(): {
        offset: number;
        limit: number;
    } | undefined;
    isLazySource(sourceId: string): boolean;
    beginDemand(planId: string, pending?: boolean): number;
    /** The source aliases of this query, in query order, for its health tree. */
    healthSources(): ReadonlyArray<HealthSource>;
    settleDemand(planId: string, generation: number): void;
    hasPendingJoinedWork(joinedSourceId: string): boolean;
    failDemand(subscription: CollectionSubscription, collection: Collection, planId: string, generation: number, error: unknown): void;
    recordSubsetError(error: unknown, fatalBeforeReady?: boolean): Error;
    trackSubsetLoadPromise(promise: Promise<unknown>): void;
    trackSubsetLoadOperationPromise(promise: Promise<unknown>): void;
    hasActiveWindowOperation(): boolean;
    getActiveWindowOperationGeneration(): number | undefined;
    scheduleGraphRunIfSyncRunCurrent(syncRunGeneration: number): void;
    trackOrderedLoadPromise(promise: Promise<unknown>, holdPublication?: boolean): void;
    retireDemand(planId: string): void;
    /** A root load of an eager source failed. */
    failRootLoad(sourceId: string, error: Error): void;
    /** A later root load of the source succeeded. */
    settleRootLoad(sourceId: string): void;
    /** A source's truncate replay loaded the query's demand again. */
    settleReplayedRequests(sourceId: string): void;
    /**
     * A source's truncate replay could not load the query's data again: each
     * of its failures, in failure order. Before the first ready the earliest
     * fails the query.
     */
    failReplay(sourceId: string, errors: Array<Error>): void;
    reportFailedRequest(key: string, errors: Array<Error>): boolean;
    /** A request settled later, or the query no longer needs its data. */
    clearFailedRequest(key: string): void;
    /** This query's sync run and its sources' sync runs. */
    private syncRuns;
    /** Replays of other subscriptions to a source's collection that still load. */
    siblingReplays(collection: Collection, sourceId: string): Promise<unknown> | undefined;
    hasPendingSourceRecovery(): boolean;
    private pendingSourceRecovery;
    private hasFailedSourceRecovery;
    getSyncRunGeneration(): number;
    advanceGraphInputRevision(): void;
    getGraphInputRevision(): number;
    maybeRunGraph(): void;
    /**
     * Schedules a graph run with the transaction-scoped scheduler.
     * Ensures each builder runs at most once per transaction, with automatic dependency tracking
     * to run parent queries before child queries. Outside a transaction, runs immediately.
     *
     * Multiple calls during a transaction are coalesced into a single execution.
     * Dependencies are discovered from subscribed live queries.
     *
     * Uses the current sync run's config and syncState from instance properties.
     *
     * @param options - Optional scheduling configuration
     * @param options.contextId - Transaction ID to group work; defaults to active transaction
     */
    scheduleGraphRun(options?: {
        contextId?: SchedulerContextId;
    }): void;
    private getSyncConfig;
    private syncFn;
    private clearSyncRunState;
    /**
     * Compiles the query pipeline with all declared aliases.
     */
    private compileBasePipeline;
    private maybeCompileBasePipeline;
    private extendPipelineWithChangeProcessing;
    private applyChanges;
    /**
     * Handle status changes from source collections
     */
    private handleSourceStatusChange;
    private handleSourceCleanupStart;
    /**
     * Update the live query status based on source collection statuses
     */
    private updateLiveQueryStatus;
    /** Whether the current run's graph result is complete. */
    private isResultComplete;
    /**
     * The query's first load failed: status `error`. A sync problem or a
     * request error after the first ready never reaches here.
     */
    private failQuery;
    /**
     * The query can no longer serve reads: a crashed source, a graph failure,
     * or a contract violation such as a source cleaned up under this query.
     */
    private crashQuery;
    /** Returns false when the query already ended. */
    private enterErrorState;
    private allRequiredSourcesReady;
    /**
     * Creates one subscription per lexical collection source.
     * Each source gets independent filters, even when aliases or collections repeat.
     * Example: `{ employee: col, manager: col }` creates two separate subscriptions.
     */
    private subscribeToAllCollections;
}
