@rozenite/tanstack-query-plugin 1.7.0-rc.2 → 1.8.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/CHANGELOG.md +31 -0
- package/dist/devtools/assets/{CXEL7IU7-DJlSmt0p.js → CXEL7IU7-DmbowaBr.js} +1 -1
- package/dist/devtools/assets/{tanstack-query-_leiFatc.js → tanstack-query-DRBLkSCy.js} +11 -11
- package/dist/devtools/tanstack-query.html +1 -1
- package/dist/react-native/chunks/useTanStackQueryDevTools.require.cjs +1 -1
- package/dist/react-native/chunks/useTanStackQueryDevTools.require.js +309 -268
- package/dist/rozenite.json +1 -1
- package/dist/sdk/index.cjs +1 -0
- package/dist/sdk/index.d.ts +1939 -0
- package/dist/sdk/index.js +167 -0
- package/package.json +13 -6
- package/sdk.ts +55 -0
- package/src/react-native/agent/__tests__/tanstack-query-agent.test.ts +73 -29
- package/src/react-native/agent/tanstack-query-agent.ts +33 -235
- package/src/react-native/agent/useTanStackQueryAgentTools.ts +39 -65
- package/src/react-native/devtools-actions.ts +17 -3
- package/src/react-native/useHandleDevToolsMessages.ts +14 -11
- package/src/shared/agent-tools.ts +403 -0
- package/src/shared/hydrate.ts +16 -13
- package/src/shared/messaging.ts +3 -0
- package/src/shared/query-data-sync.test.ts +93 -0
- package/src/shared/query-data-sync.ts +156 -0
- package/src/shared/types.ts +1 -0
- package/src/ui/tanstack-query.tsx +12 -0
- package/tsconfig.json +4 -1
- package/vite.config.ts +7 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineAgentToolContract,
|
|
3
|
+
type AgentToolContract,
|
|
4
|
+
type JSONSchema7,
|
|
5
|
+
} from '@rozenite/agent-shared';
|
|
6
|
+
import type { FetchStatus, MutationStatus, QueryStatus } from '@tanstack/react-query';
|
|
7
|
+
import type { applyTanStackQueryDevtoolsAction } from '../react-native/devtools-actions';
|
|
8
|
+
|
|
9
|
+
export const TANSTACK_QUERY_AGENT_PLUGIN_ID = '@rozenite/tanstack-query-plugin';
|
|
10
|
+
|
|
11
|
+
export type TanStackQueryAgentPaginationInput = {
|
|
12
|
+
limit?: number;
|
|
13
|
+
cursor?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type TanStackQueryAgentQueryHashInput = {
|
|
17
|
+
queryHash: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type TanStackQueryAgentQueryToggleInput =
|
|
21
|
+
TanStackQueryAgentQueryHashInput & {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type TanStackQueryAgentMutationIdInput = {
|
|
26
|
+
mutationId: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type TanStackQueryAgentOnlineStatusInput = {
|
|
30
|
+
online: boolean;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type TanStackQueryAgentSafeValue =
|
|
34
|
+
| null
|
|
35
|
+
| boolean
|
|
36
|
+
| number
|
|
37
|
+
| string
|
|
38
|
+
| TanStackQueryAgentSafeValue[]
|
|
39
|
+
| { [key: string]: TanStackQueryAgentSafeValue };
|
|
40
|
+
|
|
41
|
+
export type TanStackQueryCacheSummary = {
|
|
42
|
+
online: boolean;
|
|
43
|
+
queries: {
|
|
44
|
+
total: number;
|
|
45
|
+
active: number;
|
|
46
|
+
fetching: number;
|
|
47
|
+
pending: number;
|
|
48
|
+
success: number;
|
|
49
|
+
error: number;
|
|
50
|
+
invalidated: number;
|
|
51
|
+
};
|
|
52
|
+
mutations: {
|
|
53
|
+
total: number;
|
|
54
|
+
pending: number;
|
|
55
|
+
success: number;
|
|
56
|
+
error: number;
|
|
57
|
+
paused: number;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type TanStackQueryPage = {
|
|
62
|
+
limit: number;
|
|
63
|
+
hasMore: boolean;
|
|
64
|
+
nextCursor?: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type TanStackQueryQuerySummary = {
|
|
68
|
+
queryHash: string;
|
|
69
|
+
queryKey: TanStackQueryAgentSafeValue;
|
|
70
|
+
status: QueryStatus;
|
|
71
|
+
fetchStatus: FetchStatus;
|
|
72
|
+
observersCount: number;
|
|
73
|
+
isInvalidated: boolean;
|
|
74
|
+
dataUpdatedAt: number;
|
|
75
|
+
errorUpdatedAt: number;
|
|
76
|
+
hasData: boolean;
|
|
77
|
+
hasError: boolean;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export type TanStackQueryObserverOptionsSummary = {
|
|
81
|
+
enabled: TanStackQueryAgentSafeValue;
|
|
82
|
+
networkMode: TanStackQueryAgentSafeValue;
|
|
83
|
+
staleTime: TanStackQueryAgentSafeValue;
|
|
84
|
+
gcTime: TanStackQueryAgentSafeValue;
|
|
85
|
+
retry: TanStackQueryAgentSafeValue;
|
|
86
|
+
retryDelay: TanStackQueryAgentSafeValue;
|
|
87
|
+
refetchInterval: TanStackQueryAgentSafeValue;
|
|
88
|
+
refetchOnMount: TanStackQueryAgentSafeValue;
|
|
89
|
+
refetchOnReconnect: TanStackQueryAgentSafeValue;
|
|
90
|
+
refetchOnWindowFocus: TanStackQueryAgentSafeValue;
|
|
91
|
+
subscribed: TanStackQueryAgentSafeValue;
|
|
92
|
+
meta: TanStackQueryAgentSafeValue;
|
|
93
|
+
hasQueryFn: boolean;
|
|
94
|
+
hasSelect: boolean;
|
|
95
|
+
hasPlaceholderData: boolean;
|
|
96
|
+
hasInitialData: boolean;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type TanStackQueryListQueriesResult = TanStackQueryCacheSummary & {
|
|
100
|
+
total: number;
|
|
101
|
+
items: TanStackQueryQuerySummary[];
|
|
102
|
+
page: TanStackQueryPage;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type TanStackQueryGetQueryDetailsResult = {
|
|
106
|
+
summary: TanStackQueryCacheSummary;
|
|
107
|
+
query: TanStackQueryQuerySummary & {
|
|
108
|
+
data: TanStackQueryAgentSafeValue;
|
|
109
|
+
error: TanStackQueryAgentSafeValue;
|
|
110
|
+
observers: Array<{
|
|
111
|
+
queryHash: string;
|
|
112
|
+
options: TanStackQueryObserverOptionsSummary | null;
|
|
113
|
+
}>;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export type TanStackQueryActionResult = Awaited<
|
|
118
|
+
ReturnType<typeof applyTanStackQueryDevtoolsAction>
|
|
119
|
+
>;
|
|
120
|
+
|
|
121
|
+
export type TanStackQueryMutationSummary = {
|
|
122
|
+
mutationId: number;
|
|
123
|
+
mutationKey: TanStackQueryAgentSafeValue;
|
|
124
|
+
status: MutationStatus;
|
|
125
|
+
isPaused: boolean;
|
|
126
|
+
submittedAt: number;
|
|
127
|
+
failureCount: number;
|
|
128
|
+
hasData: boolean;
|
|
129
|
+
hasError: boolean;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export type TanStackQueryMutationOptionsSummary = {
|
|
133
|
+
mutationKey: TanStackQueryAgentSafeValue;
|
|
134
|
+
networkMode: TanStackQueryAgentSafeValue;
|
|
135
|
+
gcTime: TanStackQueryAgentSafeValue;
|
|
136
|
+
retry: TanStackQueryAgentSafeValue;
|
|
137
|
+
retryDelay: TanStackQueryAgentSafeValue;
|
|
138
|
+
meta: TanStackQueryAgentSafeValue;
|
|
139
|
+
scope: TanStackQueryAgentSafeValue;
|
|
140
|
+
hasMutationFn: boolean;
|
|
141
|
+
hasOnMutate: boolean;
|
|
142
|
+
hasOnSuccess: boolean;
|
|
143
|
+
hasOnError: boolean;
|
|
144
|
+
hasOnSettled: boolean;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export type TanStackQueryListMutationsResult = TanStackQueryCacheSummary & {
|
|
148
|
+
total: number;
|
|
149
|
+
items: TanStackQueryMutationSummary[];
|
|
150
|
+
page: TanStackQueryPage;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export type TanStackQueryGetMutationDetailsResult = {
|
|
154
|
+
summary: TanStackQueryCacheSummary;
|
|
155
|
+
mutation: TanStackQueryMutationSummary & {
|
|
156
|
+
variables: TanStackQueryAgentSafeValue;
|
|
157
|
+
data: TanStackQueryAgentSafeValue;
|
|
158
|
+
error: TanStackQueryAgentSafeValue;
|
|
159
|
+
context: TanStackQueryAgentSafeValue;
|
|
160
|
+
failureReason: TanStackQueryAgentSafeValue;
|
|
161
|
+
options: TanStackQueryMutationOptionsSummary;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export type TanStackQueryGetCacheSummaryArgs = undefined;
|
|
166
|
+
export type TanStackQueryGetCacheSummaryResult = TanStackQueryCacheSummary;
|
|
167
|
+
export type TanStackQueryGetOnlineStatusArgs = undefined;
|
|
168
|
+
export type TanStackQueryGetOnlineStatusResult = { online: boolean };
|
|
169
|
+
export type TanStackQuerySetOnlineStatusArgs = TanStackQueryAgentOnlineStatusInput;
|
|
170
|
+
export type TanStackQuerySetOnlineStatusResult = { online: boolean };
|
|
171
|
+
export type TanStackQueryListQueriesArgs = TanStackQueryAgentPaginationInput;
|
|
172
|
+
export type TanStackQueryGetQueryDetailsArgs = TanStackQueryAgentQueryHashInput;
|
|
173
|
+
export type TanStackQueryRefetchQueryArgs = TanStackQueryAgentQueryHashInput;
|
|
174
|
+
export type TanStackQuerySetQueryLoadingArgs = TanStackQueryAgentQueryToggleInput;
|
|
175
|
+
export type TanStackQuerySetQueryErrorArgs = TanStackQueryAgentQueryToggleInput;
|
|
176
|
+
export type TanStackQueryInvalidateQueryArgs = TanStackQueryAgentQueryHashInput;
|
|
177
|
+
export type TanStackQueryResetQueryArgs = TanStackQueryAgentQueryHashInput;
|
|
178
|
+
export type TanStackQueryRemoveQueryArgs = TanStackQueryAgentQueryHashInput;
|
|
179
|
+
export type TanStackQueryClearQueryCacheArgs = undefined;
|
|
180
|
+
export type TanStackQueryClearQueryCacheResult = TanStackQueryActionResult;
|
|
181
|
+
export type TanStackQueryListMutationsArgs = TanStackQueryAgentPaginationInput;
|
|
182
|
+
export type TanStackQueryGetMutationDetailsArgs = TanStackQueryAgentMutationIdInput;
|
|
183
|
+
export type TanStackQueryClearMutationCacheArgs = undefined;
|
|
184
|
+
export type TanStackQueryClearMutationCacheResult = TanStackQueryActionResult;
|
|
185
|
+
|
|
186
|
+
const queryActionProperties = {
|
|
187
|
+
queryHash: {
|
|
188
|
+
type: 'string',
|
|
189
|
+
description: 'TanStack Query queryHash identifying the query.',
|
|
190
|
+
},
|
|
191
|
+
} satisfies Record<string, JSONSchema7>;
|
|
192
|
+
|
|
193
|
+
const mutationActionProperties = {
|
|
194
|
+
mutationId: {
|
|
195
|
+
type: 'number',
|
|
196
|
+
description: 'TanStack Query mutationId identifying the mutation.',
|
|
197
|
+
},
|
|
198
|
+
} satisfies Record<string, JSONSchema7>;
|
|
199
|
+
|
|
200
|
+
const paginationProperties = {
|
|
201
|
+
limit: {
|
|
202
|
+
type: 'number',
|
|
203
|
+
description: 'Maximum number of items to return. Defaults to 20. Maximum 100.',
|
|
204
|
+
},
|
|
205
|
+
cursor: {
|
|
206
|
+
type: 'string',
|
|
207
|
+
description: 'Opaque pagination cursor from a previous list call.',
|
|
208
|
+
},
|
|
209
|
+
} satisfies Record<string, JSONSchema7>;
|
|
210
|
+
|
|
211
|
+
const emptyInputSchema: JSONSchema7 = {
|
|
212
|
+
type: 'object',
|
|
213
|
+
properties: {},
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export const tanstackQueryToolDefinitions = {
|
|
217
|
+
getCacheSummary: defineAgentToolContract<
|
|
218
|
+
TanStackQueryGetCacheSummaryArgs,
|
|
219
|
+
TanStackQueryGetCacheSummaryResult
|
|
220
|
+
>({
|
|
221
|
+
name: 'get-cache-summary',
|
|
222
|
+
description:
|
|
223
|
+
'Return aggregate TanStack Query cache health and count information.',
|
|
224
|
+
inputSchema: emptyInputSchema,
|
|
225
|
+
}),
|
|
226
|
+
getOnlineStatus: defineAgentToolContract<
|
|
227
|
+
TanStackQueryGetOnlineStatusArgs,
|
|
228
|
+
TanStackQueryGetOnlineStatusResult
|
|
229
|
+
>({
|
|
230
|
+
name: 'get-online-status',
|
|
231
|
+
description: 'Return the current TanStack Query onlineManager status.',
|
|
232
|
+
inputSchema: emptyInputSchema,
|
|
233
|
+
}),
|
|
234
|
+
setOnlineStatus: defineAgentToolContract<
|
|
235
|
+
TanStackQuerySetOnlineStatusArgs,
|
|
236
|
+
TanStackQuerySetOnlineStatusResult
|
|
237
|
+
>({
|
|
238
|
+
name: 'set-online-status',
|
|
239
|
+
description:
|
|
240
|
+
'Set the TanStack Query onlineManager status for testing offline/online behavior.',
|
|
241
|
+
inputSchema: {
|
|
242
|
+
type: 'object',
|
|
243
|
+
properties: {
|
|
244
|
+
online: {
|
|
245
|
+
type: 'boolean',
|
|
246
|
+
description: 'Whether the TanStack Query onlineManager should be online.',
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
required: ['online'],
|
|
250
|
+
},
|
|
251
|
+
}),
|
|
252
|
+
listQueries: defineAgentToolContract<
|
|
253
|
+
TanStackQueryListQueriesArgs,
|
|
254
|
+
TanStackQueryListQueriesResult
|
|
255
|
+
>({
|
|
256
|
+
name: 'list-queries',
|
|
257
|
+
description: 'List TanStack Query query summaries using cursor pagination.',
|
|
258
|
+
inputSchema: {
|
|
259
|
+
type: 'object',
|
|
260
|
+
properties: paginationProperties,
|
|
261
|
+
},
|
|
262
|
+
}),
|
|
263
|
+
getQueryDetails: defineAgentToolContract<
|
|
264
|
+
TanStackQueryGetQueryDetailsArgs,
|
|
265
|
+
TanStackQueryGetQueryDetailsResult
|
|
266
|
+
>({
|
|
267
|
+
name: 'get-query-details',
|
|
268
|
+
description:
|
|
269
|
+
'Return a JSON-safe TanStack Query query snapshot and observer summary.',
|
|
270
|
+
inputSchema: {
|
|
271
|
+
type: 'object',
|
|
272
|
+
properties: queryActionProperties,
|
|
273
|
+
required: ['queryHash'],
|
|
274
|
+
},
|
|
275
|
+
}),
|
|
276
|
+
refetchQuery: defineAgentToolContract<
|
|
277
|
+
TanStackQueryRefetchQueryArgs,
|
|
278
|
+
TanStackQueryActionResult
|
|
279
|
+
>({
|
|
280
|
+
name: 'refetch-query',
|
|
281
|
+
description: 'Refetch a TanStack Query query by queryHash.',
|
|
282
|
+
inputSchema: {
|
|
283
|
+
type: 'object',
|
|
284
|
+
properties: queryActionProperties,
|
|
285
|
+
required: ['queryHash'],
|
|
286
|
+
},
|
|
287
|
+
}),
|
|
288
|
+
setQueryLoading: defineAgentToolContract<
|
|
289
|
+
TanStackQuerySetQueryLoadingArgs,
|
|
290
|
+
TanStackQueryActionResult
|
|
291
|
+
>({
|
|
292
|
+
name: 'set-query-loading',
|
|
293
|
+
description:
|
|
294
|
+
'Enable or disable TanStack Query loading-state simulation for a query by queryHash.',
|
|
295
|
+
inputSchema: {
|
|
296
|
+
type: 'object',
|
|
297
|
+
properties: {
|
|
298
|
+
...queryActionProperties,
|
|
299
|
+
enabled: {
|
|
300
|
+
type: 'boolean',
|
|
301
|
+
description:
|
|
302
|
+
'Whether the loading-state simulation should be enabled.',
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
required: ['queryHash', 'enabled'],
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
setQueryError: defineAgentToolContract<
|
|
309
|
+
TanStackQuerySetQueryErrorArgs,
|
|
310
|
+
TanStackQueryActionResult
|
|
311
|
+
>({
|
|
312
|
+
name: 'set-query-error',
|
|
313
|
+
description:
|
|
314
|
+
'Enable or disable TanStack Query error-state simulation for a query by queryHash.',
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: 'object',
|
|
317
|
+
properties: {
|
|
318
|
+
...queryActionProperties,
|
|
319
|
+
enabled: {
|
|
320
|
+
type: 'boolean',
|
|
321
|
+
description: 'Whether the error-state simulation should be enabled.',
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
required: ['queryHash', 'enabled'],
|
|
325
|
+
},
|
|
326
|
+
}),
|
|
327
|
+
invalidateQuery: defineAgentToolContract<
|
|
328
|
+
TanStackQueryInvalidateQueryArgs,
|
|
329
|
+
TanStackQueryActionResult
|
|
330
|
+
>({
|
|
331
|
+
name: 'invalidate-query',
|
|
332
|
+
description: 'Invalidate a TanStack Query query by queryHash.',
|
|
333
|
+
inputSchema: {
|
|
334
|
+
type: 'object',
|
|
335
|
+
properties: queryActionProperties,
|
|
336
|
+
required: ['queryHash'],
|
|
337
|
+
},
|
|
338
|
+
}),
|
|
339
|
+
resetQuery: defineAgentToolContract<
|
|
340
|
+
TanStackQueryResetQueryArgs,
|
|
341
|
+
TanStackQueryActionResult
|
|
342
|
+
>({
|
|
343
|
+
name: 'reset-query',
|
|
344
|
+
description: 'Reset a TanStack Query query by queryHash.',
|
|
345
|
+
inputSchema: {
|
|
346
|
+
type: 'object',
|
|
347
|
+
properties: queryActionProperties,
|
|
348
|
+
required: ['queryHash'],
|
|
349
|
+
},
|
|
350
|
+
}),
|
|
351
|
+
removeQuery: defineAgentToolContract<
|
|
352
|
+
TanStackQueryRemoveQueryArgs,
|
|
353
|
+
TanStackQueryActionResult
|
|
354
|
+
>({
|
|
355
|
+
name: 'remove-query',
|
|
356
|
+
description: 'Remove a TanStack Query query from the cache by queryHash.',
|
|
357
|
+
inputSchema: {
|
|
358
|
+
type: 'object',
|
|
359
|
+
properties: queryActionProperties,
|
|
360
|
+
required: ['queryHash'],
|
|
361
|
+
},
|
|
362
|
+
}),
|
|
363
|
+
clearQueryCache: defineAgentToolContract<
|
|
364
|
+
TanStackQueryClearQueryCacheArgs,
|
|
365
|
+
TanStackQueryClearQueryCacheResult
|
|
366
|
+
>({
|
|
367
|
+
name: 'clear-query-cache',
|
|
368
|
+
description: 'Clear the full TanStack Query query cache.',
|
|
369
|
+
inputSchema: emptyInputSchema,
|
|
370
|
+
}),
|
|
371
|
+
listMutations: defineAgentToolContract<
|
|
372
|
+
TanStackQueryListMutationsArgs,
|
|
373
|
+
TanStackQueryListMutationsResult
|
|
374
|
+
>({
|
|
375
|
+
name: 'list-mutations',
|
|
376
|
+
description: 'List TanStack Query mutation summaries using cursor pagination.',
|
|
377
|
+
inputSchema: {
|
|
378
|
+
type: 'object',
|
|
379
|
+
properties: paginationProperties,
|
|
380
|
+
},
|
|
381
|
+
}),
|
|
382
|
+
getMutationDetails: defineAgentToolContract<
|
|
383
|
+
TanStackQueryGetMutationDetailsArgs,
|
|
384
|
+
TanStackQueryGetMutationDetailsResult
|
|
385
|
+
>({
|
|
386
|
+
name: 'get-mutation-details',
|
|
387
|
+
description:
|
|
388
|
+
'Return a JSON-safe TanStack Query mutation snapshot for a mutationId.',
|
|
389
|
+
inputSchema: {
|
|
390
|
+
type: 'object',
|
|
391
|
+
properties: mutationActionProperties,
|
|
392
|
+
required: ['mutationId'],
|
|
393
|
+
},
|
|
394
|
+
}),
|
|
395
|
+
clearMutationCache: defineAgentToolContract<
|
|
396
|
+
TanStackQueryClearMutationCacheArgs,
|
|
397
|
+
TanStackQueryClearMutationCacheResult
|
|
398
|
+
>({
|
|
399
|
+
name: 'clear-mutation-cache',
|
|
400
|
+
description: 'Clear the full TanStack Query mutation cache.',
|
|
401
|
+
inputSchema: emptyInputSchema,
|
|
402
|
+
}),
|
|
403
|
+
} as const satisfies Record<string, AgentToolContract<unknown, unknown>>;
|
package/src/shared/hydrate.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
SerializableObserver,
|
|
15
15
|
PartialQueryState,
|
|
16
16
|
} from './types';
|
|
17
|
+
import { applyRemoteQueryState, instrumentQuery } from './query-data-sync';
|
|
17
18
|
|
|
18
19
|
const mockQueryFn = () => {
|
|
19
20
|
return Promise.resolve(null);
|
|
@@ -22,7 +23,7 @@ const mockQueryFn = () => {
|
|
|
22
23
|
const hydrateObservers = (
|
|
23
24
|
client: QueryClient,
|
|
24
25
|
queryHash: string,
|
|
25
|
-
dehydratedObservers: SerializableObserver[]
|
|
26
|
+
dehydratedObservers: SerializableObserver[],
|
|
26
27
|
) => {
|
|
27
28
|
const query = client.getQueryCache().get(queryHash);
|
|
28
29
|
|
|
@@ -50,7 +51,7 @@ const hydrateObservers = (
|
|
|
50
51
|
|
|
51
52
|
const observer = new QueryObserver(
|
|
52
53
|
client,
|
|
53
|
-
hydratedOptions as QueryObserverOptions
|
|
54
|
+
hydratedOptions as QueryObserverOptions,
|
|
54
55
|
);
|
|
55
56
|
query.addObserver(observer);
|
|
56
57
|
});
|
|
@@ -58,7 +59,7 @@ const hydrateObservers = (
|
|
|
58
59
|
|
|
59
60
|
const hydrateMutation = (
|
|
60
61
|
client: QueryClient,
|
|
61
|
-
dehydratedMutation: SerializableMutation
|
|
62
|
+
dehydratedMutation: SerializableMutation,
|
|
62
63
|
) => {
|
|
63
64
|
const mutationCache = client.getMutationCache();
|
|
64
65
|
const { options, state } = dehydratedMutation;
|
|
@@ -79,7 +80,7 @@ const hydrateMutation = (
|
|
|
79
80
|
|
|
80
81
|
const hydrateQuery = (
|
|
81
82
|
client: QueryClient,
|
|
82
|
-
dehydratedQuery: SerializableQuery
|
|
83
|
+
dehydratedQuery: SerializableQuery,
|
|
83
84
|
) => {
|
|
84
85
|
const queryCache = client.getQueryCache();
|
|
85
86
|
const { queryKey, state, queryHash, observers } = dehydratedQuery;
|
|
@@ -94,7 +95,7 @@ const hydrateQuery = (
|
|
|
94
95
|
query.state.dataUpdatedAt < state.dataUpdatedAt ||
|
|
95
96
|
query.state.fetchStatus !== state.fetchStatus
|
|
96
97
|
) {
|
|
97
|
-
query
|
|
98
|
+
applyRemoteQueryState(query, {
|
|
98
99
|
...hydratedState,
|
|
99
100
|
data,
|
|
100
101
|
});
|
|
@@ -117,20 +118,22 @@ const hydrateQuery = (
|
|
|
117
118
|
{
|
|
118
119
|
...hydratedState,
|
|
119
120
|
data,
|
|
120
|
-
}
|
|
121
|
+
},
|
|
121
122
|
);
|
|
122
123
|
}
|
|
123
124
|
|
|
125
|
+
instrumentQuery(query);
|
|
126
|
+
|
|
124
127
|
hydrateObservers(client, queryHash, observers);
|
|
125
128
|
};
|
|
126
129
|
|
|
127
130
|
export const hydrateQueryClient = (
|
|
128
131
|
client: QueryClient,
|
|
129
|
-
dehydratedState: SerializableQueryClient
|
|
132
|
+
dehydratedState: SerializableQueryClient,
|
|
130
133
|
): void => {
|
|
131
134
|
// Hydrate mutations
|
|
132
135
|
dehydratedState.mutations.forEach((mutation) =>
|
|
133
|
-
hydrateMutation(client, mutation)
|
|
136
|
+
hydrateMutation(client, mutation),
|
|
134
137
|
);
|
|
135
138
|
|
|
136
139
|
// Hydrate queries
|
|
@@ -148,7 +151,7 @@ export const applyQueryEvent = (
|
|
|
148
151
|
| 'observerResultsUpdated'
|
|
149
152
|
| 'observerOptionsUpdated',
|
|
150
153
|
data: SerializableQuery | PartialQueryState,
|
|
151
|
-
action?: string
|
|
154
|
+
action?: string,
|
|
152
155
|
): void => {
|
|
153
156
|
const queryCache = queryClient.getQueryCache();
|
|
154
157
|
|
|
@@ -186,7 +189,7 @@ export const applyQueryEvent = (
|
|
|
186
189
|
// New function to handle action-based partial state updates
|
|
187
190
|
export const applyPartialQueryState = (
|
|
188
191
|
queryClient: QueryClient,
|
|
189
|
-
data: PartialQueryState
|
|
192
|
+
data: PartialQueryState,
|
|
190
193
|
): void => {
|
|
191
194
|
const queryCache = queryClient.getQueryCache();
|
|
192
195
|
const query = queryCache.get(data.queryHash);
|
|
@@ -199,7 +202,7 @@ export const applyPartialQueryState = (
|
|
|
199
202
|
|
|
200
203
|
// Apply the partial state changes
|
|
201
204
|
if (data.state) {
|
|
202
|
-
query
|
|
205
|
+
applyRemoteQueryState(query, data.state);
|
|
203
206
|
}
|
|
204
207
|
};
|
|
205
208
|
|
|
@@ -213,7 +216,7 @@ export const applyMutationEvent = (
|
|
|
213
216
|
| 'observerRemoved'
|
|
214
217
|
| 'observerResultsUpdated'
|
|
215
218
|
| 'observerOptionsUpdated',
|
|
216
|
-
data: SerializableMutation
|
|
219
|
+
data: SerializableMutation,
|
|
217
220
|
): void => {
|
|
218
221
|
const mutationCache = queryClient.getMutationCache();
|
|
219
222
|
|
|
@@ -244,7 +247,7 @@ export const applyQueryObserverEvent = (
|
|
|
244
247
|
data: {
|
|
245
248
|
queryHash: string;
|
|
246
249
|
observers: SerializableObserver[];
|
|
247
|
-
}
|
|
250
|
+
},
|
|
248
251
|
): void => {
|
|
249
252
|
hydrateObservers(queryClient, data.queryHash, data.observers);
|
|
250
253
|
};
|
package/src/shared/messaging.ts
CHANGED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
3
|
+
import {
|
|
4
|
+
applyRemoteQueryState,
|
|
5
|
+
instrumentQuery,
|
|
6
|
+
instrumentQueryClient,
|
|
7
|
+
} from './query-data-sync';
|
|
8
|
+
|
|
9
|
+
const createQueryClient = () =>
|
|
10
|
+
new QueryClient({
|
|
11
|
+
defaultOptions: {
|
|
12
|
+
queries: {
|
|
13
|
+
retry: false,
|
|
14
|
+
gcTime: Infinity,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('query data sync instrumentation', () => {
|
|
20
|
+
it('emits query data updates for data-only setState edits', () => {
|
|
21
|
+
const queryClient = createQueryClient();
|
|
22
|
+
const handler = vi.fn();
|
|
23
|
+
|
|
24
|
+
queryClient.setQueryData(['edited'], { value: 1 });
|
|
25
|
+
const query = queryClient.getQueryCache().find({ queryKey: ['edited'] })!;
|
|
26
|
+
|
|
27
|
+
instrumentQuery(query, handler);
|
|
28
|
+
|
|
29
|
+
query.setState({
|
|
30
|
+
...query.state,
|
|
31
|
+
data: { value: 2 },
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
35
|
+
expect(handler).toHaveBeenCalledWith(
|
|
36
|
+
expect.objectContaining({
|
|
37
|
+
data: { value: 2 },
|
|
38
|
+
}),
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('emits query data updates for setQueryData user edits', () => {
|
|
43
|
+
const queryClient = createQueryClient();
|
|
44
|
+
const handler = vi.fn();
|
|
45
|
+
|
|
46
|
+
instrumentQueryClient(queryClient, handler);
|
|
47
|
+
|
|
48
|
+
queryClient.setQueryData(['edited'], { value: 1 });
|
|
49
|
+
|
|
50
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
51
|
+
expect(handler).toHaveBeenCalledWith(
|
|
52
|
+
expect.objectContaining({
|
|
53
|
+
data: { value: 1 },
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('does not emit query data updates for non-data state changes', () => {
|
|
59
|
+
const queryClient = createQueryClient();
|
|
60
|
+
const handler = vi.fn();
|
|
61
|
+
|
|
62
|
+
queryClient.setQueryData(['edited'], { value: 1 });
|
|
63
|
+
const query = queryClient.getQueryCache().find({ queryKey: ['edited'] })!;
|
|
64
|
+
|
|
65
|
+
instrumentQuery(query, handler);
|
|
66
|
+
|
|
67
|
+
query.setState({
|
|
68
|
+
data: undefined,
|
|
69
|
+
status: 'pending',
|
|
70
|
+
fetchStatus: 'fetching',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(handler).not.toHaveBeenCalled();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('does not emit query data updates for remote state application', () => {
|
|
77
|
+
const queryClient = createQueryClient();
|
|
78
|
+
const handler = vi.fn();
|
|
79
|
+
|
|
80
|
+
queryClient.setQueryData(['edited'], { value: 1 });
|
|
81
|
+
const query = queryClient.getQueryCache().find({ queryKey: ['edited'] })!;
|
|
82
|
+
|
|
83
|
+
instrumentQuery(query, handler);
|
|
84
|
+
|
|
85
|
+
applyRemoteQueryState(query, {
|
|
86
|
+
...query.state,
|
|
87
|
+
data: { value: 2 },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
expect(handler).not.toHaveBeenCalled();
|
|
91
|
+
expect(query.state.data).toEqual({ value: 2 });
|
|
92
|
+
});
|
|
93
|
+
});
|