type Subscriber<T> = (newValue: T) => void;
type Middleware<T> = (value: T) => T | undefined;
type NamedMiddleware<T> = {
    name?: string;
    fn: Middleware<T>;
};
interface ChunkConfig<T> {
    name?: string;
    middleware?: (Middleware<T> | NamedMiddleware<T>)[];
    /**
     * When true, setting a value with keys not present in the initial
     * shape throws an error in development. Useful for catching accidental
     * shape mutations early. Has no effect in production. (default: false)
     */
    strict?: boolean;
}
interface Chunk<T> {
    /** Get the current value of the chunk. */
    get: () => T;
    /** Peek at the current value without tracking dependencies. */
    peek: () => T;
    /** Set a new value for the chunk & Update existing value efficiently. */
    set: (newValueOrUpdater: T | ((currentValue: T) => T)) => void;
    /** Subscribe to changes in the chunk. Returns an unsubscribe function. */
    subscribe: (callback: Subscriber<T>) => () => void;
    /** Create a derived chunk based on this chunk's value. */
    derive: <D>(fn: (value: T) => D) => ReadOnlyChunk<D>;
    /** Reset the chunk to its initial value. */
    reset: () => void;
    /** Destroy the chunk and all its subscribers. */
    destroy: () => void;
}
interface ReadOnlyChunk<T> extends Omit<Chunk<T>, 'set' | 'reset'> {
    derive: <D>(fn: (value: T) => D) => ReadOnlyChunk<D>;
}
/**
 * Groups multiple chunk updates into a single notification pass.
 *
 * Without batching, each `set()` call notifies subscribers immediately.
 * Inside a `batch()`, all updates are collected and subscribers are notified
 * once after the callback completes — even if multiple chunks were updated.
 *
 * Batches can be nested safely. Notifications only flush when the outermost
 * batch completes.
 *
 * @param callback - A function containing one or more chunk `set()` calls.
 *
 * @example
 * const x = chunk(0);
 * const y = chunk(0);
 *
 * batch(() => {
 *   x.set(1);
 *   y.set(2);
 * });
 * // Subscribers of x and y are each notified once, not twice.
 */
declare function batch(callback: () => void): void;
/**
 * Creates a reactive state unit — the core primitive of Stunk.
 *
 * A chunk holds a single value and notifies all subscribers whenever that
 * value changes. Values are compared by reference (`===`) for primitives and
 * by the result of middleware processing for objects — so setting the same
 * value twice does not trigger subscribers.
 *
 * @param initialValue - The starting value. Cannot be `undefined`.
 * @param config - Optional configuration for naming, middleware, and strict mode.
 * @returns A `Chunk<T>` with `get()`, `set()`, `peek()`, `subscribe()`, `derive()`, `reset()`, and `destroy()`.
 *
 * @throws If `initialValue` is `undefined`.
 *
 * @example
 * const count = chunk(0);
 * count.get();        // 0
 * count.set(1);       // subscribers notified
 * count.set(n => n + 1); // updater function
 * count.reset();      // back to 0
 *
 * @example
 * // Named chunk with strict mode — throws on unknown keys in dev
 * const user = chunk({ name: 'Alice', age: 30 }, { name: 'user', strict: true });
 *
 * @example
 * // With middleware
 * const positive = chunk(0, {
 *   middleware: [nonNegativeValidator]
 * });
 */
declare function chunk<T>(initialValue: T, config?: ChunkConfig<T>): Chunk<T>;

interface ChunkMeta {
    name: string;
    id: number;
}
declare function isValidChunkValue(value: unknown): boolean;
declare function isChunk<T>(value: unknown): value is Chunk<T>;
declare function getChunkMeta<T>(chunk: Chunk<T>): ChunkMeta | undefined;

