UNPKG

@reduxjs/toolkit

Version:

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

350 lines (324 loc) 9.73 kB
import type { SerializedError } from '@reduxjs/toolkit' import type { BaseQueryError } from '../baseQueryTypes' import type { BaseEndpointDefinition, EndpointDefinitions, FullTagDescription, InfiniteQueryDefinition, MutationDefinition, PageParamFrom, QueryArgFromAnyQuery, QueryDefinition, ResultTypeFrom, } from '../endpointDefinitions' import type { Id, WithRequiredProp } from '../tsHelpers' export type QueryCacheKey = string & { _type: 'queryCacheKey' } export type QuerySubstateIdentifier = { queryCacheKey: QueryCacheKey } export type MutationSubstateIdentifier = | { requestId: string; fixedCacheKey?: string } | { requestId?: string; fixedCacheKey: string } export type RefetchConfigOptions = { refetchOnMountOrArgChange: boolean | number refetchOnReconnect: boolean refetchOnFocus: boolean } export type PageParamFunction<DataType, PageParam> = ( firstPage: DataType, allPages: Array<DataType>, firstPageParam: PageParam, allPageParams: Array<PageParam>, ) => PageParam | undefined | null export type InfiniteQueryConfigOptions<DataType, PageParam> = { /** * The initial page parameter to use for the first page fetch. */ initialPageParam: PageParam /** * This function is required to automatically get the next cursor for infinite queries. * The result will also be used to determine the value of `hasNextPage`. */ getNextPageParam: PageParamFunction<DataType, PageParam> /** * 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?: PageParamFunction<DataType, PageParam> /** * If specified, only keep this many pages in cache at once. * If additional pages are fetched, older pages in the other * direction will be dropped from the cache. */ maxPages?: number } export type InfiniteData<DataType, PageParam> = { pages: Array<DataType> pageParams: Array<PageParam> } /** * Strings describing the query state at any given time. */ export enum QueryStatus { uninitialized = 'uninitialized', pending = 'pending', fulfilled = 'fulfilled', rejected = 'rejected', } export type RequestStatusFlags = | { status: QueryStatus.uninitialized isUninitialized: true isLoading: false isSuccess: false isError: false } | { status: QueryStatus.pending isUninitialized: false isLoading: true isSuccess: false isError: false } | { status: QueryStatus.fulfilled isUninitialized: false isLoading: false isSuccess: true isError: false } | { status: QueryStatus.rejected isUninitialized: false isLoading: false isSuccess: false isError: true } export function getRequestStatusFlags(status: QueryStatus): RequestStatusFlags { return { status, isUninitialized: status === QueryStatus.uninitialized, isLoading: status === QueryStatus.pending, isSuccess: status === QueryStatus.fulfilled, isError: status === QueryStatus.rejected, } as any } /** * @public */ export type SubscriptionOptions = { /** * How frequently to automatically re-fetch data (in milliseconds). Defaults to `0` (off). */ pollingInterval?: number /** * Defaults to 'false'. This setting allows you to control whether RTK Query will continue polling if the window is not focused. * * If pollingInterval is not set or set to 0, this **will not be evaluated** until pollingInterval is greater than 0. * * Note: requires [`setupListeners`](./setupListeners) to have been called. */ skipPollingIfUnfocused?: boolean /** * Defaults to `false`. This setting allows you to control whether RTK Query will try to refetch all subscribed queries after regaining a network connection. * * If you specify this option alongside `skip: true`, this **will not be evaluated** until `skip` is false. * * Note: requires [`setupListeners`](./setupListeners) to have been called. */ refetchOnReconnect?: boolean /** * Defaults to `false`. This setting allows you to control whether RTK Query will try to refetch all subscribed queries after the application window regains focus. * * If you specify this option alongside `skip: true`, this **will not be evaluated** until `skip` is false. * * Note: requires [`setupListeners`](./setupListeners) to have been called. */ refetchOnFocus?: boolean } export type Subscribers = { [requestId: string]: SubscriptionOptions } export type QueryKeys<Definitions extends EndpointDefinitions> = { [K in keyof Definitions]: Definitions[K] extends QueryDefinition< any, any, any, any > ? K : never }[keyof Definitions] export type InfiniteQueryKeys<Definitions extends EndpointDefinitions> = { [K in keyof Definitions]: Definitions[K] extends InfiniteQueryDefinition< any, any, any, any, any > ? K : never }[keyof Definitions] export type MutationKeys<Definitions extends EndpointDefinitions> = { [K in keyof Definitions]: Definitions[K] extends MutationDefinition< any, any, any, any > ? K : never }[keyof Definitions] type BaseQuerySubState< D extends BaseEndpointDefinition<any, any, any, any>, DataType = ResultTypeFrom<D>, > = { /** * The argument originally passed into the hook or `initiate` action call */ originalArgs: QueryArgFromAnyQuery<D> /** * A unique ID associated with the request */ requestId: string /** * The received data from the query */ data?: DataType /** * The received error if applicable */ error?: | SerializedError | (D extends QueryDefinition<any, infer BaseQuery, any, any> ? BaseQueryError<BaseQuery> : never) /** * The name of the endpoint associated with the query */ endpointName: string /** * Time that the latest query started */ startedTimeStamp: number /** * Time that the latest query was fulfilled */ fulfilledTimeStamp?: number } export type QuerySubState< D extends BaseEndpointDefinition<any, any, any, any>, DataType = ResultTypeFrom<D>, > = Id< | ({ status: QueryStatus.fulfilled } & WithRequiredProp< BaseQuerySubState<D, DataType>, 'data' | 'fulfilledTimeStamp' > & { error: undefined }) | ({ status: QueryStatus.pending } & BaseQuerySubState<D, DataType>) | ({ status: QueryStatus.rejected } & WithRequiredProp< BaseQuerySubState<D, DataType>, 'error' >) | { status: QueryStatus.uninitialized originalArgs?: undefined data?: undefined error?: undefined requestId?: undefined endpointName?: string startedTimeStamp?: undefined fulfilledTimeStamp?: undefined } > export type InfiniteQueryDirection = 'forward' | 'backward' export type InfiniteQuerySubState< D extends BaseEndpointDefinition<any, any, any, any>, > = D extends InfiniteQueryDefinition<any, any, any, any, any> ? QuerySubState<D, InfiniteData<ResultTypeFrom<D>, PageParamFrom<D>>> & { direction?: InfiniteQueryDirection } : never type BaseMutationSubState< D extends BaseEndpointDefinition<any, any, any, any>, > = { requestId: string data?: ResultTypeFrom<D> error?: | SerializedError | (D extends MutationDefinition<any, infer BaseQuery, any, any> ? BaseQueryError<BaseQuery> : never) endpointName: string startedTimeStamp: number fulfilledTimeStamp?: number } export type MutationSubState< D extends BaseEndpointDefinition<any, any, any, any>, > = | (({ status: QueryStatus.fulfilled } & WithRequiredProp< BaseMutationSubState<D>, 'data' | 'fulfilledTimeStamp' >) & { error: undefined }) | (({ status: QueryStatus.pending } & BaseMutationSubState<D>) & { data?: undefined }) | ({ status: QueryStatus.rejected } & WithRequiredProp< BaseMutationSubState<D>, 'error' >) | { requestId?: undefined status: QueryStatus.uninitialized data?: undefined error?: undefined endpointName?: string startedTimeStamp?: undefined fulfilledTimeStamp?: undefined } export type CombinedState< D extends EndpointDefinitions, E extends string, ReducerPath extends string, > = { queries: QueryState<D> mutations: MutationState<D> provided: InvalidationState<E> subscriptions: SubscriptionState config: ConfigState<ReducerPath> } export type InvalidationState<TagTypes extends string> = { tags: { [_ in TagTypes]: { [id: string]: Array<QueryCacheKey> [id: number]: Array<QueryCacheKey> } } keys: Record<QueryCacheKey, Array<FullTagDescription<any>>> } export type QueryState<D extends EndpointDefinitions> = { [queryCacheKey: string]: | QuerySubState<D[string]> | InfiniteQuerySubState<D[string]> | undefined } export type SubscriptionState = { [queryCacheKey: string]: Subscribers | undefined } export type ConfigState<ReducerPath> = RefetchConfigOptions & { reducerPath: ReducerPath online: boolean focused: boolean middlewareRegistered: boolean | 'conflict' } & ModifiableConfigState export type ModifiableConfigState = { keepUnusedDataFor: number invalidationBehavior: 'delayed' | 'immediately' } & RefetchConfigOptions export type MutationState<D extends EndpointDefinitions> = { [requestId: string]: MutationSubState<D[string]> | undefined } export type RootState< Definitions extends EndpointDefinitions, TagTypes extends string, ReducerPath extends string, > = { [P in ReducerPath]: CombinedState<Definitions, TagTypes, P> }