UNPKG

@reduxjs/toolkit

Version:

The official, opinionated, batteries-included toolset for efficient Redux development

1,043 lines (1,031 loc) 143 kB
import * as _reduxjs_toolkit from '@reduxjs/toolkit'; import { ThunkDispatch, Draft, AsyncThunk, SHOULD_AUTOBATCH, ThunkAction, UnknownAction, SafePromise, SerializedError, PayloadAction, ActionCreatorWithoutPayload, Reducer, Middleware, ActionCreatorWithPayload } from '@reduxjs/toolkit'; import { Patch } from 'immer'; import * as redux from 'redux'; import { CreateSelectorFunction } from 'reselect'; import { StandardSchemaV1 } from '@standard-schema/spec'; import { SchemaError } from '@standard-schema/utils'; type Id<T> = { [K in keyof T]: T[K]; } & {}; type WithRequiredProp<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>; type Override<T1, T2> = T2 extends any ? Omit<T1, keyof T2> & T2 : never; /** * Convert a Union type `(A|B)` to an intersection type `(A&B)` */ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; type NonOptionalKeys<T> = { [K in keyof T]-?: undefined extends T[K] ? never : K; }[keyof T]; type HasRequiredProps<T, True, False> = NonOptionalKeys<T> extends never ? False : True; type NonUndefined<T> = T extends undefined ? never : T; type UnwrapPromise<T> = T extends PromiseLike<infer V> ? V : T; type MaybePromise<T> = T | PromiseLike<T>; type OmitFromUnion<T, K extends keyof T> = T extends any ? Omit<T, K> : never; type IsAny<T, True, False = never> = true | false extends (T extends never ? true : false) ? True : False; type CastAny<T, CastTo> = IsAny<T, CastTo, T>; interface BaseQueryApi { signal: AbortSignal; abort: (reason?: string) => void; dispatch: ThunkDispatch<any, any, any>; getState: () => unknown; extra: unknown; endpoint: string; type: 'query' | 'mutation'; /** * Only available for queries: indicates if a query has been forced, * i.e. it would have been fetched even if there would already be a cache entry * (this does not mean that there is already a cache entry though!) * * This can be used to for example add a `Cache-Control: no-cache` header for * invalidated queries. */ forced?: boolean; /** * Only available for queries: the cache key that was used to store the query result */ queryCacheKey?: string; } type QueryReturnValue<T = unknown, E = unknown, M = unknown> = { error: E; data?: undefined; meta?: M; } | { error?: undefined; data: T; meta?: M; }; type BaseQueryFn<Args = any, Result = unknown, Error = unknown, DefinitionExtraOptions = {}, Meta = {}> = (args: Args, api: BaseQueryApi, extraOptions: DefinitionExtraOptions) => MaybePromise<QueryReturnValue<Result, Error, Meta>>; type BaseQueryEnhancer<AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, Config = void> = <BaseQuery extends BaseQueryFn>(baseQuery: BaseQuery, config: Config) => BaseQueryFn<BaseQueryArg<BaseQuery> & AdditionalArgs, BaseQueryResult<BaseQuery>, BaseQueryError<BaseQuery>, BaseQueryExtraOptions<BaseQuery> & AdditionalDefinitionExtraOptions, NonNullable<BaseQueryMeta<BaseQuery>>>; /** * @public */ type BaseQueryResult<BaseQuery extends BaseQueryFn> = UnwrapPromise<ReturnType<BaseQuery>> extends infer Unwrapped ? Unwrapped extends { data: any; } ? Unwrapped['data'] : never : never; /** * @public */ type BaseQueryMeta<BaseQuery extends BaseQueryFn> = UnwrapPromise<ReturnType<BaseQuery>>['meta']; /** * @public */ type BaseQueryError<BaseQuery extends BaseQueryFn> = Exclude<UnwrapPromise<ReturnType<BaseQuery>>, { error?: undefined; }>['error']; /** * @public */ type BaseQueryArg<T extends (arg: any, ...args: any[]) => any> = T extends (arg: infer A, ...args: any[]) => any ? A : any; /** * @public */ type BaseQueryExtraOptions<BaseQuery extends BaseQueryFn> = Parameters<BaseQuery>[2]; declare const defaultSerializeQueryArgs: SerializeQueryArgs<any>; type SerializeQueryArgs<QueryArgs, ReturnType = string> = (_: { queryArgs: QueryArgs; endpointDefinition: EndpointDefinition<any, any, any, any>; endpointName: string; }) => ReturnType; type InternalSerializeQueryArgs = (_: { queryArgs: any; endpointDefinition: EndpointDefinition<any, any, any, any>; endpointName: string; }) => QueryCacheKey; type BuildThunksApiEndpointQuery<Definition extends QueryDefinition<any, any, any, any, any>> = Matchers<QueryThunk, Definition>; type BuildThunksApiEndpointInfiniteQuery<Definition extends InfiniteQueryDefinition<any, any, any, any, any>> = Matchers<InfiniteQueryThunk<any>, Definition>; type BuildThunksApiEndpointMutation<Definition extends MutationDefinition<any, any, any, any, any>> = Matchers<MutationThunk, Definition>; type EndpointThunk<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = Definition extends EndpointDefinition<infer QueryArg, infer BaseQueryFn, any, infer ResultType> ? Thunk extends AsyncThunk<unknown, infer ATArg, infer ATConfig> ? AsyncThunk<ResultType, ATArg & { originalArgs: QueryArg; }, ATConfig & { rejectValue: BaseQueryError<BaseQueryFn>; }> : never : Definition extends InfiniteQueryDefinition<infer QueryArg, infer PageParam, infer BaseQueryFn, any, infer ResultType> ? Thunk extends AsyncThunk<unknown, infer ATArg, infer ATConfig> ? AsyncThunk<InfiniteData<ResultType, PageParam>, ATArg & { originalArgs: QueryArg; }, ATConfig & { rejectValue: BaseQueryError<BaseQueryFn>; }> : never : never; type PendingAction<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = ReturnType<EndpointThunk<Thunk, Definition>['pending']>; type FulfilledAction<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = ReturnType<EndpointThunk<Thunk, Definition>['fulfilled']>; type RejectedAction<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = ReturnType<EndpointThunk<Thunk, Definition>['rejected']>; type Matcher<M> = (value: any) => value is M; interface Matchers<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> { matchPending: Matcher<PendingAction<Thunk, Definition>>; matchFulfilled: Matcher<FulfilledAction<Thunk, Definition>>; matchRejected: Matcher<RejectedAction<Thunk, Definition>>; } type QueryThunkArg = QuerySubstateIdentifier & StartQueryActionCreatorOptions & { type: 'query'; originalArgs: unknown; endpointName: string; }; type InfiniteQueryThunkArg<D extends InfiniteQueryDefinition<any, any, any, any, any>> = QuerySubstateIdentifier & StartInfiniteQueryActionCreatorOptions<D> & { type: `query`; originalArgs: unknown; endpointName: string; param: unknown; direction?: InfiniteQueryDirection; refetchCachedPages?: boolean; }; type MutationThunkArg = { type: 'mutation'; originalArgs: unknown; endpointName: string; track?: boolean; fixedCacheKey?: string; }; type ThunkResult = unknown; type ThunkApiMetaConfig = { pendingMeta: { startedTimeStamp: number; [SHOULD_AUTOBATCH]: true; }; fulfilledMeta: { fulfilledTimeStamp: number; baseQueryMeta: unknown; [SHOULD_AUTOBATCH]: true; }; rejectedMeta: { baseQueryMeta: unknown; [SHOULD_AUTOBATCH]: true; }; }; type QueryThunk = AsyncThunk<ThunkResult, QueryThunkArg, ThunkApiMetaConfig>; type InfiniteQueryThunk<D extends InfiniteQueryDefinition<any, any, any, any, any>> = AsyncThunk<ThunkResult, InfiniteQueryThunkArg<D>, ThunkApiMetaConfig>; type MutationThunk = AsyncThunk<ThunkResult, MutationThunkArg, ThunkApiMetaConfig>; type MaybeDrafted<T> = T | Draft<T>; type Recipe<T> = (data: MaybeDrafted<T>) => void | MaybeDrafted<T>; type PatchQueryDataThunk<Definitions extends EndpointDefinitions, PartialState> = <EndpointName extends QueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFrom<Definitions[EndpointName]>, patches: readonly Patch[], updateProvided?: boolean) => ThunkAction<void, PartialState, any, UnknownAction>; type AllQueryKeys<Definitions extends EndpointDefinitions> = QueryKeys<Definitions> | InfiniteQueryKeys<Definitions>; type QueryArgFromAnyQueryDefinition<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = Definitions[EndpointName] extends InfiniteQueryDefinition<any, any, any, any, any> ? InfiniteQueryArgFrom<Definitions[EndpointName]> : Definitions[EndpointName] extends QueryDefinition<any, any, any, any> ? QueryArgFrom<Definitions[EndpointName]> : never; type DataFromAnyQueryDefinition<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = Definitions[EndpointName] extends InfiniteQueryDefinition<any, any, any, any, any> ? InfiniteData<ResultTypeFrom<Definitions[EndpointName]>, PageParamFrom<Definitions[EndpointName]>> : Definitions[EndpointName] extends QueryDefinition<any, any, any, any> ? ResultTypeFrom<Definitions[EndpointName]> : unknown; type UpsertThunkResult<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = Definitions[EndpointName] extends InfiniteQueryDefinition<any, any, any, any, any> ? InfiniteQueryActionCreatorResult<Definitions[EndpointName]> : Definitions[EndpointName] extends QueryDefinition<any, any, any, any> ? QueryActionCreatorResult<Definitions[EndpointName]> : QueryActionCreatorResult<never>; type UpdateQueryDataThunk<Definitions extends EndpointDefinitions, PartialState> = <EndpointName extends AllQueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>, updateRecipe: Recipe<DataFromAnyQueryDefinition<Definitions, EndpointName>>, updateProvided?: boolean) => ThunkAction<PatchCollection, PartialState, any, UnknownAction>; type UpsertQueryDataThunk<Definitions extends EndpointDefinitions, PartialState> = <EndpointName extends AllQueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>, value: DataFromAnyQueryDefinition<Definitions, EndpointName>) => ThunkAction<UpsertThunkResult<Definitions, EndpointName>, PartialState, any, UnknownAction>; /** * An object returned from dispatching a `api.util.updateQueryData` call. */ type PatchCollection = { /** * An `immer` Patch describing the cache update. */ patches: Patch[]; /** * An `immer` Patch to revert the cache update. */ inversePatches: Patch[]; /** * A function that will undo the cache update. */ undo: () => void; }; type SkipToken = typeof skipToken; /** * Can be passed into `useQuery`, `useQueryState` or `useQuerySubscription` * instead of the query argument to get the same effect as if setting * `skip: true` in the query options. * * Useful for scenarios where a query should be skipped when `arg` is `undefined` * and TypeScript complains about it because `arg` is not allowed to be passed * in as `undefined`, such as * * ```ts * // codeblock-meta title="will error if the query argument is not allowed to be undefined" no-transpile * useSomeQuery(arg, { skip: !!arg }) * ``` * * ```ts * // codeblock-meta title="using skipToken instead" no-transpile * useSomeQuery(arg ?? skipToken) * ``` * * If passed directly into a query or mutation selector, that selector will always * return an uninitialized state. */ export declare const skipToken: unique symbol; type BuildSelectorsApiEndpointQuery<Definition extends QueryDefinition<any, any, any, any, any>, Definitions extends EndpointDefinitions> = { select: QueryResultSelectorFactory<Definition, RootState<Definitions, TagTypesFrom<Definition>, ReducerPathFrom<Definition>>>; }; type BuildSelectorsApiEndpointInfiniteQuery<Definition extends InfiniteQueryDefinition<any, any, any, any, any>, Definitions extends EndpointDefinitions> = { select: InfiniteQueryResultSelectorFactory<Definition, RootState<Definitions, TagTypesFrom<Definition>, ReducerPathFrom<Definition>>>; }; type BuildSelectorsApiEndpointMutation<Definition extends MutationDefinition<any, any, any, any, any>, Definitions extends EndpointDefinitions> = { select: MutationResultSelectorFactory<Definition, RootState<Definitions, TagTypesFrom<Definition>, ReducerPathFrom<Definition>>>; }; type QueryResultSelectorFactory<Definition extends QueryDefinition<any, any, any, any>, RootState> = (queryArg: QueryArgFrom<Definition> | SkipToken) => (state: RootState) => QueryResultSelectorResult<Definition>; type QueryResultSelectorResult<Definition extends QueryDefinition<any, any, any, any>> = QuerySubState<Definition> & RequestStatusFlags; type InfiniteQueryResultSelectorFactory<Definition extends InfiniteQueryDefinition<any, any, any, any, any>, RootState> = (queryArg: InfiniteQueryArgFrom<Definition> | SkipToken) => (state: RootState) => InfiniteQueryResultSelectorResult<Definition>; type InfiniteQueryResultFlags = { hasNextPage: boolean; hasPreviousPage: boolean; isFetchingNextPage: boolean; isFetchingPreviousPage: boolean; isFetchNextPageError: boolean; isFetchPreviousPageError: boolean; }; type InfiniteQueryResultSelectorResult<Definition extends InfiniteQueryDefinition<any, any, any, any, any>> = InfiniteQuerySubState<Definition> & RequestStatusFlags & InfiniteQueryResultFlags; type MutationResultSelectorFactory<Definition extends MutationDefinition<any, any, any, any>, RootState> = (requestId: string | { requestId: string | undefined; fixedCacheKey: string | undefined; } | SkipToken) => (state: RootState) => MutationResultSelectorResult<Definition>; type MutationResultSelectorResult<Definition extends MutationDefinition<any, any, any, any>> = MutationSubState<Definition> & RequestStatusFlags; type BuildInitiateApiEndpointQuery<Definition extends QueryDefinition<any, any, any, any, any>> = { initiate: StartQueryActionCreator<Definition>; }; type BuildInitiateApiEndpointInfiniteQuery<Definition extends InfiniteQueryDefinition<any, any, any, any, any>> = { initiate: StartInfiniteQueryActionCreator<Definition>; }; type BuildInitiateApiEndpointMutation<Definition extends MutationDefinition<any, any, any, any, any>> = { initiate: StartMutationActionCreator<Definition>; }; declare const forceQueryFnSymbol: unique symbol; type StartQueryActionCreatorOptions = { subscribe?: boolean; forceRefetch?: boolean | number; subscriptionOptions?: SubscriptionOptions; [forceQueryFnSymbol]?: () => QueryReturnValue; }; type StartInfiniteQueryActionCreatorOptions<D extends InfiniteQueryDefinition<any, any, any, any, any>> = StartQueryActionCreatorOptions & { direction?: InfiniteQueryDirection; param?: unknown; } & Partial<Pick<Partial<InfiniteQueryConfigOptions<ResultTypeFrom<D>, PageParamFrom<D>, InfiniteQueryArgFrom<D>>>, 'initialPageParam' | 'refetchCachedPages'>>; type StartQueryActionCreator<D extends QueryDefinition<any, any, any, any, any>> = (arg: QueryArgFrom<D>, options?: StartQueryActionCreatorOptions) => ThunkAction<QueryActionCreatorResult<D>, any, any, UnknownAction>; type StartInfiniteQueryActionCreator<D extends InfiniteQueryDefinition<any, any, any, any, any>> = (arg: InfiniteQueryArgFrom<D>, options?: StartInfiniteQueryActionCreatorOptions<D>) => ThunkAction<InfiniteQueryActionCreatorResult<D>, any, any, UnknownAction>; type QueryActionCreatorFields = { requestId: string; subscriptionOptions: SubscriptionOptions | undefined; abort(): void; unsubscribe(): void; updateSubscriptionOptions(options: SubscriptionOptions): void; queryCacheKey: string; }; type QueryActionCreatorResult<D extends QueryDefinition<any, any, any, any>> = SafePromise<QueryResultSelectorResult<D>> & QueryActionCreatorFields & { arg: QueryArgFrom<D>; unwrap(): Promise<ResultTypeFrom<D>>; refetch(): QueryActionCreatorResult<D>; }; type InfiniteQueryActionCreatorResult<D extends InfiniteQueryDefinition<any, any, any, any, any>> = SafePromise<InfiniteQueryResultSelectorResult<D>> & QueryActionCreatorFields & { arg: InfiniteQueryArgFrom<D>; unwrap(): Promise<InfiniteData<ResultTypeFrom<D>, PageParamFrom<D>>>; refetch(options?: Pick<StartInfiniteQueryActionCreatorOptions<D>, 'refetchCachedPages'>): InfiniteQueryActionCreatorResult<D>; }; type StartMutationActionCreator<D extends MutationDefinition<any, any, any, any>> = (arg: QueryArgFrom<D>, options?: { /** * If this mutation should be tracked in the store. * If you just want to manually trigger this mutation using `dispatch` and don't care about the * result, state & potential errors being held in store, you can set this to false. * (defaults to `true`) */ track?: boolean; fixedCacheKey?: string; }) => ThunkAction<MutationActionCreatorResult<D>, any, any, UnknownAction>; type MutationActionCreatorResult<D extends MutationDefinition<any, any, any, any>> = SafePromise<{ data: ResultTypeFrom<D>; error?: undefined; } | { data?: undefined; error: Exclude<BaseQueryError<D extends MutationDefinition<any, infer BaseQuery, any, any> ? BaseQuery : never>, undefined> | SerializedError; }> & { /** @internal */ arg: { /** * The name of the given endpoint for the mutation */ endpointName: string; /** * The original arguments supplied to the mutation call */ originalArgs: QueryArgFrom<D>; /** * Whether the mutation is being tracked in the store. */ track?: boolean; fixedCacheKey?: string; }; /** * A unique string generated for the request sequence */ requestId: string; /** * A method to cancel the mutation promise. Note that this is not intended to prevent the mutation * that was fired off from reaching the server, but only to assist in handling the response. * * Calling `abort()` prior to the promise resolving will force it to reach the error state with * the serialized error: * `{ name: 'AbortError', message: 'Aborted' }` * * @example * ```ts * const [updateUser] = useUpdateUserMutation(); * * useEffect(() => { * const promise = updateUser(id); * promise * .unwrap() * .catch((err) => { * if (err.name === 'AbortError') return; * // else handle the unexpected error * }) * * return () => { * promise.abort(); * } * }, [id, updateUser]) * ``` */ abort(): void; /** * Unwraps a mutation call to provide the raw response/error. * * @remarks * If you need to access the error or success payload immediately after a mutation, you can chain .unwrap(). * * @example * ```ts * // codeblock-meta title="Using .unwrap" * addPost({ id: 1, name: 'Example' }) * .unwrap() * .then((payload) => console.log('fulfilled', payload)) * .catch((error) => console.error('rejected', error)); * ``` * * @example * ```ts * // codeblock-meta title="Using .unwrap with async await" * try { * const payload = await addPost({ id: 1, name: 'Example' }).unwrap(); * console.log('fulfilled', payload) * } catch (error) { * console.error('rejected', error); * } * ``` */ unwrap(): Promise<ResultTypeFrom<D>>; /** * A method to manually unsubscribe from the mutation call, meaning it will be removed from cache after the usual caching grace period. The value returned by the hook will reset to `isUninitialized` afterwards. */ reset(): void; }; type ReferenceCacheLifecycle = never; interface QueryBaseLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> extends LifecycleApi<ReducerPath> { /** * Gets the current value of this cache entry. */ getCacheEntry(): QueryResultSelectorResult<{ type: DefinitionType.query; } & BaseEndpointDefinition<QueryArg, BaseQuery, ResultType, BaseQueryResult<BaseQuery>>>; /** * Updates the current cache entry value. * For documentation see `api.util.updateQueryData`. */ updateCachedData(updateRecipe: Recipe<ResultType>): PatchCollection; } type MutationBaseLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> = LifecycleApi<ReducerPath> & { /** * Gets the current value of this cache entry. */ getCacheEntry(): MutationResultSelectorResult<{ type: DefinitionType.mutation; } & BaseEndpointDefinition<QueryArg, BaseQuery, ResultType, BaseQueryResult<BaseQuery>>>; }; type LifecycleApi<ReducerPath extends string = string> = { /** * The dispatch method for the store */ dispatch: ThunkDispatch<any, any, UnknownAction>; /** * A method to get the current state */ getState(): RootState<any, any, ReducerPath>; /** * `extra` as provided as `thunk.extraArgument` to the `configureStore` `getDefaultMiddleware` option. */ extra: unknown; /** * A unique ID generated for the mutation */ requestId: string; }; type CacheLifecyclePromises<ResultType = unknown, MetaType = unknown> = { /** * Promise that will resolve with the first value for this cache key. * This allows you to `await` until an actual value is in cache. * * If the cache entry is removed from the cache before any value has ever * been resolved, this Promise will reject with * `new Error('Promise never resolved before cacheEntryRemoved.')` * to prevent memory leaks. * You can just re-throw that error (or not handle it at all) - * it will be caught outside of `cacheEntryAdded`. * * If you don't interact with this promise, it will not throw. */ cacheDataLoaded: PromiseWithKnownReason<{ /** * The (transformed) query result. */ data: ResultType; /** * The `meta` returned by the `baseQuery` */ meta: MetaType; }, typeof neverResolvedError>; /** * Promise that allows you to wait for the point in time when the cache entry * has been removed from the cache, by not being used/subscribed to any more * in the application for too long or by dispatching `api.util.resetApiState`. */ cacheEntryRemoved: Promise<void>; }; interface QueryCacheLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> extends QueryBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>, CacheLifecyclePromises<ResultType, BaseQueryMeta<BaseQuery>> { } type MutationCacheLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> = MutationBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath> & CacheLifecyclePromises<ResultType, BaseQueryMeta<BaseQuery>>; type CacheLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = { onCacheEntryAdded?(arg: QueryArg, api: QueryCacheLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void; }; type CacheLifecycleInfiniteQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = CacheLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery, ReducerPath>; type CacheLifecycleMutationExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = { onCacheEntryAdded?(arg: QueryArg, api: MutationCacheLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void; }; declare const neverResolvedError: Error & { message: "Promise never resolved before cacheEntryRemoved."; }; type ReferenceQueryLifecycle = never; type QueryLifecyclePromises<ResultType, BaseQuery extends BaseQueryFn> = { /** * Promise that will resolve with the (transformed) query result. * * If the query fails, this promise will reject with the error. * * This allows you to `await` for the query to finish. * * If you don't interact with this promise, it will not throw. */ queryFulfilled: PromiseWithKnownReason<{ /** * The (transformed) query result. */ data: ResultType; /** * The `meta` returned by the `baseQuery` */ meta: BaseQueryMeta<BaseQuery>; }, QueryFulfilledRejectionReason<BaseQuery>>; }; type QueryFulfilledRejectionReason<BaseQuery extends BaseQueryFn> = { error: BaseQueryError<BaseQuery>; /** * If this is `false`, that means this error was returned from the `baseQuery` or `queryFn` in a controlled manner. */ isUnhandledError: false; /** * The `meta` returned by the `baseQuery` */ meta: BaseQueryMeta<BaseQuery>; } | { error: unknown; meta?: undefined; /** * If this is `true`, that means that this error is the result of `baseQueryFn`, `queryFn`, `transformResponse` or `transformErrorResponse` throwing an error instead of handling it properly. * There can not be made any assumption about the shape of `error`. */ isUnhandledError: true; }; type QueryLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = { /** * A function that is called when the individual query is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call). * * Can be used to perform side-effects throughout the lifecycle of the query. * * @example * ```ts * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'; * import { messageCreated } from './notificationsSlice'; * * export interface Post { * id: number; * name: string; * } * * const api = createApi({ * baseQuery: fetchBaseQuery({ * baseUrl: '/', * }), * endpoints: (build) => ({ * getPost: build.query<Post, number>({ * query: (id) => `post/${id}`, * async onQueryStarted(id, { dispatch, queryFulfilled }) { * // `onStart` side-effect * dispatch(messageCreated('Fetching posts...')); * try { * const { data } = await queryFulfilled; * // `onSuccess` side-effect * dispatch(messageCreated('Posts received!')); * } catch (err) { * // `onError` side-effect * dispatch(messageCreated('Error fetching posts!')); * } * }, * }), * }), * }); * ``` */ onQueryStarted?(queryArgument: QueryArg, queryLifeCycleApi: QueryLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void; }; type QueryLifecycleInfiniteQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = QueryLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery, ReducerPath>; type QueryLifecycleMutationExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = { /** * A function that is called when the individual mutation is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call). * * Can be used for `optimistic updates`. * * @example * * ```ts * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' * export interface Post { * id: number * name: string * } * * const api = createApi({ * baseQuery: fetchBaseQuery({ * baseUrl: '/', * }), * tagTypes: ['Post'], * endpoints: (build) => ({ * getPost: build.query<Post, number>({ * query: (id) => `post/${id}`, * providesTags: ['Post'], * }), * updatePost: build.mutation<void, Pick<Post, 'id'> & Partial<Post>>({ * query: ({ id, ...patch }) => ({ * url: `post/${id}`, * method: 'PATCH', * body: patch, * }), * invalidatesTags: ['Post'], * async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) { * const patchResult = dispatch( * api.util.updateQueryData('getPost', id, (draft) => { * Object.assign(draft, patch) * }) * ) * try { * await queryFulfilled * } catch { * patchResult.undo() * } * }, * }), * }), * }) * ``` */ onQueryStarted?(queryArgument: QueryArg, mutationLifeCycleApi: MutationLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void; }; interface QueryLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> extends QueryBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>, QueryLifecyclePromises<ResultType, BaseQuery> { } type MutationLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> = MutationBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath> & QueryLifecyclePromises<ResultType, BaseQuery>; /** * Provides a way to define a strongly-typed version of * {@linkcode QueryLifecycleQueryExtraOptions.onQueryStarted | onQueryStarted} * for a specific query. * * @example * <caption>#### __Create and reuse a strongly-typed `onQueryStarted` function__</caption> * * ```ts * import type { TypedQueryOnQueryStarted } from '@reduxjs/toolkit/query' * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' * * type Post = { * id: number * title: string * userId: number * } * * type PostsApiResponse = { * posts: Post[] * total: number * skip: number * limit: number * } * * type QueryArgument = number | undefined * * type BaseQueryFunction = ReturnType<typeof fetchBaseQuery> * * const baseApiSlice = createApi({ * baseQuery: fetchBaseQuery({ baseUrl: 'https://dummyjson.com' }), * reducerPath: 'postsApi', * tagTypes: ['Posts'], * endpoints: (build) => ({ * getPosts: build.query<PostsApiResponse, void>({ * query: () => `/posts`, * }), * * getPostById: build.query<Post, QueryArgument>({ * query: (postId) => `/posts/${postId}`, * }), * }), * }) * * const updatePostOnFulfilled: TypedQueryOnQueryStarted< * PostsApiResponse, * QueryArgument, * BaseQueryFunction, * 'postsApi' * > = async (queryArgument, { dispatch, queryFulfilled }) => { * const result = await queryFulfilled * * const { posts } = result.data * * // Pre-fill the individual post entries with the results * // from the list endpoint query * dispatch( * baseApiSlice.util.upsertQueryEntries( * posts.map((post) => ({ * endpointName: 'getPostById', * arg: post.id, * value: post, * })), * ), * ) * } * * export const extendedApiSlice = baseApiSlice.injectEndpoints({ * endpoints: (build) => ({ * getPostsByUserId: build.query<PostsApiResponse, QueryArgument>({ * query: (userId) => `/posts/user/${userId}`, * * onQueryStarted: updatePostOnFulfilled, * }), * }), * }) * ``` * * @template ResultType - The type of the result `data` returned by the query. * @template QueryArgumentType - The type of the argument passed into the query. * @template BaseQueryFunctionType - The type of the base query function being used. * @template ReducerPath - The type representing the `reducerPath` for the API slice. * * @since 2.4.0 * @public */ type TypedQueryOnQueryStarted<ResultType, QueryArgumentType, BaseQueryFunctionType extends BaseQueryFn, ReducerPath extends string = string> = QueryLifecycleQueryExtraOptions<ResultType, QueryArgumentType, BaseQueryFunctionType, ReducerPath>['onQueryStarted']; /** * Provides a way to define a strongly-typed version of * {@linkcode QueryLifecycleMutationExtraOptions.onQueryStarted | onQueryStarted} * for a specific mutation. * * @example * <caption>#### __Create and reuse a strongly-typed `onQueryStarted` function__</caption> * * ```ts * import type { TypedMutationOnQueryStarted } from '@reduxjs/toolkit/query' * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' * * type Post = { * id: number * title: string * userId: number * } * * type PostsApiResponse = { * posts: Post[] * total: number * skip: number * limit: number * } * * type QueryArgument = Pick<Post, 'id'> & Partial<Post> * * type BaseQueryFunction = ReturnType<typeof fetchBaseQuery> * * const baseApiSlice = createApi({ * baseQuery: fetchBaseQuery({ baseUrl: 'https://dummyjson.com' }), * reducerPath: 'postsApi', * tagTypes: ['Posts'], * endpoints: (build) => ({ * getPosts: build.query<PostsApiResponse, void>({ * query: () => `/posts`, * }), * * getPostById: build.query<Post, number>({ * query: (postId) => `/posts/${postId}`, * }), * }), * }) * * const updatePostOnFulfilled: TypedMutationOnQueryStarted< * Post, * QueryArgument, * BaseQueryFunction, * 'postsApi' * > = async ({ id, ...patch }, { dispatch, queryFulfilled }) => { * const patchCollection = dispatch( * baseApiSlice.util.updateQueryData('getPostById', id, (draftPost) => { * Object.assign(draftPost, patch) * }), * ) * * try { * await queryFulfilled * } catch { * patchCollection.undo() * } * } * * export const extendedApiSlice = baseApiSlice.injectEndpoints({ * endpoints: (build) => ({ * addPost: build.mutation<Post, Omit<QueryArgument, 'id'>>({ * query: (body) => ({ * url: `posts/add`, * method: 'POST', * body, * }), * * onQueryStarted: updatePostOnFulfilled, * }), * * updatePost: build.mutation<Post, QueryArgument>({ * query: ({ id, ...patch }) => ({ * url: `post/${id}`, * method: 'PATCH', * body: patch, * }), * * onQueryStarted: updatePostOnFulfilled, * }), * }), * }) * ``` * * @template ResultType - The type of the result `data` returned by the query. * @template QueryArgumentType - The type of the argument passed into the query. * @template BaseQueryFunctionType - The type of the base query function being used. * @template ReducerPath - The type representing the `reducerPath` for the API slice. * * @since 2.4.0 * @public */ type TypedMutationOnQueryStarted<ResultType, QueryArgumentType, BaseQueryFunctionType extends BaseQueryFn, ReducerPath extends string = string> = QueryLifecycleMutationExtraOptions<ResultType, QueryArgumentType, BaseQueryFunctionType, ReducerPath>['onQueryStarted']; /** * A typesafe single entry to be upserted into the cache */ type NormalizedQueryUpsertEntry<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = { endpointName: EndpointName; arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>; value: DataFromAnyQueryDefinition<Definitions, EndpointName>; }; /** * The internal version that is not typesafe since we can't carry the generics through `createSlice` */ type NormalizedQueryUpsertEntryPayload = { endpointName: string; arg: unknown; value: unknown; }; type ProcessedQueryUpsertEntry = { queryDescription: QueryThunkArg; value: unknown; }; /** * A typesafe representation of a util action creator that accepts cache entry descriptions to upsert */ type UpsertEntries<Definitions extends EndpointDefinitions> = (<EndpointNames extends Array<AllQueryKeys<Definitions>>>(entries: [ ...{ [I in keyof EndpointNames]: NormalizedQueryUpsertEntry<Definitions, EndpointNames[I]>; } ]) => PayloadAction<NormalizedQueryUpsertEntryPayload[]>) & { match: (action: unknown) => action is PayloadAction<NormalizedQueryUpsertEntryPayload[]>; }; declare function buildSlice({ reducerPath, queryThunk, mutationThunk, serializeQueryArgs, context: { endpointDefinitions: definitions, apiUid, extractRehydrationInfo, hasRehydrationInfo, }, assertTagType, config, }: { reducerPath: string; queryThunk: QueryThunk; infiniteQueryThunk: InfiniteQueryThunk<any>; mutationThunk: MutationThunk; serializeQueryArgs: InternalSerializeQueryArgs; context: ApiContext<EndpointDefinitions>; assertTagType: AssertTagTypes; config: Omit<ConfigState<string>, 'online' | 'focused' | 'middlewareRegistered'>; }): { reducer: redux.Reducer<{ queries: QueryState<any>; mutations: MutationState<any>; provided: InvalidationState<string>; subscriptions: SubscriptionState; config: ConfigState<string>; }, redux.UnknownAction, Partial<{ queries: QueryState<any> | undefined; mutations: MutationState<any> | undefined; provided: InvalidationState<string> | undefined; subscriptions: SubscriptionState | undefined; config: ConfigState<string> | undefined; }>>; actions: { resetApiState: _reduxjs_toolkit.ActionCreatorWithoutPayload<`${string}/resetApiState`>; updateProvidedBy: _reduxjs_toolkit.ActionCreatorWithPreparedPayload<[payload: { queryCacheKey: QueryCacheKey; providedTags: readonly FullTagDescription<string>[]; }[]], { queryCacheKey: QueryCacheKey; providedTags: readonly FullTagDescription<string>[]; }[], `${string}/invalidation/updateProvidedBy`, never, unknown>; removeMutationResult: _reduxjs_toolkit.ActionCreatorWithPreparedPayload<[payload: MutationSubstateIdentifier], MutationSubstateIdentifier, `${string}/mutations/removeMutationResult`, never, unknown>; subscriptionsUpdated: _reduxjs_toolkit.ActionCreatorWithPreparedPayload<[payload: Patch[]], Patch[], `${string}/internalSubscriptions/subscriptionsUpdated`, never, unknown>; updateSubscriptionOptions: _reduxjs_toolkit.ActionCreatorWithPayload<{ endpointName: string; requestId: string; options: Subscribers[number]; } & QuerySubstateIdentifier, `${string}/subscriptions/updateSubscriptionOptions`>; unsubscribeQueryResult: _reduxjs_toolkit.ActionCreatorWithPayload<{ requestId: string; } & QuerySubstateIdentifier, `${string}/subscriptions/unsubscribeQueryResult`>; internal_getRTKQSubscriptions: _reduxjs_toolkit.ActionCreatorWithoutPayload<`${string}/subscriptions/internal_getRTKQSubscriptions`>; removeQueryResult: _reduxjs_toolkit.ActionCreatorWithPreparedPayload<[payload: QuerySubstateIdentifier], QuerySubstateIdentifier, `${string}/queries/removeQueryResult`, never, unknown>; cacheEntriesUpserted: _reduxjs_toolkit.ActionCreatorWithPreparedPayload<[payload: NormalizedQueryUpsertEntryPayload[]], ProcessedQueryUpsertEntry[], `${string}/queries/cacheEntriesUpserted`, never, { RTK_autoBatch: boolean; requestId: string; timestamp: number; }>; queryResultPatched: _reduxjs_toolkit.ActionCreatorWithPreparedPayload<[payload: QuerySubstateIdentifier & { patches: readonly Patch[]; }], QuerySubstateIdentifier & { patches: readonly Patch[]; }, `${string}/queries/queryResultPatched`, never, unknown>; middlewareRegistered: _reduxjs_toolkit.ActionCreatorWithPayload<string, `${string}/config/middlewareRegistered`>; }; }; type SliceActions = ReturnType<typeof buildSlice>['actions']; declare const onFocus: ActionCreatorWithoutPayload<"__rtkq/focused">; declare const onFocusLost: ActionCreatorWithoutPayload<"__rtkq/unfocused">; declare const onOnline: ActionCreatorWithoutPayload<"__rtkq/online">; declare const onOffline: ActionCreatorWithoutPayload<"__rtkq/offline">; /** * A utility used to enable `refetchOnMount` and `refetchOnReconnect` behaviors. * It requires the dispatch method from your store. * Calling `setupListeners(store.dispatch)` will configure listeners with the recommended defaults, * but you have the option of providing a callback for more granular control. * * @example * ```ts * setupListeners(store.dispatch) * ``` * * @param dispatch - The dispatch method from your store * @param customHandler - An optional callback for more granular control over listener behavior * @returns Return value of the handler. * The default handler returns an `unsubscribe` method that can be called to remove the listeners. */ declare function setupListeners(dispatch: ThunkDispatch<any, any, any>, customHandler?: (dispatch: ThunkDispatch<any, any, any>, actions: { onFocus: typeof onFocus; onFocusLost: typeof onFocusLost; onOnline: typeof onOnline; onOffline: typeof onOffline; }) => () => void): () => void; /** * Note: this file should import all other files for type discovery and declaration merging */ /** * `ifOlderThan` - (default: `false` | `number`) - _number is value in seconds_ * - If specified, it will only run the query if the difference between `new Date()` and the last `fulfilledTimeStamp` is greater than the given value * * @overloadSummary * `force` * - If `force: true`, it will ignore the `ifOlderThan` value if it is set and the query will be run even if it exists in the cache. */ type PrefetchOptions = { ifOlderThan?: false | number; } | { force?: boolean; }; export declare const coreModuleName: unique symbol; type CoreModule = typeof coreModuleName | ReferenceCacheLifecycle | ReferenceQueryLifecycle | ReferenceCacheCollection; type ThunkWithReturnValue<T> = ThunkAction<T, any, any, UnknownAction>; interface ApiModules<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string> { [coreModuleName]: { /** * This api's reducer should be mounted at `store[api.reducerPath]`. * * @example * ```ts * configureStore({ * reducer: { * [api.reducerPath]: api.reducer, * }, * middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware), * }) * ``` */ reducerPath: ReducerPath; /** * Internal actions not part of the public API. Note: These are subject to change at any given time. */ internalActions: InternalActions; /** * A standard redux reducer that enables core functionality. Make sure it's included in your store. * * @example * ```ts * configureStore({ * reducer: { * [api.reducerPath]: api.reducer, * }, * middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware), * }) * ``` */ reducer: Reducer<CombinedState<Definitions, TagTypes, ReducerPath>, UnknownAction>; /** * This is a standard redux middleware and is responsible for things like polling, garbage collection and a handful of other things. Make sure it's included in your store. * * @example * ```ts * configureStore({ * reducer: { * [api.reducerPath]: api.reducer, * }, * middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware), * }) * ``` */ middleware: Middleware<{}, RootState<Definitions, string, ReducerPath>, ThunkDispatch<any, any, UnknownAction>>; /** * A collection of utility thunks for various situations. */ util: { /** * A thunk that (if dispatched) will return a specific running query, identified * by `endpointName` and `arg`. * If that query is not running, dispatching the thunk will result in `undefined`. * * Can be used to await a specific query triggered in any way, * including via hook calls or manually dispatching `initiate` actions. * * See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details. */ getRunningQueryThunk<EndpointName extends AllQueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>): ThunkWithReturnValue<QueryActionCreatorResult<Definitions[EndpointName] & { type: 'query'; }> | InfiniteQueryActionCreatorResult<Definitions[EndpointName] & { type: 'infinitequery'; }> | undefined>; /** * A thunk that (if dispatched) will return a specific running mutation, identified * by `endpointName` and `fixedCacheKey` or `requestId`. * If that mutation is not running, dispatching the thunk will result in `undefined`. * * Can be used to await a specific mutation triggered in any way, * including via hook trigger functions or manually dispatching `initiate` actions. * * See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details. */ getRunningMutationThunk<EndpointName extends MutationKeys<Definitions>>(endpointName: EndpointName, fixedCacheKeyOrRequestId: string): ThunkWithReturnValue<MutationActionCreatorResult<Definitions[EndpointName] & { type: 'mutation'; }> | undefined>; /** * A thunk that (if dispatched) will return all running queries. * * Useful for SSR scenarios to await all running queries triggered in any way, * including via hook calls or manually dispatching `initiate` actions. * * See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details. */ getRunningQueriesThunk(): ThunkWithReturnValue<Array<QueryActionCreatorResult<any> | InfiniteQueryActionCreatorResult<any>>>; /** * A thunk that (if dispatched) will return all running mutations. * * Useful for SSR scenarios to await all running mutations triggered in any way, * including via hook calls or manually dispatching `initiate` actions. * * See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details. */ getRunningMutationsThunk(): ThunkWithReturnValue<Array<MutationActionCreatorResult<any>>>; /** * A Redux thunk that can be used to manually trigger pre-fetching of data. * * The thunk accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), the appropriate query arg values to construct the desired cache key, and a set of options used to determine if the data actually should be re-fetched based on cache staleness. * * React Hooks users will most likely never need to use this directly, as the `usePrefetch` hook will dispatch this thunk internally as needed when you call the prefetching function supplied by the hook. * * @example * * ```ts no-transpile * dispatch(api.util.prefetch('getPosts', undefined, { force: true })) * ``` */ prefetch<EndpointName extends QueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFrom<Definitions[EndpointName]>, options?: PrefetchOptions): ThunkAction<void, any, any, UnknownAction>; /** * A Redux thunk action creator that, when dispatched, creates and applies a set of JSON diff/patch objects to the current state. This immediately updates the Redux state with those changes. * * The thunk action creator accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), the appropriate query arg values to construct the desired cache key, and an `updateRecipe` callback function. The callback receives an Immer-wrapped `draft` of the current state, and may modify the draft to match the expected results after the mutation completes successfully. * * The thunk executes _synchronously_, and returns an object containing `{patches: Patch[], inversePatches: Patch[], undo: () => void}`. The `patches` and `inversePatches` are generated using Immer's [`produceWithPatches` method](https://immerjs.github.io/immer/patches). * * This is typically used as the first step in implementing optimistic updates. The generated `inversePatches` can be used to revert the updates by calling `dispatch(patchQueryData(endpointName, arg, inversePatches))`. Alternatively, the `undo` method can be called directly to achieve the same effect. * * Note that the first two arguments (`endpointName` and `arg`) are used to determine which existing cache entry to update. If no existing cache entry is found, the `updateRecipe` callback will not run. * * @ex