interface Computed<T> extends ReadOnlyChunk<T> {
    /** Checks if the computed value needs to be recalculated due to dependency changes. */
    isDirty: () => boolean;
    /** Manually forces recalculation of the computed value from its dependencies. */
    recompute: () => void;
}
/**
 * Creates a derived value that automatically tracks its dependencies and
 * recomputes lazily when any of them change.
 *
 * Dependencies are discovered automatically — any chunk whose `.get()` is
 * called inside `computeFn` is tracked. Use `.peek()` inside the function
 * to read a value without tracking it as a dependency.
 *
 * The computed value is cached and only recalculated when a dependency
 * changes and the value is accessed (lazy) or when active subscribers exist
 * (eager). Object values are compared with shallow equality to prevent
 * unnecessary subscriber notifications.
 *
 * @param computeFn - A pure function that derives the computed value.
 * @returns A read-only `Computed<T>` with `isDirty()`, `recompute()`, `derive()`, `subscribe()`, `peek()`, and `destroy()`.
 */
declare function computed<T>(computeFn: () => T): Computed<T>;

interface SelectOptions {
    /**
     * When `true`, uses shallow equality to compare selected values.
     * Prevents unnecessary subscriber notifications when the selected
     * object is a new reference but has the same property values.
     */
    useShallowEqual?: boolean;
}
/**
 * Creates a read-only derived chunk that tracks a slice of a source chunk.
 *
 * Only notifies subscribers when the selected value actually changes —
 * updates to unselected parts of the source are ignored.
 *
 * @param sourceChunk - The chunk to select from.
 * @param selector - A function that extracts the desired slice.
 * @param options.useShallowEqual - When `true`, uses shallow equality to
 *   compare selected values — prevents unnecessary updates for objects.
 * @returns A `ReadOnlyChunk<S>` that updates only when the selected value changes.
 *
 * @example
 * const user = chunk({ name: 'Alice', age: 30 });
 * const name = select(user, u => u.name);
 * name.get(); // 'Alice'
 *
 * // age changes — name subscribers are NOT notified
 * user.set({ name: 'Alice', age: 31 });
 *
 * @example
 * // Shallow equality — prevents updates when object values are the same
 * const details = select(user, u => u.details, { useShallowEqual: true });
 */
declare function select<T, S>(sourceChunk: Chunk<T> | ReadOnlyChunk<T>, selector: (value: T) => S, options?: SelectOptions): ReadOnlyChunk<S>;

/**
 * Middleware that logs every value passed to `set()` to the console.
 *
 * @example
 * const count = chunk(0, { middleware: [logger()] });
 * count.set(5); // logs: "Setting value: 5"
 */
declare function logger<T>(): Middleware<T>;

/**
 * Middleware that throws if a numeric value is set below zero.
 *
 * @example
 * const balance = chunk(100, { middleware: [nonNegativeValidator] });
 * balance.set(-1); // throws: "Value must be non-negative!"
 */
declare const nonNegativeValidator: Middleware<number>;

interface ChunkWithHistory<T> extends Chunk<T> {
    /** Reverts to the previous state (if available). */
    undo: () => void;
    /** Moves to the next state (if available). */
    redo: () => void;
    /** Returns true if there is a previous state to revert to. */
    canUndo: () => boolean;
    /** Returns true if there is a next state to move to. */
    canRedo: () => boolean;
    /** Returns an array of all the values in the history. */
    getHistory: () => T[];
    /** Clears the history, keeping only the current value. */
    clearHistory: () => void;
}
/**
 * Wraps a chunk with undo/redo history tracking.
 *
 * Every `set()` call is recorded. `undo()` and `redo()` move through the stack.
 * Branching is supported — calling `set()` after `undo()` discards forward history.
 *
 * @param baseChunk - The chunk to wrap.
 * @param options.maxHistory - Max entries to keep (default: 100).
 * @param options.skipDuplicates - `true` skips strictly equal values.
 *   `'shallow'` also skips shallowly equal objects.
 *
 * @example
 * const count = chunk(0);
 * const tracked = history(count);
 * tracked.set(1); tracked.set(2);
 * tracked.undo(); // 1
 * tracked.redo(); // 2
 */
declare function history<T>(baseChunk: Chunk<T>, options?: {
    maxHistory?: number;
    /**
     * true — skip entries that are strictly equal (===) to the current value.
     * 'shallow' — also skip entries that are shallowly equal to the current value.
     */
    skipDuplicates?: boolean | "shallow";
}): ChunkWithHistory<T>;

