@tanstack/angular-query-experimental 5.62.3 → 5.62.5

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,55 @@ 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
+ ngZone.run(() => resultFromSubscriberSignal.set(null));
110
+ });
111
+ },
112
+ {
113
+ // Set allowSignalWrites to support Angular < v19
114
+ allowSignalWrites: true,
115
+ injector
116
+ }
117
+ );
118
+ effect(() => {
119
+ const observer = observerSignal();
120
+ untracked2(() => {
121
+ const unsubscribe = ngZone.runOutsideAngular(
122
+ () => observer.subscribe(
123
+ notifyManager.batchCalls((state) => {
144
124
  ngZone.run(() => {
145
125
  if (state.isError && !state.isFetching && // !isRestoring() && // todo: enable when client persistence is implemented
146
126
  shouldThrowError(observer.options.throwOnError, [
@@ -149,15 +129,21 @@ function createBaseQuery(optionsFn, Observer) {
149
129
  ])) {
150
130
  throw state.error;
151
131
  }
152
- resultSignal.set(state);
132
+ resultFromSubscriberSignal.set(state);
153
133
  });
154
- }
134
+ })
155
135
  )
156
- )
157
- );
158
- destroyRef.onDestroy(unsubscribe);
159
- return signalProxy(resultSignal);
136
+ );
137
+ destroyRef.onDestroy(unsubscribe);
138
+ });
160
139
  });
140
+ return signalProxy(
141
+ computed2(() => {
142
+ const subscriberResult = resultFromSubscriberSignal();
143
+ const optimisticResult = optimisticResultSignal();
144
+ return subscriberResult ?? optimisticResult;
145
+ })
146
+ );
161
147
  }
162
148
 
163
149
  // src/util/assert-injector/assert-injector.ts
@@ -251,7 +237,8 @@ import {
251
237
  effect as effect2,
252
238
  inject as inject5,
253
239
  runInInjectionContext as runInInjectionContext3,
254
- signal as signal4
240
+ signal as signal4,
241
+ untracked as untracked3
255
242
  } from "@angular/core";
256
243
  import {
257
244
  MutationObserver,
@@ -264,77 +251,84 @@ function injectMutation(optionsFn, injector) {
264
251
  const destroyRef = inject5(DestroyRef4);
265
252
  const ngZone = inject5(NgZone4);
266
253
  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
- );
254
+ const optionsSignal = computed3(
255
+ () => runInInjectionContext3(currentInjector, () => optionsFn())
256
+ );
257
+ const observerSignal = (() => {
258
+ let instance = null;
259
+ return computed3(() => {
260
+ return instance ||= new MutationObserver(queryClient, optionsSignal());
261
+ });
262
+ })();
263
+ const mutateFnSignal = computed3(() => {
264
+ const observer = observerSignal();
265
+ return (variables, mutateOptions) => {
266
+ observer.mutate(variables, mutateOptions).catch(noop);
267
+ };
268
+ });
269
+ const resultFromInitialOptionsSignal = computed3(() => {
270
+ const observer = observerSignal();
271
+ return observer.getCurrentResult();
272
+ });
273
+ const resultFromSubscriberSignal = signal4(null);
274
+ effect2(
275
+ () => {
276
+ const observer = observerSignal();
277
+ const options = optionsSignal();
278
+ untracked3(() => {
279
+ observer.setOptions(options);
277
280
  });
278
- const result = signal4(observer.getCurrentResult());
279
- const unsubscribe = ngZone.runOutsideAngular(
280
- () => observer.subscribe(
281
- notifyManager4.batchCalls(
282
- (state) => {
281
+ },
282
+ {
283
+ injector
284
+ }
285
+ );
286
+ effect2(
287
+ () => {
288
+ const observer = observerSignal();
289
+ untracked3(() => {
290
+ const unsubscribe = ngZone.runOutsideAngular(
291
+ () => observer.subscribe(
292
+ notifyManager4.batchCalls((state) => {
283
293
  ngZone.run(() => {
284
294
  if (state.isError && shouldThrowError(observer.options.throwOnError, [
285
295
  state.error
286
296
  ])) {
287
297
  throw state.error;
288
298
  }
289
- result.set(state);
299
+ resultFromSubscriberSignal.set(state);
290
300
  });
291
- }
301
+ })
292
302
  )
293
- )
294
- );
295
- destroyRef.onDestroy(unsubscribe);
296
- const resultSignal = computed3(() => ({
297
- ...result(),
298
- mutate,
299
- mutateAsync: result().mutate
300
- }));
301
- return signalProxy(resultSignal);
302
- })
303
+ );
304
+ destroyRef.onDestroy(unsubscribe);
305
+ });
306
+ },
307
+ {
308
+ injector
309
+ }
303
310
  );
