@@ -5,19 +5,16 @@ import {
5
5
} from '@tanstack/query-core'
6
6
import {
7
7
DestroyRef ,
8
+ Injector ,
8
9
NgZone ,
9
10
computed ,
10
11
effect ,
11
12
inject ,
13
+ runInInjectionContext ,
12
14
signal ,
15
+ untracked ,
13
16
} from '@angular/core'
14
17
import { assertInjector } from './util/assert-injector/assert-injector'
15
- import {
16
- CreateQueryOptions ,
17
- CreateQueryResult ,
18
- DefinedCreateQueryResult ,
19
- } from './types'
20
- import type { Injector , Signal } from '@angular/core'
21
18
import type {
22
19
DefaultError ,
23
20
OmitKeyof ,
@@ -26,9 +23,14 @@ import type {
26
23
QueryFunction ,
27
24
QueryKey ,
28
25
QueryObserverOptions ,
29
- QueryObserverResult ,
30
26
ThrowOnError ,
31
27
} from '@tanstack/query-core'
28
+ import type {
29
+ CreateQueryOptions ,
30
+ CreateQueryResult ,
31
+ DefinedCreateQueryResult ,
32
+ } from './types'
33
+ import type { Signal } from '@angular/core'
32
34
33
35
// This defines the `CreateQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.
34
36
// `placeholderData` function always gets undefined passed
@@ -222,50 +224,90 @@ export function injectQueries<
222
224
optionsFn : ( ) => InjectQueriesOptions < T , TCombinedResult > ,
223
225
injector ?: Injector ,
224
226
) : Signal < TCombinedResult > {
225
- return 0 as never
226
- // return assertInjector(injectQueries, injector, () => {
227
- // const destroyRef = inject(DestroyRef)
228
- // const ngZone = inject(NgZone)
229
- // const queryClient = inject(QueryClient)
230
- //
231
- // const defaultedQueries = computed(() => {
232
- // return queries().map((opts) => {
233
- // const defaultedOptions = queryClient.defaultQueryOptions(opts)
234
- // // Make sure the results are already in fetching state before subscribing or updating options
235
- // defaultedOptions._optimisticResults = 'optimistic'
236
- //
237
- // return defaultedOptions as QueryObserverOptions
238
- // })
239
- // })
240
- //
241
- // const observer = new QueriesObserver<TCombinedResult>(
242
- // queryClient,
243
- // defaultedQueries(),
244
- // options as QueriesObserverOptions<TCombinedResult>,
245
- // )
246
- //
247
- // // Do not notify on updates because of changes in the options because
248
- // // these changes should already be reflected in the optimistic result.
249
- // effect(() => {
250
- // observer.setQueries(
251
- // defaultedQueries(),
252
- // options as QueriesObserverOptions<TCombinedResult>,
253
- // { listeners: false },
254
- // )
255
- // })
256
- //
257
- // const [, getCombinedResult] = observer.getOptimisticResult(
258
- // defaultedQueries(),
259
- // (options as QueriesObserverOptions<TCombinedResult>).combine,
260
- // )
261
- //
262
- // const result = signal(getCombinedResult() as any)
263
- //
264
- // const unsubscribe = ngZone.runOutsideAngular(() =>
265
- // observer.subscribe(notifyManager.batchCalls(result.set)),
266
- // )
267
- // destroyRef.onDestroy(unsubscribe)
268
- //
269
- // return result
270
- // })
227
+ return assertInjector ( injectQueries , injector , ( ) => {
228
+ const ngInjector = inject ( Injector )
229
+ const destroyRef = inject ( DestroyRef )
230
+ const ngZone = inject ( NgZone )
231
+ const queryClient = inject ( QueryClient )
232
+
233
+ /**
234
+ * Signal that has the default options from query client applied
235
+ * computed() is used so signals can be inserted into the options
236
+ * making it reactive. Wrapping options in a function ensures embedded expressions
237
+ * are preserved and can keep being applied after signal changes
238
+ */
239
+ const optionsSignal = computed ( ( ) => {
240
+ return runInInjectionContext ( injector ?? ngInjector , ( ) => optionsFn ( ) )
241
+ } )
242
+
243
+ const defaultedQueries = computed ( ( ) => {
244
+ return optionsSignal ( ) . queries . map ( ( opts ) => {
245
+ const defaultedOptions = queryClient . defaultQueryOptions ( opts )
246
+ // Make sure the results are already in fetching state before subscribing or updating options
247
+ defaultedOptions . _optimisticResults = 'optimistic'
248
+
249
+ return defaultedOptions as QueryObserverOptions
250
+ } )
251
+ } )
252
+
253
+ const observerSignal = ( ( ) => {
254
+ let instance : QueriesObserver < TCombinedResult > | null = null
255
+
256
+ return computed ( ( ) => {
257
+ return ( instance ||= new QueriesObserver < TCombinedResult > (
258
+ queryClient ,
259
+ defaultedQueries ( ) ,
260
+ optionsSignal ( ) as QueriesObserverOptions < TCombinedResult > ,
261
+ ) )
262
+ } )
263
+ } ) ( )
264
+
265
+ const optimisticResultSignal = computed ( ( ) =>
266
+ observerSignal ( ) . getOptimisticResult (
267
+ defaultedQueries ( ) ,
268
+ ( optionsSignal ( ) as QueriesObserverOptions < TCombinedResult > ) . combine ,
269
+ ) ,
270
+ )
271
+
272
+ // Do not notify on updates because of changes in the options because
273
+ // these changes should already be reflected in the optimistic result.
274
+ effect ( ( ) => {
275
+ observerSignal ( ) . setQueries (
276
+ defaultedQueries ( ) ,
277
+ optionsSignal ( ) as QueriesObserverOptions < TCombinedResult > ,
278
+ { listeners : false } ,
279
+ )
280
+ } )
281
+
282
+ const optimisticCombinedResultSignal = computed ( ( ) => {
283
+ const [ _optimisticResult , getCombinedResult , trackResult ] =
284
+ optimisticResultSignal ( )
285
+ return getCombinedResult ( trackResult ( ) )
286
+ } )
287
+
288
+ const resultFromSubscriberSignal = signal < TCombinedResult | null > ( null )
289
+
290
+ effect ( ( ) => {
291
+ const observer = observerSignal ( )
292
+ const [ _optimisticResult , getCombinedResult ] = optimisticResultSignal ( )
293
+
294
+ untracked ( ( ) => {
295
+ const unsubscribe = ngZone . runOutsideAngular ( ( ) =>
296
+ observer . subscribe (
297
+ notifyManager . batchCalls ( ( state ) => {
298
+ resultFromSubscriberSignal . set ( getCombinedResult ( state ) )
299
+ } ) ,
300
+ ) ,
301
+ )
302
+
303
+ destroyRef . onDestroy ( unsubscribe )
304
+ } )
305
+ } )
306
+
307
+ return computed ( ( ) => {
308
+ const subscriberResult = resultFromSubscriberSignal ( )
309
+ const optimisticResult = optimisticCombinedResultSignal ( )
310
+ return subscriberResult ?? optimisticResult
311
+ } )
312
+ } ) as unknown as Signal < TCombinedResult >
271
313
}
0 commit comments