@tanstack/query-core 5.85.1 → 5.85.3

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 (87) hide show
  1. package/build/legacy/{hydration-Cvr-9VdO.d.ts → hydration-D0MPgBG9.d.ts} +4 -2
  2. package/build/legacy/{hydration-CADtEOkK.d.cts → hydration-QvU7ROZT.d.cts} +4 -2
  3. package/build/legacy/hydration.d.cts +1 -1
  4. package/build/legacy/hydration.d.ts +1 -1
  5. package/build/legacy/index.d.cts +1 -1
  6. package/build/legacy/index.d.ts +1 -1
  7. package/build/legacy/infiniteQueryBehavior.d.cts +1 -1
  8. package/build/legacy/infiniteQueryBehavior.d.ts +1 -1
  9. package/build/legacy/infiniteQueryObserver.d.cts +1 -1
  10. package/build/legacy/infiniteQueryObserver.d.ts +1 -1
  11. package/build/legacy/mutation.d.cts +1 -1
  12. package/build/legacy/mutation.d.ts +1 -1
  13. package/build/legacy/mutationCache.d.cts +1 -1
  14. package/build/legacy/mutationCache.d.ts +1 -1
  15. package/build/legacy/mutationObserver.d.cts +1 -1
  16. package/build/legacy/mutationObserver.d.ts +1 -1
  17. package/build/legacy/queriesObserver.d.cts +1 -1
  18. package/build/legacy/queriesObserver.d.ts +1 -1
  19. package/build/legacy/query.cjs +59 -60
  20. package/build/legacy/query.cjs.map +1 -1
  21. package/build/legacy/query.d.cts +1 -1
  22. package/build/legacy/query.d.ts +1 -1
  23. package/build/legacy/query.js +60 -61
  24. package/build/legacy/query.js.map +1 -1
  25. package/build/legacy/queryCache.d.cts +1 -1
  26. package/build/legacy/queryCache.d.ts +1 -1
  27. package/build/legacy/queryClient.d.cts +1 -1
  28. package/build/legacy/queryClient.d.ts +1 -1
  29. package/build/legacy/queryObserver.d.cts +1 -1
  30. package/build/legacy/queryObserver.d.ts +1 -1
  31. package/build/legacy/retryer.cjs +9 -14
  32. package/build/legacy/retryer.cjs.map +1 -1
  33. package/build/legacy/retryer.d.cts +1 -1
  34. package/build/legacy/retryer.d.ts +1 -1
  35. package/build/legacy/retryer.js +9 -14
  36. package/build/legacy/retryer.js.map +1 -1
  37. package/build/legacy/streamedQuery.d.cts +1 -1
  38. package/build/legacy/streamedQuery.d.ts +1 -1
  39. package/build/legacy/types.d.cts +1 -1
  40. package/build/legacy/types.d.ts +1 -1
  41. package/build/legacy/utils.d.cts +1 -1
  42. package/build/legacy/utils.d.ts +1 -1
  43. package/build/modern/{hydration-Cvr-9VdO.d.ts → hydration-D0MPgBG9.d.ts} +4 -2
  44. package/build/modern/{hydration-CADtEOkK.d.cts → hydration-QvU7ROZT.d.cts} +4 -2
  45. package/build/modern/hydration.d.cts +1 -1
  46. package/build/modern/hydration.d.ts +1 -1
  47. package/build/modern/index.d.cts +1 -1
  48. package/build/modern/index.d.ts +1 -1
  49. package/build/modern/infiniteQueryBehavior.d.cts +1 -1
  50. package/build/modern/infiniteQueryBehavior.d.ts +1 -1
  51. package/build/modern/infiniteQueryObserver.d.cts +1 -1
  52. package/build/modern/infiniteQueryObserver.d.ts +1 -1
  53. package/build/modern/mutation.d.cts +1 -1
  54. package/build/modern/mutation.d.ts +1 -1
  55. package/build/modern/mutationCache.d.cts +1 -1
  56. package/build/modern/mutationCache.d.ts +1 -1
  57. package/build/modern/mutationObserver.d.cts +1 -1
  58. package/build/modern/mutationObserver.d.ts +1 -1
  59. package/build/modern/queriesObserver.d.cts +1 -1
  60. package/build/modern/queriesObserver.d.ts +1 -1
  61. package/build/modern/query.cjs +52 -51
  62. package/build/modern/query.cjs.map +1 -1
  63. package/build/modern/query.d.cts +1 -1
  64. package/build/modern/query.d.ts +1 -1
  65. package/build/modern/query.js +53 -52
  66. package/build/modern/query.js.map +1 -1
  67. package/build/modern/queryCache.d.cts +1 -1
  68. package/build/modern/queryCache.d.ts +1 -1
  69. package/build/modern/queryClient.d.cts +1 -1
  70. package/build/modern/queryClient.d.ts +1 -1
  71. package/build/modern/queryObserver.d.cts +1 -1
  72. package/build/modern/queryObserver.d.ts +1 -1
  73. package/build/modern/retryer.cjs +9 -12
  74. package/build/modern/retryer.cjs.map +1 -1
  75. package/build/modern/retryer.d.cts +1 -1
  76. package/build/modern/retryer.d.ts +1 -1
  77. package/build/modern/retryer.js +9 -12
  78. package/build/modern/retryer.js.map +1 -1
  79. package/build/modern/streamedQuery.d.cts +1 -1
  80. package/build/modern/streamedQuery.d.ts +1 -1
  81. package/build/modern/types.d.cts +1 -1
  82. package/build/modern/types.d.ts +1 -1
  83. package/build/modern/utils.d.cts +1 -1
  84. package/build/modern/utils.d.ts +1 -1
  85. package/package.json +1 -1
  86. package/src/query.ts +68 -66
  87. package/src/retryer.ts +16 -14
