@tanstack/query-core 5.0.0-alpha.2 → 5.0.0-alpha.21

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 (135) hide show
  1. package/build/lib/_virtual/_rollupPluginBabelHelpers.esm.js +13 -0
  2. package/build/lib/_virtual/_rollupPluginBabelHelpers.esm.js.map +1 -0
  3. package/build/lib/_virtual/_rollupPluginBabelHelpers.js +16 -0
  4. package/build/lib/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
  5. package/build/lib/focusManager.esm.js +31 -15
  6. package/build/lib/focusManager.esm.js.map +1 -1
  7. package/build/lib/focusManager.js +31 -15
  8. package/build/lib/focusManager.js.map +1 -1
  9. package/build/lib/hydration.d.ts +2 -6
  10. package/build/lib/hydration.esm.js +9 -20
  11. package/build/lib/hydration.esm.js.map +1 -1
  12. package/build/lib/hydration.js +9 -20
  13. package/build/lib/hydration.js.map +1 -1
  14. package/build/lib/hydration.mjs +4 -18
  15. package/build/lib/hydration.mjs.map +1 -1
  16. package/build/lib/index.d.ts +3 -3
  17. package/build/lib/infiniteQueryBehavior.d.ts +2 -2
  18. package/build/lib/infiniteQueryBehavior.esm.js +52 -48
  19. package/build/lib/infiniteQueryBehavior.esm.js.map +1 -1
  20. package/build/lib/infiniteQueryBehavior.js +52 -48
  21. package/build/lib/infiniteQueryBehavior.js.map +1 -1
  22. package/build/lib/infiniteQueryBehavior.mjs +48 -45
  23. package/build/lib/infiniteQueryBehavior.mjs.map +1 -1
  24. package/build/lib/infiniteQueryObserver.d.ts +6 -6
  25. package/build/lib/infiniteQueryObserver.esm.js +7 -8
  26. package/build/lib/infiniteQueryObserver.esm.js.map +1 -1
  27. package/build/lib/infiniteQueryObserver.js +7 -8
  28. package/build/lib/infiniteQueryObserver.js.map +1 -1
  29. package/build/lib/infiniteQueryObserver.mjs +4 -6
  30. package/build/lib/infiniteQueryObserver.mjs.map +1 -1
  31. package/build/lib/mutation.d.ts +2 -1
  32. package/build/lib/mutation.esm.js +134 -101
  33. package/build/lib/mutation.esm.js.map +1 -1
  34. package/build/lib/mutation.js +134 -101
  35. package/build/lib/mutation.js.map +1 -1
  36. package/build/lib/mutation.mjs +10 -2
  37. package/build/lib/mutation.mjs.map +1 -1
  38. package/build/lib/mutationCache.d.ts +2 -2
  39. package/build/lib/mutationCache.esm.js +34 -20
  40. package/build/lib/mutationCache.esm.js.map +1 -1
  41. package/build/lib/mutationCache.js +34 -20
  42. package/build/lib/mutationCache.js.map +1 -1
  43. package/build/lib/mutationCache.mjs +5 -4
  44. package/build/lib/mutationCache.mjs.map +1 -1
  45. package/build/lib/mutationObserver.esm.js +81 -50
  46. package/build/lib/mutationObserver.esm.js.map +1 -1
  47. package/build/lib/mutationObserver.js +81 -50
  48. package/build/lib/mutationObserver.js.map +1 -1
  49. package/build/lib/mutationObserver.mjs +1 -0
  50. package/build/lib/mutationObserver.mjs.map +1 -1
  51. package/build/lib/onlineManager.esm.js +29 -14
  52. package/build/lib/onlineManager.esm.js.map +1 -1
  53. package/build/lib/onlineManager.js +29 -14
  54. package/build/lib/onlineManager.js.map +1 -1
  55. package/build/lib/queriesObserver.esm.js +95 -65
  56. package/build/lib/queriesObserver.esm.js.map +1 -1
  57. package/build/lib/queriesObserver.js +95 -65
  58. package/build/lib/queriesObserver.js.map +1 -1
  59. package/build/lib/queriesObserver.mjs +4 -3
  60. package/build/lib/queriesObserver.mjs.map +1 -1
  61. package/build/lib/query.d.ts +4 -3
  62. package/build/lib/query.esm.js +210 -161
  63. package/build/lib/query.esm.js.map +1 -1
  64. package/build/lib/query.js +210 -161
  65. package/build/lib/query.js.map +1 -1
  66. package/build/lib/query.mjs +1 -1
  67. package/build/lib/query.mjs.map +1 -1
  68. package/build/lib/queryCache.d.ts +2 -2
  69. package/build/lib/queryCache.esm.js +21 -13
  70. package/build/lib/queryCache.esm.js.map +1 -1
  71. package/build/lib/queryCache.js +21 -13
  72. package/build/lib/queryCache.js.map +1 -1
  73. package/build/lib/queryCache.mjs +5 -4
  74. package/build/lib/queryCache.mjs.map +1 -1
  75. package/build/lib/queryClient.esm.js +107 -66
  76. package/build/lib/queryClient.esm.js.map +1 -1
  77. package/build/lib/queryClient.js +107 -66
  78. package/build/lib/queryClient.js.map +1 -1
  79. package/build/lib/queryClient.mjs +5 -4
  80. package/build/lib/queryClient.mjs.map +1 -1
  81. package/build/lib/queryObserver.d.ts +2 -4
  82. package/build/lib/queryObserver.esm.js +299 -211
  83. package/build/lib/queryObserver.esm.js.map +1 -1
  84. package/build/lib/queryObserver.js +297 -209
  85. package/build/lib/queryObserver.js.map +1 -1
  86. package/build/lib/queryObserver.mjs +11 -23
  87. package/build/lib/queryObserver.mjs.map +1 -1
  88. package/build/lib/removable.esm.js +13 -6
  89. package/build/lib/removable.esm.js.map +1 -1
  90. package/build/lib/removable.js +13 -6
  91. package/build/lib/removable.js.map +1 -1
  92. package/build/lib/retryer.esm.js +15 -14
  93. package/build/lib/retryer.esm.js.map +1 -1
  94. package/build/lib/retryer.js +15 -14
  95. package/build/lib/retryer.js.map +1 -1
  96. package/build/lib/tests/utils.d.ts +4 -5
  97. package/build/lib/types.d.ts +5 -15
  98. package/build/lib/utils.esm.js +1 -1
  99. package/build/lib/utils.esm.js.map +1 -1
  100. package/build/lib/utils.js +1 -1
  101. package/build/lib/utils.js.map +1 -1
  102. package/build/umd/index.development.js +97 -109
  103. package/build/umd/index.development.js.map +1 -1
  104. package/build/umd/index.production.js +1 -1
  105. package/build/umd/index.production.js.map +1 -1
  106. package/package.json +2 -2
  107. package/src/hydration.ts +18 -37
  108. package/src/index.ts +2 -4
  109. package/src/infiniteQueryBehavior.ts +52 -60
  110. package/src/infiniteQueryObserver.ts +15 -10
  111. package/src/mutation.ts +14 -5
  112. package/src/mutationCache.ts +6 -6
  113. package/src/mutationObserver.ts +1 -0
  114. package/src/queriesObserver.ts +8 -8
  115. package/src/query.ts +13 -8
  116. package/src/queryCache.ts +9 -8
  117. package/src/queryClient.ts +2 -4
  118. package/src/queryObserver.ts +17 -31
  119. package/src/tests/focusManager.test.tsx +12 -14
  120. package/src/tests/hydration.test.tsx +22 -17
  121. package/src/tests/infiniteQueryBehavior.test.tsx +16 -9
  122. package/src/tests/infiniteQueryObserver.test.tsx +62 -1
  123. package/src/tests/mutationCache.test.tsx +11 -10
  124. package/src/tests/mutationObserver.test.tsx +3 -2
  125. package/src/tests/mutations.test.tsx +41 -9
  126. package/src/tests/notifyManager.test.tsx +7 -6
  127. package/src/tests/onlineManager.test.tsx +12 -17
  128. package/src/tests/queriesObserver.test.tsx +18 -17
  129. package/src/tests/query.test.tsx +18 -17
  130. package/src/tests/queryCache.test.tsx +14 -13
  131. package/src/tests/queryClient.test.tsx +49 -48
  132. package/src/tests/queryObserver.test.tsx +65 -9
  133. package/src/tests/utils.test.tsx +2 -1
  134. package/src/tests/utils.ts +5 -4
  135. package/src/types.ts +9 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/query-core",
