UNPKG

@pinia/colada

Version:

The smart data fetching layer for Vue.js

1,144 lines (1,143 loc) 80.5 kB
import * as _$vue from "vue"; import { ComponentInternalInstance, ComputedRef, EffectScope, MaybeRefOrGetter, Plugin, ShallowRef } from "vue"; import * as _$pinia from "pinia"; import { Pinia } from "pinia"; //#region src/data-state.d.ts /** * The status of data. * - `pending`: initial state * - `error`: has an error * - `success`: has data */ type DataStateStatus = 'pending' | 'error' | 'success'; /** * Internal base type for data state. * @internal */ interface _DataState_Base<TData, TError> { /** * The last successfully resolved data. */ data: TData; /** * The last rejected error. */ error: TError; /** * The status of the data. * @see {@link DataStateStatus} */ status: DataStateStatus; } interface DataState_Success<TData, TDataInitial> extends _DataState_Base<TData | Exclude<TDataInitial, undefined>, null> { status: 'success'; } interface DataState_Error<TData, TError, TDataInitial> extends _DataState_Base<TData | TDataInitial, TError> { status: 'error'; } interface DataState_Pending<TDataInitial> extends _DataState_Base<TDataInitial, null> { status: 'pending'; } /** * Possible states for data based on its status. */ type DataState<TData, TError, TDataInitial = undefined> = DataState_Success<TData, TDataInitial> | DataState_Error<TData, TError, TDataInitial> | DataState_Pending<TDataInitial>; /** * The status of an async operation tied to pinia colada e.g. queries and mutations. * - `idle`: not loading * - `loading`: currently loading */ type AsyncStatus = 'idle' | 'loading'; //#endregion //#region src/types-extension.d.ts /** * Allows you to extend the default types of the library. * * @example * ```ts * // types-extension.d.ts * import '@pinia/colada' * export {} * declare module '@pinia/colada' { * interface TypesConfig { * defaultError: MyCustomError * queryMeta: { * onErrorMessage?: string * } * } * } * ``` */ interface TypesConfig {} /** * The default error type used. * @internal */ type ErrorDefault = TypesConfig extends Record<'defaultError', infer E> ? E : Error; /** * The meta information stored alongside each query inferred from the {@link TypesConfig}. * @internal */ type QueryMeta = TypesConfig extends Record<'queryMeta', infer M> ? M : Record<string, unknown>; /** * The meta information stored alongside each mutation inferred from the {@link TypesConfig}. * @internal */ type MutationMeta = TypesConfig extends Record<'mutationMeta', infer M> ? M : Record<string, unknown>; //#endregion //#region src/entry-keys.d.ts declare function toCacheKey(key: undefined): undefined; declare function toCacheKey(key: EntryKey): string; declare function toCacheKey(key: EntryKey | undefined): string | undefined; /** * Used for keys * * @internal */ type JSONPrimitive = string | number | boolean | null; /** * Used for keys * * @internal */ type JSONValue = JSONPrimitive | JSONObject | JSONArray; /** * Used for keys. Interface to avoid deep recursion. * * @internal */ type JSONObject = object; /** * Used for keys. Interface to avoid deep recursion. * * @internal */ interface JSONArray extends Array<JSONValue> {} /** * Key used to identify a query or a mutation. Must be a JSON serializable * value. Type is unknwon to avoid annoying type errors like recursive types * and not being able to assign an interface to it due to its index signature. */ type EntryKey = readonly JSONValue[]; /** * Internal symbol used to tag the data type of the entry key. * * @internal */ declare const ENTRY_DATA_TAG: unique symbol; /** * Internal symbol used to tag the error type of the entry key. * * @internal */ declare const ENTRY_ERROR_TAG: unique symbol; /** * Internal symbol used to tag the data initial type of the entry key. * * @internal */ declare const ENTRY_DATA_INITIAL_TAG: unique symbol; /** * Same as {@link EntryKey} but with a data tag that allows inference of the data type. * Used by `defineQueryOptions()`. */ type EntryKeyTagged<TData, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined> = EntryKey & { [ENTRY_DATA_TAG]: TData; [ENTRY_ERROR_TAG]: TError; [ENTRY_DATA_INITIAL_TAG]: TDataInitial; }; //#endregion //#region src/entry-filter.d.ts /** * Base interface for {@link EntryFilter}. * * @internal */ interface EntryFilter_Base<TEntry> { /** * A key to filter the entries. */ key?: EntryKey; /** * If `true`, it will only match the entry of the given `key`, skipping any children entries. * It also makes `key` required. * * @example * ```ts * { key: ['a'], exact: true } * // will match ['a'] but not ['a', 'b'], while * { key: ['a'] } * // will match both * ``` */ exact?: boolean; /** * If `true` or `false`, it will only return entries that match the stale status. If set to `null` or `undefined`, it matches both. * Requires `entry.options` to be set. */ stale?: boolean | null; /** * If `true` or `false`, it will only return entries that match the active status. If set to `null` or `undefined`, it matches both. */ active?: boolean | null; /** * If it has a non _nullish_ value, it only returns the entries with the given status. */ status?: DataStateStatus | null; /** * Pass a predicate to filter the entries. This will be executed for each entry matching the other filters. * @param entry - entry to filter */ predicate?: (entry: TEntry) => boolean; } /** * Filter to get exactly one entry from the cache. Requires the `key` to be set. * * @internal */ interface EntryFilter_Key<TEntry> extends EntryFilter_Base<TEntry> { key: EntryKey; exact: true; } /** * Filter to get multiple matching entries from the cache. * * @internal */ interface EntryFilter_NoKey<TEntry> extends EntryFilter_Base<TEntry> { exact?: false; } /** * Base interface to filter entries from a cache. * * @internal */ type EntryFilter<TEntry> = EntryFilter_NoKey<TEntry> | EntryFilter_Key<TEntry>; //#endregion //#region src/query-store.d.ts /** * Allows defining extensions to the query entry that are returned by `useQuery()`. */ interface UseQueryEntryExtensions<TData, TError, TDataInitial extends TData | undefined = undefined> {} /** * NOTE: Entries could be classes but the point of having all functions within the store is to allow plugins to hook * into actions. */ /** * A query entry in the cache. */ interface UseQueryEntry<TData = unknown, TError = unknown, TDataInitial extends TData | undefined = (unknown extends TData ? unknown : undefined)> { /** * The state of the query. Contains the data, error and status. */ state: ShallowRef<DataState<TData, TError, TDataInitial>>; /** * A placeholder `data` that is initially shown while the query is loading for the first time. This will also show the * `status` as `success` until the query finishes loading (no matter the outcome). */ placeholderData: TDataInitial | TData | null | undefined; /** * The status of the query. */ asyncStatus: ShallowRef<AsyncStatus>; /** * When was this data set in the entry for the last time in ms. It can also * be 0 if the entry has been invalidated. */ when: number; /** * The serialized key associated with this query entry. */ key: EntryKey; /** * Seriaized version of the key. Used to retrieve the entry from the cache. */ keyHash: string; /** * Components and effects scopes that use this query entry. */ deps: Set<EffectScope | ComponentInternalInstance>; /** * Timeout id that scheduled a garbage collection. It is set here to clear it when the entry is used by a different component */ gcTimeout: ReturnType<typeof setTimeout> | undefined; /** * The current pending request. */ pending: null | { /** * The abort controller used to cancel the request and which `signal` is passed to the query function. */ abortController: AbortController; /** * The promise created by `queryCache.fetch` that is currently pending. */ refreshCall: Promise<DataState<TData, TError, TDataInitial>>; /** * When was this `pending` object created. */ when: number; }; /** * Options used to create the query. They can be `null` during hydration but are needed for fetching. This is why * `store.ensure()` sets this property. Note these options might be shared by multiple query entries when the key is * dynamic and that's why some methods like {@link fetch} receive the options as an argument. */ options: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null; /** * Whether the data is stale or not, requires `options.staleTime` to be set. */ readonly stale: boolean; /** * Whether the query is currently being used by a Component or EffectScope (e.g. a store). */ readonly active: boolean; /** * Resolved meta information for this query. This is the computed value * from options.meta (function/ref resolved to raw object). */ meta: QueryMeta; /** * Extensions to the query entry added by plugins. You should only add * properties to the object, not replace it. */ readonly ext: UseQueryEntryExtensions<TData, TError, TDataInitial>; /** * Internal property used in development to detect when a component with an * active query was hot-updated and invalidate the entry. For each component * type (keyed by `__hmrId`) we remember the identity of its `setup` and * `render` functions; a real HMR reload replaces these references while a * plain remount of the same component keeps them identical. Keying by * `__hmrId` is required because multiple distinct component types can share * the same query key — without it, alternating mounts would ping-pong a * single snapshot and falsely invalidate the shared entry. * * @internal */ __hmr?: { /** * Identity of the `setup` and `render` functions last seen for each * component type (keyed by `__hmrId`) that uses this entry. */ components: Map<string, { setup: unknown; render: unknown; }>; }; } /** * Filter object to get entries from the query cache. * * @see {@link QueryCache.getEntries} * @see {@link QueryCache.cancelQueries} * @see {@link QueryCache#invalidateQueries} */ type UseQueryEntryFilter = EntryFilter<UseQueryEntry>; /** * UseQueryEntry method to serialize the entry to JSON. * * @param entry - entry to serialize * @returns Serialized version of the entry */ declare const queryEntry_toJSON: <TData, TError>(entry: UseQueryEntry<TData, TError>) => UseQueryEntryNodeValueSerializd<TData, TError>; /** * A query entry that is defined with {@link defineQuery}. * @internal */ type DefineQueryEntry = [lastEnsuredEntries: UseQueryEntry[], returnValue: unknown, effect: EffectScope, paused: ShallowRef<boolean>]; /** * Composable to get the cache of the queries. As any other composable, it can * be used inside the `setup` function of a component, within another * composable, or in injectable contexts like stores and navigation guards. */ declare const useQueryCache: _$pinia.StoreDefinition<"_pc_query", Pick<{ caches: ShallowRef<Map<string, UseQueryEntry<unknown, unknown, unknown>>, Map<string, UseQueryEntry<unknown, unknown, unknown>>>; ensureDefinedQuery: <T>(fn: () => T) => DefineQueryEntry; /** * Scope to track effects and components that use the query cache. * @internal */ _s: _$vue.Raw<EffectScope>; setQueryData: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey, data: NoInfer<TData> | Exclude<NoInfer<TDataInitial>, undefined> | ((oldData: TData | TDataInitial | undefined) => TData | Exclude<TDataInitial, undefined>)) => void; setQueriesData: <TData = unknown>(filters: UseQueryEntryFilter, updater: (previous: TData | undefined) => TData) => void; getQueryData: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey) => TData | TDataInitial | undefined; invalidateQueries: (filters?: UseQueryEntryFilter, refetchActive?: boolean | "all") => Promise<unknown>; cancelQueries: (filters?: UseQueryEntryFilter, reason?: unknown) => void; invalidate: (entry: UseQueryEntry) => void; fetch: <TData, TError, TDataInitial extends TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null) => Promise<DataState<TData, TError, TDataInitial>>; refresh: <TData, TError, TDataInitial extends TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null) => Promise<DataState<TData, TError, TDataInitial>>; ensure: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(opts: UseQueryOptions<TData, TError, TDataInitial>, previousEntry?: UseQueryEntry<TData, TError, TDataInitial>) => UseQueryEntry<TData, TError, TDataInitial>; extend: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(_entry: UseQueryEntry<TData, TError, TDataInitial>) => void; track: (entry: UseQueryEntry, effect: EffectScope | ComponentInternalInstance | null | undefined) => void; untrack: (entry: UseQueryEntry, effect: EffectScope | ComponentInternalInstance | undefined | null) => void; cancel: (entry: UseQueryEntry, reason?: unknown) => void; create: <TData, TError, TDataInitial extends TData | undefined>(key: EntryKey, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null, initialData?: TDataInitial, error?: TError | null, when?: number, meta?: QueryMeta) => UseQueryEntry<TData, TError, TDataInitial>; remove: (entry: UseQueryEntry) => void; get: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey) => UseQueryEntry<TData, TError, TDataInitial> | undefined; setEntryState: <TData, TError, TDataInitial extends TData | undefined = TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, state: DataState<NoInfer<TData>, NoInfer<TError>, NoInfer<TDataInitial>>) => void; getEntries: (filters?: UseQueryEntryFilter) => UseQueryEntry[]; }, "caches" | "_s">, Pick<{ caches: ShallowRef<Map<string, UseQueryEntry<unknown, unknown, unknown>>, Map<string, UseQueryEntry<unknown, unknown, unknown>>>; ensureDefinedQuery: <T>(fn: () => T) => DefineQueryEntry; /** * Scope to track effects and components that use the query cache. * @internal */ _s: _$vue.Raw<EffectScope>; setQueryData: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey, data: NoInfer<TData> | Exclude<NoInfer<TDataInitial>, undefined> | ((oldData: TData | TDataInitial | undefined) => TData | Exclude<TDataInitial, undefined>)) => void; setQueriesData: <TData = unknown>(filters: UseQueryEntryFilter, updater: (previous: TData | undefined) => TData) => void; getQueryData: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey) => TData | TDataInitial | undefined; invalidateQueries: (filters?: UseQueryEntryFilter, refetchActive?: boolean | "all") => Promise<unknown>; cancelQueries: (filters?: UseQueryEntryFilter, reason?: unknown) => void; invalidate: (entry: UseQueryEntry) => void; fetch: <TData, TError, TDataInitial extends TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null) => Promise<DataState<TData, TError, TDataInitial>>; refresh: <TData, TError, TDataInitial extends TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null) => Promise<DataState<TData, TError, TDataInitial>>; ensure: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(opts: UseQueryOptions<TData, TError, TDataInitial>, previousEntry?: UseQueryEntry<TData, TError, TDataInitial>) => UseQueryEntry<TData, TError, TDataInitial>; extend: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(_entry: UseQueryEntry<TData, TError, TDataInitial>) => void; track: (entry: UseQueryEntry, effect: EffectScope | ComponentInternalInstance | null | undefined) => void; untrack: (entry: UseQueryEntry, effect: EffectScope | ComponentInternalInstance | undefined | null) => void; cancel: (entry: UseQueryEntry, reason?: unknown) => void; create: <TData, TError, TDataInitial extends TData | undefined>(key: EntryKey, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null, initialData?: TDataInitial, error?: TError | null, when?: number, meta?: QueryMeta) => UseQueryEntry<TData, TError, TDataInitial>; remove: (entry: UseQueryEntry) => void; get: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey) => UseQueryEntry<TData, TError, TDataInitial> | undefined; setEntryState: <TData, TError, TDataInitial extends TData | undefined = TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, state: DataState<NoInfer<TData>, NoInfer<TError>, NoInfer<TDataInitial>>) => void; getEntries: (filters?: UseQueryEntryFilter) => UseQueryEntry[]; }, never>, Pick<{ caches: ShallowRef<Map<string, UseQueryEntry<unknown, unknown, unknown>>, Map<string, UseQueryEntry<unknown, unknown, unknown>>>; ensureDefinedQuery: <T>(fn: () => T) => DefineQueryEntry; /** * Scope to track effects and components that use the query cache. * @internal */ _s: _$vue.Raw<EffectScope>; setQueryData: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey, data: NoInfer<TData> | Exclude<NoInfer<TDataInitial>, undefined> | ((oldData: TData | TDataInitial | undefined) => TData | Exclude<TDataInitial, undefined>)) => void; setQueriesData: <TData = unknown>(filters: UseQueryEntryFilter, updater: (previous: TData | undefined) => TData) => void; getQueryData: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey) => TData | TDataInitial | undefined; invalidateQueries: (filters?: UseQueryEntryFilter, refetchActive?: boolean | "all") => Promise<unknown>; cancelQueries: (filters?: UseQueryEntryFilter, reason?: unknown) => void; invalidate: (entry: UseQueryEntry) => void; fetch: <TData, TError, TDataInitial extends TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null) => Promise<DataState<TData, TError, TDataInitial>>; refresh: <TData, TError, TDataInitial extends TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null) => Promise<DataState<TData, TError, TDataInitial>>; ensure: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(opts: UseQueryOptions<TData, TError, TDataInitial>, previousEntry?: UseQueryEntry<TData, TError, TDataInitial>) => UseQueryEntry<TData, TError, TDataInitial>; extend: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(_entry: UseQueryEntry<TData, TError, TDataInitial>) => void; track: (entry: UseQueryEntry, effect: EffectScope | ComponentInternalInstance | null | undefined) => void; untrack: (entry: UseQueryEntry, effect: EffectScope | ComponentInternalInstance | undefined | null) => void; cancel: (entry: UseQueryEntry, reason?: unknown) => void; create: <TData, TError, TDataInitial extends TData | undefined>(key: EntryKey, options?: UseQueryOptionsWithDefaults<TData, TError, TDataInitial> | null, initialData?: TDataInitial, error?: TError | null, when?: number, meta?: QueryMeta) => UseQueryEntry<TData, TError, TDataInitial>; remove: (entry: UseQueryEntry) => void; get: <TData = unknown, TError = Error, TDataInitial extends TData | undefined = undefined>(key: EntryKeyTagged<TData, TError, TDataInitial> | EntryKey) => UseQueryEntry<TData, TError, TDataInitial> | undefined; setEntryState: <TData, TError, TDataInitial extends TData | undefined = TData | undefined>(entry: UseQueryEntry<TData, TError, TDataInitial>, state: DataState<NoInfer<TData>, NoInfer<TError>, NoInfer<TDataInitial>>) => void; getEntries: (filters?: UseQueryEntryFilter) => UseQueryEntry[]; }, "ensureDefinedQuery" | "setQueryData" | "setQueriesData" | "getQueryData" | "invalidateQueries" | "cancelQueries" | "invalidate" | "fetch" | "refresh" | "ensure" | "extend" | "track" | "untrack" | "cancel" | "create" | "remove" | "get" | "setEntryState" | "getEntries">>; /** * The cache of the queries. It's the store returned by {@link useQueryCache}. */ type QueryCache = ReturnType<typeof useQueryCache>; /** * Checks if the given object is a query cache. Used in SSR to apply custom serialization. * * @param cache - the object to check * * @see {@link QueryCache} * @see {@link serializeQueryCache} */ declare function isQueryCache(cache: unknown): cache is QueryCache; /** * Raw data of a query entry. Can be serialized from the server and used to * hydrate the store. Internal because the format is considered an * implementation detail that prioritizes size and performance. * * @internal */ type UseQueryEntryNodeValueSerializd<TData = unknown, TError = unknown> = [ /** * The data returned by the query. */ data: TData | undefined, /** * The error thrown by the query. */ error: TError | null, /** * When was this data fetched the last time in ms */ when?: number, /** * Meta information associated with the query */ meta?: QueryMeta]; /** * Hydrates the query cache with the serialized cache. Used during SSR. * * @param queryCache - query cache * @param serializedCache - serialized cache */ declare function hydrateQueryCache(queryCache: QueryCache, serializedCache: Record<string, UseQueryEntryNodeValueSerializd>): void; /** * Serializes the query cache to a compressed version. Used during SSR. * * @param queryCache - query cache */ declare function serializeQueryCache(queryCache: QueryCache): Record<string, UseQueryEntryNodeValueSerializd>; //#endregion //#region src/query-options.d.ts /** * Possible values for `refetchOnMount`, `refetchOnWindowFocus`, and `refetchOnReconnect`. * `true` refetches if data is stale (calles `refresh()`), `false` never refetches, `'always'` always refetches. */ type RefetchOnControl = boolean | 'always'; /** * Options for queries that can be globally overridden. */ interface UseQueryOptionsGlobal { /** * Whether the query should be enabled or not. If `false`, the query will not * be executed until `refetch()` or `refresh()` is called. If it becomes * `true`, the query will be refreshed. */ enabled?: MaybeRefOrGetter<boolean>; /** * Time in ms after which the data is considered stale and will be refreshed * on next read. * * @default 5000 (5 seconds) */ staleTime?: number; /** * Time in ms after which, once the data is no longer being used, it will be * garbage collected to free resources. Set to `false` to disable garbage * collection. * * @default 300_000 (5 minutes) */ gcTime?: number | false; /** * Whether to refetch the query when the component is mounted. * @default true */ refetchOnMount?: MaybeRefOrGetter<RefetchOnControl>; /** * Whether to refetch the query when the window regains focus. * @default true */ refetchOnWindowFocus?: MaybeRefOrGetter<RefetchOnControl>; /** * Whether to refetch the query when the network reconnects. * @default true */ refetchOnReconnect?: MaybeRefOrGetter<RefetchOnControl>; /** * A placeholder data that is initially shown while the query is loading for * the first time. This will also show the `status` as `success` until the * query finishes loading (no matter the outcome of the query). Note: unlike * with `initialData`, the placeholder does not change the cache state. */ placeholderData?: (previousData: unknown, previousEntry: UseQueryEntry | undefined) => any; /** * Whether to catch errors during SSR (onServerPrefetch) when the query fails. * @default false */ ssrCatchError?: boolean; } /** * Context object passed to the `query` function of `useQuery()`. * @see {@link UseQueryOptions} */ interface UseQueryFnContext<TData = unknown, TError = unknown, TDataInitial extends TData | undefined = (unknown extends TData ? unknown : undefined)> { /** * `AbortSignal` instance attached to the query call. If the call becomes * outdated (e.g. due to a new call with the same key), the signal will be * aborted. */ signal: AbortSignal; /** * The query entry associated with the current query. */ entry: UseQueryEntry<TData, TError, TDataInitial>; } /** * Type-only symbol to keep the type * * @internal */ declare const tErrorSymbol: unique symbol; /** * Helper function type to keep callback arguments bivariant in object properties. * * @internal */ type BivariantCallback<TArgs extends readonly unknown[], TResult> = { bivarianceHack(...args: TArgs): TResult; }['bivarianceHack']; /** * Options for `useQuery()`. Can be extended by plugins. * * @example * ```ts * // use-query-plugin.d.ts * export {} // needed * declare module '@pinia/colada' { * interface UseQueryOptions { * // Whether to refresh the data when the component is mounted. * refreshOnMount?: boolean * } * } * ``` */ interface UseQueryOptions<TData = unknown, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined> extends Pick<UseQueryOptionsGlobal, 'gcTime' | 'enabled' | 'refetchOnMount' | 'refetchOnReconnect' | 'refetchOnWindowFocus' | 'staleTime' | 'ssrCatchError'> { /** * The key used to identify the query. Array of primitives **without** * reactive values or a reactive array or getter. It should be treaded as an * array of dependencies of your queries, e.g. if you use the * `route.params.id` property, it should also be part of the key: * * ```ts * import { useRoute } from 'vue-router' * import { useQuery } from '@pinia/colada' * * const route = useRoute() * const { data } = useQuery({ * // pass a getter function (or computed, ref, etc.) to ensure reactivity * key: () => ['user', route.params.id], * query: () => fetchUser(route.params.id), * }) * ``` */ key: MaybeRefOrGetter<EntryKey>; /** * The function that will be called to fetch the data. It **must** be async. */ query(context: UseQueryFnContext<unknown, TError, TDataInitial>): Promise<TData>; /** * The data which is initially set to the query while the query is loading * for the first time. Note: unlike with {@link placeholderData}, setting the * initial data changes the state of the query (it will be set to `success`). * * @see {@link placeholderData} */ initialData?: () => TDataInitial; /** * The timestamp (in milliseconds) when the initial data was last updated. * This determines the staleness of the {@link initialData}. If not provided, * defaults to `Date.now()` when initial data is set. * * @default Date.now() when {@link initialData} is used * * @example * ```ts * // Using a static timestamp * useQuery({ * key: ['user'], * query: () => fetchUser(), * initialData: () => cachedUser, * initialDataUpdatedAt: 1234567890000 * }) * * // Using a function * useQuery({ * key: ['user'], * query: () => fetchUser(), * initialData: () => cachedUser, * initialDataUpdatedAt: () => Number(localStorage.getItem('userTimestamp')) * }) * ``` */ initialDataUpdatedAt?: number | (() => number); /** * A placeholder data that is initially shown while the query is loading for * the first time. This will also show the `status` as `success` until the * query finishes loading (no matter the outcome of the query). Note: unlike * with {@link initialData}, the placeholder does not change the cache state. * * @see {@link initialData} */ placeholderData?: NoInfer<TDataInitial> | NoInfer<TData> | BivariantCallback<[previousData: TData | undefined, previousEntry: UseQueryEntry<TData, TError, TDataInitial> | undefined], NoInfer<TDataInitial> | NoInfer<TData> | undefined>; /** * Meta information associated with the query. Can be a raw object, a function * returning the meta object, or a ref containing the meta object. * The meta is resolved when the entry is **created** and stored in * `entry.meta`. * * **Note**: Meta is serialized during SSR, so it must be serializable (no functions, * class instances, or circular references). You can also completely ignore * it during SSR with a ternary: `meta: import.meta.ev.SSR ? {} : actualMeta` * * @example * ```ts * // SSR-safe: simple serializable data * useQuery({ * key: ['user', id], * query: () => fetchUser(id), * meta: { errorMessage: true } * }) * * // Using a function to compute meta * useQuery({ * key: ['user', id], * query: () => fetchUser(id), * meta: () => ({ timestamp: Date.now() }) * }) * * // Skipping meta during SSR * useQuery({ * key: ['user', id], * query: () => fetchUser(id), * meta: { * onError: import.meta.env.SSR ? undefined : ((err) => console.log('error')) * } * }) * ``` */ meta?: MaybeRefOrGetter<QueryMeta>; /** * Ghost property to ensure TError generic parameter is included in the * interface structure. This property should never be used directly and is * only for type system correctness. it could be removed in the future if the * type can be inferred in any other way. * * @internal */ readonly [tErrorSymbol]?: TError; } /** * Default options for `useQuery()`. Modifying this object will affect all the queries that don't override these */ declare const USE_QUERY_DEFAULTS: { staleTime: number; gcTime: NonNullable<UseQueryOptions["gcTime"]>; refetchOnWindowFocus: NonNullable<UseQueryOptions["refetchOnWindowFocus"]>; refetchOnReconnect: NonNullable<UseQueryOptions["refetchOnReconnect"]>; refetchOnMount: NonNullable<UseQueryOptions["refetchOnMount"]>; enabled: MaybeRefOrGetter<boolean>; }; type UseQueryOptionsWithDefaults<TData = unknown, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined> = UseQueryOptions<TData, TError, TDataInitial> & typeof USE_QUERY_DEFAULTS; //#endregion //#region src/use-query.d.ts /** * Return type of `useQuery()`. */ interface UseQueryReturn<TData = unknown, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined> extends UseQueryEntryExtensions<TData, TError, TDataInitial> { /** * The state of the query. Contains its data, error, and status. */ state: ComputedRef<DataState<TData, TError, TDataInitial>>; /** * Status of the query. Becomes `'loading'` while the query is being fetched, is `'idle'` otherwise. */ asyncStatus: ComputedRef<AsyncStatus>; /** * The last successful data resolved by the query. Alias for `state.value.data`. * * @see {@link state} */ data: ShallowRef<TData | TDataInitial>; /** * The error rejected by the query. Alias for `state.value.error`. * * @see {@link state} */ error: ShallowRef<TError | null>; /** * The status of the query. Alias for `state.value.status`. * * @see {@link state} * @see {@link DataStateStatus} */ status: ShallowRef<DataStateStatus>; /** * Returns whether the request is still pending its first call. Alias for `status.value === 'pending'` */ isPending: ComputedRef<boolean>; /** * Returns whether the `data` is the `placeholderData`. */ isPlaceholderData: ComputedRef<boolean>; /** * Returns whether the request is currently fetching data. Alias for `asyncStatus.value === 'loading'` */ isLoading: ShallowRef<boolean>; /** * Ensures the current data is fresh. If the data is stale, refetch, if not return as is. * * @param throwOnError - whether to throw an error if the refresh fails. Defaults to `false` * @returns a promise that resolves when the refresh is done */ refresh: (throwOnError?: boolean) => Promise<DataState<TData, TError, TDataInitial>>; /** * Ignores fresh data and triggers a new fetch * * @param throwOnError - whether to throw an error if the fetch fails. Defaults to `false` * @returns a promise that resolves when the fetch is done */ refetch: (throwOnError?: boolean) => Promise<DataState<TData, TError, TDataInitial>>; } /** * Ensures and return a shared query state based on the `key` option. * * @param options - The options of the query * * @example * ```ts * const { state } = useQuery({ * key: ['documents'], * query: () => getDocuments(), * }) * ``` */ declare function useQuery<TData, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined>(options: UseQueryOptions<TData, TError, TDataInitial> | (() => DefineQueryOptions<TData, TError, TDataInitial>)): UseQueryReturn<TData, TError, TDataInitial>; //#endregion //#region src/utils.d.ts /** * Type that represents a value that can be an array or a single value. * * @internal */ type _MaybeArray<T> = T | T[]; /** * Checks if a type is exactly `any`. * * @internal */ type IsAny<T> = 0 extends 1 & T ? true : false; /** * Checks if a type is exactly `unknown`. This is useful to determine if a type is * * @internal */ type IsUnknown<T> = IsAny<T> extends true ? false : unknown extends T ? true : false; /** * Transforms a value or a function that returns a value to a value. * * @param valFn either a value or a function that returns a value * @param args arguments to pass to the function if `valFn` is a function * * @internal */ declare function toValueWithArgs<T, Args extends any[]>(valFn: T | ((...args: Args) => T), ...args: Args): T; /** * Type that represents a value that can be a promise or a single value. * * @internal */ type _Awaitable<T> = T | Promise<T>; /** * To avoid using `{}` * @internal */ interface _EmptyObject {} /** * @internal */ type _IsMaybeRefOrGetter<T> = [T] extends [MaybeRefOrGetter<infer U>] ? MaybeRefOrGetter<U> extends T ? true : false : false; /** * @internal */ type _UnwrapMaybeRefOrGetter<T> = T extends MaybeRefOrGetter<infer U> ? U : T; /** * Removes the `MaybeRefOrGetter` wrapper from all fields of an object, * except for fields specified in the `Ignore` type. * @internal */ type _RemoveMaybeRef<T, Ignore extends keyof T = never> = { [K in keyof T]: K extends Ignore ? T[K] : _IsMaybeRefOrGetter<NonNullable<T[K]>> extends true ? _UnwrapMaybeRefOrGetter<T[K]> : T[K] }; //#endregion //#region src/define-query.d.ts /** * Options to define a query with `defineQuery()`. Similar to * {@link UseQueryOptions} but disallows reactive values as `defineQuery()` is * used outside of an effect scope. */ type DefineQueryOptions<TData = unknown, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined> = _RemoveMaybeRef<UseQueryOptions<TData, TError, TDataInitial>, typeof tErrorSymbol | 'initialData' | 'placeholderData'>; /** * Define a query with the given options. Similar to `useQuery(options)` but * allows you to reuse **all** of the query state in multiple places. It only * allow static values in options. If you need dynamic values, use the function * version. * * @param options - the options to define the query * * @example * ```ts * const useTodoList = defineQuery({ * key: ['todos'], * query: () => fetch('/api/todos', { method: 'GET' }), * }) * ``` */ declare function defineQuery<TData, TError = ErrorDefault>(options: DefineQueryOptions<TData, TError>): () => UseQueryReturn<TData, TError>; /** * Define a query with a setup function. Allows to return arbitrary values from * the query function, create contextual refs, rename the returned values, etc. * The setup function will be called only once, like stores, and **must be * synchronous**. * * @param setup - a function to setup the query * * @example * ```ts * const useFilteredTodos = defineQuery(() => { * const todoFilter = ref<'all' | 'finished' | 'unfinished'>('all') * const { data, ...rest } = useQuery({ * key: ['todos', { filter: todoFilter.value }], * query: () => * fetch(`/api/todos?filter=${todoFilter.value}`, { method: 'GET' }), * }) * // expose the todoFilter ref and rename data for convenience * return { ...rest, todoList: data, todoFilter } * }) * ``` */ declare function defineQuery<T>(setup: () => T): () => T; //#endregion //#region src/define-query-options.d.ts /** * Tagged version of {@link DefineQueryOptions} that includes a key with * data type information. */ interface DefineQueryOptionsTagged<TData = unknown, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined> extends DefineQueryOptions<TData, TError, TDataInitial> { key: EntryKeyTagged<TData, TError, TDataInitial>; } /** * Define dynamic query options by passing a function that accepts an optional * arbitrary parameter and returns the query options. Enables type-safe query * keys. Pass to {@link useQuery} as a single function: * `useQuery(() => setupOptions(params))`. * * @param setupOptions - A function that returns the query options. */ declare function defineQueryOptions<Params, TData, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined>(setupOptions: (params?: Params) => DefineQueryOptions<TData, TError, TDataInitial>): (params?: Params) => DefineQueryOptionsTagged<TData, TError, TDataInitial>; /** * Define dynamic query options by passing a function that accepts an arbitrary * parameter and returns the query options. Enables type-safe query keys. * Pass to {@link useQuery} as a single function: * `useQuery(() => setupOptions(params))`. * * @param setupOptions - A function that returns the query options. */ declare function defineQueryOptions<Params, TData, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined>(setupOptions: (params: Params) => DefineQueryOptions<TData, TError, TDataInitial>): (params: Params) => DefineQueryOptionsTagged<TData, TError, TDataInitial>; /** * Define static query options that are type safe with * `queryCache.getQueryData()`. Can be passed directly to {@link useQuery}. * * @param options - The query options. */ declare function defineQueryOptions<TData, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined>(options: DefineQueryOptions<TData, TError, TDataInitial>): DefineQueryOptionsTagged<TData, TError, TDataInitial>; //#endregion //#region src/use-query-state.d.ts /** * Return type for the {@link useQueryState} composable. * * @see {@link useQueryState} */ interface UseQueryStateReturn<TData = unknown, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined> { /** * `state` of the query entry. * * @see {@link UseQueryReturn#state} */ state: ComputedRef<DataState<TData, TError, TDataInitial> | undefined>; /** * `data` of the query entry. * * @see {@link UseQueryReturn#data} */ data: ComputedRef<TData | TDataInitial | undefined>; /** * `error` of the query entry. * * @see {@link UseQueryReturn#error} */ error: ComputedRef<TError | null | undefined>; /** * `status` of the query entry. * * @see {@link DataStateStatus} * @see {@link UseQueryReturn#status} */ status: ComputedRef<DataStateStatus | undefined>; /** * `asyncStatus` of the query entry. * * @see {@link AsyncStatus} * @see {@link UseQueryReturn#asyncStatus} */ asyncStatus: ComputedRef<AsyncStatus | undefined>; /** * Is the query entry currently pending or non existent. */ isPending: ComputedRef<boolean>; } /** * Reactive access to the state of a query entry without fetching it. * * @param key - tagged key of the query entry to access */ declare function useQueryState<TData, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined>(key: MaybeRefOrGetter<EntryKeyTagged<TData, TError, TDataInitial>>): UseQueryStateReturn<TData, TError, TDataInitial>; /** * Reactive access to the state of a query entry without fetching it. * * @param key - key of the query entry to access */ declare function useQueryState<TData, TError = ErrorDefault, TDataInitial extends TData | undefined = undefined>(key: MaybeRefOrGetter<EntryKey>): UseQueryStateReturn<TData, TError, TDataInitial>; //#endregion //#region src/infinite-query.d.ts /** * Structure of data stored for infinite queries. */ interface UseInfiniteQueryData<TData, TPageParam> { /** * Each page of data fetched in order. */ pages: TData[]; /** * Each page parameter used to fetch the corresponding page in the same order. */ pageParams: TPageParam[]; } interface UseInfiniteQueryFnContext<TData, TError, TDataInitial extends TData | undefined = undefined, TPageParam = unknown> extends UseQueryFnContext<TData, TError, TDataInitial> { /** * The page parameter for the current fetch. */ pageParam: TPageParam; } /** * Options for {@link useInfiniteQuery}. * */ interface UseInfiniteQueryOptions<TData, TError, TPageParam, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined> extends Omit<UseQueryOptions<UseInfiniteQueryData<TData, TPageParam>, TError, TDataInitial>, 'query' | 'key'> { key: UseQueryOptions<UseInfiniteQueryData<TData, TPageParam>, TError, TDataInitial>['key']; /** * The function that will be called to fetch the data. It **must** be async. */ query: (context: UseInfiniteQueryFnContext<UseInfiniteQueryData<unknown, TPageParam>, TError, TDataInitial, TPageParam>) => Promise<TData>; /** * Initial page parameter or function returning it. It's passed to the query */ initialPageParam: TPageParam | (() => TPageParam); /** * Maximum number of pages to keep in the cache. Old pages will be removed * from the cache when new pages are added. If not set, all pages will * be kept. */ maxPages?: number; /** * Function to get the next page parameter based on the last page and all * pages fetched so far. If it returns `undefined` or `null`, it will * consider there are no more pages to fetch. */ getNextPageParam: (lastPage: NoInfer<TData>, allPages: NoInfer<TData>[], lastPageParam: NoInfer<TPageParam>, allPageParams: NoInfer<TPageParam>[]) => NoInfer<TPageParam> | undefined | null; /** * Function to get the previous page parameter based on the first page and * all pages fetched so far. If it returns `undefined` or `null`, it will * consider there are no more pages to fetch. */ getPreviousPageParam?: (firstPage: TData, allPages: TData[], firstPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | undefined | null; } /** * Options to define an infinite query with `defineInfiniteQueryOptions()`. * Similar to {@link UseInfiniteQueryOptions} but disallows reactive values. */ type DefineInfiniteQueryOptions<TData = unknown, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined> = _RemoveMaybeRef<UseInfiniteQueryOptions<TData, TError, TPageParam, TDataInitial>, typeof tErrorSymbol | 'initialData' | 'placeholderData'>; /** * Options for {@link UseInfiniteQueryReturn.loadNextPage} and * {@link UseInfiniteQueryReturn.loadPreviousPage}. */ interface UseInfiniteQueryLoadMoreOptions { /** * Whether to throw an error if the fetch fails. * * @default false */ throwOnError?: boolean; /** * Whether to cancel an ongoing refetch when a new one is triggered. * If set to `false`, a new load will be ignored if there's already one in * progress. * * @default true */ cancelRefetch?: boolean; } interface UseInfiniteQueryReturn<TData = unknown, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined> extends UseQueryReturn<UseInfiniteQueryData<TData, TPageParam>, TError, TDataInitial> { /** * Whether there is a next page to load. Defined based on the result of * {@link UseInfiniteQueryOptions.getNextPageParam}. */ hasNextPage: ShallowRef<boolean>; /** * Load the next page of data. */ loadNextPage: (options?: UseInfiniteQueryLoadMoreOptions) => Promise<unknown>; /** * Whether there is a previous page to load. Defined based on the result of * {@link UseInfiniteQueryOptions.getPreviousPageParam}. */ hasPreviousPage: ShallowRef<boolean>; /** * Load the previous page of data. * Requires {@link UseInfiniteQueryOptions.getPreviousPageParam} to be defined. */ loadPreviousPage: (options?: UseInfiniteQueryLoadMoreOptions) => Promise<unknown>; } /** * Sets the data of an infinite query entry in the cache. Unlike {@link QueryCache.setQueryData | `queryCache.setQueryData()`}, * this function properly marks the entry as an infinite query and initializes the * infinite query extensions (`hasNextPage`, `hasPreviousPage`, etc.). * * Use this when you need to set infinite query data before `useInfiniteQuery()` is mounted * (e.g. optimistic updates from a mutation on a different page). * * @param queryCache - The query cache instance * @param key - The key of the infinite query * @param data - The data to set, or an updater function */ declare function setInfiniteQueryData<TData = unknown, TError = ErrorDefault, TPageParam = unknown>(queryCache: QueryCache, key: EntryKeyTagged<UseInfiniteQueryData<TData, TPageParam>, TError> | EntryKey, data: UseInfiniteQueryData<TData, TPageParam> | ((oldData: UseInfiniteQueryData<TData, TPageParam> | undefined) => UseInfiniteQueryData<TData, TPageParam>)): void; /** * Store and merge paginated data into a single cache entry. Allows to handle * infinite scrolling. * * @param options - Options to configure the infinite query. */ declare function useInfiniteQuery<TData, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined>(options: UseInfiniteQueryOptions<TData, TError, TPageParam, TDataInitial>): UseInfiniteQueryReturn<TData, TError, TPageParam, TDataInitial>; /** * Store and merge paginated data into a single cache entry. Allows to handle * infinite scrolling. Accepts a getter returning options defined with * {@link defineInfiniteQueryOptions}. * * @param options - A getter that returns the infinite query options. */ declare function useInfiniteQuery<TData, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined>(options: () => DefineInfiniteQueryOptions<TData, TError, TPageParam, TDataInitial>): UseInfiniteQueryReturn<TData, TError, TPageParam, TDataInitial>; //#endregion //#region src/define-infinite-query-options.d.ts /** * Tagged version of {@link DefineInfiniteQueryOptions} that includes a key with * data type information. */ interface DefineInfiniteQueryOptionsTagged<TData = unknown, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined> extends DefineInfiniteQueryOptions<TData, TError, TPageParam, TDataInitial> { key: EntryKeyTagged<UseInfiniteQueryData<TData, TPageParam>, TError, TDataInitial>; } /** * Define dynamic infinite query options by passing a function that accepts an * optional arbitrary parameter and returns the query options. Enables type-safe * query keys. Pass to {@link useInfiniteQuery} as a single function: * `useInfiniteQuery(() => setupOptions(params))`. * * @param setupOptions - A function that returns the infinite query options. */ declare function defineInfiniteQueryOptions<Params, TData, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined>(setupOptions: (params?: Params) => UseInfiniteQueryOptions<TData, TError, TPageParam, TDataInitial>): (params?: Params) => DefineInfiniteQueryOptionsTagged<TData, TError, TPageParam, TDataInitial>; /** * Define dynamic infinite query options by passing a function that accepts an * arbitrary parameter and returns the query options. Enables type-safe query * keys. Pass to {@link useInfiniteQuery} as a single function: * `useInfiniteQuery(() => setupOptions(params))`. * * @param setupOptions - A function that returns the infinite query options. */ declare function defineInfiniteQueryOptions<Params, TData, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined>(setupOptions: (params: Params) => UseInfiniteQueryOptions<TData, TError, TPageParam, TDataInitial>): (params: Params) => DefineInfiniteQueryOptionsTagged<TData, TError, TPageParam, TDataInitial>; /** * Define static infinite query options that are type safe with * `queryCache.getQueryData()`. Can be passed directly to * {@link useInfiniteQuery}. * * @param options - The infinite query options. */ declare function defineInfiniteQueryOptions<TData, TError = ErrorDefault, TPageParam = unknown, TDataInitial extends UseInfiniteQueryData<TData, TPageParam> | undefined = undefined>(optio