@@ -1,3 +1,3 @@
1
- export { j as MutationFilters, l as QueryFilters, bk as QueryTypeFilter, S as SkipToken, U as Updater, bw as addToEnd, bx as addToStart, by as ensureQueryFn, bl as functionalUpdate, h as hashKey, bq as hashQueryKeyByOptions, bs as isPlainArray, bt as isPlainObject, i as isServer, bm as isValidTimeout, k as keepPreviousData, f as matchMutation, m as matchQuery, n as noop, p as partialMatchKey, bv as replaceData, r as replaceEqualDeep, bp as resolveEnabled, bo as resolveStaleTime, br as shallowEqualObjects, g as shouldThrowError, s as skipToken, bu as sleep, bn as timeUntilStale } from './hydration-Cvr-9VdO.js';
1
+ export { j as MutationFilters, l as QueryFilters, bk as QueryTypeFilter, S as SkipToken, U as Updater, bw as addToEnd, bx as addToStart, by as ensureQueryFn, bl as functionalUpdate, h as hashKey, bq as hashQueryKeyByOptions, bs as isPlainArray, bt as isPlainObject, i as isServer, bm as isValidTimeout, k as keepPreviousData, f as matchMutation, m as matchQuery, n as noop, p as partialMatchKey, bv as replaceData, r as replaceEqualDeep, bp as resolveEnabled, bo as resolveStaleTime, br as shallowEqualObjects, g as shouldThrowError, s as skipToken, bu as sleep, bn as timeUntilStale } from './hydration-D0MPgBG9.js';
2
2
  import './removable.js';
3
3
  import './subscribable.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/query-core",
3
- "version": "5.85.1",
3
+ "version": "5.85.3",
4
4
  "description": "The framework agnostic core that powers TanStack Query",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
package/src/query.ts CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  timeUntilStale,
9
9
  } from './utils'
10
10
  import { notifyManager } from './notifyManager'
11
- import { canFetch, createRetryer, isCancelledError } from './retryer'
11
+ import { CancelledError, canFetch, createRetryer } from './retryer'
12
12
  import { Removable } from './removable'
13
13
  import type { QueryCache } from './queryCache'
14
14
  import type { QueryClient } from './queryClient'
@@ -372,11 +372,17 @@ export class Query<
372
372
  }
373
373
  }
374
374
 
375
- fetch(
375
+ async fetch(
376
376
  options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,
377
377
  fetchOptions?: FetchOptions<TQueryFnData>,
378
378
  ): Promise<TData> {
379
- if (this.state.fetchStatus !== 'idle') {
379
+ if (
380
+ this.state.fetchStatus !== 'idle' &&
381
+ // If the promise in the retyer is already rejected, we have to definitely
382
+ // re-start the fetch; there is a chance that the query is still in a
383
+ // pending state when that happens
384
+ this.#retryer?.status() !== 'rejected'
385
+ ) {
380
386
  if (this.state.data !== undefined && fetchOptions?.cancelRefetch) {
381
387
  // Silently cancel current fetch if the user wants to cancel refetch
382
388
  this.cancel({ silent: true })
@@ -495,32 +501,6 @@ export class Query<
495
501
  this.#dispatch({ type: 'fetch', meta: context.fetchOptions?.meta })
496
502
  }
497
503
 
498
- const onError = (error: TError | { silent?: boolean }) => {
499
- // Optimistically update state if needed
500
- if (!(isCancelledError(error) && error.silent)) {
501
- this.#dispatch({
502
- type: 'error',
503
- error: error as TError,
504
- })
505
- }
506
-
507
- if (!isCancelledError(error)) {
508
- // Notify cache callback
509
- this.#cache.config.onError?.(
510
- error as any,
511
- this as Query<any, any, any, any>,
512
- )
513
- this.#cache.config.onSettled?.(
514
- this.state.data,
515
- error as any,
516
- this as Query<any, any, any, any>,
517
- )
518
- }
519
-
520
- // Schedule query gc after fetching
521
- this.scheduleGc()
522
- }
523
-
524
504
  // Try to fetch the data
