{"version":3,"file":"useQueries.mjs","sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport { QueriesObserver, notifyManager } from '@tanstack/query-core'\nimport { useSyncExternalStore } from './useSyncExternalStore'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n  ensurePreventErrorBoundaryRetry,\n  getHasError,\n  useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n  ensureStaleTime,\n  fetchOptimistic,\n  shouldSuspend,\n  willFetch,\n} from './suspense'\nimport type { QueryFunction, QueryKey } from '@tanstack/query-core'\nimport type { UseQueryOptions, UseQueryResult } from './types'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// - `context` is omitted as it is passed as a root-level option to `useQueries` instead.\ntype UseQueryOptionsForUseQueries<\n  TQueryFnData = unknown,\n  TError = unknown,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'context'>\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\ntype GetOptions<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n    ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n    : T extends { data: infer TData; error?: infer TError }\n    ? UseQueryOptionsForUseQueries<unknown, TError, TData>\n    : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n    T extends [infer TQueryFnData, infer TError, infer TData]\n    ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n    : T extends [infer TQueryFnData, infer TError]\n    ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n    : T extends [infer TQueryFnData]\n    ? UseQueryOptionsForUseQueries<TQueryFnData>\n    : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n    T extends {\n        queryFn?: QueryFunction<infer TQueryFnData, infer TQueryKey>\n        select: (data: any) => infer TData\n      }\n    ? UseQueryOptionsForUseQueries<TQueryFnData, unknown, TData, TQueryKey>\n    : T extends { queryFn?: QueryFunction<infer TQueryFnData, infer TQueryKey> }\n    ? UseQueryOptionsForUseQueries<\n        TQueryFnData,\n        unknown,\n        TQueryFnData,\n        TQueryKey\n      >\n    : // Fallback\n      UseQueryOptionsForUseQueries\n\ntype GetResults<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? UseQueryResult<TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n    ? UseQueryResult<TQueryFnData, TError>\n    : T extends { data: infer TData; error?: infer TError }\n    ? UseQueryResult<TData, TError>\n    : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n    T extends [any, infer TError, infer TData]\n    ? UseQueryResult<TData, TError>\n    : T extends [infer TQueryFnData, infer TError]\n    ? UseQueryResult<TQueryFnData, TError>\n    : T extends [infer TQueryFnData]\n    ? UseQueryResult<TQueryFnData>\n    : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n    T extends {\n        queryFn?: QueryFunction<unknown, any>\n        select: (data: any) => infer TData\n      }\n    ? UseQueryResult<TData>\n    : T extends { queryFn?: QueryFunction<infer TQueryFnData, any> }\n    ? UseQueryResult<TQueryFnData>\n    : // Fallback\n      UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n  T extends any[],\n  Result extends any[] = [],\n  Depth extends ReadonlyArray<number> = [],\n> = Depth['length'] extends MAXIMUM_DEPTH\n  ? UseQueryOptionsForUseQueries[]\n  : T extends []\n  ? []\n  : T extends [infer Head]\n  ? [...Result, GetOptions<Head>]\n  : T extends [infer Head, ...infer Tail]\n  ? QueriesOptions<[...Tail], [...Result, GetOptions<Head>], [...Depth, 1]>\n  : unknown[] extends T\n  ? T\n  : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n  // use this to infer the param types in the case of Array.map() argument\n  T extends UseQueryOptionsForUseQueries<\n      infer TQueryFnData,\n      infer TError,\n      infer TData,\n      infer TQueryKey\n    >[]\n  ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData, TQueryKey>[]\n  : // Fallback\n    UseQueryOptionsForUseQueries[]\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n  T extends any[],\n  Result extends any[] = [],\n  Depth extends ReadonlyArray<number> = [],\n> = Depth['length'] extends MAXIMUM_DEPTH\n  ? UseQueryResult[]\n  : T extends []\n  ? []\n  : T extends [infer Head]\n  ? [...Result, GetResults<Head>]\n  : T extends [infer Head, ...infer Tail]\n  ? QueriesResults<[...Tail], [...Result, GetResults<Head>], [...Depth, 1]>\n  : T extends UseQueryOptionsForUseQueries<\n      infer TQueryFnData,\n      infer TError,\n      infer TData,\n      any\n    >[]\n  ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n    UseQueryResult<unknown extends TData ? TQueryFnData : TData, TError>[]\n  : // Fallback\n    UseQueryResult[]\n\nexport function useQueries<T extends any[]>({\n  queries,\n  context,\n}: {\n  queries: readonly [...QueriesOptions<T>]\n  context?: UseQueryOptions['context']\n}): QueriesResults<T> {\n  const queryClient = useQueryClient({ context })\n  const isRestoring = useIsRestoring()\n  const errorResetBoundary = useQueryErrorResetBoundary()\n\n  const defaultedQueries = React.useMemo(\n    () =>\n      queries.map((options) => {\n        const defaultedOptions = queryClient.defaultQueryOptions(options)\n\n        // Make sure the results are already in fetching state before subscribing or updating options\n        defaultedOptions._optimisticResults = isRestoring\n          ? 'isRestoring'\n          : 'optimistic'\n\n        return defaultedOptions\n      }),\n    [queries, queryClient, isRestoring],\n  )\n\n  defaultedQueries.forEach((query) => {\n    ensureStaleTime(query)\n    ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n  })\n\n  useClearResetErrorBoundary(errorResetBoundary)\n\n  const [observer] = React.useState(\n    () => new QueriesObserver(queryClient, defaultedQueries),\n  )\n\n  const optimisticResult = observer.getOptimisticResult(defaultedQueries)\n\n  useSyncExternalStore(\n    React.useCallback(\n      (onStoreChange) =>\n        isRestoring\n          ? () => undefined\n          : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n      [observer, isRestoring],\n    ),\n    () => observer.getCurrentResult(),\n    () => observer.getCurrentResult(),\n  )\n\n  React.useEffect(() => {\n    // Do not notify on updates because of changes in the options because\n    // these changes should already be reflected in the optimistic result.\n    observer.setQueries(defaultedQueries, { listeners: false })\n  }, [defaultedQueries, observer])\n\n  const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n    shouldSuspend(defaultedQueries[index], result, isRestoring),\n  )\n\n  const suspensePromises = shouldAtLeastOneSuspend\n    ? optimisticResult.flatMap((result, index) => {\n        const options = defaultedQueries[index]\n        const queryObserver = observer.getObservers()[index]\n\n        if (options && queryObserver) {\n          if (shouldSuspend(options, result, isRestoring)) {\n            return fetchOptimistic(options, queryObserver, errorResetBoundary)\n          } else if (willFetch(result, isRestoring)) {\n            void fetchOptimistic(options, queryObserver, errorResetBoundary)\n          }\n        }\n        return []\n      })\n    : []\n\n  if (suspensePromises.length > 0) {\n    throw Promise.all(suspensePromises)\n  }\n  const observerQueries = observer.getQueries()\n  const firstSingleResultWhichShouldThrow = optimisticResult.find(\n    (result, index) =>\n      getHasError({\n        result,\n        errorResetBoundary,\n        useErrorBoundary: defaultedQueries[index]?.useErrorBoundary ?? false,\n        query: observerQueries[index]!,\n      }),\n  )\n\n  if (firstSingleResultWhichShouldThrow?.error) {\n    throw firstSingleResultWhichShouldThrow.error\n  }\n\n  return optimisticResult as QueriesResults<T>\n}\n"],"names":["context","defaultedOptions","defaultedQueries","ensurePreventErrorBoundaryRetry","useSyncExternalStore","observer","listeners"],"mappings":";;;;;;;;;;AAsJO;;AAELA;AAF0C;;AAOLA;AAAF;;;AAInC;;;AAMMC;AAIA;;AAKNC;;AAEEC;;;AAKF;AAIA;AAEAC;;AAaE;AACA;AACAC;AAAwCC;;AACzC;;AAMD;AAEM;AACA;;;;AAII;;AAEA;AACD;AACF;;AACD;;;AAIN;AACE;AACD;;AACD;;AAEE;;AAAA;;;;;AACc;AADd;;AASF;;AAEC;;AAED;AACD;;"}