interface PersistOptions<T> {
    /** Storage key (required). */
    key: string;
    /** Storage engine (default: localStorage). */
    storage?: Storage;
    /** Serialize value to string (default: JSON.stringify). */
    serialize?: (value: T) => string;
    /** Deserialize string to value (default: JSON.parse). */
    deserialize?: (value: string) => T;
    /** Called on load/save errors and type mismatches. */
    onError?: (error: Error, operation: 'load' | 'save') => void;
}
interface PersistedChunk<T> extends Chunk<T> {
    /** Remove the persisted key from storage without destroying the chunk. */
    clearStorage: () => void;
}
/**
 * Wraps a chunk with automatic persistence to a storage engine.
 *
 * Loads any saved value on creation. Saves on every `set()`.
 * Gracefully disabled in SSR when no storage is available.
 *
 * @param baseChunk - The chunk to wrap.
 * @param options.key - Storage key (required).
 * @param options.storage - Storage engine (default: `localStorage`).
 * @param options.serialize - Custom serializer (default: `JSON.stringify`).
 * @param options.deserialize - Custom deserializer (default: `JSON.parse`).
 * @param options.onError - Called on load/save errors or type mismatches.
 *
 * @example
 * const user = chunk({ name: 'Alice' });
 * const persisted = persist(user, { key: 'user' });
 * persisted.set({ name: 'Bob' }); // saved to localStorage
 * persisted.clearStorage();       // removes the key
 */
declare function persist<T>(baseChunk: Chunk<T>, options: PersistOptions<T>): PersistedChunk<T>;

declare const index$1_history: typeof history;
declare const index$1_logger: typeof logger;
declare const index$1_nonNegativeValidator: typeof nonNegativeValidator;
declare const index$1_persist: typeof persist;
declare namespace index$1 {
  export { index$1_history as history, index$1_logger as logger, index$1_nonNegativeValidator as nonNegativeValidator, index$1_persist as persist };
}

