@tanstack/angular-query-experimental 5.62.3 → 5.62.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.mjs CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  inject,
30
30
  runInInjectionContext,
31
31
  signal,
32
- untracked as untracked3
32
+ untracked as untracked2
33
33
  } from "@angular/core";
34
34
  import { QueryClient, notifyManager } from "@tanstack/query-core";
35
35
 
@@ -72,75 +72,53 @@ function shouldThrowError(throwError, params) {
72
72
  function noop() {
73
73
  }
74
74
 
75
- // src/util/lazy-init/lazy-init.ts
76
- import { untracked as untracked2 } from "@angular/core";
77
- function lazyInit(initializer) {
78
- let object = null;
79
- const initializeObject = () => {
80
- if (!object) {
81
- object = untracked2(() => initializer());
82
- }
83
- };
84
- queueMicrotask(() => initializeObject());
85
- return new Proxy({}, {
86
- get(_, prop, receiver) {
87
- initializeObject();
88
- return Reflect.get(object, prop, receiver);
89
- },
90
- has(_, prop) {
91
- initializeObject();
92
- return Reflect.has(object, prop);
93
- },
94
- ownKeys() {
95
- initializeObject();
96
- return Reflect.ownKeys(object);
97
- },
98
- getOwnPropertyDescriptor() {
99
- return {
100
- enumerable: true,
101
- configurable: true
102
- };
103
- }
104
- });
105
- }
106
-
107
75
  // src/create-base-query.ts
108
76
  function createBaseQuery(optionsFn, Observer) {
109
77
  const injector = inject(Injector);
110
- return lazyInit(() => {
111
- const ngZone = injector.get(NgZone);
112
- const destroyRef = injector.get(DestroyRef);
113
- const queryClient = injector.get(QueryClient);
114
- const defaultedOptionsSignal = computed2(() => {
115
- const options = runInInjectionContext(injector, () => optionsFn());
116
- const defaultedOptions = queryClient.defaultQueryOptions(options);
117
- defaultedOptions._optimisticResults = "optimistic";
118
- return defaultedOptions;
78
+ const ngZone = injector.get(NgZone);
79
+ const destroyRef = injector.get(DestroyRef);
80
+ const queryClient = injector.get(QueryClient);
81
+ const defaultedOptionsSignal = computed2(() => {
82
+ const options = runInInjectionContext(injector, () => optionsFn());
83
+ const defaultedOptions = queryClient.defaultQueryOptions(options);
84
+ defaultedOptions._optimisticResults = "optimistic";
85
+ return defaultedOptions;
86
+ });
87
+ const observerSignal = (() => {
88
+ let instance = null;
89
+ return computed2(() => {
90
+ return instance ||= new Observer(queryClient, defaultedOptionsSignal());
119
91
  });
120
- const observer = new Observer(queryClient, defaultedOptionsSignal());
121
- const resultSignal = signal(
122
- observer.getOptimisticResult(defaultedOptionsSignal())
123
- );
124
- effect(
125
- () => {
126
- const defaultedOptions = defaultedOptionsSignal();
92
+ })();
93
+ const optimisticResultSignal = computed2(
94
+ () => observerSignal().getOptimisticResult(defaultedOptionsSignal())
95
+ );
96
+ const resultFromSubscriberSignal = signal(null);
97
+ effect(
98
+ (onCleanup) => {
99
+ const observer = observerSignal();
100
+ const defaultedOptions = defaultedOptionsSignal();
101
+ untracked2(() => {
127
102
  observer.setOptions(defaultedOptions, {
128
103
  // Do not notify on updates because of changes in the options because
129
104
  // these changes should already be reflected in the optimistic result.
130
105
  listeners: false
131
106
  });
132
- untracked3(() => {
133
- resultSignal.set(observer.getOptimisticResult(defaultedOptions));
134
- });
135
- },
136
- {
137
- injector
138
- }
139
- );
140
- const unsubscribe = ngZone.runOutsideAngular(
141
- () => observer.subscribe(
142
- notifyManager.batchCalls(
143
- (state) => {
107
+ });
108
+ onCleanup(() => {
109
+ resultFromSubscriberSignal.set(null);
110
+ });
111
+ },
112
+ {
113
+ injector
114
+ }
115
+ );
116
+ effect(() => {
117
+ const observer = observerSignal();
118
+ untracked2(() => {
119
+ const unsubscribe = ngZone.runOutsideAngular(
120
+ () => observer.subscribe(
121
+ notifyManager.batchCalls((state) => {
144
122
  ngZone.run(() => {
145
123
  if (state.isError && !state.isFetching && // !isRestoring() && // todo: enable when client persistence is implemented
146
124
  shouldThrowError(observer.options.throwOnError, [
@@ -149,15 +127,21 @@ function createBaseQuery(optionsFn, Observer) {
149
127
  ])) {
150
128
  throw state.error;
151
129
  }
152
- resultSignal.set(state);
130
+ resultFromSubscriberSignal.set(state);
153
131
  });
154
- }
132
+ })
155
133
  )
156
- )
157
- );
158
- destroyRef.onDestroy(unsubscribe);
159
- return signalProxy(resultSignal);
134
+ );
135
+ destroyRef.onDestroy(unsubscribe);
136
+ });
160
137
  });
138
+ return signalProxy(
139
+ computed2(() => {
140
+ const subscriberResult = resultFromSubscriberSignal();
141
+ const optimisticResult = optimisticResultSignal();
142
+ return subscriberResult ?? optimisticResult;
143
+ })
144
+ );
161
145
  }
162
146
 
163
147
  // src/util/assert-injector/assert-injector.ts
@@ -251,7 +235,8 @@ import {
251
235
  effect as effect2,
252
236
  inject as inject5,
253
237
  runInInjectionContext as runInInjectionContext3,
254
- signal as signal4
238
+ signal as signal4,
239
+ untracked as untracked3
255
240
  } from "@angular/core";
256
241
  import {
257
242
  MutationObserver,
@@ -264,77 +249,84 @@ function injectMutation(optionsFn, injector) {
264
249
  const destroyRef = inject5(DestroyRef4);
265
250
  const ngZone = inject5(NgZone4);
266
251
  const queryClient = inject5(QueryClient4);
267
- return lazyInit(
268
- () => runInInjectionContext3(currentInjector, () => {
269
- const observer = new MutationObserver(queryClient, optionsFn());
270
- const mutate = (variables, mutateOptions) => {
271
- observer.mutate(variables, mutateOptions).catch(noop);
272
- };
273
- effect2(() => {
274
- observer.setOptions(
275
- runInInjectionContext3(currentInjector, () => optionsFn())
276
- );
252
+ const optionsSignal = computed3(
253
+ () => runInInjectionContext3(currentInjector, () => optionsFn())
254
+ );
255
+ const observerSignal = (() => {
256
+ let instance = null;
257
+ return computed3(() => {
258
+ return instance ||= new MutationObserver(queryClient, optionsSignal());
259
+ });
260
+ })();
261
+ const mutateFnSignal = computed3(() => {
262
+ const observer = observerSignal();
263
+ return (variables, mutateOptions) => {
264
+ observer.mutate(variables, mutateOptions).catch(noop);
265
+ };
266
+ });
267
+ const resultFromInitialOptionsSignal = computed3(() => {
268
+ const observer = observerSignal();
269
+ return observer.getCurrentResult();
270
+ });
271
+ const resultFromSubscriberSignal = signal4(null);
272
+ effect2(
273
+ () => {
274
+ const observer = observerSignal();
275
+ const options = optionsSignal();
276
+ untracked3(() => {
277
+ observer.setOptions(options);
277
278
  });
278
- const result = signal4(observer.getCurrentResult());
279
- const unsubscribe = ngZone.runOutsideAngular(
280
- () => observer.subscribe(
281
- notifyManager4.batchCalls(
282
- (state) => {
279
+ },
280
+ {
281
+ injector
282
+ }
283
+ );
284
+ effect2(
285
+ () => {
286
+ const observer = observerSignal();
287
+ untracked3(() => {
288
+ const unsubscribe = ngZone.runOutsideAngular(
289
+ () => observer.subscribe(
290
+ notifyManager4.batchCalls((state) => {
283
291
  ngZone.run(() => {
284
292
  if (state.isError && shouldThrowError(observer.options.throwOnError, [
285
293
  state.error
286
294
  ])) {
287
295
  throw state.error;
288
296
  }
289
- result.set(state);
297
+ resultFromSubscriberSignal.set(state);
290
298
  });
291
- }
299
+ })
292
300
  )
293
- )
294
- );
295
- destroyRef.onDestroy(unsubscribe);
296
- const resultSignal = computed3(() => ({
297
- ...result(),
298
- mutate,
299
- mutateAsync: result().mutate
300
- }));
301
- return signalProxy(resultSignal);
302
- })
301
+ );
302
+ destroyRef.onDestroy(unsubscribe);
303
+ });
304
+ },
305
+ {
306
+ injector
307
+ }
303
308
  );
309
+ const resultSignal = computed3(() => {
310
+ const resultFromSubscriber = resultFromSubscriberSignal();
311
+ const resultFromInitialOptions = resultFromInitialOptionsSignal();
312
+ const result = resultFromSubscriber ?? resultFromInitialOptions;
313
+ return {
314
+ ...result,
315
+ mutate: mutateFnSignal(),
316
+ mutateAsync: result.mutate
317
+ };
318
+ });
319
+ return signalProxy(resultSignal);
304
320
  });
305
321
  }
306
322
 
307
323
  // src/inject-mutation-state.ts
308
- import {
309
- DestroyRef as DestroyRef5,
310
- NgZone as NgZone5,
311
- effect as effect3,
312
- inject as inject7,
313
- signal as signal5,
314
- untracked as untracked5
315
- } from "@angular/core";
324
+ import { DestroyRef as DestroyRef5, NgZone as NgZone5, computed as computed4, inject as inject6, signal as signal5 } from "@angular/core";
316
325
  import {
317
326
  QueryClient as QueryClient5,
318
327
  notifyManager as notifyManager5,
319
328
  replaceEqualDeep
320
329
  } from "@tanstack/query-core";
321
-
322
- // src/util/lazy-signal-initializer/lazy-signal-initializer.ts
323
- import { Injector as Injector4, computed as computed4, inject as inject6, untracked as untracked4 } from "@angular/core";
324
- function lazySignalInitializer(initializerFn) {
325
- const injector = inject6(Injector4);
326
- let source = null;
327
- const unwrapSignal = () => {
328
- if (!source) {
329
- source = untracked4(() => initializerFn(injector));
330
- }
331
- return source();
332
- };
333
- queueMicrotask(() => unwrapSignal());
334
- return computed4(unwrapSignal);
335
- }
336
-
337
- // src/inject-mutation-state.ts
338
330
  function getResult(mutationCache, options) {
339
331
  return mutationCache.findAll(options.filters).map(
340
332
  (mutation) => options.select ? options.select(mutation) : mutation.state
@@ -342,41 +334,42 @@ function getResult(mutationCache, options) {
342
334
  }
343
335
  function injectMutationState(mutationStateOptionsFn = () => ({}), options) {
344
336
  return assertInjector(injectMutationState, options?.injector, () => {
345
- const destroyRef = inject7(DestroyRef5);
346
- const ngZone = inject7(NgZone5);
347
- const queryClient = inject7(QueryClient5);
337
+ const destroyRef = inject6(DestroyRef5);
338
+ const ngZone = inject6(NgZone5);
339
+ const queryClient = inject6(QueryClient5);
348
340
  const mutationCache = queryClient.getMutationCache();
349
- return lazySignalInitializer((injector) => {
350
- const result = signal5(
351
- getResult(mutationCache, mutationStateOptionsFn())
352
- );
353
- effect3(
354
- () => {
355
- const mutationStateOptions = mutationStateOptionsFn();
356
- untracked5(() => {
357
- result.set(getResult(mutationCache, mutationStateOptions));
358
- });
359
- },
360
- { injector }
361
- );
362
- const unsubscribe = ngZone.runOutsideAngular(
363
- () => mutationCache.subscribe(
364
- notifyManager5.batchCalls(() => {
365
- const nextResult = replaceEqualDeep(
366
- result(),
367
- getResult(mutationCache, mutationStateOptionsFn())
368
- );
369
- if (result() !== nextResult) {
370
- ngZone.run(() => {
371
- result.set(nextResult);
372
- });
373
- }
374
- })
375
- )
376
- );
377
- destroyRef.onDestroy(unsubscribe);
378
- return result;
341
+ const resultFromOptionsSignal = computed4(() => {
342
+ return [
343
+ getResult(mutationCache, mutationStateOptionsFn()),
344
+ performance.now()
345
+ ];
346
+ });
347
+ const resultFromSubscriberSignal = signal5(
348
+ null
349
+ );
350
+ const effectiveResultSignal = computed4(() => {
351
+ const optionsResult = resultFromOptionsSignal();
352
+ const subscriberResult = resultFromSubscriberSignal();
353
+ return subscriberResult && subscriberResult[1] > optionsResult[1] ? subscriberResult[0] : optionsResult[0];
379
354
  });
355
+ const unsubscribe = ngZone.runOutsideAngular(
356
+ () => mutationCache.subscribe(
357
+ notifyManager5.batchCalls(() => {
358
+ const [lastResult] = effectiveResultSignal();
359
+ const nextResult = replaceEqualDeep(
360
+ lastResult,
361
+ getResult(mutationCache, mutationStateOptionsFn())
362
+ );
363
+ if (lastResult !== nextResult) {
364
+ ngZone.run(() => {
365
+ resultFromSubscriberSignal.set([nextResult, performance.now()]);
366
+ });
367
+ }
368
+ })
369
+ )
370
+ );
371
+ destroyRef.onDestroy(unsubscribe);
372
+ return effectiveResultSignal;
380
373
  });
381
374
  }
382
375
 
@@ -390,8 +383,8 @@ import {
390
383
  DestroyRef as DestroyRef6,
391
384
  NgZone as NgZone6,
392
385
  computed as computed5,
393
- effect as effect4,
394
- inject as inject8,
386
+ effect as effect3,
387
+ inject as inject7,
395
388
  signal as signal6
396
389
  } from "@angular/core";
397
390
  function injectQueries({
@@ -399,9 +392,9 @@ function injectQueries({
399
392
  ...options
400
393
  }, injector) {
401
394
  return assertInjector(injectQueries, injector, () => {
402
- const destroyRef = inject8(DestroyRef6);
403
- const ngZone = inject8(NgZone6);
404
- const queryClient = inject8(QueryClient6);
395
+ const destroyRef = inject7(DestroyRef6);
396
+ const ngZone = inject7(NgZone6);
397
+ const queryClient = inject7(QueryClient6);
405
398
  const defaultedQueries = computed5(() => {
406
399
  return queries().map((opts) => {
407
400
  const defaultedOptions = queryClient.defaultQueryOptions(opts);
@@ -414,7 +407,7 @@ function injectQueries({
414
407
  defaultedQueries(),
415
408
  options
416
409
  );
417
- effect4(() => {
410
+ effect3(() => {
418
411
  observer.setQueries(
419
412
  defaultedQueries(),
420
413
  options,
@@ -445,21 +438,21 @@ function injectQuery(optionsFn, injector) {
445
438
  }
446
439
 
447
440
  // src/inject-query-client.ts
448
- import { Injector as Injector5, inject as inject9 } from "@angular/core";
441
+ import { Injector as Injector4, inject as inject8 } from "@angular/core";
449
442
  import { QueryClient as QueryClient7 } from "@tanstack/query-core";
450
443
  function injectQueryClient(injectOptions = {}) {
451
- return (injectOptions.injector ?? inject9(Injector5)).get(QueryClient7);
444
+ return (injectOptions.injector ?? inject8(Injector4)).get(QueryClient7);
452
445
  }
453
446
 
454
447
  // src/providers.ts
455
448
  import {
456
449
  DestroyRef as DestroyRef7,
457
450
  ENVIRONMENT_INITIALIZER,
458
- Injector as Injector6,
451
+ Injector as Injector5,
459
452
  PLATFORM_ID,
460
453
  computed as computed6,
461
- effect as effect5,
462
- inject as inject10,
454
+ effect as effect4,
455
+ inject as inject9,
463
456
  makeEnvironmentProviders,
464
457
  runInInjectionContext as runInInjectionContext4
465
458
  } from "@angular/core";
@@ -477,11 +470,12 @@ function provideTanStackQuery(queryClient, ...features) {
477
470
  return makeEnvironmentProviders([
478
471
  provideQueryClient(queryClient),
479
472
  {
473
+ // Do not use provideEnvironmentInitializer to support Angular < v19
480
474
  provide: ENVIRONMENT_INITIALIZER,
481
475
  multi: true,
482
476
  useValue: () => {
483
477
  queryClient.mount();
484
- inject10(DestroyRef7).onDestroy(() => queryClient.unmount());
478
+ inject9(DestroyRef7).onDestroy(() => queryClient.unmount());
485
479
  }
486
480
  },
487
481
  features.map((feature) => feature.\u0275providers)
@@ -503,9 +497,9 @@ function withDevtools(optionsFn) {
503
497
  provide: ENVIRONMENT_INITIALIZER,
504
498
  multi: true,
505
499
  useFactory: () => {
506
- if (!isPlatformBrowser(inject10(PLATFORM_ID)))
500
+ if (!isPlatformBrowser(inject9(PLATFORM_ID)))
507
501
  return noop;
508
- const injector = inject10(Injector6);
502
+ const injector = inject9(Injector5);
509
503
  const options = computed6(
510
504
  () => runInInjectionContext4(injector, () => optionsFn?.() ?? {})
511
505
  );
@@ -515,7 +509,7 @@ function withDevtools(optionsFn) {
515
509
  const { loadDevtools } = options();
516
510
  return typeof loadDevtools === "boolean" ? loadDevtools : isDevMode();
517
511
  });
518
- const destroyRef = inject10(DestroyRef7);
512
+ const destroyRef = inject9(DestroyRef7);
519
513
  const getResolvedQueryClient = () => {
520
514
  const injectedClient = injector.get(QueryClient8, null);
521
515
  const client = options().client ?? injectedClient;
@@ -529,7 +523,7 @@ function withDevtools(optionsFn) {
529
523
  el?.remove();
530
524
  devtools = null;
531
525
  };
532
- return () => effect5(() => {
526
+ return () => effect4(() => {
533
527
  const shouldLoadTools = shouldLoadToolsSignal();
534
528
  const {
535
529
  client,