@tanstack/query-core 5.48.0 → 5.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/legacy/focusManager.cjs.map +1 -1
- package/build/legacy/focusManager.js.map +1 -1
- package/build/legacy/{hydration-CTf4vERU.d.ts → hydration-ByKLEQMr.d.ts} +3 -1
- package/build/legacy/{hydration-Cm3oOWor.d.cts → hydration-DfqGmvZi.d.cts} +3 -1
- package/build/legacy/hydration.cjs +32 -15
- package/build/legacy/hydration.cjs.map +1 -1
- package/build/legacy/hydration.d.cts +1 -1
- package/build/legacy/hydration.d.ts +1 -1
- package/build/legacy/hydration.js +32 -15
- package/build/legacy/hydration.js.map +1 -1
- package/build/legacy/index.d.cts +1 -1
- package/build/legacy/index.d.ts +1 -1
- package/build/legacy/infiniteQueryBehavior.d.cts +1 -1
- package/build/legacy/infiniteQueryBehavior.d.ts +1 -1
- package/build/legacy/infiniteQueryObserver.d.cts +1 -1
- package/build/legacy/infiniteQueryObserver.d.ts +1 -1
- package/build/legacy/mutation.d.cts +1 -1
- package/build/legacy/mutation.d.ts +1 -1
- package/build/legacy/mutationCache.d.cts +1 -1
- package/build/legacy/mutationCache.d.ts +1 -1
- package/build/legacy/mutationObserver.d.cts +1 -1
- package/build/legacy/mutationObserver.d.ts +1 -1
- package/build/legacy/onlineManager.cjs.map +1 -1
- package/build/legacy/onlineManager.js.map +1 -1
- package/build/legacy/queriesObserver.d.cts +1 -1
- package/build/legacy/queriesObserver.d.ts +1 -1
- package/build/legacy/query.d.cts +1 -1
- package/build/legacy/query.d.ts +1 -1
- package/build/legacy/queryCache.d.cts +1 -1
- package/build/legacy/queryCache.d.ts +1 -1
- package/build/legacy/queryClient.cjs.map +1 -1
- package/build/legacy/queryClient.d.cts +1 -1
- package/build/legacy/queryClient.d.ts +1 -1
- package/build/legacy/queryClient.js.map +1 -1
- package/build/legacy/queryObserver.d.cts +1 -1
- package/build/legacy/queryObserver.d.ts +1 -1
- package/build/legacy/retryer.d.cts +1 -1
- package/build/legacy/retryer.d.ts +1 -1
- package/build/legacy/types.d.cts +1 -1
- package/build/legacy/types.d.ts +1 -1
- package/build/legacy/utils.d.cts +1 -1
- package/build/legacy/utils.d.ts +1 -1
- package/build/modern/focusManager.cjs.map +1 -1
- package/build/modern/focusManager.js.map +1 -1
- package/build/modern/{hydration-CTf4vERU.d.ts → hydration-ByKLEQMr.d.ts} +3 -1
- package/build/modern/{hydration-Cm3oOWor.d.cts → hydration-DfqGmvZi.d.cts} +3 -1
- package/build/modern/hydration.cjs +24 -8
- package/build/modern/hydration.cjs.map +1 -1
- package/build/modern/hydration.d.cts +1 -1
- package/build/modern/hydration.d.ts +1 -1
- package/build/modern/hydration.js +24 -8
- package/build/modern/hydration.js.map +1 -1
- package/build/modern/index.d.cts +1 -1
- package/build/modern/index.d.ts +1 -1
- package/build/modern/infiniteQueryBehavior.d.cts +1 -1
- package/build/modern/infiniteQueryBehavior.d.ts +1 -1
- package/build/modern/infiniteQueryObserver.d.cts +1 -1
- package/build/modern/infiniteQueryObserver.d.ts +1 -1
- package/build/modern/mutation.d.cts +1 -1
- package/build/modern/mutation.d.ts +1 -1
- package/build/modern/mutationCache.d.cts +1 -1
- package/build/modern/mutationCache.d.ts +1 -1
- package/build/modern/mutationObserver.d.cts +1 -1
- package/build/modern/mutationObserver.d.ts +1 -1
- package/build/modern/onlineManager.cjs.map +1 -1
- package/build/modern/onlineManager.js.map +1 -1
- package/build/modern/queriesObserver.d.cts +1 -1
- package/build/modern/queriesObserver.d.ts +1 -1
- package/build/modern/query.d.cts +1 -1
- package/build/modern/query.d.ts +1 -1
- package/build/modern/queryCache.d.cts +1 -1
- package/build/modern/queryCache.d.ts +1 -1
- package/build/modern/queryClient.cjs.map +1 -1
- package/build/modern/queryClient.d.cts +1 -1
- package/build/modern/queryClient.d.ts +1 -1
- package/build/modern/queryClient.js.map +1 -1
- package/build/modern/queryObserver.d.cts +1 -1
- package/build/modern/queryObserver.d.ts +1 -1
- package/build/modern/retryer.d.cts +1 -1
- package/build/modern/retryer.d.ts +1 -1
- package/build/modern/types.d.cts +1 -1
- package/build/modern/types.d.ts +1 -1
- package/build/modern/utils.d.cts +1 -1
- package/build/modern/utils.d.ts +1 -1
- package/package.json +1 -1
- package/src/__tests__/hydration.test.tsx +85 -2
- package/src/focusManager.ts +2 -2
- package/src/hydration.ts +41 -14
- package/src/onlineManager.ts +1 -1
- package/src/queryClient.ts +3 -1
|
@@ -15,6 +15,11 @@ async function fetchData<TData>(value: TData, ms?: number): Promise<TData> {
|
|
|
15
15
|
return value
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
async function fetchDate(value: string, ms?: number): Promise<Date> {
|
|
19
|
+
await sleep(ms || 0)
|
|
20
|
+
return new Date(value)
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
describe('dehydration and rehydration', () => {
|
|
19
24
|
test('should work with serializable values', async () => {
|
|
20
25
|
const queryCache = new QueryCache()
|
|
@@ -914,13 +919,14 @@ describe('dehydration and rehydration', () => {
|
|
|
914
919
|
defaultOptions: {
|
|
915
920
|
dehydrate: {
|
|
916
921
|
shouldDehydrateQuery: () => true,
|
|
922
|
+
serializeData: (data) => data.toISOString(),
|
|
917
923
|
},
|
|
918
924
|
},
|
|
919
925
|
})
|
|
920
926
|
|
|
921
927
|
const promise = queryClient.prefetchQuery({
|
|
922
928
|
queryKey: ['transformedStringToDate'],
|
|
923
|
-
queryFn: () =>
|
|
929
|
+
queryFn: () => fetchDate('2024-01-01T00:00:00.000Z', 20),
|
|
924
930
|
})
|
|
925
931
|
const dehydrated = dehydrate(queryClient)
|
|
926
932
|
expect(dehydrated.queries[0]?.promise).toBeInstanceOf(Promise)
|
|
@@ -928,7 +934,7 @@ describe('dehydration and rehydration', () => {
|
|
|
928
934
|
const hydrationClient = createQueryClient({
|
|
929
935
|
defaultOptions: {
|
|
930
936
|
hydrate: {
|
|
931
|
-
|
|
937
|
+
deserializeData: (data) => new Date(data),
|
|
932
938
|
},
|
|
933
939
|
},
|
|
934
940
|
})
|
|
@@ -943,4 +949,81 @@ describe('dehydration and rehydration', () => {
|
|
|
943
949
|
|
|
944
950
|
queryClient.clear()
|
|
945
951
|
})
|
|
952
|
+
|
|
953
|
+
test('should transform query data if promise is already resolved', async () => {
|
|
954
|
+
const queryClient = createQueryClient({
|
|
955
|
+
defaultOptions: {
|
|
956
|
+
dehydrate: {
|
|
957
|
+
shouldDehydrateQuery: () => true,
|
|
958
|
+
serializeData: (data) => data.toISOString(),
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
})
|
|
962
|
+
|
|
963
|
+
const promise = queryClient.prefetchQuery({
|
|
964
|
+
queryKey: ['transformedStringToDate'],
|
|
965
|
+
queryFn: () => fetchDate('2024-01-01T00:00:00.000Z', 0),
|
|
966
|
+
})
|
|
967
|
+
await sleep(20)
|
|
968
|
+
const dehydrated = dehydrate(queryClient)
|
|
969
|
+
|
|
970
|
+
const hydrationClient = createQueryClient({
|
|
971
|
+
defaultOptions: {
|
|
972
|
+
hydrate: {
|
|
973
|
+
deserializeData: (data) => new Date(data),
|
|
974
|
+
},
|
|
975
|
+
},
|
|
976
|
+
})
|
|
977
|
+
|
|
978
|
+
hydrate(hydrationClient, dehydrated)
|
|
979
|
+
await promise
|
|
980
|
+
await waitFor(() =>
|
|
981
|
+
expect(
|
|
982
|
+
hydrationClient.getQueryData(['transformedStringToDate']),
|
|
983
|
+
).toBeInstanceOf(Date),
|
|
984
|
+
)
|
|
985
|
+
|
|
986
|
+
queryClient.clear()
|
|
987
|
+
})
|
|
988
|
+
|
|
989
|
+
test('should overwrite query in cache if hydrated query is newer (with transformation)', async () => {
|
|
990
|
+
const hydrationClient = createQueryClient({
|
|
991
|
+
defaultOptions: {
|
|
992
|
+
hydrate: {
|
|
993
|
+
deserializeData: (data) => new Date(data),
|
|
994
|
+
},
|
|
995
|
+
},
|
|
996
|
+
})
|
|
997
|
+
await hydrationClient.prefetchQuery({
|
|
998
|
+
queryKey: ['date'],
|
|
999
|
+
queryFn: () => fetchDate('2024-01-01T00:00:00.000Z', 5),
|
|
1000
|
+
})
|
|
1001
|
+
|
|
1002
|
+
// ---
|
|
1003
|
+
|
|
1004
|
+
const queryClient = createQueryClient({
|
|
1005
|
+
defaultOptions: {
|
|
1006
|
+
dehydrate: {
|
|
1007
|
+
shouldDehydrateQuery: () => true,
|
|
1008
|
+
serializeData: (data) => data.toISOString(),
|
|
1009
|
+
},
|
|
1010
|
+
},
|
|
1011
|
+
})
|
|
1012
|
+
await queryClient.prefetchQuery({
|
|
1013
|
+
queryKey: ['date'],
|
|
1014
|
+
queryFn: () => fetchDate('2024-01-02T00:00:00.000Z', 10),
|
|
1015
|
+
})
|
|
1016
|
+
const dehydrated = dehydrate(queryClient)
|
|
1017
|
+
|
|
1018
|
+
// ---
|
|
1019
|
+
|
|
1020
|
+
hydrate(hydrationClient, dehydrated)
|
|
1021
|
+
|
|
1022
|
+
expect(hydrationClient.getQueryData(['date'])).toStrictEqual(
|
|
1023
|
+
new Date('2024-01-02T00:00:00.000Z'),
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
queryClient.clear()
|
|
1027
|
+
hydrationClient.clear()
|
|
1028
|
+
})
|
|
946
1029
|
})
|
package/src/focusManager.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class FocusManager extends Subscribable<Listener> {
|
|
|
17
17
|
super()
|
|
18
18
|
this.#setup = (onFocus) => {
|
|
19
19
|
// addEventListener does not exist in React Native, but window does
|
|
20
|
-
// eslint-disable-next-line
|
|
20
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
21
21
|
if (!isServer && window.addEventListener) {
|
|
22
22
|
const listener = () => onFocus()
|
|
23
23
|
// Listen to visibilitychange
|
|
@@ -78,7 +78,7 @@ export class FocusManager extends Subscribable<Listener> {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// document global can be unavailable in react native
|
|
81
|
-
// eslint-disable-next-line
|
|
81
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
82
82
|
return globalThis.document?.visibilityState !== 'hidden'
|
|
83
83
|
}
|
|
84
84
|
}
|
package/src/hydration.ts
CHANGED
|
@@ -13,15 +13,20 @@ import type { Query, QueryState } from './query'
|
|
|
13
13
|
import type { Mutation, MutationState } from './mutation'
|
|
14
14
|
|
|
15
15
|
// TYPES
|
|
16
|
+
type TransformerFn = (data: any) => any
|
|
17
|
+
function defaultTransformerFn(data: any): any {
|
|
18
|
+
return data
|
|
19
|
+
}
|
|
16
20
|
|
|
17
21
|
export interface DehydrateOptions {
|
|
22
|
+
serializeData?: TransformerFn
|
|
18
23
|
shouldDehydrateMutation?: (mutation: Mutation) => boolean
|
|
19
24
|
shouldDehydrateQuery?: (query: Query) => boolean
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
export interface HydrateOptions {
|
|
23
28
|
defaultOptions?: {
|
|
24
|
-
|
|
29
|
+
deserializeData?: TransformerFn
|
|
25
30
|
queries?: QueryOptions
|
|
26
31
|
mutations?: MutationOptions<unknown, DefaultError, unknown, unknown>
|
|
27
32
|
}
|
|
@@ -62,13 +67,21 @@ function dehydrateMutation(mutation: Mutation): DehydratedMutation {
|
|
|
62
67
|
// consuming the de/rehydrated data, typically with useQuery on the client.
|
|
63
68
|
// Sometimes it might make sense to prefetch data on the server and include
|
|
64
69
|
// in the html-payload, but not consume it on the initial render.
|
|
65
|
-
function dehydrateQuery(
|
|
70
|
+
function dehydrateQuery(
|
|
71
|
+
query: Query,
|
|
72
|
+
serializeData: TransformerFn,
|
|
73
|
+
): DehydratedQuery {
|
|
66
74
|
return {
|
|
67
|
-
state:
|
|
75
|
+
state: {
|
|
76
|
+
...query.state,
|
|
77
|
+
...(query.state.data !== undefined && {
|
|
78
|
+
data: serializeData(query.state.data),
|
|
79
|
+
}),
|
|
80
|
+
},
|
|
68
81
|
queryKey: query.queryKey,
|
|
69
82
|
queryHash: query.queryHash,
|
|
70
83
|
...(query.state.status === 'pending' && {
|
|
71
|
-
promise: query.promise?.catch((error) => {
|
|
84
|
+
promise: query.promise?.then(serializeData).catch((error) => {
|
|
72
85
|
if (process.env.NODE_ENV !== 'production') {
|
|
73
86
|
console.error(
|
|
74
87
|
`A query that was dehydrated as pending ended up rejecting. [${query.queryHash}]: ${error}; The error will be redacted in production builds`,
|
|
@@ -110,10 +123,17 @@ export function dehydrate(
|
|
|
110
123
|
client.getDefaultOptions().dehydrate?.shouldDehydrateQuery ??
|
|
111
124
|
defaultShouldDehydrateQuery
|
|
112
125
|
|
|
126
|
+
const serializeData =
|
|
127
|
+
options.serializeData ??
|
|
128
|
+
client.getDefaultOptions().dehydrate?.serializeData ??
|
|
129
|
+
defaultTransformerFn
|
|
130
|
+
|
|
113
131
|
const queries = client
|
|
114
132
|
.getQueryCache()
|
|
115
133
|
.getAll()
|
|
116
|
-
.flatMap((query) =>
|
|
134
|
+
.flatMap((query) =>
|
|
135
|
+
filterQuery(query) ? [dehydrateQuery(query, serializeData)] : [],
|
|
136
|
+
)
|
|
117
137
|
|
|
118
138
|
return { mutations, queries }
|
|
119
139
|
}
|
|
@@ -129,10 +149,14 @@ export function hydrate(
|
|
|
129
149
|
|
|
130
150
|
const mutationCache = client.getMutationCache()
|
|
131
151
|
const queryCache = client.getQueryCache()
|
|
152
|
+
const deserializeData =
|
|
153
|
+
options?.defaultOptions?.deserializeData ??
|
|
154
|
+
client.getDefaultOptions().hydrate?.deserializeData ??
|
|
155
|
+
defaultTransformerFn
|
|
132
156
|
|
|
133
|
-
// eslint-disable-next-line
|
|
157
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
134
158
|
const mutations = (dehydratedState as DehydratedState).mutations || []
|
|
135
|
-
// eslint-disable-next-line
|
|
159
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
136
160
|
const queries = (dehydratedState as DehydratedState).queries || []
|
|
137
161
|
|
|
138
162
|
mutations.forEach(({ state, ...mutationOptions }) => {
|
|
@@ -150,13 +174,19 @@ export function hydrate(
|
|
|
150
174
|
queries.forEach(({ queryKey, state, queryHash, meta, promise }) => {
|
|
151
175
|
let query = queryCache.get(queryHash)
|
|
152
176
|
|
|
177
|
+
const data =
|
|
178
|
+
state.data === undefined ? state.data : deserializeData(state.data)
|
|
179
|
+
|
|
153
180
|
// Do not hydrate if an existing query exists with newer data
|
|
154
181
|
if (query) {
|
|
155
182
|
if (query.state.dataUpdatedAt < state.dataUpdatedAt) {
|
|
156
183
|
// omit fetchStatus from dehydrated state
|
|
157
184
|
// so that query stays in its current fetchStatus
|
|
158
|
-
const { fetchStatus: _ignored, ...
|
|
159
|
-
query.setState(
|
|
185
|
+
const { fetchStatus: _ignored, ...serializedState } = state
|
|
186
|
+
query.setState({
|
|
187
|
+
...serializedState,
|
|
188
|
+
data,
|
|
189
|
+
})
|
|
160
190
|
}
|
|
161
191
|
} else {
|
|
162
192
|
// Restore query
|
|
@@ -173,19 +203,16 @@ export function hydrate(
|
|
|
173
203
|
// query being stuck in fetching state upon hydration
|
|
174
204
|
{
|
|
175
205
|
...state,
|
|
206
|
+
data,
|
|
176
207
|
fetchStatus: 'idle',
|
|
177
208
|
},
|
|
178
209
|
)
|
|
179
210
|
}
|
|
180
211
|
|
|
181
212
|
if (promise) {
|
|
182
|
-
const transformPromise =
|
|
183
|
-
client.getDefaultOptions().hydrate?.transformPromise
|
|
184
|
-
|
|
185
213
|
// Note: `Promise.resolve` required cause
|
|
186
214
|
// RSC transformed promises are not thenable
|
|
187
|
-
const initialPromise =
|
|
188
|
-
transformPromise?.(Promise.resolve(promise)) ?? promise
|
|
215
|
+
const initialPromise = Promise.resolve(promise).then(deserializeData)
|
|
189
216
|
|
|
190
217
|
// this doesn't actually fetch - it just creates a retryer
|
|
191
218
|
// which will re-use the passed `initialPromise`
|
package/src/onlineManager.ts
CHANGED
|
@@ -14,7 +14,7 @@ export class OnlineManager extends Subscribable<Listener> {
|
|
|
14
14
|
super()
|
|
15
15
|
this.#setup = (onOnline) => {
|
|
16
16
|
// addEventListener does not exist in React Native, but window does
|
|
17
|
-
// eslint-disable-next-line
|
|
17
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
18
18
|
if (!isServer && window.addEventListener) {
|
|
19
19
|
const onlineListener = () => onOnline(true)
|
|
20
20
|
const offlineListener = () => onOnline(false)
|
package/src/queryClient.ts
CHANGED
|
@@ -13,10 +13,10 @@ import { focusManager } from './focusManager'
|
|
|
13
13
|
import { onlineManager } from './onlineManager'
|
|
14
14
|
import { notifyManager } from './notifyManager'
|
|
15
15
|
import { infiniteQueryBehavior } from './infiniteQueryBehavior'
|
|
16
|
-
import type { DataTag, NoInfer, OmitKeyof } from './types'
|
|
17
16
|
import type { QueryState } from './query'
|
|
18
17
|
import type {
|
|
19
18
|
CancelOptions,
|
|
19
|
+
DataTag,
|
|
20
20
|
DefaultError,
|
|
21
21
|
DefaultOptions,
|
|
22
22
|
DefaultedQueryObserverOptions,
|
|
@@ -29,6 +29,8 @@ import type {
|
|
|
29
29
|
MutationKey,
|
|
30
30
|
MutationObserverOptions,
|
|
31
31
|
MutationOptions,
|
|
32
|
+
NoInfer,
|
|
33
|
+
OmitKeyof,
|
|
32
34
|
QueryClientConfig,
|
|
33
35
|
QueryKey,
|
|
34
36
|
QueryObserverOptions,
|