import { LogContext } from '@rocicorp/logger';
import { type Resolver } from '@rocicorp/resolver';
import { ReplicacheImpl } from '../../../replicache/src/impl.ts';
import type { Puller } from '../../../replicache/src/puller.ts';
import type { Pusher } from '../../../replicache/src/pusher.ts';
import type { ClientGroupID, ClientID } from '../../../replicache/src/sync/ids.ts';
import type { MutatorDefs } from '../../../replicache/src/types.ts';
import type { ReadonlyJSONValue } from '../../../shared/src/json.ts';
import { Subscribable } from '../../../shared/src/subscribable.ts';
import { type ClientSchema } from '../../../zero-protocol/src/client-schema.ts';
import type { DeleteClientsBody } from '../../../zero-protocol/src/delete-clients.ts';
import type { UpQueriesPatchOp } from '../../../zero-protocol/src/queries-patch.ts';
import type { NullableVersion } from '../../../zero-protocol/src/version.ts';
import type { BaseDefaultContext, BaseDefaultSchema, DefaultContext, DefaultSchema } from '../../../zero-types/src/default-types.ts';
import type { Schema } from '../../../zero-types/src/schema.ts';
import type { ViewFactory } from '../../../zql/src/ivm/view.ts';
import type { MutateRequest } from '../../../zql/src/mutate/mutator.ts';
import type { QueryDelegate } from '../../../zql/src/query/query-delegate.ts';
import { type QueryOrQueryRequest } from '../../../zql/src/query/query-registry.ts';
import { type HumanReadable, type MaterializeOptions, type PreloadOptions, type RunOptions } from '../../../zql/src/query/query.ts';
import type { ConditionalSchemaQuery } from '../../../zql/src/query/schema-query.ts';
import type { TypedView } from '../../../zql/src/query/typed-view.ts';
import { ActiveClientsManager } from './active-clients-manager.ts';
import { ConnectionManager } from './connection-manager.ts';
import { type Connection } from './connection.ts';
import { type BatchMutator } from './crud.ts';
import type { CustomMutatorDefs, MutatorResult } from './custom.ts';
import { DeleteClientsManager } from './delete-clients-manager.ts';
import { type HTTPString, type WSString } from './http-string.ts';
import { Inspector } from './inspector/inspector.ts';
import { type LogOptions } from './log-options.ts';
import type { MakeMutatePropertyType } from './make-mutate-property.ts';
import type { ZeroOptions } from './options.ts';
import { QueryManager } from './query-manager.ts';
export type NoRelations = Record<string, never>;
export type TestingContext = {
    puller: Puller;
    pusher: Pusher;
    setReload: (r: () => void) => void;
    logOptions: LogOptions;
    connectStart: () => number | undefined;
    socketResolver: () => Resolver<WebSocket>;
    connectionManager: () => ConnectionManager;
    queryDelegate: () => QueryDelegate;
    queryManager: () => QueryManager;
    enableRefresh: () => boolean;
};
export declare const exposedToTestingSymbol: unique symbol;
export declare const createLogOptionsSymbol: unique symbol;
export declare const RUN_LOOP_INTERVAL_MS = 5000;
/**
 * Default timeout for ping operations. Controls both:
 * - How long to wait in idle before sending a ping
 * - How long to wait for a pong response
 */
export declare const DEFAULT_PING_TIMEOUT_MS = 5000;
/**
 * The amount of time we wait for a pull response before we consider a pull
 * request timed out.
 */
export declare const PULL_TIMEOUT_MS = 5000;
export declare const DEFAULT_DISCONNECT_HIDDEN_DELAY_MS: number;
/**
 * The amount of time we allow for continuous connecting attempts before
 * transitioning to disconnected state.
 */
export declare const DEFAULT_DISCONNECT_TIMEOUT_MS: number;
/**
 * The amount of time we wait for a connection to be established before we
 * consider it timed out.
 */
