UNPKG

react-query-kit

Version:

🕊️ A toolkit for ReactQuery that make ReactQuery hooks more reusable and typesafe

187 lines (186 loc) • 19.6 kB
import type { DataTag, DefaultError, DefinedUseInfiniteQueryResult, DefinedUseQueryResult, InfiniteData, InfiniteQueryObserverSuccessResult, MutationFunctionContext, MutationKey, QueryClient, QueryFunction, QueryFunctionContext, QueryKey, QueryKeyHashFunction, QueryObserverSuccessResult, SkipToken, UseInfiniteQueryOptions, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult, UseQueryOptions, UseQueryResult } from '@tanstack/react-query'; type CompatibleWithV4<V5, V4> = InfiniteData<unknown> extends UseInfiniteQueryResult<InfiniteData<unknown>>['data'] ? V5 : V4; type CompatibleWithTwoV5<V6Generics, V5Generics> = UseInfiniteQueryOptions<unknown, DefaultError, unknown, QueryKey, unknown> extends never ? V5Generics : V6Generics; type CompatibleUseInfiniteQueryOptions<TFnData, TData, TError, TPageParam> = CompatibleWithV4<CompatibleWithTwoV5<UseInfiniteQueryOptions<TFnData, TError, TData, QueryKey, TPageParam>, UseInfiniteQueryOptions<TFnData, TError, TData, TFnData, QueryKey, TPageParam>>, UseInfiniteQueryOptions<TFnData, TError, TData, TFnData, QueryKey>>; type CompatibleInfiniteData<TFnData, TPageParam> = CompatibleWithV4<InfiniteData<TFnData, TPageParam>, InfiniteData<TFnData>>; type NonUndefinedGuard<T> = T extends undefined ? never : T; type WithRequired<T, K extends keyof T> = T & { [_ in K]: {}; }; type DeepPartial<T> = T extends object ? { [P in keyof T]?: DeepPartial<T[P]>; } : T; type DefaultTo<T, D> = unknown extends T ? D : T; /** * Register global options through declaration merging, e.g. set * `strictVariables: true` to require `variables` at the call site. */ export interface Register { } type RequiresVariables<TVariables> = Register extends { strictVariables: true; } ? undefined extends TVariables ? false : true : false; type WithRequiredVariables<TOptions, TVariables> = RequiresVariables<TVariables> extends true ? TOptions & { variables: CompatibleWithV4<TVariables | SkipToken, TVariables>; } : TOptions; type QueryHookArgs<TOptions, TVariables> = RequiresVariables<TVariables> extends true ? [ options: WithRequiredVariables<TOptions, TVariables>, queryClient?: CompatibleWithV4<QueryClient, void> ] : [options?: TOptions, queryClient?: CompatibleWithV4<QueryClient, void>]; export type CompatibleError = CompatibleWithV4<DefaultError, Error>; export type Fetcher<TFnData, TVariables = void, TPageParam = never> = (variables: TVariables, context: QueryFunctionContext<QueryKey, TPageParam>) => TFnData | Promise<TFnData>; export type AdditionalQueryOptions<TFnData, TVariables, TPageParam = never> = { fetcher: Fetcher<TFnData, TVariables, TPageParam>; variables?: TVariables; }; type inferMiddlewareHook<T extends (...args: any) => any> = (options: inferCreateOptions<T>, queryClient?: CompatibleWithV4<QueryClient, void>) => ReturnType<T>; export type Middleware<T extends (...args: any) => any = QueryHook<any, any, any>> = (hook: inferMiddlewareHook<T>) => inferMiddlewareHook<T>; export type ExposeFetcher<TFnData, TVariables = void, TPageParam = never> = (variables: TVariables, context?: Partial<QueryFunctionContext<QueryKey, TPageParam>>) => TFnData | Promise<TFnData>; export type ExposeMethods<TFnData, TVariables, TError, TPageParam = never> = { fetcher: ExposeFetcher<TFnData, TVariables, TPageParam>; getKey: (variables?: DeepPartial<TVariables>) => CompatibleWithV4<DataTag<QueryKey, [ TPageParam ] extends [never] ? TFnData : InfiniteData<TFnData, TPageParam>>, QueryKey>; getFetchOptions: (variables: TVariables extends void ? CompatibleWithV4<TVariables | SkipToken, TVariables> | void : CompatibleWithV4<TVariables | SkipToken, TVariables>) => Pick<ReturnType<ExposeMethods<TFnData, TVariables, TError, TPageParam>['getOptions']>, [ TPageParam ] extends [never] ? 'queryKey' | 'queryFn' | 'queryKeyHashFn' | 'gcTime' | 'staleTime' : 'queryKey' | 'queryFn' | 'queryKeyHashFn' | 'gcTime' | 'staleTime' | 'getNextPageParam' | 'getPreviousPageParam' | 'initialPageParam'>; getOptions: (variables: TVariables extends void ? CompatibleWithV4<TVariables | SkipToken, TVariables> | void : CompatibleWithV4<TVariables | SkipToken, TVariables>) => [TPageParam] extends [never] ? CompatibleWithV4<UseQueryOptions<TFnData, TError, TFnData, QueryKey> & { queryKey: DataTag<QueryKey, TFnData>; queryFn?: Exclude<UseQueryOptions<TFnData, TError, TFnData, QueryKey>['queryFn'], SkipToken>; }, { queryKey: QueryKey; queryFn: QueryFunction<TFnData, QueryKey>; queryKeyHashFn?: QueryKeyHashFunction<QueryKey>; }> : CompatibleUseInfiniteQueryOptions<TFnData, TFnData, TError, TPageParam> & { queryKey: CompatibleWithV4<DataTag<QueryKey, InfiniteData<TFnData, TPageParam>>, QueryKey>; queryFn?: Exclude<CompatibleUseInfiniteQueryOptions<TFnData, TFnData, TError, TPageParam>['queryFn'], SkipToken>; }; }; type Clone<T> = T extends infer TClone ? TClone : never; export interface CreateQueryOptions<TFnData = unknown, TVariables = void, TError = CompatibleError> extends Omit<UseQueryOptions<TFnData, TError, TFnData, QueryKey>, 'queryKey' | 'queryFn' | 'select'>, AdditionalQueryOptions<TFnData, TVariables> { queryKey: QueryKey; use?: Middleware<QueryHook<Clone<TFnData>, Clone<TVariables>, Clone<TError>>>[]; variables?: TVariables; } export interface QueryHookOptions<TFnData, TError, TData, TVariables> extends Omit<UseQueryOptions<TFnData, TError, TData, QueryKey>, 'queryKey' | 'queryFn' | 'queryKeyHashFn'> { use?: Middleware<QueryHook<TFnData, TVariables, TError>>[]; variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>; } export interface DefinedQueryHookOptions<TFnData, TError, TData, TVariables> extends Omit<QueryHookOptions<TFnData, TError, TData, TVariables>, 'initialData'> { initialData: NonUndefinedGuard<TFnData> | (() => NonUndefinedGuard<TFnData>); } export type QueryHookResult<TData, TError> = UseQueryResult<TData, TError>; export type DefinedQueryHookResult<TData, TError> = DefinedUseQueryResult<TData, TError>; export interface QueryHook<TFnData = unknown, TVariables = void, TError = CompatibleError> extends ExposeMethods<TFnData, TVariables, TError> { <TData = TFnData>(options: WithRequiredVariables<DefinedQueryHookOptions<TFnData, TError, TData, TVariables>, TVariables>, queryClient?: CompatibleWithV4<QueryClient, void>): DefinedQueryHookResult<TData, TError>; <TData = TFnData>(...args: QueryHookArgs<QueryHookOptions<TFnData, TError, TData, TVariables>, TVariables>): QueryHookResult<TData, TError>; } export interface CreateSuspenseQueryOptions<TFnData = unknown, TVariables = void, TError = CompatibleError> extends Omit<UseQueryOptions<TFnData, TError, TFnData, QueryKey>, 'queryKey' | 'queryFn' | 'enabled' | 'select' | 'suspense' | 'throwOnError' | 'placeholderData' | 'keepPreviousData' | 'useErrorBoundary'>, AdditionalQueryOptions<TFnData, TVariables> { queryKey: QueryKey; use?: Middleware<SuspenseQueryHook<Clone<TFnData>, Clone<TVariables>, Clone<TError>>>[]; variables?: TVariables; } export interface SuspenseQueryHookOptions<TFnData, TError, TData, TVariables> extends Omit<UseQueryOptions<TFnData, TError, TData, QueryKey>, 'queryKey' | 'queryFn' | 'queryKeyHashFn' | 'enabled' | 'suspense' | 'throwOnError' | 'placeholderData' | 'keepPreviousData' | 'useErrorBoundary'> { use?: Middleware<SuspenseQueryHook<TFnData, TVariables, TVariables>>[]; variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>; } export type SuspenseQueryHookResult<TData, TError> = Omit<QueryObserverSuccessResult<TData, TError>, 'isPlaceholderData' | 'isPreviousData'>; export interface SuspenseQueryHook<TFnData = unknown, TVariables = void, TError = CompatibleError> extends ExposeMethods<TFnData, TVariables, TError> { <TData = TFnData>(...args: QueryHookArgs<SuspenseQueryHookOptions<TFnData, TError, TData, TVariables>, TVariables>): SuspenseQueryHookResult<TData, TError>; } export interface CreateInfiniteQueryOptions<TFnData = unknown, TVariables = void, TError = CompatibleError, TPageParam = number> extends Omit<CompatibleUseInfiniteQueryOptions<TFnData, TFnData, TError, TPageParam>, 'queryKey' | 'queryFn' | 'select'>, AdditionalQueryOptions<TFnData, TVariables, TPageParam> { queryKey: QueryKey; use?: Middleware<InfiniteQueryHook<Clone<TFnData>, Clone<TVariables>, Clone<TError>, Clone<TPageParam>>>[]; variables?: TVariables; } export interface InfiniteQueryHookOptions<TFnData, TError, TData, TVariables, TPageParam = number> extends Omit<CompatibleUseInfiniteQueryOptions<TFnData, TData, TError, TPageParam>, 'queryKey' | 'queryFn' | 'queryKeyHashFn' | 'initialPageParam' | 'getPreviousPageParam' | 'getNextPageParam'> { use?: Middleware<InfiniteQueryHook<TFnData, TVariables, TError, TPageParam>>[]; variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>; } export interface DefinedInfiniteQueryHookOptions<TFnData, TError, TData, TVariables, TPageParam = number> extends Omit<InfiniteQueryHookOptions<TFnData, TError, TData, TVariables, TPageParam>, 'initialData'> { initialData: NonUndefinedGuard<CompatibleInfiniteData<TFnData, TPageParam>> | (() => NonUndefinedGuard<CompatibleInfiniteData<TFnData, TPageParam>>); } export type InfiniteQueryHookResult<TData, TError> = UseInfiniteQueryResult<TData, TError>; export type DefinedInfiniteQueryHookResult<TData, TError> = CompatibleWithV4<DefinedUseInfiniteQueryResult<TData, TError>, WithRequired<UseInfiniteQueryResult<TData, TError>, 'data'>>; export interface InfiniteQueryHook<TFnData = unknown, TVariables = void, TError = CompatibleError, TPageParam = number> extends ExposeMethods<TFnData, TVariables, TError, TPageParam> { <TData = CompatibleWithV4<InfiniteData<TFnData, TPageParam>, TFnData>>(options: WithRequiredVariables<DefinedInfiniteQueryHookOptions<TFnData, TError, TData, TVariables, TPageParam>, TVariables>, queryClient?: CompatibleWithV4<QueryClient, void>): DefinedInfiniteQueryHookResult<TData, TError>; <TData = CompatibleWithV4<InfiniteData<TFnData, TPageParam>, TFnData>>(...args: QueryHookArgs<InfiniteQueryHookOptions<TFnData, TError, TData, TVariables, TPageParam>, TVariables>): InfiniteQueryHookResult<TData, TError>; } export interface CreateSuspenseInfiniteQueryOptions<TFnData = unknown, TVariables = void, TError = CompatibleError, TPageParam = number> extends Omit<CompatibleUseInfiniteQueryOptions<TFnData, TFnData, TError, TPageParam>, 'queryKey' | 'queryFn' | 'enabled' | 'select' | 'suspense' | 'throwOnError' | 'placeholderData' | 'keepPreviousData' | 'useErrorBoundary'>, AdditionalQueryOptions<TFnData, TVariables, TPageParam> { queryKey: QueryKey; use?: Middleware<SuspenseInfiniteQueryHook<Clone<TFnData>, Clone<TVariables>, Clone<TError>, Clone<TPageParam>>>[]; variables?: TVariables; } export interface SuspenseInfiniteQueryHookOptions<TFnData, TError, TData, TVariables, TPageParam = number> extends Omit<CompatibleUseInfiniteQueryOptions<TFnData, TData, TError, TPageParam>, 'queryKey' | 'queryFn' | 'queryKeyHashFn' | 'enabled' | 'initialPageParam' | 'getPreviousPageParam' | 'getNextPageParam' | 'suspense' | 'throwOnError' | 'placeholderData' | 'keepPreviousData' | 'useErrorBoundary'> { use?: Middleware<SuspenseInfiniteQueryHook<TFnData, TVariables, TVariables>>[]; variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>; } export type SuspenseInfiniteQueryHookResult<TData, TError> = Omit<InfiniteQueryObserverSuccessResult<TData, TError>, 'isPlaceholderData' | 'isPreviousData'>; export interface SuspenseInfiniteQueryHook<TFnData = unknown, TVariables = void, TError = CompatibleError, TPageParam = number> extends ExposeMethods<TFnData, TVariables, TError, TPageParam> { <TData = CompatibleWithV4<InfiniteData<TFnData, TPageParam>, TFnData>>(...args: QueryHookArgs<SuspenseInfiniteQueryHookOptions<TFnData, TError, TData, TVariables, TPageParam>, TVariables>): SuspenseInfiniteQueryHookResult<TData, TError>; } export interface CreateMutationOptions<TData = unknown, TVariables = void, TError = CompatibleError, TContext = unknown> extends UseMutationOptions<TData, TError, TVariables, TContext> { use?: Middleware<MutationHook<TData, TVariables, TError>>[]; } export interface MutationHookOptions<TData, TError, TVariables, TContext> extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, 'mutationFn' | 'mutationKey'> { use?: Middleware<MutationHook<TData, TVariables, TError>>[]; } export type MutationHookResult<TData = unknown, TError = CompatibleError, TVariables = void, TContext = unknown> = UseMutationResult<TData, TError, TVariables, TContext>; export type ExposeMutationFn<TData = unknown, TVariables = void> = [ TVariables ] extends [void] ? (variables?: TVariables, context?: Partial<MutationFunctionContext>) => Promise<TData> : (variables: TVariables, context?: Partial<MutationFunctionContext>) => Promise<TData>; export interface ExposeMutationMethods<TData = unknown, TVariables = void, TError = CompatibleError, TDefaultContext = unknown> { getKey: () => MutationKey | undefined; getOptions: () => UseMutationOptions<TData, TError, TVariables, TDefaultContext>; mutationFn: ExposeMutationFn<TData, TVariables>; } export interface MutationHook<TData = unknown, TVariables = void, TError = CompatibleError, TDefaultContext = unknown> extends ExposeMutationMethods<TData, TVariables, TError, TDefaultContext> { <TContext = TDefaultContext>(options?: MutationHookOptions<TData, TError, TVariables, TContext>, queryClient?: CompatibleWithV4<QueryClient, void>): MutationHookResult<TData, TError, TVariables, TContext>; } export type inferVariables<T> = T extends { fetcher: ExposeFetcher<any, infer TVariables, infer _TPageParam>; } ? TVariables : T extends ExposeMutationMethods<any, infer TVariables, any, any> ? TVariables : never; export type inferData<T> = T extends { fetcher: ExposeFetcher<infer TFnData, any, infer TPageParam>; } ? [TPageParam] extends [never] ? TFnData : CompatibleInfiniteData<TFnData, TPageParam> : T extends ExposeMutationMethods<infer TFnData, any, any, any> ? TFnData : never; export type inferFnData<T> = T extends { fetcher: ExposeFetcher<infer TFnData, any, infer _TPageParam>; } ? TFnData : T extends ExposeMutationMethods<infer TFnData, any, any, any> ? TFnData : never; export type inferError<T> = T extends ExposeMethods<any, any, infer TError> ? TError : T extends ExposeMethods<any, any, infer TError, any> ? TError : T extends ExposeMutationMethods<any, any, infer TError, any> ? TError : never; export type inferOptions<T> = T extends QueryHook<infer TFnData, infer TVariables, infer TError> ? WithRequiredVariables<QueryHookOptions<TFnData, TError, TFnData, TVariables>, TVariables> : T extends SuspenseQueryHook<infer TFnData, infer TVariables, infer TError> ? WithRequiredVariables<SuspenseQueryHookOptions<TFnData, TError, TFnData, TVariables>, TVariables> : T extends InfiniteQueryHook<infer TFnData, infer TVariables, infer TError, infer TPageParam> ? WithRequiredVariables<InfiniteQueryHookOptions<TFnData, TError, CompatibleWithV4<InfiniteData<TFnData, TPageParam>, TFnData>, TVariables, TPageParam>, TVariables> : T extends SuspenseInfiniteQueryHook<infer TFnData, infer TVariables, infer TError, infer TPageParam> ? WithRequiredVariables<SuspenseInfiniteQueryHookOptions<TFnData, TError, CompatibleWithV4<InfiniteData<TFnData, TPageParam>, TFnData>, TVariables, TPageParam>, TVariables> : T extends MutationHook<infer TFnData, infer TVariables, infer TError> ? MutationHookOptions<TFnData, TError, TVariables, unknown> : never; export type inferCreateOptions<T> = T extends QueryHook<infer TFnData, infer TVariables, infer TError> ? CreateQueryOptions<TFnData, TVariables, TError> : T extends SuspenseQueryHook<infer TFnData, infer TVariables, infer TError> ? CreateSuspenseQueryOptions<TFnData, TVariables, TError> : T extends InfiniteQueryHook<infer TFnData, infer TVariables, infer TError, infer TPageParam> ? CreateInfiniteQueryOptions<TFnData, TVariables, TError, TPageParam> : T extends SuspenseInfiniteQueryHook<infer TFnData, infer TVariables, infer TError, infer TPageParam> ? CreateSuspenseInfiniteQueryOptions<TFnData, TVariables, TError, TPageParam> : T extends MutationHook<infer TFnData, infer TVariables, infer TError, infer TContext> ? CreateMutationOptions<TFnData, TVariables, TError, TContext> : never; export type RouterQueryOptions<TFnData, TVariables = void, TError = CompatibleError> = Omit<CreateQueryOptions<TFnData, TVariables, TError>, 'queryKey'>; export type RouterQuery<TFnData, TVariables = void, TError = CompatibleError> = RouterQueryOptions<TFnData, TVariables, TError> & { _routerType: `q`; }; export type ResolvedRouterQuery<TFnData, TVariables = void, TError = CompatibleError> = { useQuery: QueryHook<TFnData, TVariables, TError>; useSuspenseQuery: SuspenseQueryHook<TFnData, TVariables, TError>; } & ExposeMethods<TFnData, TVariables, TError>; export type RouterInfiniteQueryOptions<TFnData, TVariables = void, TError = CompatibleError, TPageParam = number> = Omit<CreateInfiniteQueryOptions<TFnData, TVariables, TError, TPageParam>, 'queryKey'>; export type RouterInfiniteQuery<TFnData, TVariables = void, TError = CompatibleError, TPageParam = number> = RouterInfiniteQueryOptions<TFnData, TVariables, TError, Clone<TPageParam>> & { _routerType: `inf`; }; export type ResolvedRouterInfiniteQuery<TFnData, TVariables = void, TError = CompatibleError, TPageParam = number> = { useInfiniteQuery: InfiniteQueryHook<TFnData, TVariables, TError, TPageParam>; useSuspenseInfiniteQuery: SuspenseInfiniteQueryHook<TFnData, TVariables, TError, TPageParam>; } & ExposeMethods<TFnData, TVariables, TError, TPageParam>; export type RouterMutationOptions<TData = unknown, TVariables = void, TError = CompatibleError, TContext = unknown> = Omit<CreateMutationOptions<TData, TVariables, TError, TContext>, 'mutationKey'>; export type RouterMutation<TData = unknown, TVariables = void, TError = CompatibleError, TContext = unknown> = RouterMutationOptions<TData, TVariables, TError, TContext> & { _routerType: `m`; }; export type ResolvedRouterMutation<TData = unknown, TVariables = void, TError = CompatibleError, TContext = unknown> = { useMutation: MutationHook<TData, DefaultTo<TVariables, void>, DefaultTo<TError, CompatibleError>, TContext>; } & ExposeMutationMethods<TData, DefaultTo<TVariables, void>, DefaultTo<TError, CompatibleError>, TContext>; export type RouterLeaf = RouterQuery<any, any, any> | RouterInfiniteQuery<any, any, any, any> | RouterMutation<any, any, any, any>; export type RouterConfig = { _routerType?: never; } & { [k: string]: RouterLeaf | RouterConfig; }; export type CreateRouter<TConfig extends RouterConfig> = { [K in keyof TConfig]: TConfig[K] extends RouterMutation<infer TFnData, infer TVariables, infer TError, infer TContext> ? ResolvedRouterMutation<TFnData, DefaultTo<TVariables, void>, DefaultTo<TError, CompatibleError>, TContext> : TConfig[K] extends RouterInfiniteQuery<infer TFnData, infer TVariables, infer TError, infer TPageParam> ? ResolvedRouterInfiniteQuery<TFnData, DefaultTo<TVariables, void>, DefaultTo<TError, CompatibleError>, DefaultTo<TPageParam, number>> : TConfig[K] extends RouterQuery<infer TFnData, infer TVariables, infer TError> ? ResolvedRouterQuery<TFnData, DefaultTo<TVariables, void>, DefaultTo<TError, CompatibleError>> : TConfig[K] extends RouterConfig ? CreateRouter<TConfig[K]> : never; } & { getKey: () => QueryKey; }; export {};