interface AsyncState<T, E extends Error> {
    loading: boolean;
    error: E | null;
    data: T | null;
    lastFetched?: number;
    /** True when showing previous data while new data is loading (keepPreviousData: true) */
    isPlaceholderData?: boolean;
}
interface PaginationState {
    page: number;
    pageSize: number;
    total?: number;
    hasMore?: boolean;
    /** Current cursor — only populated when using cursor-based pagination */
    cursor?: string;
}
interface AsyncStateWithPagination<T, E extends Error> extends AsyncState<T, E> {
    pagination?: PaginationState;
}
interface ParamAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}> extends AsyncChunk<T, E> {
    setParams: (params: Partial<Record<keyof P, P[keyof P] | null>>) => void;
    clearParams: () => void;
    reload: (params?: Partial<P>) => Promise<void>;
    refresh: (params?: Partial<P>) => Promise<void>;
}
interface PaginatedParamAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}> extends PaginatedAsyncChunk<T, E> {
    setParams: (params: Partial<Record<keyof P, P[keyof P] | null>>) => void;
    clearParams: () => void;
    reload: (params?: Partial<P>) => Promise<void>;
    refresh: (params?: Partial<P>) => Promise<void>;
}
interface FetcherResponse<T> {
    data: T;
    total?: number;
    hasMore?: boolean;
    /** Next cursor — only used when `pagination.cursorMode` is configured */
    cursor?: string;
}
interface CursorModeConfig<T> {
    /**
     * Extracts the next cursor from a fetch response. Return `undefined`
     * when there are no more pages.
     */
    getNextCursor: (response: FetcherResponse<T>) => string | undefined;
}
interface AsyncChunkOptions<T, E extends Error = Error, P extends Record<string, any> = {}> {
    /** Deduplication key — concurrent calls with the same key share one in-flight request */
    key?: string;
    /** Seed data shown before the first fetch completes */
    initialData?: T | null;
    /** Disable fetching until ready — pass a function for dynamic evaluation */
    enabled?: boolean | ((params: Partial<P>) => boolean);
    /** Called after every successful fetch */
    onSuccess?: (data: T) => void;
    /** Called when all retries are exhausted */
    onError?: (error: E) => void;
    /** Number of retries on failure (default: 0) */
    retryCount?: number;
    /** Delay in ms between retries (default: 1000) */
    retryDelay?: number;
    /** Show previous data while refetching — prevents UI flicker on param changes (default: false) */
    keepPreviousData?: boolean;
    /**
     * Clear data to null immediately when params change via setParams(), before
     * the new fetch resolves. Eliminates stale data flash when navigating between
     * detail views that share a single chunk. (default: false)
     *
     * @example
     * // jobDetailChunk will show null (loading state) immediately when ref changes,
     * // instead of showing the previous job's data while the new one loads.
     * export const jobDetailChunk = asyncChunk(
     *   (params: { ref: string }) => jobsApi.getJobDetail(params.ref),
     *   { staleTime: 0, clearOnParamChange: true }
     * );
     */
    clearOnParamChange?: boolean;
    /** Time in ms before data is considered stale (default: 0) */
    staleTime?: number;
    /** Time in ms to cache data after last subscriber leaves (default: 300_000) */
    cacheTime?: number;
    /** Auto-refetch interval in ms */
    refetchInterval?: number;
    /** Refetch when window regains focus (default: false) */
    refetchOnWindowFocus?: boolean;
    /**
    * When true, useAsyncChunk gives each calling component its own
    * independent instance of this chunk instead of sharing the module-level
    * singleton. Use for parameterized/filtered data (paginated lists, search
    * results) where multiple simultaneous consumers must not share state.
    * Leave false (default) for true app-wide singletons (current user,
    * wallet balance, notification list) that must stay in sync everywhere.
    * (default: false)
    */
    scoped?: boolean;
    pagination?: {
        /** Initial page number (default: 1) */
        initialPage?: number;
        /** Items per page (default: 10) */
        pageSize?: number;
        /** Replace data on each page load, or accumulate for infinite scroll (default: 'replace') */
        mode?: 'replace' | 'accumulate';
        /**
         * Switches the chunk to cursor-based pagination. When set, `page` is
         * ignored — the chunk tracks an opaque `cursor` string supplied by
         * your fetcher's response instead of an incrementing page number.
         */
        cursorMode?: CursorModeConfig<T>;
    };
}
interface AsyncChunk<T, E extends Error = Error> extends Chunk<AsyncStateWithPagination<T, E>> {
    /** Force a fresh fetch, ignoring stale time */
    reload: (params?: any) => Promise<void>;
    /** Fetch only if data is stale — respects staleTime */
    refresh: (params?: any) => Promise<void>;
    /** Update data directly without a network request */
    mutate: (mutator: (currentData: T | null) => T | null) => void;
    /** Reset to initial state and re-fetch */
    reset: (refetch?: boolean) => void;
    /** Safe cleanup — only tears down if no active subscribers remain */
    cleanup: () => void;
    /** Force cleanup regardless of subscriber count */
    forceCleanup: () => void;
    /** Clear all current params and refetch */
    clearParams: () => void;
    /** Cancel any in-flight request and set loading to false */
    cancel: () => void;
}
interface PaginatedAsyncChunk<T, E extends Error = Error> extends AsyncChunk<T, E> {
    /** Load the next page */
    nextPage: () => Promise<void>;
    /** Load the previous page */
    prevPage: () => Promise<void>;
    /** Jump to a specific page */
    goToPage: (page: number) => Promise<void>;
    /** Reset pagination to page 1 and re-fetch */
    resetPagination: () => Promise<void>;
}
declare function asyncChunk<T, E extends Error = Error>(fetcher: () => Promise<T | FetcherResponse<T>>, options?: Omit<AsyncChunkOptions<T, E>, 'pagination'>): AsyncChunk<T, E>;
declare function asyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}>(fetcher: (params: P) => Promise<T | FetcherResponse<T>>, options?: Omit<AsyncChunkOptions<T, E, P>, 'pagination'>): ParamAsyncChunk<T, E, P>;
/**
 * Creates a paginated async state unit — always returns `PaginatedParamAsyncChunk`
 * with `nextPage`/`prevPage`/`goToPage`/`resetPagination`.
 */