export declare const CONNECT_TIMEOUT_MS = 10000;
export interface ReplicacheInternalAPI {
    lastMutationID(): number;
}
export declare function getInternalReplicacheImplForTesting(z: object): ReplicacheImpl<MutatorDefs>;
export type ZeroMutate<S extends Schema, MD extends CustomMutatorDefs | undefined, C> = MakeMutatePropertyType<S, MD, C> & ((mr: MutateRequest<any, S, C, any>) => MutatorResult);
export declare class Zero<const S extends BaseDefaultSchema = DefaultSchema, MD extends CustomMutatorDefs | undefined = undefined, C extends BaseDefaultContext = DefaultContext> {
    #private;
    readonly version: string;
    readonly userID: string;
    readonly storageKey: string;
    /**
     * The timeout in milliseconds for ping operations. Controls both:
     * - How long to wait in idle before sending a ping
     * - How long to wait for a pong response
     *
     * Total time to detect a dead connection is 2 × pingTimeoutMs.
     *
     * The new value will take effect on the next ping cycle.
     */
    pingTimeoutMs: number;
    /**
     * Query builders for each table in the schema.
     *
     * @deprecated Use {@linkcode createBuilder} to create query builders instead.
     */
    readonly query: ConditionalSchemaQuery<S>;
    /**
     * Constructs a new Zero client.
     */
    constructor(options: ZeroOptions<S, MD, C>);
    /**
     * Preloads data for a query into the cache, without keeping it in memory.
     *
     * This function is useful when you want to populate the cache ahead of time,
     * for example after login, to avoid a flash of loading screen on the next page.
     *
     * Returns an object with two properties:
     * - `complete`: a Promise that resolves when the data is loaded
     * - `cleanup`: a function that can be called to cancel the preload
     *
     * @example
     * ```ts
     * const {complete, cleanup} = zero.preload(userQuery);
     * await complete;
     * // Now the data is cached and can be used immediately
     * ```
     */
    preload<TTable extends keyof S['tables'] & string, TInput extends ReadonlyJSONValue | undefined, TOutput extends ReadonlyJSONValue | undefined, TReturn>(query: QueryOrQueryRequest<TTable, TInput, TOutput, S, TReturn, C>, options?: PreloadOptions): {
        cleanup: () => void;
        complete: Promise<void>;
    };
    /**
     * Executes a query once and returns the results.
     *
     * By default, waits for any pending data to sync before running the query.
     * This ensures fresh results from the server. Use `{type: 'unknown'}` to
     * run immediately with whatever data is available locally.
     *
     * @param query - The query to execute
     * @param runOptions - Options controlling query execution
     * @returns A Promise resolving to the query results
     *
     * @example
     * ```ts
     * // Wait for server sync
     * const users = await zero.run(userQuery);
     *
     * // Run with local data only
     * const cachedUsers = await zero.run(userQuery, {type: 'unknown'});
     * ```
     */
    run<TTable extends keyof S['tables'] & string, TInput extends ReadonlyJSONValue | undefined, TOutput extends ReadonlyJSONValue | undefined, TReturn>(query: QueryOrQueryRequest<TTable, TInput, TOutput, S, TReturn, C>, runOptions?: RunOptions): Promise<HumanReadable<TReturn>>;
    get context(): C;
    /**
     * Creates a materialized view of a query that stays synchronized with the database.
     *
     * The materialized view automatically updates when the underlying data changes.
     * When done with the view, call `view.destroy()` to clean up subscriptions.
     *
     * Optionally accepts a factory function to create a custom view implementation.
     *
     * @param query - The query to materialize
     * @param factory - Optional factory function to create a custom view
     * @param options - Options controlling view behavior
     * @returns A TypedView that stays synchronized with the data
     *
     * @example
     * ```ts
     * // Create a standard view
     * const view = zero.materialize(userQuery);
     * console.log(view.data); // Current query results
     * view.destroy(); // Clean up when done
     *
     * // Create a custom view
     * const customView = zero.materialize(userQuery, (query) => new MyCustomView(query));
     * ```
     */
    materialize<TTable extends keyof S['tables'] & string, TInput extends ReadonlyJSONValue | undefined, TOutput extends ReadonlyJSONValue | undefined, TReturn>(query: QueryOrQueryRequest<TTable, TInput, TOutput, S, TReturn, C>, options?: MaterializeOptions): TypedView<HumanReadable<TReturn>>;
    materialize<T, TTable extends keyof S['tables'] & string, TInput extends ReadonlyJSONValue | undefined, TOutput extends ReadonlyJSONValue | undefined, TReturn>(query: QueryOrQueryRequest<TTable, TInput, TOutput, S, TReturn, C>, factory: ViewFactory<TTable, S, TReturn, T>, options?: MaterializeOptions): T;
    /**
     * The server URL that this Zero instance is configured with.
     */
    get server(): HTTPString | null;
    /**
     * The name of the IndexedDB database in which the data of this
     * instance of Zero is stored.
     */
    get idbName(): string;
    /**
     * The schema version of the data understood by this application.
     * See [[ZeroOptions.schemaVersion]].
     */
    get schemaVersion(): string;
    /**
     * The schema passed into Zero when it was constructed.
     *
     * This can be paired with the inspector API to explore the client cache for
     * debugging or tooling. The inspector exposes the raw key/value map as well
     * as the per-table rows that back `zero.query[tableName].run()`.
     *
     * ```ts
     * const inspector = __zero.inspector;
     * const client = inspector.client;
     *
     * console.log('client map:', await client.map());
     *
     * for (const tableName of Object.keys(__zero.schema.tables)) {
     *   console.table(await client.rows(tableName));
     * }
     * ```
     */
    get schema(): S;
    /**
     * The client ID for this instance of Zero. Each instance
     * gets a unique client ID.
     */
    get clientID(): ClientID;
    get clientGroupID(): Promise<ClientGroupID>;
    /**
     * Use to execute mutations. The primary flow is to call
     * `zero.mutate(mutationRequest)` with your registered custom mutators:
     *
     * ```ts
     * await zero.mutate(
     *   mutators.myMutator({id: '1', title: 'First issue'}),
     * );
     * ```
     *
     * When `schema.enableLegacyMutators` is true, legacy conveniences are added:
     * - Table-scoped CRUD helpers, e.g. `zero.mutate.issue.create` / `set` / `update` / `delete`
     * - Your custom mutators exposed directly on `zero.mutate`
     *
     * ```ts
     * await zero.mutate.issue.create({id: '1', title: 'First issue', priority: 'high'});
     * await zero.mutate.comment.create({id: '1', text: 'First comment', issueID: '1'});
     * await zero.mutate.myMutator({id: '1', title: 'First issue'});
     * ```
     *
     * The `update` methods support partials. Unspecified or `undefined` fields
     * are left unchanged:
     *
     * ```ts
     * // Priority left unchanged.
     * await zero.mutate.issue.update({id: '1', title: 'Updated title'});
     * ```
     */
    readonly mutate: ZeroMutate<S, MD, C>;
    /**
     * Provides a way to batch multiple CRUD mutations together:
     *
     * ```ts
     * await zero.mutateBatch(m => {
     *   await m.issue.create({id: '1', title: 'First issue'});
     *   await m.comment.create({id: '1', text: 'First comment', issueID: '1'});
     * });
     * ```
     *
     * Batch sends all mutations in a single transaction. If one fails, all are
     * rolled back together. Batch can also be more efficient than making many
     * individual mutations.
     *
     * `mutateBatch` is not allowed inside another `mutateBatch` call. Doing so
     * will throw an error.
     *
     * @deprecated Use `zero.mutate(mutationRequest)`
     */
    readonly mutateBatch: BatchMutator<S>;
    /**
     * The connection API for managing Zero's connection lifecycle.
     *
     * Use this to monitor connection state and manually control connections.
     *
     * @example
     * ```ts
     * // Subscribe to connection state changes
     * z.connection.state.subscribe(state => {
     *   console.log('Connection state:', state.name);
     * });
     *
     * // Manually resume connection from error state
     * await z.connection.connect();
     * ```
     */
    get connection(): Connection;
    /**
     * Whether this Zero instance has been closed.
     *
     * Once a Zero instance has been closed it no longer syncs, you can no
     * longer query or mutate data with it, and its query views stop updating.
     */
    get closed(): boolean;
    /**
     * Closes this Zero instance.
     *
     * Once a Zero instance has been closed it no longer syncs, you can no
     * longer query or mutate data with it, and its query views stop updating.
     */
    close(): Promise<void>;
    /**
     * A rough heuristic for whether the client is currently online and
     * authenticated.
     *
     * @deprecated Use `connection` instead, which provides more detailed connection state.
     */
    get online(): boolean;
    /**
     * Subscribe to online status changes.
     *
     * This is useful when you want to update state based on the online status.
     *
     * @param listener - The listener to subscribe to.
     * @returns A function to unsubscribe the listener.
     *
     * @deprecated Use `connection` instead, which provides more detailed connection state.
     */
    onOnline: (listener: (online: boolean) => void) => (() => void);
    /**
     * `inspector` is an object that can be used to inspect the state of the
     * queries a Zero instance uses. It is intended for debugging purposes.
     */
    get inspector(): Inspector;
    delete(): Promise<{
        deleted: string[];
        errors: unknown[];
    }>;
}
export declare class OnlineManager extends Subscribable<boolean> {
    #private;
    setOnline(online: boolean): void;
    get online(): boolean;
}
export declare function createSocket(rep: ReplicacheImpl, queryManager: QueryManager, deleteClientsManager: DeleteClientsManager, socketOrigin: WSString, baseCookie: NullableVersion, clientID: string, clientGroupID: string, clientSchema: ClientSchema, userID: string, auth: string | undefined, lmid: number, wsid: string, debugPerf: boolean, lc: LogContext, userPushURL: string | undefined, userPushHeaders: Record<string, string> | undefined, userQueryURL: string | undefined, userQueryHeaders: Record<string, string> | undefined, additionalConnectParams: Record<string, string> | undefined, activeClientsManager: Pick<ActiveClientsManager, 'activeClients'>, maxHeaderLength?: number): Promise<[
    WebSocket,
    Map<string, UpQueriesPatchOp> | undefined,
    DeleteClientsBody | undefined
]>;
export declare function createConnectionURL(socketOrigin: HTTPString | WSString, clientID: string, clientGroupID: string, userID: string, baseCookie: string | null, lmid: number, wsid: string, rep: Pick<ReplicacheImpl<{}>, 'profileID'>, debugPerf: boolean, additionalConnectParams: Record<string, string> | undefined, lc: LogContext<unknown[], unknown[], unknown[], unknown[]>): Promise<URL>;
//# sourceMappingURL=zero.d.ts.map