import type { ErrorTypes, SnapshotInterface, Schema, Denormalize, Queryable, SchemaArgs } from '@data-client/normalizr';
import { ExpiryStatus, EndpointInterface, FetchFunction, ResolveType, DenormalizeNullable, MemoCache } from '@data-client/normalizr';
import AbortOptimistic from './AbortOptimistic.js';
import type { EndpointUpdateFunction } from './types.js';
import { ReduxMiddlewareAPI } from '../manager/applyManager.js';
import type { GCInterface } from '../state/GCPolicy.js';
import type { ActionTypes, State } from '../types.js';
export type GenericDispatch = (value: any) => Promise<void>;
export type DataClientDispatch = (value: ActionTypes) => Promise<void>;
export interface ControllerConstructorProps<D extends GenericDispatch = DataClientDispatch> {
    dispatch?: D;
    getState?: () => State<unknown>;
    memo?: Pick<MemoCache, 'denormalize' | 'query' | 'buildQueryKey'>;
    gcPolicy?: GCInterface;
}
/**
 * Imperative control of Reactive Data Client store
 * @see https://dataclient.io/docs/api/Controller
 */
export default class Controller<D extends GenericDispatch = DataClientDispatch> {
    /**
     * Dispatches an action to Reactive Data Client reducer.
     *
     * @see https://dataclient.io/docs/api/Controller#dispatch
     */
    protected _dispatch: D;
    /**
     * Gets the latest state snapshot that is fully committed.
     *
     * This can be useful for imperative use-cases like event handlers.
     * This should *not* be used to render; instead useSuspense() or useCache()
     * @see https://dataclient.io/docs/api/Controller#getState
     */
    getState: () => State<unknown>;
    /**
     * Singleton to maintain referential equality between calls
     */
    readonly memo: Pick<MemoCache, 'denormalize' | 'query' | 'buildQueryKey'>;
    /**
     * Handles garbage collection
     */
    readonly gcPolicy: GCInterface;
    constructor({ dispatch, getState, memo, gcPolicy, }?: ControllerConstructorProps<D>);
    set dispatch(dispatch: D);
    get dispatch(): D;
    bindMiddleware({ dispatch, getState, }: {
        dispatch: D;
        getState: ReduxMiddlewareAPI['getState'];
    }): void;
    /*************** Action Dispatchers ***************/
    /**
     * Fetches the endpoint with given args, updating the Reactive Data Client cache with the response or error upon completion.
     * @see https://dataclient.io/docs/api/Controller#fetch
     */
    fetch: <E extends EndpointInterface & {
        update?: EndpointUpdateFunction<E>;
    }>(endpoint: E, ...args: readonly [...Parameters<E>]) => E["schema"] extends undefined | null ? ReturnType<E> : Promise<Denormalize<E["schema"]>>;
    /**
     * Fetches only if endpoint is considered 'stale'; otherwise returns undefined
     * @see https://dataclient.io/docs/api/Controller#fetchIfStale
     */
    fetchIfStale: <E extends EndpointInterface & {
        update?: EndpointUpdateFunction<E>;
    }>(endpoint: E, ...args: readonly [...Parameters<E>]) => E["schema"] extends undefined | null ? ReturnType<E> | ResolveType<E> : Promise<Denormalize<E["schema"]>> | Denormalize<E["schema"]>;
    /**
     * Forces refetching and suspense on useSuspense with the same Endpoint and parameters.
     * @see https://dataclient.io/docs/api/Controller#invalidate
     */
    invalidate: <E extends EndpointInterface>(endpoint: E, ...args: readonly [...Parameters<E>] | readonly [null]) => Promise<void>;
    /**
     * Forces refetching and suspense on useSuspense on all matching endpoint result keys.
     * @see https://dataclient.io/docs/api/Controller#invalidateAll
     * @returns Promise that resolves when invalidation is commited.
     */
    invalidateAll: (options: {
        testKey: (key: string) => boolean;
    }) => Promise<void>;
    /**
     * Sets all matching endpoint result keys to be STALE.
     * @see https://dataclient.io/docs/api/Controller#expireAll
     * @returns Promise that resolves when expiry is commited. *NOT* fetch promise
     */
    expireAll: (options: {
        testKey: (key: string) => boolean;
    }) => Promise<void>;
    /**
     * Resets the entire Reactive Data Client cache. All inflight requests will not resolve.
     * @see https://dataclient.io/docs/api/Controller#resetEntireStore
     */
    resetEntireStore: () => Promise<void>;
    /**
     * Sets value for the Queryable and args.
     * @see https://dataclient.io/docs/api/Controller#set
     */
    set<S extends Queryable>(schema: S, ...rest: readonly [...SchemaArgs<S>, (previousValue: Denormalize<S>) => {}]): Promise<void>;
    set<S extends Queryable>(schema: S, ...rest: readonly [...SchemaArgs<S>, {}]): Promise<void>;
    /**
     * Sets response for the Endpoint and args.
     * @see https://dataclient.io/docs/api/Controller#setResponse
     */
    setResponse: <E extends EndpointInterface & {
        update?: EndpointUpdateFunction<E>;
    }>(endpoint: E, ...rest: readonly [...Parameters<E>, any]) => Promise<void>;
    /**
     * Sets an error response for the Endpoint and args.
     * @see https://dataclient.io/docs/api/Controller#setError
     */
    setError: <E extends EndpointInterface & {
        update?: EndpointUpdateFunction<E>;
    }>(endpoint: E, ...rest: readonly [...Parameters<E>, Error]) => Promise<void>;
    /**
     * Resolves an inflight fetch.
     * @see https://dataclient.io/docs/api/Controller#resolve
     */
    resolve: <E extends EndpointInterface & {
        update?: EndpointUpdateFunction<E>;
    }>(endpoint: E, meta: {
        args: readonly [...Parameters<E>];
        response: Error;
        fetchedAt: number;
        error: true;
    } | {
        args: readonly [...Parameters<E>];
        response: any;
        fetchedAt: number;
        error?: false | undefined;
    }) => Promise<void>;
    /**
     * Marks a new subscription to a given Endpoint.
     * @see https://dataclient.io/docs/api/Controller#subscribe
     */
    subscribe: <E extends EndpointInterface<FetchFunction, Schema | undefined, undefined | false>>(endpoint: E, ...args: readonly [...Parameters<E>] | readonly [null]) => Promise<void>;
    /**
     * Marks completion of subscription to a given Endpoint.
     * @see https://dataclient.io/docs/api/Controller#unsubscribe
     */
    unsubscribe: <E extends EndpointInterface<FetchFunction, Schema | undefined, undefined | false>>(endpoint: E, ...args: readonly [...Parameters<E>] | readonly [null]) => Promise<void>;
    /*************** More ***************/
    /**
     * Gets a snapshot (https://dataclient.io/docs/api/Snapshot)
     * @see https://dataclient.io/docs/api/Controller#snapshot
     */
    snapshot: (state: State<unknown>, fetchedAt?: number) => Snapshot<unknown>;
    /**
     * Gets the error, if any, for a given endpoint. Returns undefined for no errors.
     * @see https://dataclient.io/docs/api/Controller#getError
     */
    getError<E extends EndpointInterface>(endpoint: E, ...rest: readonly [null, State<unknown>] | readonly [...Parameters<E>, State<unknown>]): ErrorTypes | undefined;
    getError<E extends Pick<EndpointInterface, 'key'>>(endpoint: E, ...rest: readonly [null, State<unknown>] | readonly [...Parameters<E['key']>, State<unknown>]): ErrorTypes | undefined;
    /**
     * Gets the (globally referentially stable) response for a given endpoint/args pair from state given.
     * @see https://dataclient.io/docs/api/Controller#getResponse
     */
    getResponse<E extends EndpointInterface>(endpoint: E, ...rest: readonly [null, State<unknown>] | readonly [...Parameters<E>, State<unknown>]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
        countRef: () => () => void;
    };
    getResponse<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...rest: readonly [
        ...(readonly [...Parameters<E['key']>] | readonly [null]),
        State<unknown>
    ]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
        countRef: () => () => void;
    };
    /**
     * Gets the (globally referentially stable) response for a given endpoint/args pair from state given.
     * @see https://dataclient.io/docs/api/Controller#getResponseMeta
     */
    getResponseMeta<E extends EndpointInterface>(endpoint: E, ...rest: readonly [null, State<unknown>] | readonly [...Parameters<E>, State<unknown>]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
        countRef: () => () => void;
    };
    getResponseMeta<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...rest: readonly [
        ...(readonly [...Parameters<E['key']>] | readonly [null]),
        State<unknown>
    ]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
        countRef: () => () => void;
    };
    /**
     * Queries the store for a Querable schema
     * @see https://dataclient.io/docs/api/Controller#get
     */
    get<S extends Queryable>(schema: S, ...rest: readonly [
        ...SchemaArgs<S>,
        Pick<State<unknown>, 'entities' | 'entityMeta'>
    ]): DenormalizeNullable<S> | undefined;
    /**
     * Queries the store for a Querable schema; providing related metadata
     * @see https://dataclient.io/docs/api/Controller#getQueryMeta
     */
    getQueryMeta<S extends Queryable>(schema: S, ...rest: readonly [
        ...SchemaArgs<S>,
        Pick<State<unknown>, 'entities' | 'entityMeta'>
    ]): {
        data: DenormalizeNullable<S> | undefined;
        countRef: () => () => void;
    };
    private getSchemaResponse;
}
export type { ErrorTypes };
declare class Snapshot<T = unknown> implements SnapshotInterface {
    static readonly abort: AbortOptimistic;
    private state;
    private controller;
    readonly fetchedAt: number;
    readonly abort: AbortOptimistic;
    constructor(controller: Controller, state: State<T>, fetchedAt?: number);
    /*************** Data Access ***************/
    /** @see https://dataclient.io/docs/api/Snapshot#getResponse */
    getResponse<E extends EndpointInterface>(endpoint: E, ...args: readonly [null]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
    };
    getResponse<E extends EndpointInterface>(endpoint: E, ...args: readonly [...Parameters<E>]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
    };
    getResponse<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...args: readonly [...Parameters<E['key']>] | readonly [null]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
    };
    /** @see https://dataclient.io/docs/api/Snapshot#getResponseMeta */
    getResponseMeta<E extends EndpointInterface>(endpoint: E, ...args: readonly [null]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
    };
    getResponseMeta<E extends EndpointInterface>(endpoint: E, ...args: readonly [...Parameters<E>]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
    };
    getResponseMeta<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...args: readonly [...Parameters<E['key']>] | readonly [null]): {
        data: DenormalizeNullable<E['schema']>;
        expiryStatus: ExpiryStatus;
        expiresAt: number;
    };
    /** @see https://dataclient.io/docs/api/Snapshot#getError */
    getError<E extends EndpointInterface>(endpoint: E, ...args: readonly [...Parameters<E>] | readonly [null]): ErrorTypes | undefined;
    getError<E extends Pick<EndpointInterface, 'key'>>(endpoint: E, ...args: readonly [...Parameters<E['key']>] | readonly [null]): ErrorTypes | undefined;
    /**
     * Retrieved memoized value for any Querable schema
     * @see https://dataclient.io/docs/api/Snapshot#get
     */
    get<S extends Queryable>(schema: S, ...args: SchemaArgs<S>): DenormalizeNullable<S> | undefined;
    /**
     * Queries the store for a Querable schema; providing related metadata
     * @see https://dataclient.io/docs/api/Snapshot#getQueryMeta
     */
    getQueryMeta<S extends Queryable>(schema: S, ...args: SchemaArgs<S>): {
        data: DenormalizeNullable<S> | undefined;
        countRef: () => () => void;
    };
}
//# sourceMappingURL=Controller.d.ts.map