declare function paginatedAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}>(fetcher: (params: P & {
    page?: number;
    pageSize: number;
    cursor?: string;
}) => Promise<FetcherResponse<T>>, options: AsyncChunkOptions<T, E, P> & {
    pagination: NonNullable<AsyncChunkOptions<T, E, P>['pagination']>;
}): PaginatedParamAsyncChunk<T, E, P>;

type InfiniteAsyncChunkOptions<T, E extends Error = Error> = Omit<AsyncChunkOptions<T[], E>, 'pagination'> & {
    /** Items per page (default: 10) */
    pageSize?: number;
    /**
     * Use cursor-based pagination instead of page-number based.
     * Required when the backend returns an opaque cursor (e.g. base64-encoded)
     * rather than supporting page numbers directly.
     */
    cursorMode?: CursorModeConfig<T[]>;
};
type InfiniteAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}> = PaginatedParamAsyncChunk<T[], E, P & {
    page?: number;
    pageSize: number;
    cursor?: string;
}>;
/**
 * Creates an infinite scroll async chunk that accumulates pages.
 *
 * Supports both page-number pagination (default) and cursor-based pagination
 * via `options.cursorMode` — use cursor mode when your backend returns an
 * opaque `nextCursor` rather than working with page numbers.
 *
 * @example
 * // Page-based (default)
 * const posts = infiniteAsyncChunk(
 *   async ({ page, pageSize }) => fetchPosts({ page, pageSize }),
 *   { pageSize: 20 }
 * );
 *
 * @example
 * // Cursor-based
 * const conversations = infiniteAsyncChunk(
 *   async ({ cursor, pageSize }) => {
 *     const res = await listConversations({ cursor, limit: pageSize });
 *     return { data: res.data, hasMore: res.hasMore, cursor: res.nextCursor };
 *   },
 *   { pageSize: 20, cursorMode: { getNextCursor: (res) => res.cursor } }
 * );
 */
declare function infiniteAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}>(fetcher: (params: P & {
    page?: number;
    pageSize: number;
    cursor?: string;
}) => Promise<{
    data: T[];
    hasMore?: boolean;
    total?: number;
    cursor?: string;
}>, options?: InfiniteAsyncChunkOptions<T, E>): InfiniteAsyncChunk<T, E, P>;

type InferAsyncData<T> = T extends AsyncChunk<infer U, Error> ? U : never;
type CombinedData<T extends Record<string, AsyncChunk<any>>> = {
    [K in keyof T]: InferAsyncData<T[K]> | null;
};
type CombinedState<T extends Record<string, AsyncChunk<any>>> = {
    loading: boolean;
    error: Error | null;
    errors: Partial<{
        [K in keyof T]: Error;
    }>;
    data: CombinedData<T>;
};

/**
 * Combines multiple async chunks into a single unified state chunk.
 *
 * The result tracks `loading` (true if any chunk is loading), `error` (first
 * error encountered), `errors` (per-chunk errors), and `data` (per-chunk data).
 *
 * @param chunks - A record of named `AsyncChunk` instances.
 * @returns A `Chunk<CombinedState<T>>` that reflects the live state of all inputs.
 *
 * @example
 * const combined = combineAsyncChunks({ user: userChunk, posts: postsChunk });
 * combined.get(); // { loading, error, errors, data: { user, posts } }
 */
declare function combineAsyncChunks<T extends Record<string, AsyncChunk<any>>>(chunks: T): Chunk<CombinedState<T>>;

