@tanstack/query-core 5.83.1 → 5.87.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/build/legacy/{hydration-Cvr-9VdO.d.ts → hydration-BYonJkjc.d.ts} +8 -6
  2. package/build/legacy/{hydration-CADtEOkK.d.cts → hydration-_hO-y142.d.cts} +8 -6
  3. package/build/legacy/hydration.d.cts +1 -1
  4. package/build/legacy/hydration.d.ts +1 -1
  5. package/build/legacy/index.cjs +14 -12
  6. package/build/legacy/index.cjs.map +1 -1
  7. package/build/legacy/index.d.cts +5 -4
  8. package/build/legacy/index.d.ts +5 -4
  9. package/build/legacy/index.js +26 -23
  10. package/build/legacy/index.js.map +1 -1
  11. package/build/legacy/infiniteQueryBehavior.d.cts +1 -1
  12. package/build/legacy/infiniteQueryBehavior.d.ts +1 -1
  13. package/build/legacy/infiniteQueryObserver.d.cts +1 -1
  14. package/build/legacy/infiniteQueryObserver.d.ts +1 -1
  15. package/build/legacy/mutation.d.cts +1 -1
  16. package/build/legacy/mutation.d.ts +1 -1
  17. package/build/legacy/mutationCache.d.cts +1 -1
  18. package/build/legacy/mutationCache.d.ts +1 -1
  19. package/build/legacy/mutationObserver.d.cts +1 -1
  20. package/build/legacy/mutationObserver.d.ts +1 -1
  21. package/build/legacy/notifyManager.cjs +2 -1
  22. package/build/legacy/notifyManager.cjs.map +1 -1
  23. package/build/legacy/notifyManager.js +2 -1
  24. package/build/legacy/notifyManager.js.map +1 -1
  25. package/build/legacy/queriesObserver.cjs +19 -13
  26. package/build/legacy/queriesObserver.cjs.map +1 -1
  27. package/build/legacy/queriesObserver.d.cts +1 -1
  28. package/build/legacy/queriesObserver.d.ts +1 -1
  29. package/build/legacy/queriesObserver.js +20 -14
  30. package/build/legacy/queriesObserver.js.map +1 -1
  31. package/build/legacy/query.cjs +78 -61
  32. package/build/legacy/query.cjs.map +1 -1
  33. package/build/legacy/query.d.cts +1 -1
  34. package/build/legacy/query.d.ts +1 -1
  35. package/build/legacy/query.js +79 -62
  36. package/build/legacy/query.js.map +1 -1
  37. package/build/legacy/queryCache.d.cts +1 -1
  38. package/build/legacy/queryCache.d.ts +1 -1
  39. package/build/legacy/queryClient.d.cts +1 -1
  40. package/build/legacy/queryClient.d.ts +1 -1
  41. package/build/legacy/queryObserver.cjs +12 -9
  42. package/build/legacy/queryObserver.cjs.map +1 -1
  43. package/build/legacy/queryObserver.d.cts +1 -1
  44. package/build/legacy/queryObserver.d.ts +1 -1
  45. package/build/legacy/queryObserver.js +12 -9
  46. package/build/legacy/queryObserver.js.map +1 -1
  47. package/build/legacy/removable.cjs +3 -2
  48. package/build/legacy/removable.cjs.map +1 -1
  49. package/build/legacy/removable.js +3 -2
  50. package/build/legacy/removable.js.map +1 -1
  51. package/build/legacy/retryer.cjs +12 -16
  52. package/build/legacy/retryer.cjs.map +1 -1
  53. package/build/legacy/retryer.d.cts +1 -1
  54. package/build/legacy/retryer.d.ts +1 -1
  55. package/build/legacy/retryer.js +12 -16
  56. package/build/legacy/retryer.js.map +1 -1
  57. package/build/legacy/streamedQuery.cjs +7 -8
  58. package/build/legacy/streamedQuery.cjs.map +1 -1
  59. package/build/legacy/streamedQuery.d.cts +18 -10
  60. package/build/legacy/streamedQuery.d.ts +18 -10
  61. package/build/legacy/streamedQuery.js +7 -8
  62. package/build/legacy/streamedQuery.js.map +1 -1
  63. package/build/legacy/timeoutManager.cjs +110 -0
  64. package/build/legacy/timeoutManager.cjs.map +1 -0
  65. package/build/legacy/timeoutManager.d.cts +58 -0
  66. package/build/legacy/timeoutManager.d.ts +58 -0
  67. package/build/legacy/timeoutManager.js +81 -0
  68. package/build/legacy/timeoutManager.js.map +1 -0
  69. package/build/legacy/types.d.cts +1 -1
  70. package/build/legacy/types.d.ts +1 -1
  71. package/build/legacy/utils.cjs +26 -22
  72. package/build/legacy/utils.cjs.map +1 -1
  73. package/build/legacy/utils.d.cts +1 -1
  74. package/build/legacy/utils.d.ts +1 -1
  75. package/build/legacy/utils.js +26 -22
  76. package/build/legacy/utils.js.map +1 -1
  77. package/build/modern/{hydration-Cvr-9VdO.d.ts → hydration-BYonJkjc.d.ts} +8 -6
  78. package/build/modern/{hydration-CADtEOkK.d.cts → hydration-_hO-y142.d.cts} +8 -6
  79. package/build/modern/hydration.d.cts +1 -1
  80. package/build/modern/hydration.d.ts +1 -1
  81. package/build/modern/index.cjs +14 -12
  82. package/build/modern/index.cjs.map +1 -1
  83. package/build/modern/index.d.cts +5 -4
  84. package/build/modern/index.d.ts +5 -4
  85. package/build/modern/index.js +26 -23
  86. package/build/modern/index.js.map +1 -1
  87. package/build/modern/infiniteQueryBehavior.d.cts +1 -1
  88. package/build/modern/infiniteQueryBehavior.d.ts +1 -1
  89. package/build/modern/infiniteQueryObserver.d.cts +1 -1
  90. package/build/modern/infiniteQueryObserver.d.ts +1 -1
  91. package/build/modern/mutation.d.cts +1 -1
  92. package/build/modern/mutation.d.ts +1 -1
  93. package/build/modern/mutationCache.d.cts +1 -1
  94. package/build/modern/mutationCache.d.ts +1 -1
  95. package/build/modern/mutationObserver.d.cts +1 -1
  96. package/build/modern/mutationObserver.d.ts +1 -1
  97. package/build/modern/notifyManager.cjs +2 -1
  98. package/build/modern/notifyManager.cjs.map +1 -1
  99. package/build/modern/notifyManager.js +2 -1
  100. package/build/modern/notifyManager.js.map +1 -1
  101. package/build/modern/queriesObserver.cjs +19 -13
  102. package/build/modern/queriesObserver.cjs.map +1 -1
  103. package/build/modern/queriesObserver.d.cts +1 -1
  104. package/build/modern/queriesObserver.d.ts +1 -1
  105. package/build/modern/queriesObserver.js +20 -14
  106. package/build/modern/queriesObserver.js.map +1 -1
  107. package/build/modern/query.cjs +71 -52
  108. package/build/modern/query.cjs.map +1 -1
  109. package/build/modern/query.d.cts +1 -1
  110. package/build/modern/query.d.ts +1 -1
  111. package/build/modern/query.js +72 -53
  112. package/build/modern/query.js.map +1 -1
  113. package/build/modern/queryCache.d.cts +1 -1
  114. package/build/modern/queryCache.d.ts +1 -1
  115. package/build/modern/queryClient.d.cts +1 -1
  116. package/build/modern/queryClient.d.ts +1 -1
  117. package/build/modern/queryObserver.cjs +12 -9
  118. package/build/modern/queryObserver.cjs.map +1 -1
  119. package/build/modern/queryObserver.d.cts +1 -1
  120. package/build/modern/queryObserver.d.ts +1 -1
  121. package/build/modern/queryObserver.js +12 -9
  122. package/build/modern/queryObserver.js.map +1 -1
  123. package/build/modern/removable.cjs +3 -2
  124. package/build/modern/removable.cjs.map +1 -1
  125. package/build/modern/removable.js +3 -2
  126. package/build/modern/removable.js.map +1 -1
  127. package/build/modern/retryer.cjs +12 -14
  128. package/build/modern/retryer.cjs.map +1 -1
  129. package/build/modern/retryer.d.cts +1 -1
  130. package/build/modern/retryer.d.ts +1 -1
  131. package/build/modern/retryer.js +12 -14
  132. package/build/modern/retryer.js.map +1 -1
  133. package/build/modern/streamedQuery.cjs +7 -8
  134. package/build/modern/streamedQuery.cjs.map +1 -1
  135. package/build/modern/streamedQuery.d.cts +18 -10
  136. package/build/modern/streamedQuery.d.ts +18 -10
  137. package/build/modern/streamedQuery.js +7 -8
  138. package/build/modern/streamedQuery.js.map +1 -1
  139. package/build/modern/timeoutManager.cjs +98 -0
  140. package/build/modern/timeoutManager.cjs.map +1 -0
  141. package/build/modern/timeoutManager.d.cts +58 -0
  142. package/build/modern/timeoutManager.d.ts +58 -0
  143. package/build/modern/timeoutManager.js +70 -0
  144. package/build/modern/timeoutManager.js.map +1 -0
  145. package/build/modern/types.d.cts +1 -1
  146. package/build/modern/types.d.ts +1 -1
  147. package/build/modern/utils.cjs +26 -22
  148. package/build/modern/utils.cjs.map +1 -1
  149. package/build/modern/utils.d.cts +1 -1
  150. package/build/modern/utils.d.ts +1 -1
  151. package/build/modern/utils.js +26 -22
  152. package/build/modern/utils.js.map +1 -1
  153. package/package.json +1 -1
  154. package/src/index.ts +32 -27
  155. package/src/notifyManager.ts +3 -1
  156. package/src/queriesObserver.ts +24 -15
  157. package/src/query.ts +96 -69
  158. package/src/queryObserver.ts +19 -11
  159. package/src/removable.ts +5 -3
  160. package/src/retryer.ts +20 -17
  161. package/src/streamedQuery.ts +47 -23
  162. package/src/timeoutManager.ts +135 -0
  163. package/src/utils.ts +39 -31
