{"version":3,"file":"inject-queries.mjs","sources":["../src/inject-queries.ts"],"sourcesContent":["import {\n  QueriesObserver,\n  QueryClient,\n  notifyManager,\n} from '@tanstack/query-core'\nimport {\n  DestroyRef,\n  Injector,\n  NgZone,\n  assertInInjectionContext,\n  computed,\n  effect,\n  inject,\n  runInInjectionContext,\n  signal,\n  untracked,\n} from '@angular/core'\nimport { signalProxy } from './signal-proxy'\nimport { injectIsRestoring } from './inject-is-restoring'\nimport type {\n  DefaultError,\n  OmitKeyof,\n  QueriesObserverOptions,\n  QueriesPlaceholderDataFunction,\n  QueryFunction,\n  QueryKey,\n  QueryObserverOptions,\n  ThrowOnError,\n} from '@tanstack/query-core'\nimport type {\n  CreateQueryOptions,\n  CreateQueryResult,\n  DefinedCreateQueryResult,\n} from './types'\nimport type { Signal } from '@angular/core'\n\n// This defines the `CreateQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype QueryObserverOptionsForCreateQueries<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'placeholderData'\n> & {\n  placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction<TQueryFnData>\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForCreateQueries = symbol\n\ntype GetCreateQueryOptionsForCreateQueries<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    ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? QueryObserverOptionsForCreateQueries<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          ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? QueryObserverOptionsForCreateQueries<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForCreateQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? QueryObserverOptionsForCreateQueries<\n                    TQueryFnData,\n                    unknown extends TError ? DefaultError : TError,\n                    unknown extends TData ? TQueryFnData : TData,\n                    TQueryKey\n                  >\n                : // Fallback\n                  QueryObserverOptionsForCreateQueries\n\n// A defined initialData setting should return a DefinedCreateQueryResult rather than CreateQueryResult\ntype GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {\n  initialData?: infer TInitialData\n}\n  ? unknown extends TInitialData\n    ? CreateQueryResult<TData, TError>\n    : TInitialData extends TData\n      ? DefinedCreateQueryResult<TData, TError>\n      : TInitialData extends () => infer TInitialDataResult\n        ? unknown extends TInitialDataResult\n          ? CreateQueryResult<TData, TError>\n          : TInitialDataResult extends TData\n            ? DefinedCreateQueryResult<TData, TError>\n            : CreateQueryResult<TData, TError>\n        : CreateQueryResult<TData, TError>\n  : CreateQueryResult<TData, TError>\n\ntype GetCreateQueryResult<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    ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? GetDefinedOrUndefinedQueryResult<T, 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          ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForCreateQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? GetDefinedOrUndefinedQueryResult<\n                    T,\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : // Fallback\n                  CreateQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<QueryObserverOptionsForCreateQueries>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetCreateQueryOptionsForCreateQueries<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesOptions<\n            [...Tails],\n            [...TResults, GetCreateQueryOptionsForCreateQueries<Head>],\n            [...TDepth, 1]\n          >\n        : ReadonlyArray<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 Array<\n                QueryObserverOptionsForCreateQueries<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                QueryObserverOptionsForCreateQueries<\n                  TQueryFnData,\n                  TError,\n                  TData,\n                  TQueryKey\n                >\n              >\n            : // Fallback\n              Array<QueryObserverOptionsForCreateQueries>\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<CreateQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetCreateQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesResults<\n            [...Tails],\n            [...TResults, GetCreateQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetCreateQueryResult<T[K]> }\n\nexport interface InjectQueriesOptions<\n  T extends Array<any>,\n  TCombinedResult = QueriesResults<T>,\n> {\n  queries:\n    | readonly [...QueriesOptions<T>]\n    | readonly [\n        ...{ [K in keyof T]: GetCreateQueryOptionsForCreateQueries<T[K]> },\n      ]\n  combine?: (result: QueriesResults<T>) => TCombinedResult\n}\n\n/**\n * @param optionsFn - A function that returns queries' options.\n * @param injector - The Angular injector to use.\n */\nexport function injectQueries<\n  T extends Array<any>,\n  TCombinedResult = QueriesResults<T>,\n>(\n  optionsFn: () => InjectQueriesOptions<T, TCombinedResult>,\n  injector?: Injector,\n): Signal<TCombinedResult> {\n  !injector && assertInInjectionContext(injectQueries)\n  return runInInjectionContext(injector ?? inject(Injector), () => {\n    const destroyRef = inject(DestroyRef)\n    const ngZone = inject(NgZone)\n    const queryClient = inject(QueryClient)\n    const isRestoring = injectIsRestoring()\n\n    /**\n     * Signal that has the default options from query client applied\n     * computed() is used so signals can be inserted into the options\n     * making it reactive. Wrapping options in a function ensures embedded expressions\n     * are preserved and can keep being applied after signal changes\n     */\n    const optionsSignal = computed(() => {\n      return optionsFn()\n    })\n\n    const defaultedQueries = computed(() => {\n      return optionsSignal().queries.map((opts) => {\n        const defaultedOptions = queryClient.defaultQueryOptions(\n          opts as QueryObserverOptions,\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 as QueryObserverOptions\n      })\n    })\n\n    const observerSignal = (() => {\n      let instance: QueriesObserver<TCombinedResult> | null = null\n\n      return computed(() => {\n        return (instance ||= new QueriesObserver<TCombinedResult>(\n          queryClient,\n          defaultedQueries(),\n          optionsSignal() as QueriesObserverOptions<TCombinedResult>,\n        ))\n      })\n    })()\n\n    const optimisticResultSignal = computed(() =>\n      observerSignal().getOptimisticResult(\n        defaultedQueries(),\n        (optionsSignal() as QueriesObserverOptions<TCombinedResult>).combine,\n      ),\n    )\n\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    effect(() => {\n      observerSignal().setQueries(\n        defaultedQueries(),\n        optionsSignal() as QueriesObserverOptions<TCombinedResult>,\n      )\n    })\n\n    const optimisticCombinedResultSignal = computed(() => {\n      const [_optimisticResult, getCombinedResult, trackResult] =\n        optimisticResultSignal()\n      return getCombinedResult(trackResult())\n    })\n\n    const resultFromSubscriberSignal = signal<TCombinedResult | null>(null)\n\n    effect(() => {\n      const observer = observerSignal()\n      const [_optimisticResult, getCombinedResult] = optimisticResultSignal()\n\n      untracked(() => {\n        const unsubscribe = isRestoring()\n          ? () => undefined\n          : ngZone.runOutsideAngular(() =>\n              observer.subscribe(\n                notifyManager.batchCalls((state) => {\n                  resultFromSubscriberSignal.set(getCombinedResult(state))\n                }),\n              ),\n            )\n\n        destroyRef.onDestroy(unsubscribe)\n      })\n    })\n\n    const resultSignal = computed(() => {\n      const subscriberResult = resultFromSubscriberSignal()\n      const optimisticResult = optimisticCombinedResultSignal()\n      return subscriberResult ?? optimisticResult\n    })\n\n    return computed(() => {\n      const result = resultSignal()\n      const { combine } = optionsSignal()\n\n      return combine\n        ? result\n        : (result as QueriesResults<T>).map((query) =>\n            signalProxy(signal(query)),\n          )\n    })\n  }) as unknown as Signal<TCombinedResult>\n}\n"],"names":[],"mappings":";;;;AA2NO,SAAS,cAId,WACA,UACyB;AACzB,GAAC,YAAY,yBAAyB,aAAa;AACnD,SAAO,sBAAsB,YAAY,OAAO,QAAQ,GAAG,MAAM;AAC/D,UAAM,aAAa,OAAO,UAAU;AACpC,UAAM,SAAS,OAAO,MAAM;AAC5B,UAAM,cAAc,OAAO,WAAW;AACtC,UAAM,cAAc,kBAAA;AAQpB,UAAM,gBAAgB,SAAS,MAAM;AACnC,aAAO,UAAA;AAAA,IACT,CAAC;AAED,UAAM,mBAAmB,SAAS,MAAM;AACtC,aAAO,cAAA,EAAgB,QAAQ,IAAI,CAAC,SAAS;AAC3C,cAAM,mBAAmB,YAAY;AAAA,UACnC;AAAA,QAAA;AAGF,yBAAiB,qBAAqB,YAAA,IAClC,gBACA;AAEJ,eAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AAED,UAAM,kBAAkB,MAAM;AAC5B,UAAI,WAAoD;AAExD,aAAO,SAAS,MAAM;AACpB,eAAQ,wBAAa,IAAI;AAAA,UACvB;AAAA,UACA,iBAAA;AAAA,UACA,cAAA;AAAA,QAAc;AAAA,MAElB,CAAC;AAAA,IACH,GAAA;AAEA,UAAM,yBAAyB;AAAA,MAAS,MACtC,iBAAiB;AAAA,QACf,iBAAA;AAAA,QACC,gBAA4D;AAAA,MAAA;AAAA,IAC/D;AAKF,WAAO,MAAM;AACX,qBAAA,EAAiB;AAAA,QACf,iBAAA;AAAA,QACA,cAAA;AAAA,MAAc;AAAA,IAElB,CAAC;AAED,UAAM,iCAAiC,SAAS,MAAM;AACpD,YAAM,CAAC,mBAAmB,mBAAmB,WAAW,IACtD,uBAAA;AACF,aAAO,kBAAkB,aAAa;AAAA,IACxC,CAAC;AAED,UAAM,6BAA6B,OAA+B,IAAI;AAEtE,WAAO,MAAM;AACX,YAAM,WAAW,eAAA;AACjB,YAAM,CAAC,mBAAmB,iBAAiB,IAAI,uBAAA;AAE/C,gBAAU,MAAM;AACd,cAAM,cAAc,YAAA,IAChB,MAAM,SACN,OAAO;AAAA,UAAkB,MACvB,SAAS;AAAA,YACP,cAAc,WAAW,CAAC,UAAU;AAClC,yCAA2B,IAAI,kBAAkB,KAAK,CAAC;AAAA,YACzD,CAAC;AAAA,UAAA;AAAA,QACH;AAGN,mBAAW,UAAU,WAAW;AAAA,MAClC,CAAC;AAAA,IACH,CAAC;AAED,UAAM,eAAe,SAAS,MAAM;AAClC,YAAM,mBAAmB,2BAAA;AACzB,YAAM,mBAAmB,+BAAA;AACzB,aAAO,oBAAoB;AAAA,IAC7B,CAAC;AAED,WAAO,SAAS,MAAM;AACpB,YAAM,SAAS,aAAA;AACf,YAAM,EAAE,QAAA,IAAY,cAAA;AAEpB,aAAO,UACH,SACC,OAA6B;AAAA,QAAI,CAAC,UACjC,YAAY,OAAO,KAAK,CAAC;AAAA,MAAA;AAAA,IAEjC,CAAC;AAAA,EACH,CAAC;AACH;"}