import { LogContext } from '@rocicorp/logger';
import type { MaybePromise } from '../../shared/src/types.ts';
import { type Cookie } from './cookies.ts';
import { LazyStore } from './dag/lazy-store.ts';
import { type Store } from './dag/store.ts';
import { type Hash } from './hash.ts';
import { type PendingMutation } from './pending-mutations.ts';
import { type OnClientsDeleted } from './persist/clients.ts';
import type { Puller } from './puller.ts';
import { type Pusher } from './pusher.ts';
import type { ReplicacheOptions, ZeroOption } from './replicache-options.ts';
import { type SubscribeOptions, type SubscriptionsManager, type WatchCallbackForOptions, type WatchNoIndexCallback, type WatchOptions } from './subscriptions.ts';
import type { ReadTransaction } from './transactions.ts';
import type { BeginPullResult, MakeMutators, MutatorDefs, PokeInternal, QueryInternal, RequestOptions, UpdateNeededReason } from './types.ts';
/** @deprecated Not used any more */
export interface MakeSubscriptionsManager {
    (queryInternal: QueryInternal, lc: LogContext): SubscriptionsManager;
}
export interface ReplicacheImplOptions {
    /**
     * Defaults to true.
     */
    enableMutationRecovery?: boolean | undefined;
    /**
     * Defaults to true.
     */
    enableScheduledPersist?: boolean | undefined;
    /**
     * Defaults to true.
     */
    enableScheduledRefresh?: boolean | undefined;
    /**
     * Defaults to true.
     */
    enablePullAndPushInOpen?: boolean | undefined;
    /**
     * @deprecated Not used anymore.
     */
    makeSubscriptionsManager?: unknown;
    /**
     * Default is `true`.  If `false` if an exact match client group
     * is not found, a new client group is always made instead of forking
     * from an existing client group.
     */
    enableClientGroupForking?: boolean | undefined;
    /**
     * Callback for when Replicache has deleted clients.
     */
    onClientsDeleted?: OnClientsDeleted | undefined;
    /**
     * Internal option used by Zero.
     * Replicache will call this to and, if zero is enabled, will
     * invoke various hooks to allow Zero the keep IVM in sync with Replicache's b-trees.
     */
    zero?: ZeroOption | undefined;
}
export declare class ReplicacheImpl<MD extends MutatorDefs = {}> {
    #private;
    /** The URL to use when doing a pull request. */
    pullURL: string;
    /** The URL to use when doing a push request. */
    pushURL: string;
    /** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */
    readonly name: string;
    /**
     * Client groups gets disabled when the server does not know about it.
     * A disabled client group prevents the client from pushing and pulling.
     */
    isClientGroupDisabled: boolean;
    lastMutationID: number;
    /**
     * This is the name Replicache uses for the IndexedDB database where data is
     * stored.
     */
    get idbName(): string;
    set auth(auth: string);
    get auth(): string;
    /** The schema version of the data understood by this application. */
    readonly schemaVersion: string;
    /**
     * The mutators that was registered in the constructor.
     */
    readonly mutate: MakeMutators<MD>;
    /**
     * The duration between each periodic {@link pull}. Setting this to `null`
     * disables periodic pull completely. Pull will still happen if you call
     * {@link pull} manually.
     */
    pullInterval: number | null;
    /**
     * The delay between when a change is made to Replicache and when Replicache
     * attempts to push that change.
     */
    pushDelay: number;
    /**
     * The function to use to pull data from the server.
     */
    puller: Puller;
    /**
     * The function to use to push data to the server.
     */
    pusher: Pusher;
    readonly memdag: LazyStore;
    readonly perdag: Store;
    /**
     * The options used to control the {@link pull} and push request behavior. This
     * object is live so changes to it will affect the next pull or push call.
     */
    get requestOptions(): Required<RequestOptions>;
    /**
     * `onSync(true)` is called when Replicache transitions from no push or pull
     * happening to at least one happening. `onSync(false)` is called in the
     * opposite case: when Replicache transitions from at least one push or pull
     * happening to none happening.
     *
     * This can be used in a React like app by doing something like the following:
     *
     * ```js
     * const [syncing, setSyncing] = useState(false);
     * useEffect(() => {
     *   rep.onSync = setSyncing;
     * }, [rep]);
     * ```
     */
    onSync: ((syncing: boolean) => void) | null;
    /**
     * `onClientStateNotFound` is called when the persistent client has been
     * garbage collected. This can happen if the client has no pending mutations
     * and has not been used for a while.
     *
     * The default behavior is to reload the page (using `location.reload()`). Set
     * this to `null` or provide your own function to prevent the page from
     * reloading automatically.
     */
    onClientStateNotFound: (() => void) | null;
    /**
     * `onUpdateNeeded` is called when a code update is needed.
     *
     * A code update can be needed because:
     * - the server no longer supports the {@link pushVersion},
     *   {@link pullVersion} or {@link schemaVersion} of the current code.
     * - a new Replicache client has created a new client group, because its code
     *   has different mutators, indexes, schema version and/or format version
     *   from this Replicache client. This is likely due to the new client having
     *   newer code. A code update is needed to be able to locally sync with this
     *   new Replicache client (i.e. to sync while offline, the clients can still
     *   sync with each other via the server).
     *
     * The default behavior is to reload the page (using `location.reload()`). Set
     * this to `null` or provide your own function to prevent the page from
     * reloading automatically. You may want to provide your own function to
     * display a toast to inform the end user there is a new version of your app
     * available and prompting them to refresh.
     */
    onUpdateNeeded: ((reason: UpdateNeededReason) => void) | null;
    /**
     * This gets called when we get an HTTP unauthorized (401) response from the
     * push or pull endpoint. Set this to a function that will ask your user to
     * reauthenticate.
     */
    getAuth: (() => MaybePromise<string | null | undefined>) | null | undefined;
    onPushInvoked: () => undefined;
    onBeginPull: () => undefined;
    onRecoverMutations: (r: Promise<boolean>) => Promise<boolean>;
    constructor(options: ReplicacheOptions<MD>, implOptions?: ReplicacheImplOptions);
    /**
     * The browser profile ID for this browser profile. Every instance of Replicache
     * browser-profile-wide shares the same profile ID.
     */
    get profileID(): Promise<string>;
    /**
     * The client ID for this instance of Replicache. Each instance of Replicache
     * gets a unique client ID.
     */
    get clientID(): string;
    /**
     * The client group ID for this instance of Replicache. Instances of
     * Replicache will have the same client group ID if and only if they have
     * the same name, mutators, indexes, schema version, format version, and
     * browser profile.
     */
    get clientGroupID(): Promise<string>;
    /**
     * `onOnlineChange` is called when the {@link online} property changes. See
     * {@link online} for more details.
     */
    onOnlineChange: ((online: boolean) => void) | null;
    /**
     * A rough heuristic for whether the client is currently online. Note that
     * there is no way to know for certain whether a client is online - the next
     * request can always fail. This property returns true if the last sync attempt succeeded,
     * and false otherwise.
     */
    get online(): boolean;
    /**
     * Whether the Replicache database has been closed. Once Replicache has been
     * closed it no longer syncs and you can no longer read or write data out of
     * it. After it has been closed it is pretty much useless and should not be
     * used any more.
     */
    get closed(): boolean;
    /**
     * Closes this Replicache instance.
     *
     * When closed all subscriptions end and no more read or writes are allowed.
     */
    close(): Promise<void>;
    maybeEndPull(syncHead: Hash, requestID: string): Promise<void>;
    /**
     * Push pushes pending changes to the {@link pushURL}.
     *
     * You do not usually need to manually call push. If {@link pushDelay} is
     * non-zero (which it is by default) pushes happen automatically shortly after
     * mutations.
     *
     * If the server endpoint fails push will be continuously retried with an
     * exponential backoff.
     *
     * @param [now=false] If true, push will happen immediately and ignore
     *   {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the
     *   exponential backoff in case of errors.
     * @returns A promise that resolves when the next push completes. In case of
     * errors the first error will reject the returned promise. Subsequent errors
     * will not be reflected in the promise.
     */
    push({ now }?: {
        now?: boolean | undefined;
    }): Promise<void>;
    /**
     * Pull pulls changes from the {@link pullURL}. If there are any changes local
     * changes will get replayed on top of the new server state.
     *
     * If the server endpoint fails pull will be continuously retried with an
     * exponential backoff.
     *
     * @param [now=false] If true, pull will happen immediately and ignore
     *   {@link RequestOptions.minDelayMs} as well as the exponential backoff in
     *   case of errors.
     * @returns A promise that resolves when the next pull completes. In case of
     * errors the first error will reject the returned promise. Subsequent errors
     * will not be reflected in the promise.
     */
    pull({ now }?: {
        now?: boolean | undefined;
    }): Promise<void>;
    /**
     * Applies an update from the server to Replicache.
     * Throws an error if cookie does not match. In that case the server thinks
     * this client has a different cookie than it does; the caller should disconnect
     * from the server and re-register, which transmits the cookie the client actually
     * has.
     *
     * @experimental This method is under development and its semantics will change.
     */
    poke(poke: PokeInternal): Promise<void>;
    beginPull(): Promise<BeginPullResult>;
    persist(): Promise<void>;
    refresh(): Promise<void>;
    disableClientGroup(): Promise<void>;
    /**
     * Subscribe to the result of a {@link query}. The `body` function is
     * evaluated once and its results are returned via `onData`.
     *
     * Thereafter, each time the the result of `body` changes, `onData` is fired
     * again with the new result.
     *
     * `subscribe()` goes to significant effort to avoid extraneous work
     * re-evaluating subscriptions:
     *
     * 1. subscribe tracks the keys that `body` accesses each time it runs. `body`
     *    is only re-evaluated when those keys change.
     * 2. subscribe only re-fires `onData` in the case that a result changes by
     *    way of the `isEqual` option which defaults to doing a deep JSON value
     *    equality check.
     *
     * Because of (1), `body` must be a pure function of the data in Replicache.
     * `body` must not access anything other than the `tx` parameter passed to it.
     *
     * Although subscribe is as efficient as it can be, it is somewhat constrained
     * by the goal of returning an arbitrary computation of the cache. For even
     * better performance (but worse dx), see {@link experimentalWatch}.
     *
     * If an error occurs in the `body` the `onError` function is called if
     * present. Otherwise, the error is logged at log level 'error'.
     *
     * To cancel the subscription, call the returned function.
     *
     * @param body The function to evaluate to get the value to pass into
     *    `onData`.
     * @param options Options is either a function or an object. If it is a
     *    function it is equivalent to passing it as the `onData` property of an
     *    object.
     */
    subscribe<R>(body: (tx: ReadTransaction) => Promise<R>, options: SubscribeOptions<R> | ((result: R) => void)): () => void;
    /**
     * Watches Replicache for changes.
     *
     * The `callback` gets called whenever the underlying data changes and the
     * `key` changes matches the `prefix` of {@link ExperimentalWatchIndexOptions} or
     * {@link ExperimentalWatchNoIndexOptions} if present. If a change
     * occurs to the data but the change does not impact the key space the
     * callback is not called. In other words, the callback is never called with
     * an empty diff.
     *
     * This gets called after commit (a mutation or a rebase).
     *
     * @experimental This method is under development and its semantics will
     * change.
     */
    experimentalWatch(callback: WatchNoIndexCallback): () => void;
    experimentalWatch<Options extends WatchOptions>(callback: WatchCallbackForOptions<Options>, options?: Options): () => void;
    /**
     * Query is used for read transactions. It is recommended to use transactions
     * to ensure you get a consistent view across multiple calls to `get`, `has`
     * and `scan`.
     */
    query<R>(body: (tx: ReadTransaction) => Promise<R> | R): Promise<R>;
    get cookie(): Promise<Cookie>;
    recoverMutations(): Promise<boolean> | void;
    /**
     * List of pending mutations. The order of this is from oldest to newest.
     *
     * Gives a list of local mutations that have `mutationID` >
     * `syncHead.mutationID` that exists on the main client group.
     *
     * @experimental This method is experimental and may change in the future.
     */
    experimentalPendingMutations(): Promise<readonly PendingMutation[]>;
}
//# sourceMappingURL=replicache-impl.d.ts.map