@tanstack/react-query 5.0.0-alpha.49 → 5.0.0-alpha.50

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.
@@ -1,3043 +0,0 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactQuery = {}, global.React));
5
- })(this, (function (exports, React) { 'use strict';
6
-
7
- function _interopNamespaceDefault(e) {
8
- var n = Object.create(null);
9
- if (e) {
10
- Object.keys(e).forEach(function (k) {
11
- if (k !== 'default') {
12
- var d = Object.getOwnPropertyDescriptor(e, k);
13
- Object.defineProperty(n, k, d.get ? d : {
14
- enumerable: true,
15
- get: function () { return e[k]; }
16
- });
17
- }
18
- });
19
- }
20
- n.default = e;
21
- return Object.freeze(n);
22
- }
23
-
24
- var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
25
-
26
- class Subscribable {
27
- constructor() {
28
- this.listeners = new Set();
29
- this.subscribe = this.subscribe.bind(this);
30
- }
31
- subscribe(listener) {
32
- this.listeners.add(listener);
33
- this.onSubscribe();
34
- return () => {
35
- this.listeners.delete(listener);
36
- this.onUnsubscribe();
37
- };
38
- }
39
- hasListeners() {
40
- return this.listeners.size > 0;
41
- }
42
- onSubscribe() {
43
- // Do nothing
44
- }
45
- onUnsubscribe() {
46
- // Do nothing
47
- }
48
- }
49
-
50
- // TYPES
51
-
52
- // UTILS
53
-
54
- const isServer = typeof window === 'undefined' || 'Deno' in window;
55
- function noop$1() {
56
- return undefined;
57
- }
58
- function functionalUpdate(updater, input) {
59
- return typeof updater === 'function' ? updater(input) : updater;
60
- }
61
- function isValidTimeout(value) {
62
- return typeof value === 'number' && value >= 0 && value !== Infinity;
63
- }
64
- function timeUntilStale(updatedAt, staleTime) {
65
- return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0);
66
- }
67
- function matchQuery(filters, query) {
68
- const {
69
- type = 'all',
70
- exact,
71
- fetchStatus,
72
- predicate,
73
- queryKey,
74
- stale
75
- } = filters;
76
- if (queryKey) {
77
- if (exact) {
78
- if (query.queryHash !== hashQueryKeyByOptions(queryKey, query.options)) {
79
- return false;
80
- }
81
- } else if (!partialMatchKey(query.queryKey, queryKey)) {
82
- return false;
83
- }
84
- }
85
- if (type !== 'all') {
86
- const isActive = query.isActive();
87
- if (type === 'active' && !isActive) {
88
- return false;
89
- }
90
- if (type === 'inactive' && isActive) {
91
- return false;
92
- }
93
- }
94
- if (typeof stale === 'boolean' && query.isStale() !== stale) {
95
- return false;
96
- }
97
- if (typeof fetchStatus !== 'undefined' && fetchStatus !== query.state.fetchStatus) {
98
- return false;
99
- }
100
- if (predicate && !predicate(query)) {
101
- return false;
102
- }
103
- return true;
104
- }
105
- function matchMutation(filters, mutation) {
106
- const {
107
- exact,
108
- status,
109
- predicate,
110
- mutationKey
111
- } = filters;
112
- if (mutationKey) {
113
- if (!mutation.options.mutationKey) {
114
- return false;
115
- }
116
- if (exact) {
117
- if (hashKey(mutation.options.mutationKey) !== hashKey(mutationKey)) {
118
- return false;
119
- }
120
- } else if (!partialMatchKey(mutation.options.mutationKey, mutationKey)) {
121
- return false;
122
- }
123
- }
124
- if (status && mutation.state.status !== status) {
125
- return false;
126
- }
127
- if (predicate && !predicate(mutation)) {
128
- return false;
129
- }
130
- return true;
131
- }
132
- function hashQueryKeyByOptions(queryKey, options) {
133
- const hashFn = options?.queryKeyHashFn || hashKey;
134
- return hashFn(queryKey);
135
- }
136
-
137
- /**
138
- * Default query & mutation keys hash function.
139
- * Hashes the value into a stable hash.
140
- */
141
- function hashKey(queryKey) {
142
- return JSON.stringify(queryKey, (_, val) => isPlainObject(val) ? Object.keys(val).sort().reduce((result, key) => {
143
- result[key] = val[key];
144
- return result;
145
- }, {}) : val);
146
- }
147
-
148
- /**
149
- * Checks if key `b` partially matches with key `a`.
150
- */
151
-
152
- function partialMatchKey(a, b) {
153
- if (a === b) {
154
- return true;
155
- }
156
- if (typeof a !== typeof b) {
157
- return false;
158
- }
159
- if (a && b && typeof a === 'object' && typeof b === 'object') {
160
- return !Object.keys(b).some(key => !partialMatchKey(a[key], b[key]));
161
- }
162
- return false;
163
- }
164
-
165
- /**
166
- * This function returns `a` if `b` is deeply equal.
167
- * If not, it will replace any deeply equal children of `b` with those of `a`.
168
- * This can be used for structural sharing between JSON values for example.
169
- */
170
-
171
- function replaceEqualDeep(a, b) {
172
- if (a === b) {
173
- return a;
174
- }
175
- const array = isPlainArray(a) && isPlainArray(b);
176
- if (array || isPlainObject(a) && isPlainObject(b)) {
177
- const aSize = array ? a.length : Object.keys(a).length;
178
- const bItems = array ? b : Object.keys(b);
179
- const bSize = bItems.length;
180
- const copy = array ? [] : {};
181
- let equalItems = 0;
182
- for (let i = 0; i < bSize; i++) {
183
- const key = array ? i : bItems[i];
184
- copy[key] = replaceEqualDeep(a[key], b[key]);
185
- if (copy[key] === a[key]) {
186
- equalItems++;
187
- }
188
- }
189
- return aSize === bSize && equalItems === aSize ? a : copy;
190
- }
191
- return b;
192
- }
193
-
194
- /**
195
- * Shallow compare objects. Only works with objects that always have the same properties.
196
- */
197
- function shallowEqualObjects(a, b) {
198
- if (a && !b || b && !a) {
199
- return false;
200
- }
201
- for (const key in a) {
202
- if (a[key] !== b[key]) {
203
- return false;
204
- }
205
- }
206
- return true;
207
- }
208
- function isPlainArray(value) {
209
- return Array.isArray(value) && value.length === Object.keys(value).length;
210
- }
211
-
212
- // Copied from: https://github.com/jonschlinkert/is-plain-object
213
- function isPlainObject(o) {
214
- if (!hasObjectPrototype(o)) {
215
- return false;
216
- }
217
-
218
- // If has modified constructor
219
- const ctor = o.constructor;
220
- if (typeof ctor === 'undefined') {
221
- return true;
222
- }
223
-
224
- // If has modified prototype
225
- const prot = ctor.prototype;
226
- if (!hasObjectPrototype(prot)) {
227
- return false;
228
- }
229
-
230
- // If constructor does not have an Object-specific method
231
- if (!prot.hasOwnProperty('isPrototypeOf')) {
232
- return false;
233
- }
234
-
235
- // Most likely a plain Object
236
- return true;
237
- }
238
- function hasObjectPrototype(o) {
239
- return Object.prototype.toString.call(o) === '[object Object]';
240
- }
241
- function sleep(timeout) {
242
- return new Promise(resolve => {
243
- setTimeout(resolve, timeout);
244
- });
245
- }
246
-
247
- /**
248
- * Schedules a microtask.
249
- * This can be useful to schedule state updates after rendering.
250
- */
251
- function scheduleMicrotask(callback) {
252
- sleep(0).then(callback);
253
- }
254
- function replaceData(prevData, data, options) {
255
- if (typeof options.structuralSharing === 'function') {
256
- return options.structuralSharing(prevData, data);
257
- } else if (options.structuralSharing !== false) {
258
- // Structurally share data between prev and new data if needed
259
- return replaceEqualDeep(prevData, data);
260
- }
261
- return data;
262
- }
263
- function keepPreviousData(previousData) {
264
- return previousData;
265
- }
266
- function addToEnd(items, item, max = 0) {
267
- const newItems = [...items, item];
268
- return max && newItems.length > max ? newItems.slice(1) : newItems;
269
- }
270
- function addToStart(items, item, max = 0) {
271
- const newItems = [item, ...items];
272
- return max && newItems.length > max ? newItems.slice(0, -1) : newItems;
273
- }
274
-
275
- class FocusManager extends Subscribable {
276
- #focused;
277
- #cleanup;
278
- #setup;
279
- constructor() {
280
- super();
281
- this.#setup = onFocus => {
282
- // addEventListener does not exist in React Native, but window does
283
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
284
- if (!isServer && window.addEventListener) {
285
- const listener = () => onFocus();
286
- // Listen to visibilitychange
287
- window.addEventListener('visibilitychange', listener, false);
288
- return () => {
289
- // Be sure to unsubscribe if a new handler is set
290
- window.removeEventListener('visibilitychange', listener);
291
- };
292
- }
293
- return;
294
- };
295
- }
296
- onSubscribe() {
297
- if (!this.#cleanup) {
298
- this.setEventListener(this.#setup);
299
- }
300
- }
301
- onUnsubscribe() {
302
- if (!this.hasListeners()) {
303
- this.#cleanup?.();
304
- this.#cleanup = undefined;
305
- }
306
- }
307
- setEventListener(setup) {
308
- this.#setup = setup;
309
- this.#cleanup?.();
310
- this.#cleanup = setup(focused => {
311
- if (typeof focused === 'boolean') {
312
- this.setFocused(focused);
313
- } else {
314
- this.onFocus();
315
- }
316
- });
317
- }
318
- setFocused(focused) {
319
- this.#focused = focused;
320
- if (focused) {
321
- this.onFocus();
322
- }
323
- }
324
- onFocus() {
325
- this.listeners.forEach(listener => {
326
- listener();
327
- });
328
- }
329
- isFocused() {
330
- if (typeof this.#focused === 'boolean') {
331
- return this.#focused;
332
- }
333
-
334
- // document global can be unavailable in react native
335
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
336
- return globalThis.document?.visibilityState !== 'hidden';
337
- }
338
- }
339
- const focusManager = new FocusManager();
340
-
341
- class OnlineManager extends Subscribable {
342
- #online;
343
- #cleanup;
344
- #setup;
345
- constructor() {
346
- super();
347
- this.#setup = onOnline => {
348
- // addEventListener does not exist in React Native, but window does
349
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
350
- if (!isServer && window.addEventListener) {
351
- const listener = () => onOnline();
352
- // Listen to online
353
- window.addEventListener('online', listener, false);
354
- window.addEventListener('offline', listener, false);
355
- return () => {
356
- // Be sure to unsubscribe if a new handler is set
357
- window.removeEventListener('online', listener);
358
- window.removeEventListener('offline', listener);
359
- };
360
- }
361
- return;
362
- };
363
- }
364
- onSubscribe() {
365
- if (!this.#cleanup) {
366
- this.setEventListener(this.#setup);
367
- }
368
- }
369
- onUnsubscribe() {
370
- if (!this.hasListeners()) {
371
- this.#cleanup?.();
372
- this.#cleanup = undefined;
373
- }
374
- }
375
- setEventListener(setup) {
376
- this.#setup = setup;
377
- this.#cleanup?.();
378
- this.#cleanup = setup(online => {
379
- if (typeof online === 'boolean') {
380
- this.setOnline(online);
381
- } else {
382
- this.onOnline();
383
- }
384
- });
385
- }
386
- setOnline(online) {
387
- this.#online = online;
388
- if (online) {
389
- this.onOnline();
390
- }
391
- }
392
- onOnline() {
393
- this.listeners.forEach(listener => {
394
- listener();
395
- });
396
- }
397
- isOnline() {
398
- if (typeof this.#online === 'boolean') {
399
- return this.#online;
400
- }
401
- if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
402
- return true;
403
- }
404
- return navigator.onLine;
405
- }
406
- }
407
- const onlineManager = new OnlineManager();
408
-
409
- // TYPES
410
-
411
- function defaultRetryDelay(failureCount) {
412
- return Math.min(1000 * 2 ** failureCount, 30000);
413
- }
414
- function canFetch(networkMode) {
415
- return (networkMode ?? 'online') === 'online' ? onlineManager.isOnline() : true;
416
- }
417
- class CancelledError {
418
- constructor(options) {
419
- this.revert = options?.revert;
420
- this.silent = options?.silent;
421
- }
422
- }
423
- function isCancelledError(value) {
424
- return value instanceof CancelledError;
425
- }
426
- function createRetryer(config) {
427
- let isRetryCancelled = false;
428
- let failureCount = 0;
429
- let isResolved = false;
430
- let continueFn;
431
- let promiseResolve;
432
- let promiseReject;
433
- const promise = new Promise((outerResolve, outerReject) => {
434
- promiseResolve = outerResolve;
435
- promiseReject = outerReject;
436
- });
437
- const cancel = cancelOptions => {
438
- if (!isResolved) {
439
- reject(new CancelledError(cancelOptions));
440
- config.abort?.();
441
- }
442
- };
443
- const cancelRetry = () => {
444
- isRetryCancelled = true;
445
- };
446
- const continueRetry = () => {
447
- isRetryCancelled = false;
448
- };
449
- const shouldPause = () => !focusManager.isFocused() || config.networkMode !== 'always' && !onlineManager.isOnline();
450
- const resolve = value => {
451
- if (!isResolved) {
452
- isResolved = true;
453
- config.onSuccess?.(value);
454
- continueFn?.();
455
- promiseResolve(value);
456
- }
457
- };
458
- const reject = value => {
459
- if (!isResolved) {
460
- isResolved = true;
461
- config.onError?.(value);
462
- continueFn?.();
463
- promiseReject(value);
464
- }
465
- };
466
- const pause = () => {
467
- return new Promise(continueResolve => {
468
- continueFn = value => {
469
- const canContinue = isResolved || !shouldPause();
470
- if (canContinue) {
471
- continueResolve(value);
472
- }
473
- return canContinue;
474
- };
475
- config.onPause?.();
476
- }).then(() => {
477
- continueFn = undefined;
478
- if (!isResolved) {
479
- config.onContinue?.();
480
- }
481
- });
482
- };
483
-
484
- // Create loop function
485
- const run = () => {
486
- // Do nothing if already resolved
487
- if (isResolved) {
488
- return;
489
- }
490
- let promiseOrValue;
491
-
492
- // Execute query
493
- try {
494
- promiseOrValue = config.fn();
495
- } catch (error) {
496
- promiseOrValue = Promise.reject(error);
497
- }
498
- Promise.resolve(promiseOrValue).then(resolve).catch(error => {
499
- // Stop if the fetch is already resolved
500
- if (isResolved) {
501
- return;
502
- }
503
-
504
- // Do we need to retry the request?
505
- const retry = config.retry ?? 3;
506
- const retryDelay = config.retryDelay ?? defaultRetryDelay;
507
- const delay = typeof retryDelay === 'function' ? retryDelay(failureCount, error) : retryDelay;
508
- const shouldRetry = retry === true || typeof retry === 'number' && failureCount < retry || typeof retry === 'function' && retry(failureCount, error);
509
- if (isRetryCancelled || !shouldRetry) {
510
- // We are done if the query does not need to be retried
511
- reject(error);
512
- return;
513
- }
514
- failureCount++;
515
-
516
- // Notify on fail
517
- config.onFail?.(failureCount, error);
518
-
519
- // Delay
520
- sleep(delay)
521
- // Pause if the document is not visible or when the device is offline
522
- .then(() => {
523
- if (shouldPause()) {
524
- return pause();
525
- }
526
- return;
527
- }).then(() => {
528
- if (isRetryCancelled) {
529
- reject(error);
530
- } else {
531
- run();
532
- }
533
- });
534
- });
535
- };
536
-
537
- // Start loop
538
- if (canFetch(config.networkMode)) {
539
- run();
540
- } else {
541
- pause().then(run);
542
- }
543
- return {
544
- promise,
545
- cancel,
546
- continue: () => {
547
- const didContinue = continueFn?.();
548
- return didContinue ? promise : Promise.resolve();
549
- },
550
- cancelRetry,
551
- continueRetry
552
- };
553
- }
554
-
555
- // TYPES
556
-
557
- function createNotifyManager() {
558
- let queue = [];
559
- let transactions = 0;
560
- let notifyFn = callback => {
561
- callback();
562
- };
563
- let batchNotifyFn = callback => {
564
- callback();
565
- };
566
- const batch = callback => {
567
- let result;
568
- transactions++;
569
- try {
570
- result = callback();
571
- } finally {
572
- transactions--;
573
- if (!transactions) {
574
- flush();
575
- }
576
- }
577
- return result;
578
- };
579
- const schedule = callback => {
580
- if (transactions) {
581
- queue.push(callback);
582
- } else {
583
- scheduleMicrotask(() => {
584
- notifyFn(callback);
585
- });
586
- }
587
- };
588
-
589
- /**
590
- * All calls to the wrapped function will be batched.
591
- */
592
- const batchCalls = callback => {
593
- return (...args) => {
594
- schedule(() => {
595
- callback(...args);
596
- });
597
- };
598
- };
599
- const flush = () => {
600
- const originalQueue = queue;
601
- queue = [];
602
- if (originalQueue.length) {
603
- scheduleMicrotask(() => {
604
- batchNotifyFn(() => {
605
- originalQueue.forEach(callback => {
606
- notifyFn(callback);
607
- });
608
- });
609
- });
610
- }
611
- };
612
-
613
- /**
614
- * Use this method to set a custom notify function.
615
- * This can be used to for example wrap notifications with `React.act` while running tests.
616
- */
617
- const setNotifyFunction = fn => {
618
- notifyFn = fn;
619
- };
620
-
621
- /**
622
- * Use this method to set a custom function to batch notifications together into a single tick.
623
- * By default React Query will use the batch function provided by ReactDOM or React Native.
624
- */
625
- const setBatchNotifyFunction = fn => {
626
- batchNotifyFn = fn;
627
- };
628
- return {
629
- batch,
630
- batchCalls,
631
- schedule,
632
- setNotifyFunction,
633
- setBatchNotifyFunction
634
- };
635
- }
636
-
637
- // SINGLETON
638
- const notifyManager = createNotifyManager();
639
-
640
- class Removable {
641
- #gcTimeout;
642
- destroy() {
643
- this.clearGcTimeout();
644
- }
645
- scheduleGc() {
646
- this.clearGcTimeout();
647
- if (isValidTimeout(this.gcTime)) {
648
- this.#gcTimeout = setTimeout(() => {
649
- this.optionalRemove();
650
- }, this.gcTime);
651
- }
652
- }
653
- updateGcTime(newGcTime) {
654
- // Default to 5 minutes (Infinity for server-side) if no gcTime is set
655
- this.gcTime = Math.max(this.gcTime || 0, newGcTime ?? (isServer ? Infinity : 5 * 60 * 1000));
656
- }
657
- clearGcTimeout() {
658
- if (this.#gcTimeout) {
659
- clearTimeout(this.#gcTimeout);
660
- this.#gcTimeout = undefined;
661
- }
662
- }
663
- }
664
-
665
- // TYPES
666
-
667
- // CLASS
668
-
669
- class Query extends Removable {
670
- #initialState;
671
- #revertState;
672
- #cache;
673
- #promise;
674
- #retryer;
675
- #observers;
676
- #defaultOptions;
677
- #abortSignalConsumed;
678
- constructor(config) {
679
- super();
680
- this.#abortSignalConsumed = false;
681
- this.#defaultOptions = config.defaultOptions;
682
- this.#setOptions(config.options);
683
- this.#observers = [];
684
- this.#cache = config.cache;
685
- this.queryKey = config.queryKey;
686
- this.queryHash = config.queryHash;
687
- this.#initialState = config.state || getDefaultState$1(this.options);
688
- this.state = this.#initialState;
689
- this.scheduleGc();
690
- }
691
- get meta() {
692
- return this.options.meta;
693
- }
694
- #setOptions(options) {
695
- this.options = {
696
- ...this.#defaultOptions,
697
- ...options
698
- };
699
- this.updateGcTime(this.options.gcTime);
700
- }
701
- optionalRemove() {
702
- if (!this.#observers.length && this.state.fetchStatus === 'idle') {
703
- this.#cache.remove(this);
704
- }
705
- }
706
- setData(newData, options) {
707
- const data = replaceData(this.state.data, newData, this.options);
708
-
709
- // Set data and mark it as cached
710
- this.#dispatch({
711
- data,
712
- type: 'success',
713
- dataUpdatedAt: options?.updatedAt,
714
- manual: options?.manual
715
- });
716
- return data;
717
- }
718
- setState(state, setStateOptions) {
719
- this.#dispatch({
720
- type: 'setState',
721
- state,
722
- setStateOptions
723
- });
724
- }
725
- cancel(options) {
726
- const promise = this.#promise;
727
- this.#retryer?.cancel(options);
728
- return promise ? promise.then(noop$1).catch(noop$1) : Promise.resolve();
729
- }
730
- destroy() {
731
- super.destroy();
732
- this.cancel({
733
- silent: true
734
- });
735
- }
736
- reset() {
737
- this.destroy();
738
- this.setState(this.#initialState);
739
- }
740
- isActive() {
741
- return this.#observers.some(observer => observer.options.enabled !== false);
742
- }
743
- isDisabled() {
744
- return this.getObserversCount() > 0 && !this.isActive();
745
- }
746
- isStale() {
747
- return this.state.isInvalidated || !this.state.dataUpdatedAt || this.#observers.some(observer => observer.getCurrentResult().isStale);
748
- }
749
- isStaleByTime(staleTime = 0) {
750
- return this.state.isInvalidated || !this.state.dataUpdatedAt || !timeUntilStale(this.state.dataUpdatedAt, staleTime);
751
- }
752
- onFocus() {
753
- const observer = this.#observers.find(x => x.shouldFetchOnWindowFocus());
754
- observer?.refetch({
755
- cancelRefetch: false
756
- });
757
-
758
- // Continue fetch if currently paused
759
- this.#retryer?.continue();
760
- }
761
- onOnline() {
762
- const observer = this.#observers.find(x => x.shouldFetchOnReconnect());
763
- observer?.refetch({
764
- cancelRefetch: false
765
- });
766
-
767
- // Continue fetch if currently paused
768
- this.#retryer?.continue();
769
- }
770
- addObserver(observer) {
771
- if (this.#observers.indexOf(observer) === -1) {
772
- this.#observers.push(observer);
773
-
774
- // Stop the query from being garbage collected
775
- this.clearGcTimeout();
776
- this.#cache.notify({
777
- type: 'observerAdded',
778
- query: this,
779
- observer
780
- });
781
- }
782
- }
783
- removeObserver(observer) {
784
- if (this.#observers.indexOf(observer) !== -1) {
785
- this.#observers = this.#observers.filter(x => x !== observer);
786
- if (!this.#observers.length) {
787
- // If the transport layer does not support cancellation
788
- // we'll let the query continue so the result can be cached
789
- if (this.#retryer) {
790
- if (this.#abortSignalConsumed) {
791
- this.#retryer.cancel({
792
- revert: true
793
- });
794
- } else {
795
- this.#retryer.cancelRetry();
796
- }
797
- }
798
- this.scheduleGc();
799
- }
800
- this.#cache.notify({
801
- type: 'observerRemoved',
802
- query: this,
803
- observer
804
- });
805
- }
806
- }
807
- getObserversCount() {
808
- return this.#observers.length;
809
- }
810
- invalidate() {
811
- if (!this.state.isInvalidated) {
812
- this.#dispatch({
813
- type: 'invalidate'
814
- });
815
- }
816
- }
817
- fetch(options, fetchOptions) {
818
- if (this.state.fetchStatus !== 'idle') {
819
- if (this.state.dataUpdatedAt && fetchOptions?.cancelRefetch) {
820
- // Silently cancel current fetch if the user wants to cancel refetches
821
- this.cancel({
822
- silent: true
823
- });
824
- } else if (this.#promise) {
825
- // make sure that retries that were potentially cancelled due to unmounts can continue
826
- this.#retryer?.continueRetry();
827
- // Return current promise if we are already fetching
828
- return this.#promise;
829
- }
830
- }
831
-
832
- // Update config if passed, otherwise the config from the last execution is used
833
- if (options) {
834
- this.#setOptions(options);
835
- }
836
-
837
- // Use the options from the first observer with a query function if no function is found.
838
- // This can happen when the query is hydrated or created with setQueryData.
839
- if (!this.options.queryFn) {
840
- const observer = this.#observers.find(x => x.options.queryFn);
841
- if (observer) {
842
- this.#setOptions(observer.options);
843
- }
844
- }
845
- {
846
- if (!Array.isArray(this.options.queryKey)) {
847
- console.error(`As of v4, queryKey needs to be an Array. If you are using a string like 'repoData', please change it to an Array, e.g. ['repoData']`);
848
- }
849
- }
850
- const abortController = new AbortController();
851
-
852
- // Create query function context
853
- const queryFnContext = {
854
- queryKey: this.queryKey,
855
- meta: this.meta
856
- };
857
-
858
- // Adds an enumerable signal property to the object that
859
- // which sets abortSignalConsumed to true when the signal
860
- // is read.
861
- const addSignalProperty = object => {
862
- Object.defineProperty(object, 'signal', {
863
- enumerable: true,
864
- get: () => {
865
- this.#abortSignalConsumed = true;
866
- return abortController.signal;
867
- }
868
- });
869
- };
870
- addSignalProperty(queryFnContext);
871
-
872
- // Create fetch function
873
- const fetchFn = () => {
874
- if (!this.options.queryFn) {
875
- return Promise.reject(new Error('Missing queryFn'));
876
- }
877
- this.#abortSignalConsumed = false;
878
- return this.options.queryFn(queryFnContext);
879
- };
880
-
881
- // Trigger behavior hook
882
- const context = {
883
- fetchOptions,
884
- options: this.options,
885
- queryKey: this.queryKey,
886
- state: this.state,
887
- fetchFn
888
- };
889
- addSignalProperty(context);
890
- this.options.behavior?.onFetch(context);
891
-
892
- // Store state in case the current fetch needs to be reverted
893
- this.#revertState = this.state;
894
-
895
- // Set to fetching state if not already in it
896
- if (this.state.fetchStatus === 'idle' || this.state.fetchMeta !== context.fetchOptions?.meta) {
897
- this.#dispatch({
898
- type: 'fetch',
899
- meta: context.fetchOptions?.meta
900
- });
901
- }
902
- const onError = error => {
903
- // Optimistically update state if needed
904
- if (!(isCancelledError(error) && error.silent)) {
905
- this.#dispatch({
906
- type: 'error',
907
- error: error
908
- });
909
- }
910
- if (!isCancelledError(error)) {
911
- // Notify cache callback
912
- this.#cache.config.onError?.(error, this);
913
- this.#cache.config.onSettled?.(this.state.data, error, this);
914
- }
915
- if (!this.isFetchingOptimistic) {
916
- // Schedule query gc after fetching
917
- this.scheduleGc();
918
- }
919
- this.isFetchingOptimistic = false;
920
- };
921
-
922
- // Try to fetch the data
923
- this.#retryer = createRetryer({
924
- fn: context.fetchFn,
925
- abort: abortController.abort.bind(abortController),
926
- onSuccess: data => {
927
- if (typeof data === 'undefined') {
928
- {
929
- console.error(`Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`);
930
- }
931
- onError(new Error(`${this.queryHash} data is undefined`));
932
- return;
933
- }
934
- this.setData(data);
935
-
936
- // Notify cache callback
937
- this.#cache.config.onSuccess?.(data, this);
938
- this.#cache.config.onSettled?.(data, this.state.error, this);
939
- if (!this.isFetchingOptimistic) {
940
- // Schedule query gc after fetching
941
- this.scheduleGc();
942
- }
943
- this.isFetchingOptimistic = false;
944
- },
945
- onError,
946
- onFail: (failureCount, error) => {
947
- this.#dispatch({
948
- type: 'failed',
949
- failureCount,
950
- error
951
- });
952
- },
953
- onPause: () => {
954
- this.#dispatch({
955
- type: 'pause'
956
- });
957
- },
958
- onContinue: () => {
959
- this.#dispatch({
960
- type: 'continue'
961
- });
962
- },
963
- retry: context.options.retry,
964
- retryDelay: context.options.retryDelay,
965
- networkMode: context.options.networkMode
966
- });
967
- this.#promise = this.#retryer.promise;
968
- return this.#promise;
969
- }
970
- #dispatch(action) {
971
- const reducer = state => {
972
- switch (action.type) {
973
- case 'failed':
974
- return {
975
- ...state,
976
- fetchFailureCount: action.failureCount,
977
- fetchFailureReason: action.error
978
- };
979
- case 'pause':
980
- return {
981
- ...state,
982
- fetchStatus: 'paused'
983
- };
984
- case 'continue':
985
- return {
986
- ...state,
987
- fetchStatus: 'fetching'
988
- };
989
- case 'fetch':
990
- return {
991
- ...state,
992
- fetchFailureCount: 0,
993
- fetchFailureReason: null,
994
- fetchMeta: action.meta ?? null,
995
- fetchStatus: canFetch(this.options.networkMode) ? 'fetching' : 'paused',
996
- ...(!state.dataUpdatedAt && {
997
- error: null,
998
- status: 'pending'
999
- })
1000
- };
1001
- case 'success':
1002
- return {
1003
- ...state,
1004
- data: action.data,
1005
- dataUpdateCount: state.dataUpdateCount + 1,
1006
- dataUpdatedAt: action.dataUpdatedAt ?? Date.now(),
1007
- error: null,
1008
- isInvalidated: false,
1009
- status: 'success',
1010
- ...(!action.manual && {
1011
- fetchStatus: 'idle',
1012
- fetchFailureCount: 0,
1013
- fetchFailureReason: null
1014
- })
1015
- };
1016
- case 'error':
1017
- const error = action.error;
1018
- if (isCancelledError(error) && error.revert && this.#revertState) {
1019
- return {
1020
- ...this.#revertState
1021
- };
1022
- }
1023
- return {
1024
- ...state,
1025
- error: error,
1026
- errorUpdateCount: state.errorUpdateCount + 1,
1027
- errorUpdatedAt: Date.now(),
1028
- fetchFailureCount: state.fetchFailureCount + 1,
1029
- fetchFailureReason: error,
1030
- fetchStatus: 'idle',
1031
- status: 'error'
1032
- };
1033
- case 'invalidate':
1034
- return {
1035
- ...state,
1036
- isInvalidated: true
1037
- };
1038
- case 'setState':
1039
- return {
1040
- ...state,
1041
- ...action.state
1042
- };
1043
- }
1044
- };
1045
- this.state = reducer(this.state);
1046
- notifyManager.batch(() => {
1047
- this.#observers.forEach(observer => {
1048
- observer.onQueryUpdate();
1049
- });
1050
- this.#cache.notify({
1051
- query: this,
1052
- type: 'updated',
1053
- action
1054
- });
1055
- });
1056
- }
1057
- }
1058
- function getDefaultState$1(options) {
1059
- const data = typeof options.initialData === 'function' ? options.initialData() : options.initialData;
1060
- const hasData = typeof data !== 'undefined';
1061
- const initialDataUpdatedAt = hasData ? typeof options.initialDataUpdatedAt === 'function' ? options.initialDataUpdatedAt() : options.initialDataUpdatedAt : 0;
1062
- return {
1063
- data,
1064
- dataUpdateCount: 0,
1065
- dataUpdatedAt: hasData ? initialDataUpdatedAt ?? Date.now() : 0,
1066
- error: null,
1067
- errorUpdateCount: 0,
1068
- errorUpdatedAt: 0,
1069
- fetchFailureCount: 0,
1070
- fetchFailureReason: null,
1071
- fetchMeta: null,
1072
- isInvalidated: false,
1073
- status: hasData ? 'success' : 'pending',
1074
- fetchStatus: 'idle'
1075
- };
1076
- }
1077
-
1078
- // TYPES
1079
-
1080
- // CLASS
1081
-
1082
- class QueryCache extends Subscribable {
1083
- #queries;
1084
- constructor(config = {}) {
1085
- super();
1086
- this.config = config;
1087
- this.#queries = new Map();
1088
- }
1089
- build(client, options, state) {
1090
- const queryKey = options.queryKey;
1091
- const queryHash = options.queryHash ?? hashQueryKeyByOptions(queryKey, options);
1092
- let query = this.get(queryHash);
1093
- if (!query) {
1094
- query = new Query({
1095
- cache: this,
1096
- queryKey,
1097
- queryHash,
1098
- options: client.defaultQueryOptions(options),
1099
- state,
1100
- defaultOptions: client.getQueryDefaults(queryKey)
1101
- });
1102
- this.add(query);
1103
- }
1104
- return query;
1105
- }
1106
- add(query) {
1107
- if (!this.#queries.has(query.queryHash)) {
1108
- this.#queries.set(query.queryHash, query);
1109
- this.notify({
1110
- type: 'added',
1111
- query
1112
- });
1113
- }
1114
- }
1115
- remove(query) {
1116
- const queryInMap = this.#queries.get(query.queryHash);
1117
- if (queryInMap) {
1118
- query.destroy();
1119
- if (queryInMap === query) {
1120
- this.#queries.delete(query.queryHash);
1121
- }
1122
- this.notify({
1123
- type: 'removed',
1124
- query
1125
- });
1126
- }
1127
- }
1128
- clear() {
1129
- notifyManager.batch(() => {
1130
- this.getAll().forEach(query => {
1131
- this.remove(query);
1132
- });
1133
- });
1134
- }
1135
- get(queryHash) {
1136
- return this.#queries.get(queryHash);
1137
- }
1138
- getAll() {
1139
- return [...this.#queries.values()];
1140
- }
1141
- find(filters) {
1142
- const defaultedFilters = {
1143
- exact: true,
1144
- ...filters
1145
- };
1146
- return this.getAll().find(query => matchQuery(defaultedFilters, query));
1147
- }
1148
- findAll(filters = {}) {
1149
- const queries = this.getAll();
1150
- return Object.keys(filters).length > 0 ? queries.filter(query => matchQuery(filters, query)) : queries;
1151
- }
1152
- notify(event) {
1153
- notifyManager.batch(() => {
1154
- this.listeners.forEach(listener => {
1155
- listener(event);
1156
- });
1157
- });
1158
- }
1159
- onFocus() {
1160
- notifyManager.batch(() => {
1161
- this.getAll().forEach(query => {
1162
- query.onFocus();
1163
- });
1164
- });
1165
- }
1166
- onOnline() {
1167
- notifyManager.batch(() => {
1168
- this.getAll().forEach(query => {
1169
- query.onOnline();
1170
- });
1171
- });
1172
- }
1173
- }
1174
-
1175
- // TYPES
1176
-
1177
- // CLASS
1178
-
1179
- class Mutation extends Removable {
1180
- #observers;
1181
- #defaultOptions;
1182
- #mutationCache;
1183
- #retryer;
1184
- constructor(config) {
1185
- super();
1186
- this.mutationId = config.mutationId;
1187
- this.#defaultOptions = config.defaultOptions;
1188
- this.#mutationCache = config.mutationCache;
1189
- this.#observers = [];
1190
- this.state = config.state || getDefaultState();
1191
- this.setOptions(config.options);
1192
- this.scheduleGc();
1193
- }
1194
- setOptions(options) {
1195
- this.options = {
1196
- ...this.#defaultOptions,
1197
- ...options
1198
- };
1199
- this.updateGcTime(this.options.gcTime);
1200
- }
1201
- get meta() {
1202
- return this.options.meta;
1203
- }
1204
- addObserver(observer) {
1205
- if (this.#observers.indexOf(observer) === -1) {
1206
- this.#observers.push(observer);
1207
-
1208
- // Stop the mutation from being garbage collected
1209
- this.clearGcTimeout();
1210
- this.#mutationCache.notify({
1211
- type: 'observerAdded',
1212
- mutation: this,
1213
- observer
1214
- });
1215
- }
1216
- }
1217
- removeObserver(observer) {
1218
- this.#observers = this.#observers.filter(x => x !== observer);
1219
- this.scheduleGc();
1220
- this.#mutationCache.notify({
1221
- type: 'observerRemoved',
1222
- mutation: this,
1223
- observer
1224
- });
1225
- }
1226
- optionalRemove() {
1227
- if (!this.#observers.length) {
1228
- if (this.state.status === 'pending') {
1229
- this.scheduleGc();
1230
- } else {
1231
- this.#mutationCache.remove(this);
1232
- }
1233
- }
1234
- }
1235
- continue() {
1236
- return this.#retryer?.continue() ??
1237
- // continuing a mutation assumes that variables are set, mutation must have been dehydrated before
1238
- this.execute(this.state.variables);
1239
- }
1240
- async execute(variables) {
1241
- const executeMutation = () => {
1242
- this.#retryer = createRetryer({
1243
- fn: () => {
1244
- if (!this.options.mutationFn) {
1245
- return Promise.reject(new Error('No mutationFn found'));
1246
- }
1247
- return this.options.mutationFn(variables);
1248
- },
1249
- onFail: (failureCount, error) => {
1250
- this.#dispatch({
1251
- type: 'failed',
1252
- failureCount,
1253
- error
1254
- });
1255
- },
1256
- onPause: () => {
1257
- this.#dispatch({
1258
- type: 'pause'
1259
- });
1260
- },
1261
- onContinue: () => {
1262
- this.#dispatch({
1263
- type: 'continue'
1264
- });
1265
- },
1266
- retry: this.options.retry ?? 0,
1267
- retryDelay: this.options.retryDelay,
1268
- networkMode: this.options.networkMode
1269
- });
1270
- return this.#retryer.promise;
1271
- };
1272
- const restored = this.state.status === 'pending';
1273
- try {
1274
- if (!restored) {
1275
- this.#dispatch({
1276
- type: 'pending',
1277
- variables
1278
- });
1279
- // Notify cache callback
1280
- await this.#mutationCache.config.onMutate?.(variables, this);
1281
- const context = await this.options.onMutate?.(variables);
1282
- if (context !== this.state.context) {
1283
- this.#dispatch({
1284
- type: 'pending',
1285
- context,
1286
- variables
1287
- });
1288
- }
1289
- }
1290
- const data = await executeMutation();
1291
-
1292
- // Notify cache callback
1293
- await this.#mutationCache.config.onSuccess?.(data, variables, this.state.context, this);
1294
- await this.options.onSuccess?.(data, variables, this.state.context);
1295
-
1296
- // Notify cache callback
1297
- await this.#mutationCache.config.onSettled?.(data, null, this.state.variables, this.state.context, this);
1298
- await this.options.onSettled?.(data, null, variables, this.state.context);
1299
- this.#dispatch({
1300
- type: 'success',
1301
- data
1302
- });
1303
- return data;
1304
- } catch (error) {
1305
- try {
1306
- // Notify cache callback
1307
- await this.#mutationCache.config.onError?.(error, variables, this.state.context, this);
1308
- await this.options.onError?.(error, variables, this.state.context);
1309
-
1310
- // Notify cache callback
1311
- await this.#mutationCache.config.onSettled?.(undefined, error, this.state.variables, this.state.context, this);
1312
- await this.options.onSettled?.(undefined, error, variables, this.state.context);
1313
- throw error;
1314
- } finally {
1315
- this.#dispatch({
1316
- type: 'error',
1317
- error: error
1318
- });
1319
- }
1320
- }
1321
- }
1322
- #dispatch(action) {
1323
- const reducer = state => {
1324
- switch (action.type) {
1325
- case 'failed':
1326
- return {
1327
- ...state,
1328
- failureCount: action.failureCount,
1329
- failureReason: action.error
1330
- };
1331
- case 'pause':
1332
- return {
1333
- ...state,
1334
- isPaused: true
1335
- };
1336
- case 'continue':
1337
- return {
1338
- ...state,
1339
- isPaused: false
1340
- };
1341
- case 'pending':
1342
- return {
1343
- ...state,
1344
- context: action.context,
1345
- data: undefined,
1346
- failureCount: 0,
1347
- failureReason: null,
1348
- error: null,
1349
- isPaused: !canFetch(this.options.networkMode),
1350
- status: 'pending',
1351
- variables: action.variables,
1352
- submittedAt: Date.now()
1353
- };
1354
- case 'success':
1355
- return {
1356
- ...state,
1357
- data: action.data,
1358
- failureCount: 0,
1359
- failureReason: null,
1360
- error: null,
1361
- status: 'success',
1362
- isPaused: false
1363
- };
1364
- case 'error':
1365
- return {
1366
- ...state,
1367
- data: undefined,
1368
- error: action.error,
1369
- failureCount: state.failureCount + 1,
1370
- failureReason: action.error,
1371
- isPaused: false,
1372
- status: 'error'
1373
- };
1374
- }
1375
- };
1376
- this.state = reducer(this.state);
1377
- notifyManager.batch(() => {
1378
- this.#observers.forEach(observer => {
1379
- observer.onMutationUpdate(action);
1380
- });
1381
- this.#mutationCache.notify({
1382
- mutation: this,
1383
- type: 'updated',
1384
- action
1385
- });
1386
- });
1387
- }
1388
- }
1389
- function getDefaultState() {
1390
- return {
1391
- context: undefined,
1392
- data: undefined,
1393
- error: null,
1394
- failureCount: 0,
1395
- failureReason: null,
1396
- isPaused: false,
1397
- status: 'idle',
1398
- variables: undefined,
1399
- submittedAt: 0
1400
- };
1401
- }
1402
-
1403
- // TYPES
1404
-
1405
- // CLASS
1406
-
1407
- class MutationCache extends Subscribable {
1408
- #mutations;
1409
- #mutationId;
1410
- #resuming;
1411
- constructor(config = {}) {
1412
- super();
1413
- this.config = config;
1414
- this.#mutations = [];
1415
- this.#mutationId = 0;
1416
- }
1417
- build(client, options, state) {
1418
- const mutation = new Mutation({
1419
- mutationCache: this,
1420
- mutationId: ++this.#mutationId,
1421
- options: client.defaultMutationOptions(options),
1422
- state
1423
- });
1424
- this.add(mutation);
1425
- return mutation;
1426
- }
1427
- add(mutation) {
1428
- this.#mutations.push(mutation);
1429
- this.notify({
1430
- type: 'added',
1431
- mutation
1432
- });
1433
- }
1434
- remove(mutation) {
1435
- this.#mutations = this.#mutations.filter(x => x !== mutation);
1436
- this.notify({
1437
- type: 'removed',
1438
- mutation
1439
- });
1440
- }
1441
- clear() {
1442
- notifyManager.batch(() => {
1443
- this.#mutations.forEach(mutation => {
1444
- this.remove(mutation);
1445
- });
1446
- });
1447
- }
1448
- getAll() {
1449
- return this.#mutations;
1450
- }
1451
- find(filters) {
1452
- const defaultedFilters = {
1453
- exact: true,
1454
- ...filters
1455
- };
1456
- return this.#mutations.find(mutation => matchMutation(defaultedFilters, mutation));
1457
- }
1458
- findAll(filters = {}) {
1459
- return this.#mutations.filter(mutation => matchMutation(filters, mutation));
1460
- }
1461
- notify(event) {
1462
- notifyManager.batch(() => {
1463
- this.listeners.forEach(listener => {
1464
- listener(event);
1465
- });
1466
- });
1467
- }
1468
- resumePausedMutations() {
1469
- this.#resuming = (this.#resuming ?? Promise.resolve()).then(() => {
1470
- const pausedMutations = this.#mutations.filter(x => x.state.isPaused);
1471
- return notifyManager.batch(() => pausedMutations.reduce((promise, mutation) => promise.then(() => mutation.continue().catch(noop$1)), Promise.resolve()));
1472
- }).then(() => {
1473
- this.#resuming = undefined;
1474
- });
1475
- return this.#resuming;
1476
- }
1477
- }
1478
-
1479
- function infiniteQueryBehavior() {
1480
- return {
1481
- onFetch: context => {
1482
- context.fetchFn = async () => {
1483
- const options = context.options;
1484
- const direction = context.fetchOptions?.meta?.fetchMore?.direction;
1485
- const oldPages = context.state.data?.pages || [];
1486
- const oldPageParams = context.state.data?.pageParams || [];
1487
- const empty = {
1488
- pages: [],
1489
- pageParams: []
1490
- };
1491
- let cancelled = false;
1492
- const addSignalProperty = object => {
1493
- Object.defineProperty(object, 'signal', {
1494
- enumerable: true,
1495
- get: () => {
1496
- if (context.signal.aborted) {
1497
- cancelled = true;
1498
- } else {
1499
- context.signal.addEventListener('abort', () => {
1500
- cancelled = true;
1501
- });
1502
- }
1503
- return context.signal;
1504
- }
1505
- });
1506
- };
1507
-
1508
- // Get query function
1509
- const queryFn = context.options.queryFn || (() => Promise.reject(new Error('Missing queryFn')));
1510
-
1511
- // Create function to fetch a page
1512
- const fetchPage = async (data, param, previous) => {
1513
- if (cancelled) {
1514
- return Promise.reject();
1515
- }
1516
- if (typeof param === 'undefined' && data.pages.length) {
1517
- return Promise.resolve(data);
1518
- }
1519
- const queryFnContext = {
1520
- queryKey: context.queryKey,
1521
- pageParam: param,
1522
- direction: previous ? 'backward' : 'forward',
1523
- meta: context.options.meta
1524
- };
1525
- addSignalProperty(queryFnContext);
1526
- const page = await queryFn(queryFnContext);
1527
- const {
1528
- maxPages
1529
- } = context.options;
1530
- const addTo = previous ? addToStart : addToEnd;
1531
- return {
1532
- pages: addTo(data.pages, page, maxPages),
1533
- pageParams: addTo(data.pageParams, param, maxPages)
1534
- };
1535
- };
1536
- let result;
1537
-
1538
- // Fetch first page?
1539
- if (!oldPages.length) {
1540
- result = await fetchPage(empty, options.defaultPageParam);
1541
- }
1542
-
1543
- // fetch next / previous page?
1544
- else if (direction) {
1545
- const previous = direction === 'backward';
1546
- const pageParamFn = previous ? getPreviousPageParam : getNextPageParam;
1547
- const oldData = {
1548
- pages: oldPages,
1549
- pageParams: oldPageParams
1550
- };
1551
- const param = pageParamFn(options, oldData);
1552
- result = await fetchPage(oldData, param, previous);
1553
- }
1554
-
1555
- // Refetch pages
1556
- else {
1557
- // Fetch first page
1558
- result = await fetchPage(empty, oldPageParams[0]);
1559
-
1560
- // Fetch remaining pages
1561
- for (let i = 1; i < oldPages.length; i++) {
1562
- const param = getNextPageParam(options, result);
1563
- result = await fetchPage(result, param);
1564
- }
1565
- }
1566
- return result;
1567
- };
1568
- }
1569
- };
1570
- }
1571
- function getNextPageParam(options, {
1572
- pages,
1573
- pageParams
1574
- }) {
1575
- const lastIndex = pages.length - 1;
1576
- return options.getNextPageParam(pages[lastIndex], pages, pageParams[lastIndex], pageParams);
1577
- }
1578
- function getPreviousPageParam(options, {
1579
- pages,
1580
- pageParams
1581
- }) {
1582
- return options.getPreviousPageParam?.(pages[0], pages, pageParams[0], pageParams);
1583
- }
1584
-
1585
- /**
1586
- * Checks if there is a next page.
1587
- */
1588
- function hasNextPage(options, data) {
1589
- if (!data) return false;
1590
- return typeof getNextPageParam(options, data) !== 'undefined';
1591
- }
1592
-
1593
- /**
1594
- * Checks if there is a previous page.
1595
- */
1596
- function hasPreviousPage(options, data) {
1597
- if (!data || !options.getPreviousPageParam) return false;
1598
- return typeof getPreviousPageParam(options, data) !== 'undefined';
1599
- }
1600
-
1601
- // TYPES
1602
-
1603
- // CLASS
1604
-
1605
- class QueryClient {
1606
- #queryCache;
1607
- #mutationCache;
1608
- #defaultOptions;
1609
- #queryDefaults;
1610
- #mutationDefaults;
1611
- #mountCount;
1612
- #unsubscribeFocus;
1613
- #unsubscribeOnline;
1614
- constructor(config = {}) {
1615
- this.#queryCache = config.queryCache || new QueryCache();
1616
- this.#mutationCache = config.mutationCache || new MutationCache();
1617
- this.#defaultOptions = config.defaultOptions || {};
1618
- this.#queryDefaults = new Map();
1619
- this.#mutationDefaults = new Map();
1620
- this.#mountCount = 0;
1621
- }
1622
- mount() {
1623
- this.#mountCount++;
1624
- if (this.#mountCount !== 1) return;
1625
- this.#unsubscribeFocus = focusManager.subscribe(() => {
1626
- if (focusManager.isFocused()) {
1627
- this.resumePausedMutations();
1628
- this.#queryCache.onFocus();
1629
- }
1630
- });
1631
- this.#unsubscribeOnline = onlineManager.subscribe(() => {
1632
- if (onlineManager.isOnline()) {
1633
- this.resumePausedMutations();
1634
- this.#queryCache.onOnline();
1635
- }
1636
- });
1637
- }
1638
- unmount() {
1639
- this.#mountCount--;
1640
- if (this.#mountCount !== 0) return;
1641
- this.#unsubscribeFocus?.();
1642
- this.#unsubscribeFocus = undefined;
1643
- this.#unsubscribeOnline?.();
1644
- this.#unsubscribeOnline = undefined;
1645
- }
1646
- isFetching(filters) {
1647
- return this.#queryCache.findAll({
1648
- ...filters,
1649
- fetchStatus: 'fetching'
1650
- }).length;
1651
- }
1652
- isMutating(filters) {
1653
- return this.#mutationCache.findAll({
1654
- ...filters,
1655
- status: 'pending'
1656
- }).length;
1657
- }
1658
- getQueryData(queryKey) {
1659
- return this.#queryCache.find({
1660
- queryKey
1661
- })?.state.data;
1662
- }
1663
- ensureQueryData(options) {
1664
- const cachedData = this.getQueryData(options.queryKey);
1665
- return cachedData ? Promise.resolve(cachedData) : this.fetchQuery(options);
1666
- }
1667
- getQueriesData(filters) {
1668
- return this.getQueryCache().findAll(filters).map(({
1669
- queryKey,
1670
- state
1671
- }) => {
1672
- const data = state.data;
1673
- return [queryKey, data];
1674
- });
1675
- }
1676
- setQueryData(queryKey, updater, options) {
1677
- const query = this.#queryCache.find({
1678
- queryKey
1679
- });
1680
- const prevData = query?.state.data;
1681
- const data = functionalUpdate(updater, prevData);
1682
- if (typeof data === 'undefined') {
1683
- return undefined;
1684
- }
1685
- const defaultedOptions = this.defaultQueryOptions({
1686
- queryKey
1687
- });
1688
- return this.#queryCache.build(this, defaultedOptions).setData(data, {
1689
- ...options,
1690
- manual: true
1691
- });
1692
- }
1693
- setQueriesData(filters, updater, options) {
1694
- return notifyManager.batch(() => this.getQueryCache().findAll(filters).map(({
1695
- queryKey
1696
- }) => [queryKey, this.setQueryData(queryKey, updater, options)]));
1697
- }
1698
- getQueryState(queryKey) {
1699
- return this.#queryCache.find({
1700
- queryKey
1701
- })?.state;
1702
- }
1703
- removeQueries(filters) {
1704
- const queryCache = this.#queryCache;
1705
- notifyManager.batch(() => {
1706
- queryCache.findAll(filters).forEach(query => {
1707
- queryCache.remove(query);
1708
- });
1709
- });
1710
- }
1711
- resetQueries(filters, options) {
1712
- const queryCache = this.#queryCache;
1713
- const refetchFilters = {
1714
- type: 'active',
1715
- ...filters
1716
- };
1717
- return notifyManager.batch(() => {
1718
- queryCache.findAll(filters).forEach(query => {
1719
- query.reset();
1720
- });
1721
- return this.refetchQueries(refetchFilters, options);
1722
- });
1723
- }
1724
- cancelQueries(filters = {}, cancelOptions = {}) {
1725
- const defaultedCancelOptions = {
1726
- revert: true,
1727
- ...cancelOptions
1728
- };
1729
- const promises = notifyManager.batch(() => this.#queryCache.findAll(filters).map(query => query.cancel(defaultedCancelOptions)));
1730
- return Promise.all(promises).then(noop$1).catch(noop$1);
1731
- }
1732
- invalidateQueries(filters = {}, options = {}) {
1733
- return notifyManager.batch(() => {
1734
- this.#queryCache.findAll(filters).forEach(query => {
1735
- query.invalidate();
1736
- });
1737
- if (filters.refetchType === 'none') {
1738
- return Promise.resolve();
1739
- }
1740
- const refetchFilters = {
1741
- ...filters,
1742
- type: filters.refetchType ?? filters.type ?? 'active'
1743
- };
1744
- return this.refetchQueries(refetchFilters, options);
1745
- });
1746
- }
1747
- refetchQueries(filters = {}, options) {
1748
- const fetchOptions = {
1749
- ...options,
1750
- cancelRefetch: options?.cancelRefetch ?? true
1751
- };
1752
- const promises = notifyManager.batch(() => this.#queryCache.findAll(filters).filter(query => !query.isDisabled()).map(query => {
1753
- let promise = query.fetch(undefined, fetchOptions);
1754
- if (!fetchOptions.throwOnError) {
1755
- promise = promise.catch(noop$1);
1756
- }
1757
- return query.state.fetchStatus === 'paused' ? Promise.resolve() : promise;
1758
- }));
1759
- return Promise.all(promises).then(noop$1);
1760
- }
1761
- fetchQuery(options) {
1762
- const defaultedOptions = this.defaultQueryOptions(options);
1763
-
1764
- // https://github.com/tannerlinsley/react-query/issues/652
1765
- if (typeof defaultedOptions.retry === 'undefined') {
1766
- defaultedOptions.retry = false;
1767
- }
1768
- const query = this.#queryCache.build(this, defaultedOptions);
1769
- return query.isStaleByTime(defaultedOptions.staleTime) ? query.fetch(defaultedOptions) : Promise.resolve(query.state.data);
1770
- }
1771
- prefetchQuery(options) {
1772
- return this.fetchQuery(options).then(noop$1).catch(noop$1);
1773
- }
1774
- fetchInfiniteQuery(options) {
1775
- options.behavior = infiniteQueryBehavior();
1776
- return this.fetchQuery(options);
1777
- }
1778
- prefetchInfiniteQuery(options) {
1779
- return this.fetchInfiniteQuery(options).then(noop$1).catch(noop$1);
1780
- }
1781
- resumePausedMutations() {
1782
- return this.#mutationCache.resumePausedMutations();
1783
- }
1784
- getQueryCache() {
1785
- return this.#queryCache;
1786
- }
1787
- getMutationCache() {
1788
- return this.#mutationCache;
1789
- }
1790
- getDefaultOptions() {
1791
- return this.#defaultOptions;
1792
- }
1793
- setDefaultOptions(options) {
1794
- this.#defaultOptions = options;
1795
- }
1796
- setQueryDefaults(queryKey, options) {
1797
- this.#queryDefaults.set(hashKey(queryKey), {
1798
- queryKey,
1799
- defaultOptions: options
1800
- });
1801
- }
1802
- getQueryDefaults(queryKey) {
1803
- const defaults = [...this.#queryDefaults.values()];
1804
- let result = {};
1805
- defaults.forEach(queryDefault => {
1806
- if (partialMatchKey(queryKey, queryDefault.queryKey)) {
1807
- result = {
1808
- ...result,
1809
- ...queryDefault.defaultOptions
1810
- };
1811
- }
1812
- });
1813
- return result;
1814
- }
1815
- setMutationDefaults(mutationKey, options) {
1816
- this.#mutationDefaults.set(hashKey(mutationKey), {
1817
- mutationKey,
1818
- defaultOptions: options
1819
- });
1820
- }
1821
- getMutationDefaults(mutationKey) {
1822
- const defaults = [...this.#mutationDefaults.values()];
1823
- let result = {};
1824
- defaults.forEach(queryDefault => {
1825
- if (partialMatchKey(mutationKey, queryDefault.mutationKey)) {
1826
- result = {
1827
- ...result,
1828
- ...queryDefault.defaultOptions
1829
- };
1830
- }
1831
- });
1832
- return result;
1833
- }
1834
- defaultQueryOptions(options) {
1835
- if (options?._defaulted) {
1836
- return options;
1837
- }
1838
- const defaultedOptions = {
1839
- ...this.#defaultOptions.queries,
1840
- ...(options?.queryKey && this.getQueryDefaults(options.queryKey)),
1841
- ...options,
1842
- _defaulted: true
1843
- };
1844
- if (!defaultedOptions.queryHash) {
1845
- defaultedOptions.queryHash = hashQueryKeyByOptions(defaultedOptions.queryKey, defaultedOptions);
1846
- }
1847
-
1848
- // dependent default values
1849
- if (typeof defaultedOptions.refetchOnReconnect === 'undefined') {
1850
- defaultedOptions.refetchOnReconnect = defaultedOptions.networkMode !== 'always';
1851
- }
1852
- if (typeof defaultedOptions.throwOnError === 'undefined') {
1853
- defaultedOptions.throwOnError = !!defaultedOptions.suspense;
1854
- }
1855
- return defaultedOptions;
1856
- }
1857
- defaultMutationOptions(options) {
1858
- if (options?._defaulted) {
1859
- return options;
1860
- }
1861
- return {
1862
- ...this.#defaultOptions.mutations,
1863
- ...(options?.mutationKey && this.getMutationDefaults(options.mutationKey)),
1864
- ...options,
1865
- _defaulted: true
1866
- };
1867
- }
1868
- clear() {
1869
- this.#queryCache.clear();
1870
- this.#mutationCache.clear();
1871
- }
1872
- }
1873
-
1874
- class QueryObserver extends Subscribable {
1875
- #client;
1876
- #currentQuery = undefined;
1877
- #currentQueryInitialState = undefined;
1878
- #currentResult = undefined;
1879
- #currentResultState;
1880
- #currentResultOptions;
1881
- #selectError;
1882
- #selectFn;
1883
- #selectResult;
1884
- // This property keeps track of the last query with defined data.
1885
- // It will be used to pass the previous data and query to the placeholder function between renders.
1886
- #lastQueryWithDefinedData;
1887
- #staleTimeoutId;
1888
- #refetchIntervalId;
1889
- #currentRefetchInterval;
1890
- #trackedProps = new Set();
1891
- constructor(client, options) {
1892
- super();
1893
- this.#client = client;
1894
- this.options = options;
1895
- this.#selectError = null;
1896
- this.bindMethods();
1897
- this.setOptions(options);
1898
- }
1899
- bindMethods() {
1900
- this.refetch = this.refetch.bind(this);
1901
- }
1902
- onSubscribe() {
1903
- if (this.listeners.size === 1) {
1904
- this.#currentQuery.addObserver(this);
1905
- if (shouldFetchOnMount(this.#currentQuery, this.options)) {
1906
- this.#executeFetch();
1907
- }
1908
- this.#updateTimers();
1909
- }
1910
- }
1911
- onUnsubscribe() {
1912
- if (!this.hasListeners()) {
1913
- this.destroy();
1914
- }
1915
- }
1916
- shouldFetchOnReconnect() {
1917
- return shouldFetchOn(this.#currentQuery, this.options, this.options.refetchOnReconnect);
1918
- }
1919
- shouldFetchOnWindowFocus() {
1920
- return shouldFetchOn(this.#currentQuery, this.options, this.options.refetchOnWindowFocus);
1921
- }
1922
- destroy() {
1923
- this.listeners = new Set();
1924
- this.#clearStaleTimeout();
1925
- this.#clearRefetchInterval();
1926
- this.#currentQuery.removeObserver(this);
1927
- }
1928
- setOptions(options, notifyOptions) {
1929
- const prevOptions = this.options;
1930
- const prevQuery = this.#currentQuery;
1931
- this.options = this.#client.defaultQueryOptions(options);
1932
- if (!shallowEqualObjects(prevOptions, this.options)) {
1933
- this.#client.getQueryCache().notify({
1934
- type: 'observerOptionsUpdated',
1935
- query: this.#currentQuery,
1936
- observer: this
1937
- });
1938
- }
1939
- if (typeof this.options.enabled !== 'undefined' && typeof this.options.enabled !== 'boolean') {
1940
- throw new Error('Expected enabled to be a boolean');
1941
- }
1942
-
1943
- // Keep previous query key if the user does not supply one
1944
- if (!this.options.queryKey) {
1945
- this.options.queryKey = prevOptions.queryKey;
1946
- }
1947
- this.#updateQuery();
1948
- const mounted = this.hasListeners();
1949
-
1950
- // Fetch if there are subscribers
1951
- if (mounted && shouldFetchOptionally(this.#currentQuery, prevQuery, this.options, prevOptions)) {
1952
- this.#executeFetch();
1953
- }
1954
-
1955
- // Update result
1956
- this.#updateResult(notifyOptions);
1957
-
1958
- // Update stale interval if needed
1959
- if (mounted && (this.#currentQuery !== prevQuery || this.options.enabled !== prevOptions.enabled || this.options.staleTime !== prevOptions.staleTime)) {
1960
- this.#updateStaleTimeout();
1961
- }
1962
- const nextRefetchInterval = this.#computeRefetchInterval();
1963
-
1964
- // Update refetch interval if needed
1965
- if (mounted && (this.#currentQuery !== prevQuery || this.options.enabled !== prevOptions.enabled || nextRefetchInterval !== this.#currentRefetchInterval)) {
1966
- this.#updateRefetchInterval(nextRefetchInterval);
1967
- }
1968
- }
1969
- getOptimisticResult(options) {
1970
- const query = this.#client.getQueryCache().build(this.#client, options);
1971
- return this.createResult(query, options);
1972
- }
1973
- getCurrentResult() {
1974
- return this.#currentResult;
1975
- }
1976
- trackResult(result) {
1977
- const trackedResult = {};
1978
- Object.keys(result).forEach(key => {
1979
- Object.defineProperty(trackedResult, key, {
1980
- configurable: false,
1981
- enumerable: true,
1982
- get: () => {
1983
- this.#trackedProps.add(key);
1984
- return result[key];
1985
- }
1986
- });
1987
- });
1988
- return trackedResult;
1989
- }
1990
- getCurrentQuery() {
1991
- return this.#currentQuery;
1992
- }
1993
- refetch({
1994
- ...options
1995
- } = {}) {
1996
- return this.fetch({
1997
- ...options
1998
- });
1999
- }
2000
- fetchOptimistic(options) {
2001
- const defaultedOptions = this.#client.defaultQueryOptions(options);
2002
- const query = this.#client.getQueryCache().build(this.#client, defaultedOptions);
2003
- query.isFetchingOptimistic = true;
2004
- return query.fetch().then(() => this.createResult(query, defaultedOptions));
2005
- }
2006
- fetch(fetchOptions) {
2007
- return this.#executeFetch({
2008
- ...fetchOptions,
2009
- cancelRefetch: fetchOptions.cancelRefetch ?? true
2010
- }).then(() => {
2011
- this.#updateResult();
2012
- return this.#currentResult;
2013
- });
2014
- }
2015
- #executeFetch(fetchOptions) {
2016
- // Make sure we reference the latest query as the current one might have been removed
2017
- this.#updateQuery();
2018
-
2019
- // Fetch
2020
- let promise = this.#currentQuery.fetch(this.options, fetchOptions);
2021
- if (!fetchOptions?.throwOnError) {
2022
- promise = promise.catch(noop$1);
2023
- }
2024
- return promise;
2025
- }
2026
- #updateStaleTimeout() {
2027
- this.#clearStaleTimeout();
2028
- if (isServer || this.#currentResult.isStale || !isValidTimeout(this.options.staleTime)) {
2029
- return;
2030
- }
2031
- const time = timeUntilStale(this.#currentResult.dataUpdatedAt, this.options.staleTime);
2032
-
2033
- // The timeout is sometimes triggered 1 ms before the stale time expiration.
2034
- // To mitigate this issue we always add 1 ms to the timeout.
2035
- const timeout = time + 1;
2036
- this.#staleTimeoutId = setTimeout(() => {
2037
- if (!this.#currentResult.isStale) {
2038
- this.#updateResult();
2039
- }
2040
- }, timeout);
2041
- }
2042
- #computeRefetchInterval() {
2043
- return (typeof this.options.refetchInterval === 'function' ? this.options.refetchInterval(this.#currentResult.data, this.#currentQuery) : this.options.refetchInterval) ?? false;
2044
- }
2045
- #updateRefetchInterval(nextInterval) {
2046
- this.#clearRefetchInterval();
2047
- this.#currentRefetchInterval = nextInterval;
2048
- if (isServer || this.options.enabled === false || !isValidTimeout(this.#currentRefetchInterval) || this.#currentRefetchInterval === 0) {
2049
- return;
2050
- }
2051
- this.#refetchIntervalId = setInterval(() => {
2052
- if (this.options.refetchIntervalInBackground || focusManager.isFocused()) {
2053
- this.#executeFetch();
2054
- }
2055
- }, this.#currentRefetchInterval);
2056
- }
2057
- #updateTimers() {
2058
- this.#updateStaleTimeout();
2059
- this.#updateRefetchInterval(this.#computeRefetchInterval());
2060
- }
2061
- #clearStaleTimeout() {
2062
- if (this.#staleTimeoutId) {
2063
- clearTimeout(this.#staleTimeoutId);
2064
- this.#staleTimeoutId = undefined;
2065
- }
2066
- }
2067
- #clearRefetchInterval() {
2068
- if (this.#refetchIntervalId) {
2069
- clearInterval(this.#refetchIntervalId);
2070
- this.#refetchIntervalId = undefined;
2071
- }
2072
- }
2073
- createResult(query, options) {
2074
- const prevQuery = this.#currentQuery;
2075
- const prevOptions = this.options;
2076
- const prevResult = this.#currentResult;
2077
- const prevResultState = this.#currentResultState;
2078
- const prevResultOptions = this.#currentResultOptions;
2079
- const queryChange = query !== prevQuery;
2080
- const queryInitialState = queryChange ? query.state : this.#currentQueryInitialState;
2081
- const {
2082
- state
2083
- } = query;
2084
- let {
2085
- error,
2086
- errorUpdatedAt,
2087
- fetchStatus,
2088
- status
2089
- } = state;
2090
- let isPlaceholderData = false;
2091
- let data;
2092
-
2093
- // Optimistically set result in fetching state if needed
2094
- if (options._optimisticResults) {
2095
- const mounted = this.hasListeners();
2096
- const fetchOnMount = !mounted && shouldFetchOnMount(query, options);
2097
- const fetchOptionally = mounted && shouldFetchOptionally(query, prevQuery, options, prevOptions);
2098
- if (fetchOnMount || fetchOptionally) {
2099
- fetchStatus = canFetch(query.options.networkMode) ? 'fetching' : 'paused';
2100
- if (!state.dataUpdatedAt) {
2101
- status = 'pending';
2102
- }
2103
- }
2104
- if (options._optimisticResults === 'isRestoring') {
2105
- fetchStatus = 'idle';
2106
- }
2107
- }
2108
-
2109
- // Select data if needed
2110
- if (options.select && typeof state.data !== 'undefined') {
2111
- // Memoize select result
2112
- if (prevResult && state.data === prevResultState?.data && options.select === this.#selectFn) {
2113
- data = this.#selectResult;
2114
- } else {
2115
- try {
2116
- this.#selectFn = options.select;
2117
- data = options.select(state.data);
2118
- data = replaceData(prevResult?.data, data, options);
2119
- this.#selectResult = data;
2120
- this.#selectError = null;
2121
- } catch (selectError) {
2122
- this.#selectError = selectError;
2123
- }
2124
- }
2125
- }
2126
- // Use query data
2127
- else {
2128
- data = state.data;
2129
- }
2130
-
2131
- // Show placeholder data if needed
2132
- if (typeof options.placeholderData !== 'undefined' && typeof data === 'undefined' && status === 'pending') {
2133
- let placeholderData;
2134
-
2135
- // Memoize placeholder data
2136
- if (prevResult?.isPlaceholderData && options.placeholderData === prevResultOptions?.placeholderData) {
2137
- placeholderData = prevResult.data;
2138
- } else {
2139
- placeholderData = typeof options.placeholderData === 'function' ? options.placeholderData(this.#lastQueryWithDefinedData?.state.data, this.#lastQueryWithDefinedData) : options.placeholderData;
2140
- if (options.select && typeof placeholderData !== 'undefined') {
2141
- try {
2142
- placeholderData = options.select(placeholderData);
2143
- this.#selectError = null;
2144
- } catch (selectError) {
2145
- this.#selectError = selectError;
2146
- }
2147
- }
2148
- }
2149
- if (typeof placeholderData !== 'undefined') {
2150
- status = 'success';
2151
- data = replaceData(prevResult?.data, placeholderData, options);
2152
- isPlaceholderData = true;
2153
- }
2154
- }
2155
- if (this.#selectError) {
2156
- error = this.#selectError;
2157
- data = this.#selectResult;
2158
- errorUpdatedAt = Date.now();
2159
- status = 'error';
2160
- }
2161
- const isFetching = fetchStatus === 'fetching';
2162
- const isPending = status === 'pending';
2163
- const isError = status === 'error';
2164
- const isLoading = isPending && isFetching;
2165
- const result = {
2166
- status,
2167
- fetchStatus,
2168
- isPending,
2169
- isSuccess: status === 'success',
2170
- isError,
2171
- isInitialLoading: isLoading,
2172
- isLoading,
2173
- data,
2174
- dataUpdatedAt: state.dataUpdatedAt,
2175
- error,
2176
- errorUpdatedAt,
2177
- failureCount: state.fetchFailureCount,
2178
- failureReason: state.fetchFailureReason,
2179
- errorUpdateCount: state.errorUpdateCount,
2180
- isFetched: state.dataUpdateCount > 0 || state.errorUpdateCount > 0,
2181
- isFetchedAfterMount: state.dataUpdateCount > queryInitialState.dataUpdateCount || state.errorUpdateCount > queryInitialState.errorUpdateCount,
2182
- isFetching,
2183
- isRefetching: isFetching && !isPending,
2184
- isLoadingError: isError && state.dataUpdatedAt === 0,
2185
- isPaused: fetchStatus === 'paused',
2186
- isPlaceholderData,
2187
- isRefetchError: isError && state.dataUpdatedAt !== 0,
2188
- isStale: isStale(query, options),
2189
- refetch: this.refetch
2190
- };
2191
- return result;
2192
- }
2193
- #updateResult(notifyOptions) {
2194
- const prevResult = this.#currentResult;
2195
- const nextResult = this.createResult(this.#currentQuery, this.options);
2196
- this.#currentResultState = this.#currentQuery.state;
2197
- this.#currentResultOptions = this.options;
2198
-
2199
- // Only notify and update result if something has changed
2200
- if (shallowEqualObjects(nextResult, prevResult)) {
2201
- return;
2202
- }
2203
- if (this.#currentResultState.data !== undefined) {
2204
- this.#lastQueryWithDefinedData = this.#currentQuery;
2205
- }
2206
- this.#currentResult = nextResult;
2207
-
2208
- // Determine which callbacks to trigger
2209
- const defaultNotifyOptions = {};
2210
- const shouldNotifyListeners = () => {
2211
- if (!prevResult) {
2212
- return true;
2213
- }
2214
- const {
2215
- notifyOnChangeProps
2216
- } = this.options;
2217
- if (notifyOnChangeProps === 'all' || !notifyOnChangeProps && !this.#trackedProps.size) {
2218
- return true;
2219
- }
2220
- const includedProps = new Set(notifyOnChangeProps ?? this.#trackedProps);
2221
- if (this.options.throwOnError) {
2222
- includedProps.add('error');
2223
- }
2224
- return Object.keys(this.#currentResult).some(key => {
2225
- const typedKey = key;
2226
- const changed = this.#currentResult[typedKey] !== prevResult[typedKey];
2227
- return changed && includedProps.has(typedKey);
2228
- });
2229
- };
2230
- if (notifyOptions?.listeners !== false && shouldNotifyListeners()) {
2231
- defaultNotifyOptions.listeners = true;
2232
- }
2233
- this.#notify({
2234
- ...defaultNotifyOptions,
2235
- ...notifyOptions
2236
- });
2237
- }
2238
- #updateQuery() {
2239
- const query = this.#client.getQueryCache().build(this.#client, this.options);
2240
- if (query === this.#currentQuery) {
2241
- return;
2242
- }
2243
- const prevQuery = this.#currentQuery;
2244
- this.#currentQuery = query;
2245
- this.#currentQueryInitialState = query.state;
2246
- if (this.hasListeners()) {
2247
- prevQuery?.removeObserver(this);
2248
- query.addObserver(this);
2249
- }
2250
- }
2251
- onQueryUpdate() {
2252
- this.#updateResult();
2253
- if (this.hasListeners()) {
2254
- this.#updateTimers();
2255
- }
2256
- }
2257
- #notify(notifyOptions) {
2258
- notifyManager.batch(() => {
2259
- // First, trigger the listeners
2260
- if (notifyOptions.listeners) {
2261
- this.listeners.forEach(listener => {
2262
- listener(this.#currentResult);
2263
- });
2264
- }
2265
-
2266
- // Then the cache listeners
2267
- this.#client.getQueryCache().notify({
2268
- query: this.#currentQuery,
2269
- type: 'observerResultsUpdated'
2270
- });
2271
- });
2272
- }
2273
- }
2274
- function shouldLoadOnMount(query, options) {
2275
- return options.enabled !== false && !query.state.dataUpdatedAt && !(query.state.status === 'error' && options.retryOnMount === false);
2276
- }
2277
- function shouldFetchOnMount(query, options) {
2278
- return shouldLoadOnMount(query, options) || query.state.dataUpdatedAt > 0 && shouldFetchOn(query, options, options.refetchOnMount);
2279
- }
2280
- function shouldFetchOn(query, options, field) {
2281
- if (options.enabled !== false) {
2282
- const value = typeof field === 'function' ? field(query) : field;
2283
- return value === 'always' || value !== false && isStale(query, options);
2284
- }
2285
- return false;
2286
- }
2287
- function shouldFetchOptionally(query, prevQuery, options, prevOptions) {
2288
- return options.enabled !== false && (query !== prevQuery || prevOptions.enabled === false) && (!options.suspense || query.state.status !== 'error') && isStale(query, options);
2289
- }
2290
- function isStale(query, options) {
2291
- return query.isStaleByTime(options.staleTime);
2292
- }
2293
-
2294
- function difference(array1, array2) {
2295
- return array1.filter(x => array2.indexOf(x) === -1);
2296
- }
2297
- function replaceAt(array, index, value) {
2298
- const copy = array.slice(0);
2299
- copy[index] = value;
2300
- return copy;
2301
- }
2302
- class QueriesObserver extends Subscribable {
2303
- #client;
2304
- #result;
2305
- #queries;
2306
- #observers;
2307
- #options;
2308
- #combinedResult;
2309
- constructor(client, queries, options) {
2310
- super();
2311
- this.#client = client;
2312
- this.#queries = [];
2313
- this.#observers = [];
2314
- this.#setResult([]);
2315
- this.setQueries(queries, options);
2316
- }
2317
- #setResult(value) {
2318
- this.#result = value;
2319
- this.#combinedResult = this.#combineResult(value);
2320
- }
2321
- onSubscribe() {
2322
- if (this.listeners.size === 1) {
2323
- this.#observers.forEach(observer => {
2324
- observer.subscribe(result => {
2325
- this.#onUpdate(observer, result);
2326
- });
2327
- });
2328
- }
2329
- }
2330
- onUnsubscribe() {
2331
- if (!this.listeners.size) {
2332
- this.destroy();
2333
- }
2334
- }
2335
- destroy() {
2336
- this.listeners = new Set();
2337
- this.#observers.forEach(observer => {
2338
- observer.destroy();
2339
- });
2340
- }
2341
- setQueries(queries, options, notifyOptions) {
2342
- this.#queries = queries;
2343
- this.#options = options;
2344
- notifyManager.batch(() => {
2345
- const prevObservers = this.#observers;
2346
- const newObserverMatches = this.#findMatchingObservers(this.#queries);
2347
-
2348
- // set options for the new observers to notify of changes
2349
- newObserverMatches.forEach(match => match.observer.setOptions(match.defaultedQueryOptions, notifyOptions));
2350
- const newObservers = newObserverMatches.map(match => match.observer);
2351
- const newResult = newObservers.map(observer => observer.getCurrentResult());
2352
- const hasIndexChange = newObservers.some((observer, index) => observer !== prevObservers[index]);
2353
- if (prevObservers.length === newObservers.length && !hasIndexChange) {
2354
- return;
2355
- }
2356
- this.#observers = newObservers;
2357
- this.#setResult(newResult);
2358
- if (!this.hasListeners()) {
2359
- return;
2360
- }
2361
- difference(prevObservers, newObservers).forEach(observer => {
2362
- observer.destroy();
2363
- });
2364
- difference(newObservers, prevObservers).forEach(observer => {
2365
- observer.subscribe(result => {
2366
- this.#onUpdate(observer, result);
2367
- });
2368
- });
2369
- this.#notify();
2370
- });
2371
- }
2372
- getCurrentResult() {
2373
- return this.#combinedResult;
2374
- }
2375
- getQueries() {
2376
- return this.#observers.map(observer => observer.getCurrentQuery());
2377
- }
2378
- getObservers() {
2379
- return this.#observers;
2380
- }
2381
- getOptimisticResult(queries) {
2382
- const matches = this.#findMatchingObservers(queries);
2383
- const result = matches.map(match => match.observer.getOptimisticResult(match.defaultedQueryOptions));
2384
- return [result, r => {
2385
- return this.#combineResult(r ?? result);
2386
- }, () => {
2387
- return matches.map((match, index) => {
2388
- const observerResult = result[index];
2389
- return !match.defaultedQueryOptions.notifyOnChangeProps ? match.observer.trackResult(observerResult) : observerResult;
2390
- });
2391
- }];
2392
- }
2393
- #combineResult(input) {
2394
- const combine = this.#options?.combine;
2395
- if (combine) {
2396
- return replaceEqualDeep(this.#combinedResult, combine(input));
2397
- }
2398
- return input;
2399
- }
2400
- #findMatchingObservers(queries) {
2401
- const prevObservers = this.#observers;
2402
- const prevObserversMap = new Map(prevObservers.map(observer => [observer.options.queryHash, observer]));
2403
- const defaultedQueryOptions = queries.map(options => this.#client.defaultQueryOptions(options));
2404
- const matchingObservers = defaultedQueryOptions.flatMap(defaultedOptions => {
2405
- const match = prevObserversMap.get(defaultedOptions.queryHash);
2406
- if (match != null) {
2407
- return [{
2408
- defaultedQueryOptions: defaultedOptions,
2409
- observer: match
2410
- }];
2411
- }
2412
- return [];
2413
- });
2414
- const matchedQueryHashes = new Set(matchingObservers.map(match => match.defaultedQueryOptions.queryHash));
2415
- const unmatchedQueries = defaultedQueryOptions.filter(defaultedOptions => !matchedQueryHashes.has(defaultedOptions.queryHash));
2416
- const getObserver = options => {
2417
- const defaultedOptions = this.#client.defaultQueryOptions(options);
2418
- const currentObserver = this.#observers.find(o => o.options.queryHash === defaultedOptions.queryHash);
2419
- return currentObserver ?? new QueryObserver(this.#client, defaultedOptions);
2420
- };
2421
- const newOrReusedObservers = unmatchedQueries.map(options => {
2422
- return {
2423
- defaultedQueryOptions: options,
2424
- observer: getObserver(options)
2425
- };
2426
- });
2427
- const sortMatchesByOrderOfQueries = (a, b) => defaultedQueryOptions.indexOf(a.defaultedQueryOptions) - defaultedQueryOptions.indexOf(b.defaultedQueryOptions);
2428
- return matchingObservers.concat(newOrReusedObservers).sort(sortMatchesByOrderOfQueries);
2429
- }
2430
- #onUpdate(observer, result) {
2431
- const index = this.#observers.indexOf(observer);
2432
- if (index !== -1) {
2433
- this.#setResult(replaceAt(this.#result, index, result));
2434
- this.#notify();
2435
- }
2436
- }
2437
- #notify() {
2438
- notifyManager.batch(() => {
2439
- this.listeners.forEach(listener => {
2440
- listener(this.#result);
2441
- });
2442
- });
2443
- }
2444
- }
2445
-
2446
- class InfiniteQueryObserver extends QueryObserver {
2447
- // Type override
2448
-
2449
- // Type override
2450
-
2451
- // Type override
2452
-
2453
- // eslint-disable-next-line @typescript-eslint/no-useless-constructor
2454
- constructor(client, options) {
2455
- super(client, options);
2456
- }
2457
- bindMethods() {
2458
- super.bindMethods();
2459
- this.fetchNextPage = this.fetchNextPage.bind(this);
2460
- this.fetchPreviousPage = this.fetchPreviousPage.bind(this);
2461
- }
2462
- setOptions(options, notifyOptions) {
2463
- super.setOptions({
2464
- ...options,
2465
- behavior: infiniteQueryBehavior()
2466
- }, notifyOptions);
2467
- }
2468
- getOptimisticResult(options) {
2469
- options.behavior = infiniteQueryBehavior();
2470
- return super.getOptimisticResult(options);
2471
- }
2472
- fetchNextPage(options) {
2473
- return this.fetch({
2474
- ...options,
2475
- meta: {
2476
- fetchMore: {
2477
- direction: 'forward'
2478
- }
2479
- }
2480
- });
2481
- }
2482
- fetchPreviousPage(options) {
2483
- return this.fetch({
2484
- ...options,
2485
- meta: {
2486
- fetchMore: {
2487
- direction: 'backward'
2488
- }
2489
- }
2490
- });
2491
- }
2492
- createResult(query, options) {
2493
- const {
2494
- state
2495
- } = query;
2496
- const result = super.createResult(query, options);
2497
- const {
2498
- isFetching,
2499
- isRefetching
2500
- } = result;
2501
- const isFetchingNextPage = isFetching && state.fetchMeta?.fetchMore?.direction === 'forward';
2502
- const isFetchingPreviousPage = isFetching && state.fetchMeta?.fetchMore?.direction === 'backward';
2503
- return {
2504
- ...result,
2505
- fetchNextPage: this.fetchNextPage,
2506
- fetchPreviousPage: this.fetchPreviousPage,
2507
- hasNextPage: hasNextPage(options, state.data),
2508
- hasPreviousPage: hasPreviousPage(options, state.data),
2509
- isFetchingNextPage,
2510
- isFetchingPreviousPage,
2511
- isRefetching: isRefetching && !isFetchingNextPage && !isFetchingPreviousPage
2512
- };
2513
- }
2514
- }
2515
-
2516
- // TYPES
2517
-
2518
- // CLASS
2519
-
2520
- class MutationObserver extends Subscribable {
2521
- #client;
2522
- #currentResult = undefined;
2523
- #currentMutation;
2524
- #mutateOptions;
2525
- constructor(client, options) {
2526
- super();
2527
- this.#client = client;
2528
- this.setOptions(options);
2529
- this.bindMethods();
2530
- this.#updateResult();
2531
- }
2532
- bindMethods() {
2533
- this.mutate = this.mutate.bind(this);
2534
- this.reset = this.reset.bind(this);
2535
- }
2536
- setOptions(options) {
2537
- const prevOptions = this.options;
2538
- this.options = this.#client.defaultMutationOptions(options);
2539
- if (!shallowEqualObjects(prevOptions, this.options)) {
2540
- this.#client.getMutationCache().notify({
2541
- type: 'observerOptionsUpdated',
2542
- mutation: this.#currentMutation,
2543
- observer: this
2544
- });
2545
- }
2546
- this.#currentMutation?.setOptions(this.options);
2547
- }
2548
- onUnsubscribe() {
2549
- if (!this.hasListeners()) {
2550
- this.#currentMutation?.removeObserver(this);
2551
- }
2552
- }
2553
- onMutationUpdate(action) {
2554
- this.#updateResult();
2555
- this.#notify(action);
2556
- }
2557
- getCurrentResult() {
2558
- return this.#currentResult;
2559
- }
2560
- reset() {
2561
- this.#currentMutation = undefined;
2562
- this.#updateResult();
2563
- this.#notify();
2564
- }
2565
- mutate(variables, options) {
2566
- this.#mutateOptions = options;
2567
- this.#currentMutation?.removeObserver(this);
2568
- this.#currentMutation = this.#client.getMutationCache().build(this.#client, this.options);
2569
- this.#currentMutation.addObserver(this);
2570
- return this.#currentMutation.execute(variables);
2571
- }
2572
- #updateResult() {
2573
- const state = this.#currentMutation?.state ?? getDefaultState();
2574
- this.#currentResult = {
2575
- ...state,
2576
- isPending: state.status === 'pending',
2577
- isSuccess: state.status === 'success',
2578
- isError: state.status === 'error',
2579
- isIdle: state.status === 'idle',
2580
- mutate: this.mutate,
2581
- reset: this.reset
2582
- };
2583
- }
2584
- #notify(action) {
2585
- notifyManager.batch(() => {
2586
- // First trigger the mutate callbacks
2587
- if (this.#mutateOptions && this.hasListeners()) {
2588
- if (action?.type === 'success') {
2589
- this.#mutateOptions.onSuccess?.(action.data, this.#currentResult.variables, this.#currentResult.context);
2590
- this.#mutateOptions.onSettled?.(action.data, null, this.#currentResult.variables, this.#currentResult.context);
2591
- } else if (action?.type === 'error') {
2592
- this.#mutateOptions.onError?.(action.error, this.#currentResult.variables, this.#currentResult.context);
2593
- this.#mutateOptions.onSettled?.(undefined, action.error, this.#currentResult.variables, this.#currentResult.context);
2594
- }
2595
- }
2596
-
2597
- // Then trigger the listeners
2598
- this.listeners.forEach(listener => {
2599
- listener(this.#currentResult);
2600
- });
2601
- });
2602
- }
2603
- }
2604
-
2605
- // TYPES
2606
-
2607
- // FUNCTIONS
2608
-
2609
- function dehydrateMutation(mutation) {
2610
- return {
2611
- mutationKey: mutation.options.mutationKey,
2612
- state: mutation.state
2613
- };
2614
- }
2615
-
2616
- // Most config is not dehydrated but instead meant to configure again when
2617
- // consuming the de/rehydrated data, typically with useQuery on the client.
2618
- // Sometimes it might make sense to prefetch data on the server and include
2619
- // in the html-payload, but not consume it on the initial render.
2620
- function dehydrateQuery(query) {
2621
- return {
2622
- state: query.state,
2623
- queryKey: query.queryKey,
2624
- queryHash: query.queryHash
2625
- };
2626
- }
2627
- function defaultShouldDehydrateMutation(mutation) {
2628
- return mutation.state.isPaused;
2629
- }
2630
- function defaultShouldDehydrateQuery(query) {
2631
- return query.state.status === 'success';
2632
- }
2633
- function dehydrate(client, options = {}) {
2634
- const filterMutation = options.shouldDehydrateMutation ?? defaultShouldDehydrateMutation;
2635
- const mutations = client.getMutationCache().getAll().flatMap(mutation => filterMutation(mutation) ? [dehydrateMutation(mutation)] : []);
2636
- const filterQuery = options.shouldDehydrateQuery ?? defaultShouldDehydrateQuery;
2637
- const queries = client.getQueryCache().getAll().flatMap(query => filterQuery(query) ? [dehydrateQuery(query)] : []);
2638
- return {
2639
- mutations,
2640
- queries
2641
- };
2642
- }
2643
- function hydrate(client, dehydratedState, options) {
2644
- if (typeof dehydratedState !== 'object' || dehydratedState === null) {
2645
- return;
2646
- }
2647
- const mutationCache = client.getMutationCache();
2648
- const queryCache = client.getQueryCache();
2649
-
2650
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2651
- const mutations = dehydratedState.mutations || [];
2652
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2653
- const queries = dehydratedState.queries || [];
2654
- mutations.forEach(dehydratedMutation => {
2655
- mutationCache.build(client, {
2656
- ...options?.defaultOptions?.mutations,
2657
- mutationKey: dehydratedMutation.mutationKey
2658
- }, dehydratedMutation.state);
2659
- });
2660
- queries.forEach(dehydratedQuery => {
2661
- const query = queryCache.get(dehydratedQuery.queryHash);
2662
-
2663
- // Reset fetch status to idle in the dehydrated state to avoid
2664
- // query being stuck in fetching state upon hydration
2665
- const dehydratedQueryState = {
2666
- ...dehydratedQuery.state,
2667
- fetchStatus: 'idle'
2668
- };
2669
-
2670
- // Do not hydrate if an existing query exists with newer data
2671
- if (query) {
2672
- if (query.state.dataUpdatedAt < dehydratedQueryState.dataUpdatedAt) {
2673
- query.setState(dehydratedQueryState);
2674
- }
2675
- return;
2676
- }
2677
-
2678
- // Restore query
2679
- queryCache.build(client, {
2680
- ...options?.defaultOptions?.queries,
2681
- queryKey: dehydratedQuery.queryKey,
2682
- queryHash: dehydratedQuery.queryHash
2683
- }, dehydratedQueryState);
2684
- });
2685
- }
2686
-
2687
- const QueryClientContext = /*#__PURE__*/React__namespace.createContext(undefined);
2688
- const useQueryClient = queryClient => {
2689
- const client = React__namespace.useContext(QueryClientContext);
2690
- if (queryClient) {
2691
- return queryClient;
2692
- }
2693
- if (!client) {
2694
- throw new Error('No QueryClient set, use QueryClientProvider to set one');
2695
- }
2696
- return client;
2697
- };
2698
- const QueryClientProvider = ({
2699
- client,
2700
- children
2701
- }) => {
2702
- React__namespace.useEffect(() => {
2703
- client.mount();
2704
- return () => {
2705
- client.unmount();
2706
- };
2707
- }, [client]);
2708
- return /*#__PURE__*/React__namespace.createElement(QueryClientContext.Provider, {
2709
- value: client
2710
- }, children);
2711
- };
2712
-
2713
- const IsRestoringContext = /*#__PURE__*/React__namespace.createContext(false);
2714
- const useIsRestoring = () => React__namespace.useContext(IsRestoringContext);
2715
- const IsRestoringProvider = IsRestoringContext.Provider;
2716
-
2717
- // CONTEXT
2718
-
2719
- function createValue() {
2720
- let isReset = false;
2721
- return {
2722
- clearReset: () => {
2723
- isReset = false;
2724
- },
2725
- reset: () => {
2726
- isReset = true;
2727
- },
2728
- isReset: () => {
2729
- return isReset;
2730
- }
2731
- };
2732
- }
2733
- const QueryErrorResetBoundaryContext = /*#__PURE__*/React__namespace.createContext(createValue());
2734
-
2735
- // HOOK
2736
-
2737
- const useQueryErrorResetBoundary = () => React__namespace.useContext(QueryErrorResetBoundaryContext);
2738
-
2739
- // COMPONENT
2740
-
2741
- const QueryErrorResetBoundary = ({
2742
- children
2743
- }) => {
2744
- const [value] = React__namespace.useState(() => createValue());
2745
- return /*#__PURE__*/React__namespace.createElement(QueryErrorResetBoundaryContext.Provider, {
2746
- value: value
2747
- }, typeof children === 'function' ? children(value) : children);
2748
- };
2749
-
2750
- function shouldThrowError(throwError, params) {
2751
- // Allow throwError function to override throwing behavior on a per-error basis
2752
- if (typeof throwError === 'function') {
2753
- return throwError(...params);
2754
- }
2755
- return !!throwError;
2756
- }
2757
-
2758
- const ensurePreventErrorBoundaryRetry = (options, errorResetBoundary) => {
2759
- if (options.suspense || options.throwOnError) {
2760
- // Prevent retrying failed query if the error boundary has not been reset yet
2761
- if (!errorResetBoundary.isReset()) {
2762
- options.retryOnMount = false;
2763
- }
2764
- }
2765
- };
2766
- const useClearResetErrorBoundary = errorResetBoundary => {
2767
- React__namespace.useEffect(() => {
2768
- errorResetBoundary.clearReset();
2769
- }, [errorResetBoundary]);
2770
- };
2771
- const getHasError = ({
2772
- result,
2773
- errorResetBoundary,
2774
- throwOnError,
2775
- query
2776
- }) => {
2777
- return result.isError && !errorResetBoundary.isReset() && !result.isFetching && shouldThrowError(throwOnError, [result.error, query]);
2778
- };
2779
-
2780
- const ensureStaleTime = defaultedOptions => {
2781
- if (defaultedOptions.suspense) {
2782
- // Always set stale time when using suspense to prevent
2783
- // fetching again when directly mounting after suspending
2784
- if (typeof defaultedOptions.staleTime !== 'number') {
2785
- defaultedOptions.staleTime = 1000;
2786
- }
2787
- }
2788
- };
2789
- const willFetch = (result, isRestoring) => result.isLoading && result.isFetching && !isRestoring;
2790
- const shouldSuspend = (defaultedOptions, result, isRestoring) => defaultedOptions?.suspense && willFetch(result, isRestoring);
2791
- const fetchOptimistic = (defaultedOptions, observer, errorResetBoundary) => observer.fetchOptimistic(defaultedOptions).catch(() => {
2792
- errorResetBoundary.clearReset();
2793
- });
2794
-
2795
- // This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.
2796
- // `placeholderData` function does not have a parameter
2797
- // Avoid TS depth-limit error in case of large array literal
2798
- /**
2799
- * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param
2800
- */
2801
- /**
2802
- * QueriesResults reducer recursively maps type param to results
2803
- */
2804
- function useQueries({
2805
- queries,
2806
- ...options
2807
- }, queryClient) {
2808
- const client = useQueryClient(queryClient);
2809
- const isRestoring = useIsRestoring();
2810
- const errorResetBoundary = useQueryErrorResetBoundary();
2811
- const defaultedQueries = React__namespace.useMemo(() => queries.map(opts => {
2812
- const defaultedOptions = client.defaultQueryOptions(opts);
2813
-
2814
- // Make sure the results are already in fetching state before subscribing or updating options
2815
- defaultedOptions._optimisticResults = isRestoring ? 'isRestoring' : 'optimistic';
2816
- return defaultedOptions;
2817
- }), [queries, client, isRestoring]);
2818
- defaultedQueries.forEach(query => {
2819
- ensureStaleTime(query);
2820
- ensurePreventErrorBoundaryRetry(query, errorResetBoundary);
2821
- });
2822
- useClearResetErrorBoundary(errorResetBoundary);
2823
- const [observer] = React__namespace.useState(() => new QueriesObserver(client, defaultedQueries, options));
2824
- const [optimisticResult, getCombinedResult, trackResult] = observer.getOptimisticResult(defaultedQueries);
2825
- React__namespace.useSyncExternalStore(React__namespace.useCallback(onStoreChange => isRestoring ? () => undefined : observer.subscribe(notifyManager.batchCalls(onStoreChange)), [observer, isRestoring]), () => observer.getCurrentResult(), () => observer.getCurrentResult());
2826
- React__namespace.useEffect(() => {
2827
- // Do not notify on updates because of changes in the options because
2828
- // these changes should already be reflected in the optimistic result.
2829
- observer.setQueries(defaultedQueries, options, {
2830
- listeners: false
2831
- });
2832
- }, [defaultedQueries, options, observer]);
2833
- const shouldAtLeastOneSuspend = optimisticResult.some((result, index) => shouldSuspend(defaultedQueries[index], result, isRestoring));
2834
- const suspensePromises = shouldAtLeastOneSuspend ? optimisticResult.flatMap((result, index) => {
2835
- const opts = defaultedQueries[index];
2836
- const queryObserver = observer.getObservers()[index];
2837
- if (opts && queryObserver) {
2838
- if (shouldSuspend(opts, result, isRestoring)) {
2839
- return fetchOptimistic(opts, queryObserver, errorResetBoundary);
2840
- } else if (willFetch(result, isRestoring)) {
2841
- void fetchOptimistic(opts, queryObserver, errorResetBoundary);
2842
- }
2843
- }
2844
- return [];
2845
- }) : [];
2846
- if (suspensePromises.length > 0) {
2847
- throw Promise.all(suspensePromises);
2848
- }
2849
- const observerQueries = observer.getQueries();
2850
- const firstSingleResultWhichShouldThrow = optimisticResult.find((result, index) => getHasError({
2851
- result,
2852
- errorResetBoundary,
2853
- throwOnError: defaultedQueries[index]?.throwOnError ?? false,
2854
- query: observerQueries[index]
2855
- }));
2856
- if (firstSingleResultWhichShouldThrow?.error) {
2857
- throw firstSingleResultWhichShouldThrow.error;
2858
- }
2859
- return getCombinedResult(trackResult());
2860
- }
2861
-
2862
- function useBaseQuery(options, Observer, queryClient) {
2863
- const client = useQueryClient(queryClient);
2864
- const isRestoring = useIsRestoring();
2865
- const errorResetBoundary = useQueryErrorResetBoundary();
2866
- const defaultedOptions = client.defaultQueryOptions(options);
2867
-
2868
- // Make sure results are optimistically set in fetching state before subscribing or updating options
2869
- defaultedOptions._optimisticResults = isRestoring ? 'isRestoring' : 'optimistic';
2870
- ensureStaleTime(defaultedOptions);
2871
- ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary);
2872
- useClearResetErrorBoundary(errorResetBoundary);
2873
- const [observer] = React__namespace.useState(() => new Observer(client, defaultedOptions));
2874
- const result = observer.getOptimisticResult(defaultedOptions);
2875
- React__namespace.useSyncExternalStore(React__namespace.useCallback(onStoreChange => isRestoring ? () => undefined : observer.subscribe(notifyManager.batchCalls(onStoreChange)), [observer, isRestoring]), () => observer.getCurrentResult(), () => observer.getCurrentResult());
2876
- React__namespace.useEffect(() => {
2877
- // Do not notify on updates because of changes in the options because
2878
- // these changes should already be reflected in the optimistic result.
2879
- observer.setOptions(defaultedOptions, {
2880
- listeners: false
2881
- });
2882
- }, [defaultedOptions, observer]);
2883
-
2884
- // Handle suspense
2885
- if (shouldSuspend(defaultedOptions, result, isRestoring)) {
2886
- throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary);
2887
- }
2888
-
2889
- // Handle error boundary
2890
- if (getHasError({
2891
- result,
2892
- errorResetBoundary,
2893
- throwOnError: defaultedOptions.throwOnError,
2894
- query: observer.getCurrentQuery()
2895
- })) {
2896
- throw result.error;
2897
- }
2898
-
2899
- // Handle result property usage tracking
2900
- return !defaultedOptions.notifyOnChangeProps ? observer.trackResult(result) : result;
2901
- }
2902
-
2903
- function queryOptions(options) {
2904
- return options;
2905
- }
2906
-
2907
- // HOOK
2908
-
2909
- function useQuery(options, queryClient) {
2910
- return useBaseQuery(options, QueryObserver, queryClient);
2911
- }
2912
-
2913
- const HydrationBoundary = ({
2914
- children,
2915
- options = {},
2916
- state,
2917
- queryClient
2918
- }) => {
2919
- const client = useQueryClient(queryClient);
2920
- const optionsRef = React__namespace.useRef(options);
2921
- optionsRef.current = options;
2922
-
2923
- // Running hydrate again with the same queries is safe,
2924
- // it wont overwrite or initialize existing queries,
2925
- // relying on useMemo here is only a performance optimization.
2926
- // hydrate can and should be run *during* render here for SSR to work properly
2927
- React__namespace.useMemo(() => {
2928
- if (state) {
2929
- hydrate(client, state, optionsRef.current);
2930
- }
2931
- }, [client, state]);
2932
- return children;
2933
- };
2934
-
2935
- function useIsFetching(filters, queryClient) {
2936
- const client = useQueryClient(queryClient);
2937
- const queryCache = client.getQueryCache();
2938
- return React__namespace.useSyncExternalStore(React__namespace.useCallback(onStoreChange => queryCache.subscribe(notifyManager.batchCalls(onStoreChange)), [queryCache]), () => client.isFetching(filters), () => client.isFetching(filters));
2939
- }
2940
-
2941
- function useIsMutating(filters, queryClient) {
2942
- const client = useQueryClient(queryClient);
2943
- return useMutationState({
2944
- filters: {
2945
- ...filters,
2946
- status: 'pending'
2947
- }
2948
- }, client).length;
2949
- }
2950
- function getResult(mutationCache, options) {
2951
- return mutationCache.findAll(options.filters).map(mutation => options.select ? options.select(mutation) : mutation.state);
2952
- }
2953
- function useMutationState(options = {}, queryClient) {
2954
- const mutationCache = useQueryClient(queryClient).getMutationCache();
2955
- const optionsRef = React__namespace.useRef(options);
2956
- const result = React__namespace.useRef();
2957
- if (!result.current) {
2958
- result.current = getResult(mutationCache, options);
2959
- }
2960
- React__namespace.useEffect(() => {
2961
- optionsRef.current = options;
2962
- });
2963
- return React__namespace.useSyncExternalStore(React__namespace.useCallback(onStoreChange => mutationCache.subscribe(() => {
2964
- const nextResult = replaceEqualDeep(result.current, getResult(mutationCache, optionsRef.current));
2965
- if (result.current !== nextResult) {
2966
- result.current = nextResult;
2967
- notifyManager.schedule(onStoreChange);
2968
- }
2969
- }), [mutationCache]), () => result.current, () => result.current);
2970
- }
2971
-
2972
- // HOOK
2973
-
2974
- function useMutation(options, queryClient) {
2975
- const client = useQueryClient(queryClient);
2976
- const [observer] = React__namespace.useState(() => new MutationObserver(client, options));
2977
- React__namespace.useEffect(() => {
2978
- observer.setOptions(options);
2979
- }, [observer, options]);
2980
- const result = React__namespace.useSyncExternalStore(React__namespace.useCallback(onStoreChange => observer.subscribe(notifyManager.batchCalls(onStoreChange)), [observer]), () => observer.getCurrentResult(), () => observer.getCurrentResult());
2981
- const mutate = React__namespace.useCallback((variables, mutateOptions) => {
2982
- observer.mutate(variables, mutateOptions).catch(noop);
2983
- }, [observer]);
2984
- if (result.error && shouldThrowError(observer.options.throwOnError, [result.error])) {
2985
- throw result.error;
2986
- }
2987
- return {
2988
- ...result,
2989
- mutate,
2990
- mutateAsync: result.mutate
2991
- };
2992
- }
2993
-
2994
- // eslint-disable-next-line @typescript-eslint/no-empty-function
2995
- function noop() {}
2996
-
2997
- // HOOK
2998
- function useInfiniteQuery(options, queryClient) {
2999
- return useBaseQuery(options,
3000
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
3001
- InfiniteQueryObserver, queryClient);
3002
- }
3003
-
3004
- exports.CancelledError = CancelledError;
3005
- exports.HydrationBoundary = HydrationBoundary;
3006
- exports.InfiniteQueryObserver = InfiniteQueryObserver;
3007
- exports.IsRestoringProvider = IsRestoringProvider;
3008
- exports.MutationCache = MutationCache;
3009
- exports.MutationObserver = MutationObserver;
3010
- exports.QueriesObserver = QueriesObserver;
3011
- exports.QueryCache = QueryCache;
3012
- exports.QueryClient = QueryClient;
3013
- exports.QueryClientContext = QueryClientContext;
3014
- exports.QueryClientProvider = QueryClientProvider;
3015
- exports.QueryErrorResetBoundary = QueryErrorResetBoundary;
3016
- exports.QueryObserver = QueryObserver;
3017
- exports.defaultShouldDehydrateMutation = defaultShouldDehydrateMutation;
3018
- exports.defaultShouldDehydrateQuery = defaultShouldDehydrateQuery;
3019
- exports.dehydrate = dehydrate;
3020
- exports.focusManager = focusManager;
3021
- exports.hashKey = hashKey;
3022
- exports.hydrate = hydrate;
3023
- exports.isCancelledError = isCancelledError;
3024
- exports.isServer = isServer;
3025
- exports.keepPreviousData = keepPreviousData;
3026
- exports.matchQuery = matchQuery;
3027
- exports.notifyManager = notifyManager;
3028
- exports.onlineManager = onlineManager;
3029
- exports.queryOptions = queryOptions;
3030
- exports.replaceEqualDeep = replaceEqualDeep;
3031
- exports.useInfiniteQuery = useInfiniteQuery;
3032
- exports.useIsFetching = useIsFetching;
3033
- exports.useIsMutating = useIsMutating;
3034
- exports.useIsRestoring = useIsRestoring;
3035
- exports.useMutation = useMutation;
3036
- exports.useMutationState = useMutationState;
3037
- exports.useQueries = useQueries;
3038
- exports.useQuery = useQuery;
3039
- exports.useQueryClient = useQueryClient;
3040
- exports.useQueryErrorResetBoundary = useQueryErrorResetBoundary;
3041
-
3042
- }));
3043
- //# sourceMappingURL=index.development.js.map