3
- "version": "5.0.0-alpha.2",
3
+ "version": "5.0.0-alpha.21",
4
4
  "description": "The framework agnostic core that powers TanStack Query",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -31,7 +31,7 @@
31
31
  "clean": "rimraf ./build",
32
32
  "test:eslint": "eslint --ext .ts,.tsx ./src",
33
33
  "test:types": "tsc",
34
- "test:lib": "jest --config ./jest.config.ts",
34
+ "test:lib": "vitest run --coverage",
35
35
  "test:lib:dev": "pnpm run test:lib --watch",
36
36
  "build:types": "tsc --build"
37
37
  }
package/src/hydration.ts CHANGED
@@ -11,10 +11,8 @@ import type { Mutation, MutationState } from './mutation'
11
11
  // TYPES
12
12
 
13
13
  export interface DehydrateOptions {
14
- dehydrateMutations?: boolean
15
- dehydrateQueries?: boolean
16
- shouldDehydrateMutation?: ShouldDehydrateMutationFunction
17
- shouldDehydrateQuery?: ShouldDehydrateQueryFunction
14
+ shouldDehydrateMutation?: (mutation: Mutation) => boolean
15
+ shouldDehydrateQuery?: (query: Query) => boolean
18
16
  }
19
17
 
20
18
  export interface HydrateOptions {
@@ -40,10 +38,6 @@ export interface DehydratedState {
40
38
  queries: DehydratedQuery[]
41
39
  }
42
40
 
43
- export type ShouldDehydrateQueryFunction = (query: Query) => boolean
44
-
45
- export type ShouldDehydrateMutationFunction = (mutation: Mutation) => boolean
46
-
47
41
  // FUNCTIONS
48
42
 
49
43
  function dehydrateMutation(mutation: Mutation): DehydratedMutation {
@@ -77,36 +71,23 @@ export function dehydrate(
77
71
  client: QueryClient,
78
72
  options: DehydrateOptions = {},
79
73
  ): DehydratedState {
80
- const mutations: DehydratedMutation[] = []
81
- const queries: DehydratedQuery[] = []
82
-
83
- if (options.dehydrateMutations !== false) {
84
- const shouldDehydrateMutation =
85
- options.shouldDehydrateMutation || defaultShouldDehydrateMutation
86
-
87
- client
88
- .getMutationCache()
89
- .getAll()
90
- .forEach((mutation) => {
91
- if (shouldDehydrateMutation(mutation)) {
92
- mutations.push(dehydrateMutation(mutation))
93
- }
94
- })
95
- }
74
+ const filterMutation =
75
+ options.shouldDehydrateMutation ?? defaultShouldDehydrateMutation
76
+
77
+ const mutations = client
78
+ .getMutationCache()
79
+ .getAll()
80
+ .flatMap((mutation) =>
81
+ filterMutation(mutation) ? [dehydrateMutation(mutation)] : [],
82
+ )
96
83
 
97
- if (options.dehydrateQueries !== false) {
98
- const shouldDehydrateQuery =
99
- options.shouldDehydrateQuery || defaultShouldDehydrateQuery
100
-
101
- client
102
- .getQueryCache()
103
- .getAll()
104
- .forEach((query) => {
105
- if (shouldDehydrateQuery(query)) {
106
- queries.push(dehydrateQuery(query))
107
- }
108
- })
109
- }
84
+ const filterQuery =
85
+ options.shouldDehydrateQuery ?? defaultShouldDehydrateQuery
86
+
87
+ const queries = client
88
+ .getQueryCache()
89
+ .getAll()
90
+ .flatMap((query) => (filterQuery(query) ? [dehydrateQuery(query)] : []))
110
91
 
111
92
  return { mutations, queries }
112
93
  }
package/src/index.ts CHANGED
@@ -23,18 +23,16 @@ export { isCancelledError } from './retryer'
23
23
  export {
24
24
  dehydrate,
25
25
  hydrate,
26
- defaultShouldDehydrateMutation,
27
26
  defaultShouldDehydrateQuery,
27
+ defaultShouldDehydrateMutation,
28
28
  } from './hydration'
29
29
 
30
30
  // Types
31
31
  export * from './types'
32
32
  export type { Query, QueryState } from './query'
33
- export type { Mutation } from './mutation'
33
+ export type { Mutation, MutationState } from './mutation'
34
34
  export type {
35
35
  DehydrateOptions,
36
36
  DehydratedState,
37
37
  HydrateOptions,
38
- ShouldDehydrateMutationFunction,
39
- ShouldDehydrateQueryFunction,
40
38
  } from './hydration'
@@ -14,12 +14,12 @@ export function infiniteQueryBehavior<
14
14
  >(): QueryBehavior<TQueryFnData, TError, InfiniteData<TData>> {
15
15
  return {
16
16
  onFetch: (context) => {
17
- context.fetchFn = () => {
17
+ context.fetchFn = async () => {
18
18
  const options = context.options as InfiniteQueryPageParamsOptions<TData>
19
19
  const direction = context.fetchOptions?.meta?.fetchMore?.direction
20
20
  const oldPages = context.state.data?.pages || []
21
21
  const oldPageParams = context.state.data?.pageParams || []
22
- let newPageParams = oldPageParams
22
+ const empty = { pages: [], pageParams: [] }
23
23
  let cancelled = false
24
24
 
25
25
  const addSignalProperty = (object: unknown) => {
@@ -43,35 +43,18 @@ export function infiniteQueryBehavior<
43
43
  context.options.queryFn ||
44
44
  (() => Promise.reject(new Error('Missing queryFn')))
45
45
 
46
- const buildNewPages = (
47
- pages: unknown[],
48
- param: unknown,
49
- page: unknown,
50
- previous?: boolean,
51
- ) => {
52
- const { maxPages } = context.options
53
-
54
- if (previous) {
55
- newPageParams = addToStart(newPageParams, param, maxPages)
56
- return addToStart(pages, page, maxPages)
57
- }
58
-
59
- newPageParams = addToEnd(newPageParams, param, maxPages)
60
- return addToEnd(pages, page, maxPages)
61
- }
62
-
63
46
  // Create function to fetch a page
64
- const fetchPage = (
65
- pages: unknown[],
47
+ const fetchPage = async (
48
+ data: InfiniteData<unknown>,
66
49
  param: unknown,
67
50
  previous?: boolean,
68
- ): Promise<unknown[]> => {
51
+ ): Promise<InfiniteData<unknown>> => {
69
52
  if (cancelled) {
70
53
  return Promise.reject()
71
54
  }
72
55
 
73
- if (typeof param === 'undefined' && pages.length) {
74
- return Promise.resolve(pages)
56
+ if (typeof param === 'undefined' && data.pages.length) {
57
+ return Promise.resolve(data)
75
58
  }
76
59
 
77
60
  const queryFnContext: Omit<
@@ -80,60 +63,58 @@ export function infiniteQueryBehavior<
80
63
  > = {
81
64
  queryKey: context.queryKey,
82
65
  pageParam: param,
66
+ direction: previous ? 'backward' : 'forward',
83
67
  meta: context.options.meta,
84
68
  }
85
69
 
86
70
  addSignalProperty(queryFnContext)
87
71
 
88
- const queryFnResult = queryFn(
72
+ const page = await queryFn(
89
73
  queryFnContext as QueryFunctionContext<QueryKey, unknown>,
90
74
  )
91
75
 
92
- const promise = Promise.resolve(queryFnResult).then((page) =>
93
- buildNewPages(pages, param, page, previous),
94
- )
76
+ const { maxPages } = context.options
77
+ const addTo = previous ? addToStart : addToEnd
95
78
 
96
- return promise
79
+ return {
80
+ pages: addTo(data.pages, page, maxPages),
81
+ pageParams: addTo(data.pageParams, param, maxPages),
82
+ }
97
83
  }
98
84
 
99
- let promise: Promise<unknown[]>
85
+ let result: InfiniteData<unknown>
100
86
 
101
87
  // Fetch first page?
102
88
  if (!oldPages.length) {
103
- promise = fetchPage([], options.defaultPageParam)
89
+ result = await fetchPage(empty, options.defaultPageParam)
104
90
  }
105
91
 
106
92
  // fetch next / previous page?
107
93
  else if (direction) {
108
94
  const previous = direction === 'backward'
109
- const param = previous
110
- ? getPreviousPageParam(options, oldPages)
111
- : getNextPageParam(options, oldPages)
112
- promise = fetchPage(oldPages, param, previous)
95
+ const pageParamFn = previous ? getPreviousPageParam : getNextPageParam
96
+ const oldData = {
97
+ pages: oldPages,
98
+ pageParams: oldPageParams,
99
+ }
100
+ const param = pageParamFn(options, oldData)
101
+
102
+ result = await fetchPage(oldData, param, previous)
113
103
  }
114
104
 
115
105
  // Refetch pages
116
106
  else {
117
- newPageParams = []
118
-
119
107
  // Fetch first page
120
- promise = fetchPage([], oldPageParams[0])
108
+ result = await fetchPage(empty, oldPageParams[0])
121
109
 
122
110
  // Fetch remaining pages
123
111
  for (let i = 1; i < oldPages.length; i++) {
124
- promise = promise.then((pages) => {
125
- const param = getNextPageParam(options, pages)
126
- return fetchPage(pages, param)
127
- })
112
+ const param = getNextPageParam(options, result)
113
+ result = await fetchPage(result, param)
128
114
  }
129
115
  }
130
116
 
131
- const finalPromise = promise.then((pages) => ({
132
- pages,
133
- pageParams: newPageParams,
134
- }))
135
-
136
- return finalPromise
117
+ return result
137
118
  }
138
119
  },
139
120
  }
@@ -141,36 +122,47 @@ export function infiniteQueryBehavior<
141
122
 
142
123
  function getNextPageParam(
143
124
  options: InfiniteQueryPageParamsOptions<any>,
144
- pages: unknown[],
125
+ { pages, pageParams }: InfiniteData<unknown>,
145
126
  ): unknown | undefined {
146
- return options.getNextPageParam(pages[pages.length - 1], pages)
127
+ const lastIndex = pages.length - 1
128
+ return options.getNextPageParam(
129
+ pages[lastIndex],
130
+ pages,
131
+ pageParams[lastIndex],
132
+ pageParams,
133
+ )
147
134
  }
148
135
 
149
136
  function getPreviousPageParam(
150
137
  options: InfiniteQueryPageParamsOptions<any>,
151
- pages: unknown[],
138
+ { pages, pageParams }: InfiniteData<unknown>,
152
139
  ): unknown | undefined {
153
- return options.getPreviousPageParam?.(pages[0], pages)
140
+ return options.getPreviousPageParam?.(
141
+ pages[0],
142
+ pages,
143
+ pageParams[0],
144
+ pageParams,
145
+ )
154
146
  }
155
147
 
156
148
  /**
157
149
  * Checks if there is a next page.
158
150
  */
159
151
  export function hasNextPage(
160
- options: InfiniteQueryPageParamsOptions<any>,
161
- pages?: unknown[],
152
+ options: InfiniteQueryPageParamsOptions<any, any>,
153
+ data?: InfiniteData<unknown>,
162
154
  ): boolean {
163
- if (!pages) return false
164
- return typeof getNextPageParam(options, pages) !== 'undefined'
155
+ if (!data) return false
156
+ return typeof getNextPageParam(options, data) !== 'undefined'
165
157
  }
166
158
 
167
159
  /**
168
160
  * Checks if there is a previous page.
169
161
  */
170
162
  export function hasPreviousPage(
171
- options: InfiniteQueryPageParamsOptions<any>,
172
- pages?: unknown[],
163
+ options: InfiniteQueryPageParamsOptions<any, any>,
164
+ data?: InfiniteData<unknown>,
173
165
  ): boolean {
174
- if (!pages || !options.getPreviousPageParam) return false
175
- return typeof getPreviousPageParam(options, pages) !== 'undefined'
166
+ if (!data || !options.getPreviousPageParam) return false
167
+ return typeof getPreviousPageParam(options, data) !== 'undefined'
176
168
  }
@@ -28,6 +28,7 @@ export class InfiniteQueryObserver<
28
28
  TData = InfiniteData<TQueryFnData>,
29
29
  TQueryData = TQueryFnData,
30
30
  TQueryKey extends QueryKey = QueryKey,
31
+ TPageParam = unknown,
31
32
  > extends QueryObserver<
32
33
  TQueryFnData,
33
34
  TError,
@@ -56,7 +57,8 @@ export class InfiniteQueryObserver<
56
57
  TError,
57
58
  TData,
58
59
  TQueryData,
59
- TQueryKey
60
+ TQueryKey,
61
+ TPageParam
60
62
  >,
61
63
  ) {
62
64
  super(client, options)
@@ -74,7 +76,8 @@ export class InfiniteQueryObserver<
74
76
  TError,
75
77
  TData,
76
78
  TQueryData,
77
- TQueryKey
79
+ TQueryKey,
80
+ TPageParam
78
81
  >,
79
82
  notifyOptions?: NotifyOptions,
80
83
  ): void {
@@ -93,7 +96,8 @@ export class InfiniteQueryObserver<
93
96
  TError,
94
97
  TData,
95
98
  TQueryData,
96
- TQueryKey
99
+ TQueryKey,
100
+ TPageParam
97
101
  >,
98
102
  ): InfiniteQueryObserverResult<TData, TError> {
99
103
  options.behavior = infiniteQueryBehavior()
@@ -104,7 +108,7 @@ export class InfiniteQueryObserver<
104
108
  }
105
109
 
106
110
  fetchNextPage(
107
- options: FetchNextPageOptions = {},
111
+ options?: FetchNextPageOptions,
108
112
  ): Promise<InfiniteQueryObserverResult<TData, TError>> {
109
113
  return this.fetch({
110
114
  ...options,
@@ -114,9 +118,9 @@ export class InfiniteQueryObserver<
114
118
  })
115
119
  }
116
120
 
117
- fetchPreviousPage({ ...options }: FetchPreviousPageOptions = {}): Promise<
118
- InfiniteQueryObserverResult<TData, TError>
119
- > {
121
+ fetchPreviousPage(
122
+ options?: FetchPreviousPageOptions,
123
+ ): Promise<InfiniteQueryObserverResult<TData, TError>> {
120
124
  return this.fetch({
121
125
  ...options,
122
126
  meta: {
@@ -132,7 +136,8 @@ export class InfiniteQueryObserver<
132
136
  TError,
133
137
  TData,
134
138
  TQueryData,
135
- TQueryKey
139
+ TQueryKey,
140
+ TPageParam
136
141
  >,
137
142
  ): InfiniteQueryObserverResult<TData, TError> {
138
143
  const { state } = query
@@ -150,8 +155,8 @@ export class InfiniteQueryObserver<
150
155
  ...result,
151
156
  fetchNextPage: this.fetchNextPage,
152
157
  fetchPreviousPage: this.fetchPreviousPage,
153
- hasNextPage: hasNextPage(options, state.data?.pages),
154
- hasPreviousPage: hasPreviousPage(options, state.data?.pages),
158
+ hasNextPage: hasNextPage(options, state.data),
159
+ hasPreviousPage: hasPreviousPage(options, state.data),
155
160
  isFetchingNextPage,
156
161
  isFetchingPreviousPage,
157
162
  isRefetching:
package/src/mutation.ts CHANGED
@@ -85,26 +85,35 @@ export class Mutation<
85
85
  TContext = unknown,
86
86
  > extends Removable {
87
87
  state: MutationState<TData, TError, TVariables, TContext>
88
- readonly options: MutationOptions<TData, TError, TVariables, TContext>
88
+ options!: MutationOptions<TData, TError, TVariables, TContext>
89
89
  readonly mutationId: number
90
90
 
91
91
  #observers: MutationObserver<TData, TError, TVariables, TContext>[]
92
+ #defaultOptions?: MutationOptions<TData, TError, TVariables, TContext>
92
93
  #mutationCache: MutationCache
93
94
  #retryer?: Retryer<TData>
94
95
 
95
96
  constructor(config: MutationConfig<TData, TError, TVariables, TContext>) {
96
97
  super()
97
98
 
98
- this.options = config.options
99
99
  this.mutationId = config.mutationId
100
+ this.#defaultOptions = config.defaultOptions
100
101
  this.#mutationCache = config.mutationCache
101
102
  this.#observers = []
102
103
  this.state = config.state || getDefaultState()
103
104
 
104
- this.updateGcTime(this.options.gcTime)
105
+ this.setOptions(config.options)
105
106
  this.scheduleGc()
106
107
  }
107
108
 
109
+ setOptions(
110
+ options?: MutationOptions<TData, TError, TVariables, TContext>,
111
+ ): void {
112
+ this.options = { ...this.#defaultOptions, ...options }
113
+
114
+ this.updateGcTime(this.options.gcTime)
115
+ }
116
+
108
117
  get meta(): MutationMeta | undefined {
109
118
  return this.options.meta
110
119
  }
@@ -228,7 +237,7 @@ export class Mutation<
228
237
  try {
229
238
  // Notify cache callback
230
239
  await this.#mutationCache.config.onError?.(
231
- error,
240
+ error as any,
232
241
  variables,
233
242
  this.state.context,
234
243
  this as Mutation<unknown, unknown, unknown, unknown>,
@@ -243,7 +252,7 @@ export class Mutation<
243
252
  // Notify cache callback
244
253
  await this.#mutationCache.config.onSettled?.(
245
254
  undefined,
246
- error,
255
+ error as any,
247
256
  this.state.variables,
248
257
  this.state.context,
249
258
  this as Mutation<unknown, unknown, unknown, unknown>,
@@ -12,7 +12,7 @@ import { Subscribable } from './subscribable'
12
12
 
13
13
  interface MutationCacheConfig {
14
14
  onError?: (
15
- error: unknown,
15
+ error: DefaultError,
16
16
  variables: unknown,
17
17
  context: unknown,
18
18
  mutation: Mutation<unknown, unknown, unknown>,
@@ -29,7 +29,7 @@ interface MutationCacheConfig {
29
29
  ) => Promise<unknown> | unknown
30
30
  onSettled?: (
31
31
  data: unknown | undefined,
32
- error: unknown | null,
32
+ error: DefaultError | null,
33
33
  variables: unknown,
34
34
  context: unknown,
35
35
  mutation: Mutation<unknown, unknown, unknown>,
@@ -139,11 +139,11 @@ export class MutationCache extends Subscribable<MutationCacheListener> {
139
139
  >(
140
140
  filters: MutationFilters,
141
141
  ): Mutation<TData, TError, TVariables, TContext> | undefined {
142
- if (typeof filters.exact === 'undefined') {
143
- filters.exact = true
144
- }
142
+ const defaultedFilters = { exact: true, ...filters }
145
143
 
146
- return this.#mutations.find((mutation) => matchMutation(filters, mutation))
144
+ return this.#mutations.find((mutation) =>
145
+ matchMutation(defaultedFilters, mutation),
146
+ )
147
147
  }
148
148
 
149
149
  findAll(filters: MutationFilters = {}): Mutation[] {
@@ -64,6 +64,7 @@ export class MutationObserver<
64
64
  observer: this,
65
65
  })
66
66
  }
67
+ this.#currentMutation?.setOptions(this.options)
67
68
  }
68
69
 
69
70
  protected onUnsubscribe(): void {
@@ -134,28 +134,28 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
134
134
  queries: QueryObserverOptions[],
135
135
  ): QueryObserverMatch[] {
136
136
  const prevObservers = this.#observers
137
+ const prevObserversMap = new Map(
138
+ prevObservers.map((observer) => [observer.options.queryHash, observer]),
139
+ )
140
+
137
141
  const defaultedQueryOptions = queries.map((options) =>
138
142
  this.#client.defaultQueryOptions(options),
139
143
  )
140
144
 
141
145
  const matchingObservers: QueryObserverMatch[] =
142
146
  defaultedQueryOptions.flatMap((defaultedOptions) => {
143
- const match = prevObservers.find(
144
- (observer) =>
145
- observer.options.queryHash === defaultedOptions.queryHash,
146
- )
147
+ const match = prevObserversMap.get(defaultedOptions.queryHash)
147
148
  if (match != null) {
148
149
  return [{ defaultedQueryOptions: defaultedOptions, observer: match }]
149
150
  }
150
151
  return []
151
152
  })
152
153
 
153
- const matchedQueryHashes = matchingObservers.map(
154
- (match) => match.defaultedQueryOptions.queryHash,
154
+ const matchedQueryHashes = new Set(
155
+ matchingObservers.map((match) => match.defaultedQueryOptions.queryHash),
155
156
  )
156
157
  const unmatchedQueries = defaultedQueryOptions.filter(
157
- (defaultedOptions) =>
158
- !matchedQueryHashes.includes(defaultedOptions.queryHash),
158
+ (defaultedOptions) => !matchedQueryHashes.has(defaultedOptions.queryHash),
159
159
  )
160
160
 
161
161
  const getObserver = (options: QueryObserverOptions): QueryObserver => {
package/src/query.ts CHANGED
@@ -74,8 +74,10 @@ export interface QueryBehavior<
74
74
  ) => void
75
75
  }
76
76
 
77
+ export type FetchDirection = 'forward' | 'backward'
78
+
77
79
  export interface FetchMeta {
78
- fetchMore?: { direction: 'forward' | 'backward' }
80
+ fetchMore?: { direction: FetchDirection }
79
81
  }
80
82
 
81
83
  export interface FetchOptions {
@@ -120,7 +122,7 @@ interface ContinueAction {
120
122
 
121
123
  interface SetStateAction<TData, TError> {
122
124
  type: 'setState'
123
- state: QueryState<TData, TError>
125
+ state: Partial<QueryState<TData, TError>>
124
126
  setStateOptions?: SetStateOptions
125
127
  }
126
128
 
@@ -211,7 +213,7 @@ export class Query<
211
213
  }
212
214
 
213
215
  setState(
214
- state: QueryState<TData, TError>,
216
+ state: Partial<QueryState<TData, TError>>,
215
217
  setStateOptions?: SetStateOptions,
216
218
  ): void {
217
219
  this.#dispatch({ type: 'setState', state, setStateOptions })
@@ -433,10 +435,13 @@ export class Query<
433
435
 
434
436
  if (!isCancelledError(error)) {
435
437
  // Notify cache callback
436
- this.#cache.config.onError?.(error, this as Query<any, any, any, any>)
438
+ this.#cache.config.onError?.(
439
+ error as any,
440
+ this as Query<any, any, any, any>,
441
+ )
437
442
  this.#cache.config.onSettled?.(
438
443
  this.state.data,
439
- error,
444
+ error as any,
440
445
  this as Query<any, any, any, any>,
441
446
  )
442
447
  }
@@ -450,7 +455,7 @@ export class Query<
450
455
 
451
456
  // Try to fetch the data
452
457
  this.#retryer = createRetryer({
453
- fn: context.fetchFn as () => TData,
458
+ fn: context.fetchFn as () => Promise<TData>,
454
459
  abort: abortController.abort.bind(abortController),
455
460
  onSuccess: (data) => {
456
461
  if (typeof data === 'undefined') {
@@ -469,7 +474,7 @@ export class Query<
469
474
  this.#cache.config.onSuccess?.(data, this as Query<any, any, any, any>)
470
475
  this.#cache.config.onSettled?.(
471
476
  data,
472
- this.state.error,
477
+ this.state.error as any,
473
478
  this as Query<any, any, any, any>,
474
479
  )
475
480
 
@@ -583,7 +588,7 @@ export class Query<
583
588
 
584
589
  notifyManager.batch(() => {
585
590
  this.#observers.forEach((observer) => {
586
- observer.onQueryUpdate(action)
591
+ observer.onQueryUpdate()
587
592
  })
588
593
 
589
594
  this.#cache.notify({ query: this, type: 'updated', action })
package/src/queryCache.ts CHANGED
@@ -17,11 +17,14 @@ import type { QueryObserver } from './queryObserver'
17
17
  // TYPES
18
18
 
19
19
  interface QueryCacheConfig {
20
- onError?: (error: unknown, query: Query<unknown, unknown, unknown>) => void
20
+ onError?: (
21
+ error: DefaultError,
22
+ query: Query<unknown, unknown, unknown>,
23
+ ) => void
21
24
  onSuccess?: (data: unknown, query: Query<unknown, unknown, unknown>) => void
22
25
  onSettled?: (
23
26
  data: unknown | undefined,
24
- error: unknown | null,
27
+ error: DefaultError | null,
25
28
  query: Query<unknown, unknown, unknown>,
26
29
  ) => void
27
30
  createStore?: () => QueryStore
@@ -173,13 +176,11 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
173
176
  find<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData>(
174
177
  filters: WithRequired<QueryFilters, 'queryKey'>,
175
178
  ): Query<TQueryFnData, TError, TData> | undefined {
176
- if (typeof filters.exact === 'undefined') {
177
- filters.exact = true
178
- }
179
+ const defaultedFilters = { exact: true, ...filters }
179
180
 
180
- return this.getAll().find((query) => matchQuery(filters, query)) as
181
- | Query<TQueryFnData, TError, TData>
182
- | undefined
181
+ return this.getAll().find((query) =>
182
+ matchQuery(defaultedFilters, query),
183
+ ) as Query<TQueryFnData, TError, TData> | undefined
183
184
  }
184
185
 
185
186
  findAll(filters: QueryFilters = {}): Query[] {
@@ -212,14 +212,12 @@ export class QueryClient {
212
212
  filters: QueryFilters = {},
213
213
  cancelOptions: CancelOptions = {},
214
214
  ): Promise<void> {
215
- if (typeof cancelOptions.revert === 'undefined') {
216
- cancelOptions.revert = true
217
- }
215
+ const defaultedCancelOptions = { revert: true, ...cancelOptions }
218
216
 
219
217
  const promises = notifyManager.batch(() =>
220
218
  this.#queryCache
221
219
  .findAll(filters)
222
- .map((query) => query.cancel(cancelOptions)),
220
+ .map((query) => query.cancel(defaultedCancelOptions)),
223
221
  )
224
222
 
225
223
  return Promise.all(promises).then(noop).catch(noop)