interface GlobalQueryConfig {
    /**
     * Default configuration applied to all asyncChunk instances.
     * Per-chunk options always override these defaults.
     */
    query?: {
        /** Time in ms before data is considered stale (default: 0) */
        staleTime?: number;
        /** Time in ms to cache data after last subscriber leaves (default: 300_000) */
        cacheTime?: number;
        /** Auto-refetch interval in ms */
        refetchInterval?: number;
        /** Refetch when window regains focus (default: false) */
        refetchOnWindowFocus?: boolean;
        /** Number of retries on failure (default: 0) */
        retryCount?: number;
        /** Delay in ms between retries (default: 1000) */
        retryDelay?: number;
        /** Global error handler — called when all retries are exhausted */
        onError?: (error: Error) => void;
        /** Global success handler — called after every successful fetch */
        onSuccess?: (data: unknown) => void;
    };
    /**
     * Default configuration applied to all mutation instances.
     * Reserved for when mutation() ships — per-mutation options always override.
     */
    mutation?: {
        /** Global error handler for mutations */
        onError?: (error: Error) => void;
        /** Global success handler for mutations */
        onSuccess?: (data: unknown) => void;
    };
}
/**
 * Configures global defaults for all `asyncChunk` and `mutation` instances.
 *
 * Call this once at app entry — before any `asyncChunk` is created.
 * Per-chunk options always take precedence over these defaults.
 *
 * @param config.query  - Defaults for all async chunks (staleTime, retryCount, onError, etc.)
 * @param config.mutation - Defaults for all mutations (onError, onSuccess)
 *
 * @example
 * import { configureQuery } from "stunk/query";
 *
 * configureQuery({
 *   query: {
 *     staleTime: 30_000,
 *     retryCount: 3,
 *     refetchOnWindowFocus: true,
 *     onError: (err) => toast.error(err.message),
 *   },
 *   mutation: {
 *     onError: (err) => toast.error(err.message),
 *     onSuccess: () => toast.success("Done!"),
 *   },
 * });
 */
declare function configureQuery(config: GlobalQueryConfig): void;
/**
 * Returns the current global query config.
 * Used internally by asyncChunk and mutation to read defaults.
 */
declare function getGlobalQueryConfig(): GlobalQueryConfig;
/**
 * Resets the global config back to defaults.
 * Primarily useful in tests to avoid config bleed between test cases.
 *
 * @example
 * afterEach(() => resetQueryConfig());
 */
declare function resetQueryConfig(): void;

type MutationFn<TData, TVariables> = (variables: TVariables) => Promise<TData>;
interface MutationOptions<TData, TError extends Error = Error, TVariables = void> {
    /** Chunks to automatically reload after a successful mutation */
    invalidates?: AsyncChunk<any, any>[];
    /** Called after a successful mutation with the returned data and original variables */
    onSuccess?: (data: TData, variables: TVariables) => void;
    /** Called when the mutation fails with the error and original variables */
    onError?: (error: TError, variables: TVariables) => void;
    /** Called after every attempt — success or failure — useful for unconditional cleanup */
    onSettled?: (data: TData | null, error: TError | null, variables: TVariables) => void;
}
interface MutationState<TData, TError extends Error = Error> {
    /** True while the mutation is in progress */
    loading: boolean;
    /** The data returned from the last successful mutation, or null */
    data: TData | null;
    /** The error from the last failed mutation, or null */
    error: TError | null;
    /** True after a successful mutation — distinct from data since data can be null on success */
    isSuccess: boolean;
}
interface MutationResult<TData, TError extends Error = Error> {
    /** The returned data on success, or null on failure */
    data: TData | null;
    /** The error on failure, or null on success */
    error: TError | null;
}
interface Mutation<TData, TError extends Error = Error, TVariables = void> {
    /**
     * Execute the mutation. Always resolves — never throws.
     * Returns `{ data, error }` so you can await it or fire and forget safely.
     *
     * @example
     * // Fire and forget — safe
     * createPost.mutate({ title: 'Hello' });
     *
     * // Await for local UI control — no try/catch needed
     * const { data, error } = await createPost.mutate({ title: 'Hello' });
     * if (!error) router.push('/posts');
     */
    mutate: (...args: TVariables extends void ? [] : [variables: TVariables]) => Promise<MutationResult<TData, TError>>;
    /** Returns the current mutation state */
    get: () => MutationState<TData, TError>;
    /** Subscribe to state changes. Returns an unsubscribe function. */
    subscribe: (callback: (state: MutationState<TData, TError>) => void) => () => void;
    /** Reset state back to initial — clears data, error, isSuccess */
    reset: () => void;
}
/**
 * Creates a reactive mutation for POST, PUT, DELETE, or any async side effect.
 *
 * Always returns a promise that resolves — never throws.
 * On success, automatically reloads any chunks listed in `invalidates`.
 *
 * @param mutationFn - Async function that performs the side effect.
 * @param options.invalidates - Chunks to reload after a successful mutation.
 * @param options.onSuccess - Called with data and variables on success.
 * @param options.onError - Called with error and variables on failure.
 * @param options.onSettled - Called after every attempt regardless of outcome.
 *
 * @example
 * const createPost = mutation(
 *   async (data: NewPost) => fetchAPI('/posts', { method: 'POST', body: data }),
 *   {
 *     invalidates: [postsChunk],
 *     onSuccess: (data) => toast.success('Post created!'),
 *     onError: (err) => toast.error(err.message),
 *   }
 * );
 *
 * // Fire and forget
 * createPost.mutate({ title: 'Hello' });
 *
 * // Await for local control
 * const { data, error } = await createPost.mutate({ title: 'Hello' });
 * if (!error) router.push('/posts');
 */
