import { Collection } from './collection/index.js';
import { ChangeMessage, CollectionStatus } from './types.js';
/**
 * The canonical, adapter-agnostic view of a live query at a point in time.
 *
 * `getSnapshot()` returns a stable object identity that only changes when the
 * query changes, so `useSyncExternalStore`-style consumers can compare by
 * reference. Each snapshot owns a captured view of `state`/`data`, so reading
 * an older snapshot cannot expose rows from a later revision.
 */
export interface LiveQuerySnapshot<T extends object, TKey extends string | number> {
    /** Keyed results, or `undefined` for a disabled query. */
    state: ReadonlyMap<TKey, T> | undefined;
    /** Ordered results (single row for `findOne`), or `undefined` when disabled. */
    data: T | ReadonlyArray<T> | undefined;
    /** The underlying collection, or `undefined` when disabled. */
    collection: Collection<T, TKey, any> | undefined;
    /**
     * Monotonic counter bumped whenever the visible layout (the ordered key
     * sequence) changes — membership, ordering, or an order-only move. Lets
     * consumers detect a reorder that changed no row value (which `data`/`state`
     * identity alone can't express once row values are structurally shared).
     *
     * It is NOT in lockstep with snapshot identity: a value-only update produces a
     * new snapshot while `layoutRevision` stays put. A `layoutRevision` change
     * always accompanies a new snapshot, but not vice versa.
     */
    layoutRevision: number;
    status: CollectionStatus | `disabled`;
    isLoading: boolean;
    isReady: boolean;
    isIdle: boolean;
    isError: boolean;
    isCleanedUp: boolean;
    isEnabled: boolean;
}
/**
 * Listener payload: changes, `[]` for an internal layout-only publication, or
 * `undefined` for a synthetic status/ready notification.
 */
export type LiveQueryObserverListener<T extends object, TKey extends string | number> = (changes: Array<ChangeMessage<T, TKey>> | undefined) => void;
/**
 * Wraps a resolved live-query `Collection` (or `null` for a disabled query) with
 * the shared lifecycle every framework adapter needs: start sync on first
 * subscribe, subscribe to changes and status transitions, expose a stable
 * snapshot for wholesale consumers, and deliver the raw change set for
 * granular consumers.
 *
 * Input resolution (query fn / config / collection / disabled) stays in the
 * adapter — it is framework-reactive. The observer owns everything after the
 * input is resolved to a concrete collection.
 *
 * @internal Unstable contract for TanStack DB's official framework adapters —
 * not a public extension point yet; may change in any release.
 */
export interface LiveQueryObserver<T extends object, TKey extends string | number> {
    /** Stable per-revision snapshot for wholesale materialization. */
    getSnapshot: () => LiveQuerySnapshot<T, TKey>;
    /**
     * Subscribe to changes. The listener receives the change set (or `undefined`
     * for the synthetic notify a ready collection emits on attach). Granular
     * adapters apply the changes; wholesale adapters can ignore them and re-read
     * `getSnapshot()`. Returns an unsubscribe function.
     */
    subscribe: (listener: LiveQueryObserverListener<T, TKey>) => () => void;
    /** Resolve once the collection has loaded its first data. */
    preload: () => Promise<void>;
    /** Idempotent teardown. */
    dispose: () => void;
}
export interface CreateLiveQueryObserverOptions {
    /**
     * How subscribers consume the observer:
     *
     * - `granular` (default): subscribers apply the delivered `ChangeMessage[]`
     *   deltas to their own keyed state (Vue/Svelte/Solid). The observer
     *   subscribes with initial state and seeds late subscribers, so every
     *   subscriber converges from deltas alone.
     * - `wholesale`: subscribers treat notifications as a wake-up and re-read
     *   `getSnapshot()` (React/Angular). The observer subscribes WITHOUT initial
     *   state, preserving those adapters' loading policy — no snapshot request,
     *   so no unfiltered `loadSubset` against on-demand collections. Nothing is
     *   delivered synchronously during `subscribe`, which keeps
     *   `useSyncExternalStore`-style consumers safe by construction.
     */
    mode?: `granular` | `wholesale`;
}
/**
 * Create a {@link LiveQueryObserver} for a resolved live-query collection, or a
 * disabled observer when `collection` is `null`/`undefined`.
 *
 * @internal This is an unstable contract shared by TanStack DB's official
 * framework adapters. It is exported so the adapter packages can use it, but
 * it is not a public extension point yet: its API may change in any release
 * without a semver major.
 */
export declare function createLiveQueryObserver<T extends object, TKey extends string | number>(collection: Collection<T, TKey, any> | null | undefined, options?: CreateLiveQueryObserverOptions): LiveQueryObserver<T, TKey>;
