UNPKG

stunk

Version:

Stunk is a lightweight, framework-agnostic state management library for JavaScript and TypeScript. It uses chunk-based state units for efficient updates, reactivity, and performance optimization in React, Vue(WIP), Svelte(Coming soon), and Vanilla JS/TS a

668 lines (651 loc) 28.9 kB
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 };