declare function mutation<TData, TError extends Error = Error, TVariables = void>(mutationFn: MutationFn<TData, TVariables>, options?: MutationOptions<TData, TError, TVariables>): Mutation<TData, TError, TVariables>;

type index_AsyncChunk<T, E extends Error = Error> = AsyncChunk<T, E>;
type index_AsyncState<T, E extends Error> = AsyncState<T, E>;
type index_AsyncStateWithPagination<T, E extends Error> = AsyncStateWithPagination<T, E>;
type index_GlobalQueryConfig = GlobalQueryConfig;
type index_Mutation<TData, TError extends Error = Error, TVariables = void> = Mutation<TData, TError, TVariables>;
type index_MutationFn<TData, TVariables> = MutationFn<TData, TVariables>;
type index_MutationOptions<TData, TError extends Error = Error, TVariables = void> = MutationOptions<TData, TError, TVariables>;
type index_MutationResult<TData, TError extends Error = Error> = MutationResult<TData, TError>;
type index_MutationState<TData, TError extends Error = Error> = MutationState<TData, TError>;
type index_PaginatedAsyncChunk<T, E extends Error = Error> = PaginatedAsyncChunk<T, E>;
type index_PaginatedParamAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}> = PaginatedParamAsyncChunk<T, E, P>;
declare const index_asyncChunk: typeof asyncChunk;
declare const index_combineAsyncChunks: typeof combineAsyncChunks;
declare const index_configureQuery: typeof configureQuery;
declare const index_getGlobalQueryConfig: typeof getGlobalQueryConfig;
declare const index_infiniteAsyncChunk: typeof infiniteAsyncChunk;
declare const index_mutation: typeof mutation;
declare const index_paginatedAsyncChunk: typeof paginatedAsyncChunk;
declare const index_resetQueryConfig: typeof resetQueryConfig;
declare namespace index {
  export { type index_AsyncChunk as AsyncChunk, type index_AsyncState as AsyncState, type index_AsyncStateWithPagination as AsyncStateWithPagination, type index_GlobalQueryConfig as GlobalQueryConfig, type index_Mutation as Mutation, type index_MutationFn as MutationFn, type index_MutationOptions as MutationOptions, type index_MutationResult as MutationResult, type index_MutationState as MutationState, type index_PaginatedAsyncChunk as PaginatedAsyncChunk, type index_PaginatedParamAsyncChunk as PaginatedParamAsyncChunk, index_asyncChunk as asyncChunk, index_combineAsyncChunks as combineAsyncChunks, index_configureQuery as configureQuery, index_getGlobalQueryConfig as getGlobalQueryConfig, index_infiniteAsyncChunk as infiniteAsyncChunk, index_mutation as mutation, index_paginatedAsyncChunk as paginatedAsyncChunk, index_resetQueryConfig as resetQueryConfig };
}

export { type Chunk, type Middleware, batch, chunk, computed, getChunkMeta, isChunk, isValidChunkValue, index$1 as middleware, index as query, select };
