UNPKG

@tanstack/query-core

Version:

The framework agnostic core that powers TanStack Query

844 lines (768 loc) 24 kB
/* istanbul ignore file */ import type { MutationState } from './mutation' import type { FetchDirection, Query, QueryBehavior } from './query' import type { RetryDelayValue, RetryValue } from './retryer' import type { QueryFilters, QueryTypeFilter } from './utils' import type { QueryCache } from './queryCache' import type { MutationCache } from './mutationCache' export type NoInfer<T> = [T][T extends any ? 0 : never] export interface Register { // defaultError: Error // queryMeta: Record<string, unknown> // mutationMeta: Record<string, unknown> } export type DefaultError = Register extends { defaultError: infer TError } ? TError : Error export type QueryKey = ReadonlyArray<unknown> export declare const dataTagSymbol: unique symbol export type DataTag<Type, Value> = Type & { [dataTagSymbol]: Value } export type QueryFunction< T = unknown, TQueryKey extends QueryKey = QueryKey, TPageParam = never, > = (context: QueryFunctionContext<TQueryKey, TPageParam>) => T | Promise<T> export type QueryPersister< T = unknown, TQueryKey extends QueryKey = QueryKey, TPageParam = never, > = [TPageParam] extends [never] ? ( queryFn: QueryFunction<T, TQueryKey, never>, context: QueryFunctionContext<TQueryKey>, query: Query, ) => T | Promise<T> : ( queryFn: QueryFunction<T, TQueryKey, TPageParam>, context: QueryFunctionContext<TQueryKey>, query: Query, ) => T | Promise<T> export type QueryFunctionContext< TQueryKey extends QueryKey = QueryKey, TPageParam = never, > = [TPageParam] extends [never] ? { queryKey: TQueryKey signal: AbortSignal meta: QueryMeta | undefined } : { queryKey: TQueryKey signal: AbortSignal pageParam: TPageParam direction: FetchDirection meta: QueryMeta | undefined } export type InitialDataFunction<T> = () => T | undefined type NonFunctionGuard<T> = T extends Function ? never : T export type PlaceholderDataFunction< TQueryFnData = unknown, TError = DefaultError, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, > = ( previousData: TQueryData | undefined, previousQuery: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined, ) => TQueryData | undefined export type QueriesPlaceholderDataFunction<TQueryData> = ( previousData: undefined, previousQuery: undefined, ) => TQueryData | undefined export type QueryKeyHashFunction<TQueryKey extends QueryKey> = ( queryKey: TQueryKey, ) => string export type GetPreviousPageParamFunction<TPageParam, TQueryFnData = unknown> = ( firstPage: TQueryFnData, allPages: Array<TQueryFnData>, firstPageParam: TPageParam, allPageParams: Array<TPageParam>, ) => TPageParam | undefined | null export type GetNextPageParamFunction<TPageParam, TQueryFnData = unknown> = ( lastPage: TQueryFnData, allPages: Array<TQueryFnData>, lastPageParam: TPageParam, allPageParams: Array<TPageParam>, ) => TPageParam | undefined | null export interface InfiniteData<TData, TPageParam = unknown> { pages: Array<TData> pageParams: Array<TPageParam> } export type QueryMeta = Register extends { queryMeta: infer TQueryMeta } ? TQueryMeta extends Record<string, unknown> ? TQueryMeta : Record<string, unknown> : Record<string, unknown> export type NetworkMode = 'online' | 'always' | 'offlineFirst' export type NotifyOnChangeProps = | Array<keyof InfiniteQueryObserverResult> | 'all' | (() => Array<keyof InfiniteQueryObserverResult> | 'all') export interface QueryOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = never, > { /** * If `false`, failed queries will not retry by default. * If `true`, failed queries will retry infinitely., failureCount: num * If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. * If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. */ retry?: RetryValue<TError> retryDelay?: RetryDelayValue<TError> networkMode?: NetworkMode gcTime?: number queryFn?: QueryFunction<TQueryFnData, TQueryKey, TPageParam> persister?: QueryPersister< NoInfer<TQueryFnData>, NoInfer<TQueryKey>, NoInfer<TPageParam> > queryHash?: string queryKey?: TQueryKey queryKeyHashFn?: QueryKeyHashFunction<TQueryKey> initialData?: TData | InitialDataFunction<TData> initialDataUpdatedAt?: number | (() => number | undefined) behavior?: QueryBehavior<TQueryFnData, TError, TData, TQueryKey> /** * Set this to `false` to disable structural sharing between query results. * Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. * Defaults to `true`. */ structuralSharing?: boolean | (<T>(oldData: T | undefined, newData: T) => T) _defaulted?: boolean /** * Additional payload to be stored on each query. * Use this property to pass information that can be used in other places. */ meta?: QueryMeta /** * Maximum number of pages to store in the data of an infinite query. */ maxPages?: number } export interface InitialPageParam<TPageParam = unknown> { initialPageParam: TPageParam } export interface InfiniteQueryPageParamsOptions< TQueryFnData = unknown, TPageParam = unknown, > extends InitialPageParam<TPageParam> { /** * This function can be set to automatically get the previous cursor for infinite queries. * The result will also be used to determine the value of `hasPreviousPage`. */ getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TQueryFnData> /** * This function can be set to automatically get the next cursor for infinite queries. * The result will also be used to determine the value of `hasNextPage`. */ getNextPageParam: GetNextPageParamFunction<TPageParam, TQueryFnData> } export type ThrowOnError< TQueryFnData, TError, TQueryData, TQueryKey extends QueryKey, > = | boolean | (( error: TError, query: Query<TQueryFnData, TError, TQueryData, TQueryKey>, ) => boolean) export interface QueryObserverOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = never, > extends QueryOptions< TQueryFnData, TError, TQueryData, TQueryKey, TPageParam > { /** * Set this to `false` to disable automatic refetching when the query mounts or changes query keys. * To refetch the query, use the `refetch` method returned from the `useQuery` instance. * Defaults to `true`. */ enabled?: boolean /** * The time in milliseconds after data is considered stale. * If set to `Infinity`, the data will never be considered stale. */ staleTime?: number /** * If set to a number, the query will continuously refetch at this frequency in milliseconds. * If set to a function, the function will be executed with the latest data and query to compute a frequency * Defaults to `false`. */ refetchInterval?: | number | false | (( query: Query<TQueryFnData, TError, TQueryData, TQueryKey>, ) => number | false | undefined) /** * If set to `true`, the query will continue to refetch while their tab/window is in the background. * Defaults to `false`. */ refetchIntervalInBackground?: boolean /** * If set to `true`, the query will refetch on window focus if the data is stale. * If set to `false`, the query will not refetch on window focus. * If set to `'always'`, the query will always refetch on window focus. * If set to a function, the function will be executed with the latest data and query to compute the value. * Defaults to `true`. */ refetchOnWindowFocus?: | boolean | 'always' | (( query: Query<TQueryFnData, TError, TQueryData, TQueryKey>, ) => boolean | 'always') /** * If set to `true`, the query will refetch on reconnect if the data is stale. * If set to `false`, the query will not refetch on reconnect. * If set to `'always'`, the query will always refetch on reconnect. * If set to a function, the function will be executed with the latest data and query to compute the value. * Defaults to the value of `networkOnline` (`true`) */ refetchOnReconnect?: | boolean | 'always' | (( query: Query<TQueryFnData, TError, TQueryData, TQueryKey>, ) => boolean | 'always') /** * If set to `true`, the query will refetch on mount if the data is stale. * If set to `false`, will disable additional instances of a query to trigger background refetches. * If set to `'always'`, the query will always refetch on mount. * If set to a function, the function will be executed with the latest data and query to compute the value * Defaults to `true`. */ refetchOnMount?: | boolean | 'always' | (( query: Query<TQueryFnData, TError, TQueryData, TQueryKey>, ) => boolean | 'always') /** * If set to `false`, the query will not be retried on mount if it contains an error. * Defaults to `true`. */ retryOnMount?: boolean /** * If set, the component will only re-render if any of the listed properties change. * When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. * When set to `'all'`, the component will re-render whenever a query is updated. * When set to a function, the function will be executed to compute the list of properties. * By default, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. */ notifyOnChangeProps?: NotifyOnChangeProps /** * Whether errors should be thrown instead of setting the `error` property. * If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. * If set to `false` and `suspense` is `false`, errors are returned as state. * If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). * Defaults to `false`. */ throwOnError?: ThrowOnError<TQueryFnData, TError, TQueryData, TQueryKey> /** * This option can be used to transform or select a part of the data returned by the query function. */ select?: (data: TQueryData) => TData /** * If set to `true`, the query will suspend when `status === 'pending'` * and throw errors when `status === 'error'`. * Defaults to `false`. */ suspense?: boolean /** * If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. */ placeholderData?: | NonFunctionGuard<TQueryData> | PlaceholderDataFunction<NonFunctionGuard<TQueryData>> _optimisticResults?: 'optimistic' | 'isRestoring' } export type WithRequired<T, K extends keyof T> = T & { [_ in K]: {} } export type DefaultedQueryObserverOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, > = WithRequired< QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>, 'throwOnError' | 'refetchOnReconnect' > export interface InfiniteQueryObserverOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown, > extends QueryObserverOptions< TQueryFnData, TError, TData, InfiniteData<TQueryData, TPageParam>, TQueryKey, TPageParam >, InfiniteQueryPageParamsOptions<TQueryFnData, TPageParam> {} export type DefaultedInfiniteQueryObserverOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown, > = WithRequired< InfiniteQueryObserverOptions< TQueryFnData, TError, TData, TQueryData, TQueryKey, TPageParam >, 'throwOnError' | 'refetchOnReconnect' > export interface FetchQueryOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = never, > extends WithRequired< QueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, 'queryKey' > { /** * The time in milliseconds after data is considered stale. * If the data is fresh it will be returned from the cache. */ staleTime?: number } type FetchInfiniteQueryPages<TQueryFnData = unknown, TPageParam = unknown> = | { pages?: never } | { pages: number getNextPageParam: GetNextPageParamFunction<TPageParam, TQueryFnData> } export type FetchInfiniteQueryOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown, > = FetchQueryOptions< TQueryFnData, TError, InfiniteData<TData, TPageParam>, TQueryKey, TPageParam > & InitialPageParam<TPageParam> & FetchInfiniteQueryPages<TQueryFnData, TPageParam> export interface ResultOptions { throwOnError?: boolean } export interface RefetchOptions extends ResultOptions { cancelRefetch?: boolean } export interface InvalidateQueryFilters extends QueryFilters { refetchType?: QueryTypeFilter | 'none' } export interface RefetchQueryFilters extends QueryFilters {} export interface InvalidateOptions extends RefetchOptions {} export interface ResetOptions extends RefetchOptions {} export interface FetchNextPageOptions extends ResultOptions { cancelRefetch?: boolean } export interface FetchPreviousPageOptions extends ResultOptions { cancelRefetch?: boolean } export type QueryStatus = 'pending' | 'error' | 'success' export type FetchStatus = 'fetching' | 'paused' | 'idle' export interface QueryObserverBaseResult< TData = unknown, TError = DefaultError, > { data: TData | undefined dataUpdatedAt: number error: TError | null errorUpdatedAt: number failureCount: number failureReason: TError | null errorUpdateCount: number isError: boolean isFetched: boolean isFetchedAfterMount: boolean isFetching: boolean isLoading: boolean isPending: boolean isLoadingError: boolean /** * @deprecated isInitialLoading is being deprecated in favor of isLoading * and will be removed in the next major version. */ isInitialLoading: boolean isPaused: boolean isPlaceholderData: boolean isRefetchError: boolean isRefetching: boolean isStale: boolean isSuccess: boolean refetch: ( options?: RefetchOptions, ) => Promise<QueryObserverResult<TData, TError>> status: QueryStatus fetchStatus: FetchStatus } export interface QueryObserverLoadingResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult<TData, TError> { data: undefined error: null isError: false isPending: true isLoadingError: false isRefetchError: false isSuccess: false status: 'pending' } export interface QueryObserverLoadingErrorResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult<TData, TError> { data: undefined error: TError isError: true isPending: false isLoadingError: true isRefetchError: false isSuccess: false status: 'error' } export interface QueryObserverRefetchErrorResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult<TData, TError> { data: TData error: TError isError: true isPending: false isLoadingError: false isRefetchError: true isSuccess: false status: 'error' } export interface QueryObserverSuccessResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult<TData, TError> { data: TData error: null isError: false isPending: false isLoadingError: false isRefetchError: false isSuccess: true status: 'success' } export type DefinedQueryObserverResult< TData = unknown, TError = DefaultError, > = | QueryObserverRefetchErrorResult<TData, TError> | QueryObserverSuccessResult<TData, TError> export type QueryObserverResult<TData = unknown, TError = DefaultError> = | DefinedQueryObserverResult<TData, TError> | QueryObserverLoadingErrorResult<TData, TError> | QueryObserverLoadingResult<TData, TError> export interface InfiniteQueryObserverBaseResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult<TData, TError> { fetchNextPage: ( options?: FetchNextPageOptions, ) => Promise<InfiniteQueryObserverResult<TData, TError>> fetchPreviousPage: ( options?: FetchPreviousPageOptions, ) => Promise<InfiniteQueryObserverResult<TData, TError>> hasNextPage: boolean hasPreviousPage: boolean isFetchingNextPage: boolean isFetchingPreviousPage: boolean } export interface InfiniteQueryObserverLoadingResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult<TData, TError> { data: undefined error: null isError: false isPending: true isLoadingError: false isRefetchError: false isSuccess: false status: 'pending' } export interface InfiniteQueryObserverLoadingErrorResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult<TData, TError> { data: undefined error: TError isError: true isPending: false isLoadingError: true isRefetchError: false isSuccess: false status: 'error' } export interface InfiniteQueryObserverRefetchErrorResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult<TData, TError> { data: TData error: TError isError: true isPending: false isLoadingError: false isRefetchError: true isSuccess: false status: 'error' } export interface InfiniteQueryObserverSuccessResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult<TData, TError> { data: TData error: null isError: false isPending: false isLoadingError: false isRefetchError: false isSuccess: true status: 'success' } export type DefinedInfiniteQueryObserverResult< TData = unknown, TError = DefaultError, > = | InfiniteQueryObserverRefetchErrorResult<TData, TError> | InfiniteQueryObserverSuccessResult<TData, TError> export type InfiniteQueryObserverResult< TData = unknown, TError = DefaultError, > = | InfiniteQueryObserverLoadingErrorResult<TData, TError> | InfiniteQueryObserverLoadingResult<TData, TError> | DefinedInfiniteQueryObserverResult<TData, TError> export type MutationKey = ReadonlyArray<unknown> export type MutationStatus = 'idle' | 'pending' | 'success' | 'error' export type MutationMeta = Register extends { mutationMeta: infer TMutationMeta } ? TMutationMeta : Record<string, unknown> export type MutationFunction<TData = unknown, TVariables = unknown> = ( variables: TVariables, ) => Promise<TData> export interface MutationOptions< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > { mutationFn?: MutationFunction<TData, TVariables> mutationKey?: MutationKey onMutate?: ( variables: TVariables, ) => Promise<TContext | undefined> | TContext | undefined onSuccess?: ( data: TData, variables: TVariables, context: TContext | undefined, ) => Promise<unknown> | unknown onError?: ( error: TError, variables: TVariables, context: TContext | undefined, ) => Promise<unknown> | unknown onSettled?: ( data: TData | undefined, error: TError | null, variables: TVariables, context: TContext | undefined, ) => Promise<unknown> | unknown retry?: RetryValue<TError> retryDelay?: RetryDelayValue<TError> networkMode?: NetworkMode gcTime?: number _defaulted?: boolean meta?: MutationMeta } export interface MutationObserverOptions< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > extends MutationOptions<TData, TError, TVariables, TContext> { throwOnError?: boolean | ((error: TError) => boolean) } export interface MutateOptions< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > { onSuccess?: (data: TData, variables: TVariables, context: TContext) => void onError?: ( error: TError, variables: TVariables, context: TContext | undefined, ) => void onSettled?: ( data: TData | undefined, error: TError | null, variables: TVariables, context: TContext | undefined, ) => void } export type MutateFunction< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > = ( variables: TVariables, options?: MutateOptions<TData, TError, TVariables, TContext>, ) => Promise<TData> export interface MutationObserverBaseResult< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > extends MutationState<TData, TError, TVariables, TContext> { isError: boolean isIdle: boolean isPending: boolean isSuccess: boolean mutate: MutateFunction<TData, TError, TVariables, TContext> reset: () => void } export interface MutationObserverIdleResult< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > extends MutationObserverBaseResult<TData, TError, TVariables, TContext> { data: undefined variables: undefined error: null isError: false isIdle: true isPending: false isSuccess: false status: 'idle' } export interface MutationObserverLoadingResult< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > extends MutationObserverBaseResult<TData, TError, TVariables, TContext> { data: undefined variables: TVariables error: null isError: false isIdle: false isPending: true isSuccess: false status: 'pending' } export interface MutationObserverErrorResult< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > extends MutationObserverBaseResult<TData, TError, TVariables, TContext> { data: undefined error: TError variables: TVariables isError: true isIdle: false isPending: false isSuccess: false status: 'error' } export interface MutationObserverSuccessResult< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > extends MutationObserverBaseResult<TData, TError, TVariables, TContext> { data: TData error: null variables: TVariables isError: false isIdle: false isPending: false isSuccess: true status: 'success' } export type MutationObserverResult< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, > = | MutationObserverIdleResult<TData, TError, TVariables, TContext> | MutationObserverLoadingResult<TData, TError, TVariables, TContext> | MutationObserverErrorResult<TData, TError, TVariables, TContext> | MutationObserverSuccessResult<TData, TError, TVariables, TContext> export interface QueryClientConfig { queryCache?: QueryCache mutationCache?: MutationCache defaultOptions?: DefaultOptions } export interface DefaultOptions<TError = DefaultError> { queries?: QueryObserverOptions<unknown, TError> mutations?: MutationObserverOptions<unknown, TError, unknown, unknown> } export interface CancelOptions { revert?: boolean silent?: boolean } export interface SetDataOptions { updatedAt?: number } export type NotifyEventType = | 'added' | 'removed' | 'updated' | 'observerAdded' | 'observerRemoved' | 'observerResultsUpdated' | 'observerOptionsUpdated' export interface NotifyEvent { type: NotifyEventType }