@@ -0,0 +1,135 @@
1
+ /**
2
+ * {@link TimeoutManager} does not support passing arguments to the callback.
3
+ *
4
+ * `(_: void)` is the argument type inferred by TypeScript's default typings for
5
+ * `setTimeout(cb, number)`.
6
+ * If we don't accept a single void argument, then
7
+ * `new Promise(resolve => timeoutManager.setTimeout(resolve, N))` is a type error.
8
+ */
9
+ export type TimeoutCallback = (_: void) => void
10
+
11
+ /**
12
+ * Wrapping `setTimeout` is awkward from a typing perspective because platform
13
+ * typings may extend the return type of `setTimeout`. For example, NodeJS
14
+ * typings add `NodeJS.Timeout`; but a non-default `timeoutManager` may not be
15
+ * able to return such a type.
16
+ */
17
+ export type ManagedTimerId = number | { [Symbol.toPrimitive]: () => number }
18
+
19
+ /**
20
+ * Backend for timer functions.
21
+ */
22
+ export type TimeoutProvider<TTimerId extends ManagedTimerId = ManagedTimerId> =
23
+ {
24
+ readonly setTimeout: (callback: TimeoutCallback, delay: number) => TTimerId
25
+ readonly clearTimeout: (timeoutId: TTimerId | undefined) => void
26
+
27
+ readonly setInterval: (callback: TimeoutCallback, delay: number) => TTimerId
28
+ readonly clearInterval: (intervalId: TTimerId | undefined) => void
29
+ }
30
+
31
+ export const defaultTimeoutProvider: TimeoutProvider<
32
+ ReturnType<typeof setTimeout>
33
+ > = {
34
+ // We need the wrapper function syntax below instead of direct references to
35
+ // global setTimeout etc.
36
+ //
37
+ // BAD: `setTimeout: setTimeout`
38
+ // GOOD: `setTimeout: (cb, delay) => setTimeout(cb, delay)`
39
+ //
40
+ // If we use direct references here, then anything that wants to spy on or
41
+ // replace the global setTimeout (like tests) won't work since we'll already
42
+ // have a hard reference to the original implementation at the time when this
43
+ // file was imported.
44
+ setTimeout: (callback, delay) => setTimeout(callback, delay),
45
+ clearTimeout: (timeoutId) => clearTimeout(timeoutId),
46
+
47
+ setInterval: (callback, delay) => setInterval(callback, delay),
48
+ clearInterval: (intervalId) => clearInterval(intervalId),
49
+ }
50
+
51
+ /**
52
+ * Allows customization of how timeouts are created.
53
+ *
54
+ * @tanstack/query-core makes liberal use of timeouts to implement `staleTime`
55
+ * and `gcTime`. The default TimeoutManager provider uses the platform's global
56
+ * `setTimeout` implementation, which is known to have scalability issues with
57
+ * thousands of timeouts on the event loop.
58
+ *
59
+ * If you hit this limitation, consider providing a custom TimeoutProvider that
60
+ * coalesces timeouts.
61
+ */
62
+ export class TimeoutManager implements Omit<TimeoutProvider, 'name'> {
63
+ // We cannot have TimeoutManager<T> as we must instantiate it with a concrete
64
+ // type at app boot; and if we leave that type, then any new timer provider
65
+ // would need to support ReturnType<typeof setTimeout>, which is infeasible.
66
+ //
67
+ // We settle for type safety for the TimeoutProvider type, and accept that
68
+ // this class is unsafe internally to allow for extension.
69
+ #provider: TimeoutProvider<any> = defaultTimeoutProvider
70
+ #providerCalled = false
71
+
72
+ setTimeoutProvider<TTimerId extends ManagedTimerId>(
73
+ provider: TimeoutProvider<TTimerId>,
74
+ ): void {
75
+ if (process.env.NODE_ENV !== 'production') {
76
+ if (this.#providerCalled && provider !== this.#provider) {
77
+ // After changing providers, `clearTimeout` will not work as expected for
78
+ // timeouts from the previous provider.
79
+ //
80
+ // Since they may allocate the same timeout ID, clearTimeout may cancel an
81
+ // arbitrary different timeout, or unexpected no-op.
82
+ //
83
+ // We could protect against this by mixing the timeout ID bits
84
+ // deterministically with some per-provider bits.
85
+ //
86
+ // We could internally queue `setTimeout` calls to `TimeoutManager` until
87
+ // some API call to set the initial provider.
88
+ console.error(
89
+ `[timeoutManager]: Switching provider after calls to previous provider might result in unexpected behavior.`,
90
+ { previous: this.#provider, provider },
91
+ )
92
+ }
93
+ }
94
+
95
+ this.#provider = provider
96
+ if (process.env.NODE_ENV !== 'production') {
97
+ this.#providerCalled = false
98
+ }
99
+ }
100
+
101
+ setTimeout(callback: TimeoutCallback, delay: number): ManagedTimerId {
102
+ if (process.env.NODE_ENV !== 'production') {
103
+ this.#providerCalled = true
104
+ }
105
+ return this.#provider.setTimeout(callback, delay)
106
+ }
107
+
108
+ clearTimeout(timeoutId: ManagedTimerId | undefined): void {
109
+ this.#provider.clearTimeout(timeoutId)
110
+ }
111
+
112
+ setInterval(callback: TimeoutCallback, delay: number): ManagedTimerId {
113
+ if (process.env.NODE_ENV !== 'production') {
114
+ this.#providerCalled = true
115
+ }
116
+ return this.#provider.setInterval(callback, delay)
117
+ }
118
+
119
+ clearInterval(intervalId: ManagedTimerId | undefined): void {
120
+ this.#provider.clearInterval(intervalId)
121
+ }
122
+ }
123
+
124
+ export const timeoutManager = new TimeoutManager()
125
+
126
+ /**
127
+ * In many cases code wants to delay to the next event loop tick; this is not
128
+ * mediated by {@link timeoutManager}.
129
+ *
130
+ * This function is provided to make auditing the `tanstack/query-core` for
131
+ * incorrect use of system `setTimeout` easier.
132
+ */
133
+ export function systemSetTimeoutZero(callback: TimeoutCallback): void {
134
+ setTimeout(callback, 0)
135
+ }
package/src/utils.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { timeoutManager } from './timeoutManager'
1
2
  import type {
2
3
  DefaultError,
3
4
  Enabled,
@@ -245,6 +246,8 @@ export function partialMatchKey(a: any, b: any): boolean {
245
246
  return false
246
247
  }
247
248
 
249
+ const hasOwn = Object.prototype.hasOwnProperty
250
+
248
251
  /**
249
252
  * This function returns `a` if `b` is deeply equal.
250
253
  * If not, it will replace any deeply equal children of `b` with those of `a`.
@@ -258,37 +261,43 @@ export function replaceEqualDeep(a: any, b: any): any {
258
261
 
259
262
  const array = isPlainArray(a) && isPlainArray(b)
260
263
 
261
- if (array || (isPlainObject(a) && isPlainObject(b))) {
262
- const aItems = array ? a : Object.keys(a)
263
- const aSize = aItems.length
264
- const bItems = array ? b : Object.keys(b)
265
- const bSize = bItems.length
266
- const copy: any = array ? [] : {}
267
- const aItemsSet = new Set(aItems)
268
-
269
- let equalItems = 0
270
-
271
- for (let i = 0; i < bSize; i++) {
272
- const key = array ? i : bItems[i]
273
- if (
274
- ((!array && aItemsSet.has(key)) || array) &&
275
- a[key] === undefined &&
276
- b[key] === undefined
277
- ) {
278
- copy[key] = undefined
279
- equalItems++
280
- } else {
281
- copy[key] = replaceEqualDeep(a[key], b[key])
282
- if (copy[key] === a[key] && a[key] !== undefined) {
283
- equalItems++
284
- }
285
- }
264
+ if (!array && !(isPlainObject(a) && isPlainObject(b))) return b
265
+
266
+ const aItems = array ? a : Object.keys(a)
267
+ const aSize = aItems.length
268
+ const bItems = array ? b : Object.keys(b)
269
+ const bSize = bItems.length
270
+ const copy: any = array ? new Array(bSize) : {}
271
+
272
+ let equalItems = 0
273
+
274
+ for (let i = 0; i < bSize; i++) {
275
+ const key: any = array ? i : bItems[i]
276
+ const aItem = a[key]
277
+ const bItem = b[key]
278
+
279
+ if (aItem === bItem) {
280
+ copy[key] = aItem
281
+ if (array ? i < aSize : hasOwn.call(a, key)) equalItems++
282
+ continue
283
+ }
284
+
285
+ if (
286
+ aItem === null ||
287
+ bItem === null ||
288
+ typeof aItem !== 'object' ||
289
+ typeof bItem !== 'object'
290
+ ) {
291
+ copy[key] = bItem
292
+ continue
286
293
  }
287
294
 
288
- return aSize === bSize && equalItems === aSize ? a : copy
295
+ const v = replaceEqualDeep(aItem, bItem)
296
+ copy[key] = v
297
+ if (v === aItem) equalItems++
289
298
  }
290
299
 
291
- return b
300
+ return aSize === bSize && equalItems === aSize ? a : copy
292
301
  }
293
302
 
294
303
  /**
@@ -311,13 +320,12 @@ export function shallowEqualObjects<T extends Record<string, any>>(
311
320
  return true
312
321
  }
313
322
 
314
- export function isPlainArray(value: unknown) {
323
+ export function isPlainArray(value: unknown): value is Array<unknown> {
315
324
  return Array.isArray(value) && value.length === Object.keys(value).length
316
325
  }
317
326
 
318
327
  // Copied from: https://github.com/jonschlinkert/is-plain-object
319
- // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
320
- export function isPlainObject(o: any): o is Object {
328
+ export function isPlainObject(o: any): o is Record<PropertyKey, unknown> {
321
329
  if (!hasObjectPrototype(o)) {
322
330
  return false
323
331
  }
@@ -354,7 +362,7 @@ function hasObjectPrototype(o: any): boolean {
354
362
 
355
363
  export function sleep(timeout: number): Promise<void> {
356
364
  return new Promise((resolve) => {
357
- setTimeout(resolve, timeout)
365
+ timeoutManager.setTimeout(resolve, timeout)
358
366
  })
359
367
  }
360
368