311
+ const resultSignal = computed3(() => {
312
+ const resultFromSubscriber = resultFromSubscriberSignal();
313
+ const resultFromInitialOptions = resultFromInitialOptionsSignal();
314
+ const result = resultFromSubscriber ?? resultFromInitialOptions;
315
+ return {
316
+ ...result,
317
+ mutate: mutateFnSignal(),
318
+ mutateAsync: result.mutate
319
+ };
320
+ });
321
+ return signalProxy(resultSignal);
304
322
  });
305
323
  }
306
324
 
307
325
  // 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";
326
+ import { DestroyRef as DestroyRef5, NgZone as NgZone5, computed as computed4, inject as inject6, signal as signal5 } from "@angular/core";
316
327
  import {
317
328
  QueryClient as QueryClient5,
318
329
  notifyManager as notifyManager5,
319
330
  replaceEqualDeep
320
331
  } 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
332
  function getResult(mutationCache, options) {
339
333
  return mutationCache.findAll(options.filters).map(
340
334
  (mutation) => options.select ? options.select(mutation) : mutation.state
@@ -342,41 +336,42 @@ function getResult(mutationCache, options) {
342
336
  }
343
337
  function injectMutationState(mutationStateOptionsFn = () => ({}), options) {
344
338
  return assertInjector(injectMutationState, options?.injector, () => {
345
- const destroyRef = inject7(DestroyRef5);
346
- const ngZone = inject7(NgZone5);
347
- const queryClient = inject7(QueryClient5);
339
+ const destroyRef = inject6(DestroyRef5);
340
+ const ngZone = inject6(NgZone5);
341
+ const queryClient = inject6(QueryClient5);
348
342
  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;
343
+ const resultFromOptionsSignal = computed4(() => {
344
+ return [
345
+ getResult(mutationCache, mutationStateOptionsFn()),
346
+ performance.now()
347
+ ];
348
+ });
349
+ const resultFromSubscriberSignal = signal5(
350
+ null
351
+ );
352
+ const effectiveResultSignal = computed4(() => {
353
+ const optionsResult = resultFromOptionsSignal();
354
+ const subscriberResult = resultFromSubscriberSignal();
355
+ return subscriberResult && subscriberResult[1] > optionsResult[1] ? subscriberResult[0] : optionsResult[0];
379
356
  });
357
+ const unsubscribe = ngZone.runOutsideAngular(
358
+ () => mutationCache.subscribe(
359
+ notifyManager5.batchCalls(() => {
360
+ const [lastResult] = effectiveResultSignal();
361
+ const nextResult = replaceEqualDeep(
362
+ lastResult,
363
+ getResult(mutationCache, mutationStateOptionsFn())
364
+ );
365
+ if (lastResult !== nextResult) {
366
+ ngZone.run(() => {
367
+ resultFromSubscriberSignal.set([nextResult, performance.now()]);
368
+ });
369
+ }
370
+ })
371
+ )
372
+ );
373
+ destroyRef.onDestroy(unsubscribe);
374
+ return effectiveResultSignal;
380
375
  });
381
376
  }
382
377
 
@@ -390,8 +385,8 @@ import {
390
385
  DestroyRef as DestroyRef6,
391
386
  NgZone as NgZone6,
392
387
  computed as computed5,
393
- effect as effect4,
394
- inject as inject8,
388
+ effect as effect3,
389
+ inject as inject7,
395
390
  signal as signal6
396
391
  } from "@angular/core";
397
392
  function injectQueries({
@@ -399,9 +394,9 @@ function injectQueries({
399
394
  ...options
400
395
  }, injector) {
401
396
  return assertInjector(injectQueries, injector, () => {
402
- const destroyRef = inject8(DestroyRef6);
403
- const ngZone = inject8(NgZone6);
404
- const queryClient = inject8(QueryClient6);
397
+ const destroyRef = inject7(DestroyRef6);
398
+ const ngZone = inject7(NgZone6);
399
+ const queryClient = inject7(QueryClient6);
405
400
  const defaultedQueries = computed5(() => {
406
401
  return queries().map((opts) => {
407
402
  const defaultedOptions = queryClient.defaultQueryOptions(opts);
@@ -414,7 +409,7 @@ function injectQueries({
414
409
  defaultedQueries(),
415
410
  options
416
411
  );
417
- effect4(() => {
412
+ effect3(() => {
418
413
  observer.setQueries(
419
414
  defaultedQueries(),
420
415
  options,
@@ -445,21 +440,21 @@ function injectQuery(optionsFn, injector) {
445
440
  }
446
441
 
447
442
  // src/inject-query-client.ts
448
- import { Injector as Injector5, inject as inject9 } from "@angular/core";
443
+ import { Injector as Injector4, inject as inject8 } from "@angular/core";
449
444
  import { QueryClient as QueryClient7 } from "@tanstack/query-core";
450
445
  function injectQueryClient(injectOptions = {}) {
451
- return (injectOptions.injector ?? inject9(Injector5)).get(QueryClient7);
446
+ return (injectOptions.injector ?? inject8(Injector4)).get(QueryClient7);
452
447
  }
453
448
 
454
449
  // src/providers.ts
455
450
  import {
456
451
  DestroyRef as DestroyRef7,
457
452
  ENVIRONMENT_INITIALIZER,
458
- Injector as Injector6,
453
+ Injector as Injector5,
459
454
  PLATFORM_ID,
460
455
  computed as computed6,
461
- effect as effect5,
462
- inject as inject10,
456
+ effect as effect4,
457
+ inject as inject9,
463
458
  makeEnvironmentProviders,
464
459
  runInInjectionContext as runInInjectionContext4
465
460
  } from "@angular/core";
@@ -477,11 +472,12 @@ function provideTanStackQuery(queryClient, ...features) {
477
472
  return makeEnvironmentProviders([
478
473
  provideQueryClient(queryClient),
479
474
  {
475
+ // Do not use provideEnvironmentInitializer to support Angular < v19
480
476
  provide: ENVIRONMENT_INITIALIZER,
481
477
  multi: true,
482
478
  useValue: () => {
483
479
  queryClient.mount();
484
- inject10(DestroyRef7).onDestroy(() => queryClient.unmount());
480
+ inject9(DestroyRef7).onDestroy(() => queryClient.unmount());
485
481
  }
486
482
  },
487
483
  features.map((feature) => feature.\u0275providers)
@@ -503,9 +499,9 @@ function withDevtools(optionsFn) {
503
499
  provide: ENVIRONMENT_INITIALIZER,
504
500
  multi: true,
505
501
  useFactory: () => {
506
- if (!isPlatformBrowser(inject10(PLATFORM_ID)))
502
+ if (!isPlatformBrowser(inject9(PLATFORM_ID)))
507
503
  return noop;
508
- const injector = inject10(Injector6);
504
+ const injector = inject9(Injector5);
509
505
  const options = computed6(
510
506
  () => runInInjectionContext4(injector, () => optionsFn?.() ?? {})
511
507
  );
@@ -515,7 +511,7 @@ function withDevtools(optionsFn) {
515
511
  const { loadDevtools } = options();
516
512
  return typeof loadDevtools === "boolean" ? loadDevtools : isDevMode();
517
513
  });
518
- const destroyRef = inject10(DestroyRef7);
514
+ const destroyRef = inject9(DestroyRef7);
519
515
  const getResolvedQueryClient = () => {
520
516
  const injectedClient = injector.get(QueryClient8, null);
521
517
  const client = options().client ?? injectedClient;
@@ -529,7 +525,7 @@ function withDevtools(optionsFn) {
529
525
  el?.remove();
530
526
  devtools = null;
531
527
  };
532
- return () => effect5(() => {
528
+ return () => effect4(() => {
533
529
  const shouldLoadTools = shouldLoadToolsSignal();
534
530
  const {
535
531
  client,