525
505
  this.#retryer = createRetryer({
526
506
  initialPromise: fetchOptions?.initialPromise as
@@ -528,36 +508,6 @@ export class Query<
528
508
  | undefined,
529
509
  fn: context.fetchFn as () => Promise<TData>,
530
510
  abort: abortController.abort.bind(abortController),
531
- onSuccess: (data) => {
532
- if (data === undefined) {
533
- if (process.env.NODE_ENV !== 'production') {
534
- console.error(
535
- `Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`,
536
- )
537
- }
538
- onError(new Error(`${this.queryHash} data is undefined`) as any)
539
- return
540
- }
541
-
542
- try {
543
- this.setData(data)
544
- } catch (error) {
545
- onError(error as TError)
546
- return
547
- }
548
-
549
- // Notify cache callback
550
- this.#cache.config.onSuccess?.(data, this as Query<any, any, any, any>)
551
- this.#cache.config.onSettled?.(
552
- data,
553
- this.state.error as any,
554
- this as Query<any, any, any, any>,
555
- )
556
-
557
- // Schedule query gc after fetching
558
- this.scheduleGc()
559
- },
560
- onError,
561
511
  onFail: (failureCount, error) => {
562
512
  this.#dispatch({ type: 'failed', failureCount, error })
563
513
  },
@@ -573,7 +523,65 @@ export class Query<
573
523
  canRun: () => true,
574
524
  })
575
525
 
576
- return this.#retryer.start()
526
+ try {
527
+ const data = await this.#retryer.start()
528
+ // this is more of a runtime guard
529
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
530
+ if (data === undefined) {
531
+ if (process.env.NODE_ENV !== 'production') {
532
+ console.error(
533
+ `Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`,
534
+ )
535
+ }
536
+ throw new Error(`${this.queryHash} data is undefined`)
537
+ }
538
+
539
+ this.setData(data)
540
+
541
+ // Notify cache callback
542
+ this.#cache.config.onSuccess?.(data, this as Query<any, any, any, any>)
543
+ this.#cache.config.onSettled?.(
544
+ data,
545
+ this.state.error as any,
546
+ this as Query<any, any, any, any>,
547
+ )
548
+ return data
549
+ } catch (error) {
550
+ if (error instanceof CancelledError) {
551
+ if (error.silent) {
552
+ // silent cancellation implies a new fetch is going to be started,
553
+ // so we hatch onto that promise
554
+ return this.#retryer.promise
555
+ } else if (error.revert) {
556
+ this.setState({
557
+ ...this.#revertState,
558
+ fetchStatus: 'idle' as const,
559
+ })
560
+ // transform error into reverted state data
561
+ return this.state.data!
562
+ }
563
+ }
564
+ this.#dispatch({
565
+ type: 'error',
566
+ error: error as TError,
567
+ })
568
+
569
+ // Notify cache callback
570
+ this.#cache.config.onError?.(
571
+ error as any,
572
+ this as Query<any, any, any, any>,
573
+ )
574
+ this.#cache.config.onSettled?.(
575
+ this.state.data,
576
+ error as any,
577
+ this as Query<any, any, any, any>,
578
+ )
579
+
580
+ throw error // rethrow the error for further handling
581
+ } finally {
582
+ // Schedule query gc after fetching
583
+ this.scheduleGc()
584
+ }
577
585
  }
578
586
 
579
587
  #dispatch(action: Action<TData, TError>): void {
@@ -618,7 +626,6 @@ export class Query<
618
626
  fetchFailureReason: null,
619
627
  }),
620
628
  }
621
-
622
629
  // If fetching ends successfully, we don't need revertState as a fallback anymore.
623
630
  // For manual updates, capture the state to revert to it in case of a cancellation.
624
631
  this.#revertState = action.manual ? newState : undefined
@@ -626,11 +633,6 @@ export class Query<
626
633
  return newState
627
634
  case 'error':
628
635
  const error = action.error
