|
'use client' |
|
import { skipToken } from '@tanstack/query-core' |
|
import { useQueries } from './useQueries' |
|
import { defaultThrowOnError } from './suspense' |
|
import type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' |
|
import type { |
|
DefaultError, |
|
QueryClient, |
|
QueryFunction, |
|
ThrowOnError, |
|
} from '@tanstack/query-core' |
|
|
|
|
|
type MAXIMUM_DEPTH = 20 |
|
|
|
|
|
type SkipTokenForUseQueries = symbol |
|
|
|
type GetUseSuspenseQueryOptions<T> = |
|
|
|
T extends { |
|
queryFnData: infer TQueryFnData |
|
error?: infer TError |
|
data: infer TData |
|
} |
|
? UseSuspenseQueryOptions<TQueryFnData, TError, TData> |
|
: T extends { queryFnData: infer TQueryFnData; error?: infer TError } |
|
? UseSuspenseQueryOptions<TQueryFnData, TError> |
|
: T extends { data: infer TData; error?: infer TError } |
|
? UseSuspenseQueryOptions<unknown, TError, TData> |
|
: |
|
T extends [infer TQueryFnData, infer TError, infer TData] |
|
? UseSuspenseQueryOptions<TQueryFnData, TError, TData> |
|
: T extends [infer TQueryFnData, infer TError] |
|
? UseSuspenseQueryOptions<TQueryFnData, TError> |
|
: T extends [infer TQueryFnData] |
|
? UseSuspenseQueryOptions<TQueryFnData> |
|
: |
|
T extends { |
|
queryFn?: |
|
| QueryFunction<infer TQueryFnData, infer TQueryKey> |
|
| SkipTokenForUseQueries |
|
select?: (data: any) => infer TData |
|
throwOnError?: ThrowOnError<any, infer TError, any, any> |
|
} |
|
? UseSuspenseQueryOptions< |
|
TQueryFnData, |
|
TError, |
|
TData, |
|
TQueryKey |
|
> |
|
: T extends { |
|
queryFn?: |
|
| QueryFunction<infer TQueryFnData, infer TQueryKey> |
|
| SkipTokenForUseQueries |
|
throwOnError?: ThrowOnError<any, infer TError, any, any> |
|
} |
|
? UseSuspenseQueryOptions< |
|
TQueryFnData, |
|
TError, |
|
TQueryFnData, |
|
TQueryKey |
|
> |
|
: |
|
UseSuspenseQueryOptions |
|
|
|
type GetUseSuspenseQueryResult<T> = |
|
|
|
T extends { queryFnData: any; error?: infer TError; data: infer TData } |
|
? UseSuspenseQueryResult<TData, TError> |
|
: T extends { queryFnData: infer TQueryFnData; error?: infer TError } |
|
? UseSuspenseQueryResult<TQueryFnData, TError> |
|
: T extends { data: infer TData; error?: infer TError } |
|
? UseSuspenseQueryResult<TData, TError> |
|
: |
|
T extends [any, infer TError, infer TData] |
|
? UseSuspenseQueryResult<TData, TError> |
|
: T extends [infer TQueryFnData, infer TError] |
|
? UseSuspenseQueryResult<TQueryFnData, TError> |
|
: T extends [infer TQueryFnData] |
|
? UseSuspenseQueryResult<TQueryFnData> |
|
: |
|
T extends { |
|
queryFn?: |
|
| QueryFunction<infer TQueryFnData, any> |
|
| SkipTokenForUseQueries |
|
select?: (data: any) => infer TData |
|
throwOnError?: ThrowOnError<any, infer TError, any, any> |
|
} |
|
? UseSuspenseQueryResult< |
|
unknown extends TData ? TQueryFnData : TData, |
|
unknown extends TError ? DefaultError : TError |
|
> |
|
: T extends { |
|
queryFn?: |
|
| QueryFunction<infer TQueryFnData, any> |
|
| SkipTokenForUseQueries |
|
throwOnError?: ThrowOnError<any, infer TError, any, any> |
|
} |
|
? UseSuspenseQueryResult< |
|
TQueryFnData, |
|
unknown extends TError ? DefaultError : TError |
|
> |
|
: |
|
UseSuspenseQueryResult |
|
|
|
|
|
|
|
|
|
export type SuspenseQueriesOptions< |
|
T extends Array<any>, |
|
TResults extends Array<any> = [], |
|
TDepth extends ReadonlyArray<number> = [], |
|
> = TDepth['length'] extends MAXIMUM_DEPTH |
|
? Array<UseSuspenseQueryOptions> |
|
: T extends [] |
|
? [] |
|
: T extends [infer Head] |
|
? [...TResults, GetUseSuspenseQueryOptions<Head>] |
|
: T extends [infer Head, ...infer Tails] |
|
? SuspenseQueriesOptions< |
|
[...Tails], |
|
[...TResults, GetUseSuspenseQueryOptions<Head>], |
|
[...TDepth, 1] |
|
> |
|
: Array<unknown> extends T |
|
? T |
|
: |
|
|
|
T extends Array< |
|
UseSuspenseQueryOptions< |
|
infer TQueryFnData, |
|
infer TError, |
|
infer TData, |
|
infer TQueryKey |
|
> |
|
> |
|
? Array< |
|
UseSuspenseQueryOptions<TQueryFnData, TError, TData, TQueryKey> |
|
> |
|
: |
|
Array<UseSuspenseQueryOptions> |
|
|
|
|
|
|
|
|
|
export type SuspenseQueriesResults< |
|
T extends Array<any>, |
|
TResults extends Array<any> = [], |
|
TDepth extends ReadonlyArray<number> = [], |
|
> = TDepth['length'] extends MAXIMUM_DEPTH |
|
? Array<UseSuspenseQueryResult> |
|
: T extends [] |
|
? [] |
|
: T extends [infer Head] |
|
? [...TResults, GetUseSuspenseQueryResult<Head>] |
|
: T extends [infer Head, ...infer Tails] |
|
? SuspenseQueriesResults< |
|
[...Tails], |
|
[...TResults, GetUseSuspenseQueryResult<Head>], |
|
[...TDepth, 1] |
|
> |
|
: T extends Array< |
|
UseSuspenseQueryOptions< |
|
infer TQueryFnData, |
|
infer TError, |
|
infer TData, |
|
any |
|
> |
|
> |
|
? |
|
Array< |
|
UseSuspenseQueryResult< |
|
unknown extends TData ? TQueryFnData : TData, |
|
unknown extends TError ? DefaultError : TError |
|
> |
|
> |
|
: |
|
Array<UseSuspenseQueryResult> |
|
|
|
export function useSuspenseQueries< |
|
T extends Array<any>, |
|
TCombinedResult = SuspenseQueriesResults<T>, |
|
>( |
|
options: { |
|
queries: readonly [...SuspenseQueriesOptions<T>] |
|
combine?: (result: SuspenseQueriesResults<T>) => TCombinedResult |
|
}, |
|
queryClient?: QueryClient, |
|
): TCombinedResult { |
|
return useQueries( |
|
{ |
|
...options, |
|
queries: options.queries.map((query) => { |
|
if (process.env.NODE_ENV !== 'production') { |
|
if (query.queryFn === skipToken) { |
|
console.error('skipToken is not allowed for useSuspenseQueries') |
|
} |
|
} |
|
|
|
return { |
|
...query, |
|
suspense: true, |
|
throwOnError: defaultThrowOnError, |
|
enabled: true, |
|
placeholderData: undefined, |
|
} |
|
}), |
|
} as any, |
|
queryClient, |
|
) |
|
} |
|
|