629
-
630
- if (isCancelledError(error) && error.revert && this.#revertState) {
631
- return { ...this.#revertState, fetchStatus: 'idle' }
632
- }
633
-
634
636
  return {
635
637
  ...state,
636
638
  error,
package/src/retryer.ts CHANGED
@@ -2,6 +2,7 @@ import { focusManager } from './focusManager'
2
2
  import { onlineManager } from './onlineManager'
3
3
  import { pendingThenable } from './thenable'
4
4
  import { isServer, sleep } from './utils'
5
+ import type { Thenable } from './thenable'
5
6
  import type { CancelOptions, DefaultError, NetworkMode } from './types'
6
7
 
7
8
  // TYPES
@@ -10,8 +11,6 @@ interface RetryerConfig<TData = unknown, TError = DefaultError> {
10
11
  fn: () => TData | Promise<TData>
11
12
  initialPromise?: Promise<TData>
12
13
  abort?: () => void
13
- onError?: (error: TError) => void
14
- onSuccess?: (data: TData) => void
15
14
  onFail?: (failureCount: number, error: TError) => void
16
15
  onPause?: () => void
17
16
  onContinue?: () => void
@@ -29,6 +28,7 @@ export interface Retryer<TData = unknown> {
29
28
  continueRetry: () => void
30
29
  canStart: () => boolean
31
30
  start: () => Promise<TData>
31
+ status: () => 'pending' | 'resolved' | 'rejected'
32
32
  }
33
33
 
34
34
  export type RetryValue<TError> = boolean | number | ShouldRetryFunction<TError>
@@ -65,6 +65,9 @@ export class CancelledError extends Error {
65
65
  }
66
66
  }
67
67
 
68
+ /**
69
+ * @deprecated Use instanceof `CancelledError` instead.
70
+ */
68
71
  export function isCancelledError(value: any): value is CancelledError {
69
72
  return value instanceof CancelledError
70
73
  }
@@ -74,13 +77,15 @@ export function createRetryer<TData = unknown, TError = DefaultError>(
74
77
  ): Retryer<TData> {
75
78
  let isRetryCancelled = false
76
79
  let failureCount = 0
77
- let isResolved = false
78
80
  let continueFn: ((value?: unknown) => void) | undefined
79
81
 
80
82
  const thenable = pendingThenable<TData>()
81
83
 
84
+ const isResolved = () =>
85
+ (thenable.status as Thenable<TData>['status']) !== 'pending'
86
+
82
87
  const cancel = (cancelOptions?: CancelOptions): void => {
83
- if (!isResolved) {
88
+ if (!isResolved()) {
84
89
  reject(new CancelledError(cancelOptions))
85
90
 
86
91
  config.abort?.()
@@ -102,18 +107,14 @@ export function createRetryer<TData = unknown, TError = DefaultError>(
102
107
  const canStart = () => canFetch(config.networkMode) && config.canRun()
103
108
 
104
109
  const resolve = (value: any) => {
105
- if (!isResolved) {
106
- isResolved = true
107
- config.onSuccess?.(value)
110
+ if (!isResolved()) {
108
111
  continueFn?.()
109
112
  thenable.resolve(value)
110
113
  }
111
114
  }
112
115
 
113
116
  const reject = (value: any) => {
114
- if (!isResolved) {
115
- isResolved = true
116
- config.onError?.(value)
117
+ if (!isResolved()) {
117
118
  continueFn?.()
118
119
  thenable.reject(value)
119
120
  }
@@ -122,14 +123,14 @@ export function createRetryer<TData = unknown, TError = DefaultError>(
122
123
  const pause = () => {
123
124
  return new Promise((continueResolve) => {
124
125
  continueFn = (value) => {
125
- if (isResolved || canContinue()) {
126
+ if (isResolved() || canContinue()) {
126
127
  continueResolve(value)
127
128
  }
128
129
  }
129
130
  config.onPause?.()
130
131
  }).then(() => {
131
132
  continueFn = undefined
132
- if (!isResolved) {
133
+ if (!isResolved()) {
133
134
  config.onContinue?.()
134
135
  }
135
136
  })
@@ -138,7 +139,7 @@ export function createRetryer<TData = unknown, TError = DefaultError>(
138
139
  // Create loop function
139
140
  const run = () => {
140
141
  // Do nothing if already resolved
141
- if (isResolved) {
142
+ if (isResolved()) {
142
143
  return
143
144
  }
144
145
 
@@ -159,7 +160,7 @@ export function createRetryer<TData = unknown, TError = DefaultError>(
159
160
  .then(resolve)
160
161
  .catch((error) => {
161
162
  // Stop if the fetch is already resolved
162
- if (isResolved) {
163
+ if (isResolved()) {
163
164
  return
164
165
  }
165
166
 
@@ -204,6 +205,7 @@ export function createRetryer<TData = unknown, TError = DefaultError>(
204
205
 
205
206
  return {
206
207
  promise: thenable,
208
+ status: () => thenable.status,
207
209
  cancel,
208
210
  continue: () => {
209
211
  continueFn?.()