@rozenite/tanstack-query-plugin 2.4.0 → 2.5.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/react-native/cjs/src/react-native/agent/tanstack-query-agent.js +60 -68
  3. package/dist/react-native/cjs/src/react-native/agent/useTanStackQueryAgentTools.js +0 -12
  4. package/dist/react-native/cjs/src/shared/agent-tools.js +36 -6
  5. package/dist/react-native/src/react-native/agent/tanstack-query-agent.d.ts +16 -19
  6. package/dist/react-native/src/react-native/agent/tanstack-query-agent.js +60 -68
  7. package/dist/react-native/src/react-native/agent/useTanStackQueryAgentTools.js +1 -13
  8. package/dist/react-native/src/shared/agent-tools.d.ts +17 -5
  9. package/dist/react-native/src/shared/agent-tools.js +36 -6
  10. package/dist/rozenite.json +1 -1
  11. package/dist/sdk/sdk.d.ts +2 -2
  12. package/dist/sdk/src/shared/agent-tools.d.ts +17 -5
  13. package/dist/sdk/src/shared/agent-tools.js +36 -6
  14. package/package.json +12 -8
  15. package/react-native.ts +0 -18
  16. package/rozenite.config.ts +0 -9
  17. package/sdk.ts +0 -52
  18. package/src/__tests__/release-bundle.test.ts +0 -32
  19. package/src/react-native/agent/__tests__/tanstack-query-agent.test.ts +0 -553
  20. package/src/react-native/agent/tanstack-query-agent.ts +0 -484
  21. package/src/react-native/agent/useTanStackQueryAgentTools.ts +0 -116
  22. package/src/react-native/devtools-actions.ts +0 -204
  23. package/src/react-native/useHandleDevToolsMessages.ts +0 -32
  24. package/src/react-native/useHandleInitialData.ts +0 -31
  25. package/src/react-native/useSyncTanStackCache.ts +0 -231
  26. package/src/react-native/useTanStackQueryDevTools.ts +0 -24
  27. package/src/shared/agent-tools.ts +0 -418
  28. package/src/shared/dehydrate.ts +0 -40
  29. package/src/shared/hydrate.ts +0 -243
  30. package/src/shared/messaging.ts +0 -63
  31. package/src/shared/query-data-sync.test.ts +0 -89
  32. package/src/shared/query-data-sync.ts +0 -129
  33. package/src/shared/types.ts +0 -49
  34. package/src/shared/useSyncOnlineStatus.ts +0 -24
  35. package/src/ui/tanstack-query.tsx +0 -46
  36. package/src/ui/useHandleSyncMessages.ts +0 -58
  37. package/src/ui/useSyncDevToolsEvents.ts +0 -46
  38. package/src/ui/useSyncInitialData.test.tsx +0 -76
  39. package/src/ui/useSyncInitialData.ts +0 -27
  40. package/tsconfig.json +0 -36
  41. package/vite.config.ts +0 -27
package/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # @rozenite/tanstack-query-plugin
2
2
 
3
+ ## 2.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#541](https://github.com/callstackincubator/rozenite/pull/541) [`56cdf09`](https://github.com/callstackincubator/rozenite/commit/56cdf098c5b3ba2bfc8c4461b1631030c9b40e7d) Thanks [@V3RON](https://github.com/V3RON)! - `list-queries` and `list-mutations` now page with the shared agent cursor,
8
+ keyed by `queryHash` and `mutationId`. A query or mutation added while an
9
+ agent pages no longer invalidates its cursor, and a cursor whose row was
10
+ removed answers `reset: true` instead of an error. An invalid `limit` is now
11
+ an error instead of quietly falling back to 20.
12
+
13
+ Default changes, each reachable through an argument:
14
+
15
+ - `list-queries` default columns: `queryHash,queryKey,status,fetchStatus,hasError`
16
+ → `queryHash,status,fetchStatus,hasError` (`queryHash` already spells out
17
+ the key; `--fields queryKey` brings it back).
18
+ - Pages printed by the CLI: the full cache summary → `total` only. The SDK
19
+ result still carries the summary, and `get-cache-summary` returns it.
20
+ - `get-query-details` / `get-mutation-details` values: unbounded → 4 levels
21
+ deep, 512 characters per string and 100 items per array or object, with
22
+ cuts marked `[object(N keys)]`, `[array(N)]`, `[+N chars]`, a last
23
+ `"[+N items]"` array item or a last `"[+N keys]": true` object entry, and
24
+ `truncated: true`. Raise them with `maxDepth` / `maxValueLength` /
25
+ `maxItems`, or read one sub-tree with `path` (for example `data.items.0`).
26
+
27
+ ### Patch Changes
28
+
29
+ - [#560](https://github.com/callstackincubator/rozenite/pull/560) [`a7985fa`](https://github.com/callstackincubator/rozenite/commit/a7985fa7876500ed5dd47bb3e61a97c75e0cfb58) Thanks [@V3RON](https://github.com/V3RON)! - The published packages no longer include development fixtures, tests and build
30
+ configuration (such as `rozenite.config.ts`, `__tests__` and `tsconfig.json`),
31
+ which makes installs smaller: `@rozenite/expo-atlas-plugin` alone drops from
32
+ about 6 MB to 90 KB. Every package now lists its `CHANGELOG.md`, so changelogs
33
+ ship. Plugins generated by `rozenite generate` get the same treatment: they
34
+ publish only their built output, without `rozenite.config.ts`, sources, tests
35
+ or build configuration.
36
+
37
+ - [#560](https://github.com/callstackincubator/rozenite/pull/560) [`a7985fa`](https://github.com/callstackincubator/rozenite/commit/a7985fa7876500ed5dd47bb3e61a97c75e0cfb58) Thanks [@V3RON](https://github.com/V3RON)! - Fix dev-mode bundles (Re.Pack, webpack, Rspack and Vite) failing to resolve
38
+ `@rozenite/agent-bridge`, `@rozenite/agent-shared` and the other packages
39
+ that publish an `exports` map: it carried a `development` condition pointing at
40
+ TypeScript source that was not in the package. The published packages no
41
+ longer have that condition, so these tools pick the built output in every mode.
42
+
43
+ `rozenite build` also stops adding a `development` condition to a plugin's
44
+ `./sdk` export and removes the `./sdk.ts` one that earlier versions wrote; a
45
+ `development` condition you wrote yourself (any other value) is kept. If your
46
+ `package.json` has a `publishConfig.exports`, `rozenite build` now keeps its
47
+ managed entries (`.`, `./sdk`, `./metro`) in step with `exports`.
48
+
49
+ - Updated dependencies [[`2a72f21`](https://github.com/callstackincubator/rozenite/commit/2a72f2115eb6eda0b806fa4fcdaf5427f8b2d2c9), [`fb29800`](https://github.com/callstackincubator/rozenite/commit/fb298007eea021f23863b1b6a9534cb62d5260bf), [`f59e90b`](https://github.com/callstackincubator/rozenite/commit/f59e90b8cb63cfbe045c1768bb482424a8650cb5), [`a7985fa`](https://github.com/callstackincubator/rozenite/commit/a7985fa7876500ed5dd47bb3e61a97c75e0cfb58), [`a7985fa`](https://github.com/callstackincubator/rozenite/commit/a7985fa7876500ed5dd47bb3e61a97c75e0cfb58)]:
50
+ - @rozenite/agent-shared@2.5.0
51
+ - @rozenite/agent-bridge@2.5.0
52
+ - @rozenite/plugin-bridge@2.5.0
53
+
3
54
  ## 2.4.0
4
55
 
5
56
  ### Patch Changes
@@ -2,10 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createTanStackQueryAgentController = exports.buildTanStackQueryCacheSummary = exports.TANSTACK_QUERY_AGENT_TOOLS = exports.clearMutationCacheTool = exports.getMutationDetailsTool = exports.listMutationsTool = exports.clearQueryCacheTool = exports.removeQueryTool = exports.resetQueryTool = exports.invalidateQueryTool = exports.setQueryErrorTool = exports.setQueryLoadingTool = exports.refetchQueryTool = exports.getQueryDetailsTool = exports.listQueriesTool = exports.setOnlineStatusTool = exports.getOnlineStatusTool = exports.getCacheSummaryTool = exports.serializeForAgent = void 0;
4
4
  const react_query_1 = require("@tanstack/react-query");
5
+ const agent_shared_1 = require("@rozenite/agent-shared");
5
6
  const devtools_actions_1 = require("../devtools-actions");
6
7
  const agent_tools_1 = require("../../shared/agent-tools");
7
- const DEFAULT_PAGE_LIMIT = 20;
8
- const MAX_PAGE_LIMIT = 100;
9
8
  const isPlainObject = (value) => {
10
9
  return !!value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype;
11
10
  };
@@ -62,47 +61,6 @@ const serializeForAgent = (value, seen = new WeakSet()) => {
62
61
  return String(value);
63
62
  };
64
63
  exports.serializeForAgent = serializeForAgent;
65
- const sanitizeLimit = (limit) => {
66
- if (typeof limit !== 'number' ||
67
- !Number.isFinite(limit) ||
68
- !Number.isInteger(limit) ||
69
- limit < 1) {
70
- return DEFAULT_PAGE_LIMIT;
71
- }
72
- return Math.min(limit, MAX_PAGE_LIMIT);
73
- };
74
- const encodeCursor = (kind, generation, offset) => {
75
- return `${kind}:${generation}:${offset}`;
76
- };
77
- const decodeCursor = (cursor, kind, generation) => {
78
- const [cursorKind, rawGeneration, rawOffset] = cursor.split(':', 3);
79
- if (cursorKind !== kind || !rawGeneration || !rawOffset) {
80
- throw new Error('Cursor does not match the requested listing. Run the command again.');
81
- }
82
- const cursorGeneration = Number(rawGeneration);
83
- const offset = Number(rawOffset);
84
- if (!Number.isInteger(cursorGeneration) || cursorGeneration !== generation) {
85
- throw new Error('Cursor does not match the requested listing. Run the command again.');
86
- }
87
- if (!Number.isInteger(offset) || offset < 0) {
88
- throw new Error('Cursor is invalid. Run the command again.');
89
- }
90
- return offset;
91
- };
92
- const paginate = (rows, kind, generation, input) => {
93
- const limit = sanitizeLimit(input.limit);
94
- const startIndex = input.cursor ? decodeCursor(input.cursor, kind, generation) : 0;
95
- const endIndex = Math.min(startIndex + limit, rows.length);
96
- const hasMore = endIndex < rows.length;
97
- return {
98
- items: rows.slice(startIndex, endIndex),
99
- page: {
100
- limit,
101
- hasMore,
102
- ...(hasMore ? { nextCursor: encodeCursor(kind, generation, endIndex) } : {}),
103
- },
104
- };
105
- };
106
64
  exports.getCacheSummaryTool = agent_tools_1.tanstackQueryToolDefinitions.getCacheSummary;
107
65
  exports.getOnlineStatusTool = agent_tools_1.tanstackQueryToolDefinitions.getOnlineStatus;
108
66
  exports.setOnlineStatusTool = agent_tools_1.tanstackQueryToolDefinitions.setOnlineStatus;
@@ -198,6 +156,40 @@ const getMutationSummary = (mutation) => {
198
156
  hasError: mutation.state.error != null,
199
157
  };
200
158
  };
159
+ /**
160
+ * Applies `path`, `maxDepth`, `maxValueLength` and `maxItems` to the named value fields
161
+ * of a details result. `path` must start with one of `fields`.
162
+ */
163
+ const createValueBounder = (fields, args) => {
164
+ const bounds = (0, agent_shared_1.normalizeBoundedValueArgs)(args);
165
+ const pathField = bounds.path?.[0];
166
+ if (bounds.path && !fields.includes(pathField)) {
167
+ throw new Error(`"path" must start with ${fields.map((field) => `"${field}"`).join(', ')}.`);
168
+ }
169
+ let truncated = false;
170
+ return {
171
+ bound(field, value) {
172
+ const selected = bounds.path && pathField === field
173
+ ? (0, agent_shared_1.selectValuePath)(value, bounds.path.slice(1), [field])
174
+ : value;
175
+ const result = (0, agent_shared_1.boundValue)(selected, {
176
+ maxDepth: bounds.maxDepth,
177
+ maxValueLength: bounds.maxValueLength,
178
+ maxItems: bounds.maxItems,
179
+ });
180
+ truncated = truncated || result.truncated;
181
+ return result.value;
182
+ },
183
+ finish() {
184
+ return {
185
+ ...(bounds.path ? { path: bounds.path.join('.') } : {}),
186
+ truncated,
187
+ };
188
+ },
189
+ };
190
+ };
191
+ const QUERY_VALUE_FIELDS = ['data', 'error'];
192
+ const MUTATION_VALUE_FIELDS = ['variables', 'data', 'error', 'context', 'failureReason'];
201
193
  const resolveQuery = (queryClient, queryHash) => {
202
194
  const query = queryClient.getQueryCache().get(queryHash);
203
195
  if (!query) {
@@ -250,21 +242,7 @@ const buildTanStackQueryCacheSummary = (queryClient) => {
250
242
  };
251
243
  exports.buildTanStackQueryCacheSummary = buildTanStackQueryCacheSummary;
252
244
  const createTanStackQueryAgentController = (queryClient) => {
253
- const cursorState = {
254
- queriesGeneration: 0,
255
- mutationsGeneration: 0,
256
- };
257
245
  return {
258
- handleQueryCacheEvent(event) {
259
- if (event.type === 'added' || event.type === 'removed') {
260
- cursorState.queriesGeneration += 1;
261
- }
262
- },
263
- handleMutationCacheEvent(event) {
264
- if (event.type === 'added' || event.type === 'removed') {
265
- cursorState.mutationsGeneration += 1;
266
- }
267
- },
268
246
  getCacheSummary() {
269
247
  return (0, exports.buildTanStackQueryCacheSummary)(queryClient);
270
248
  },
@@ -284,22 +262,29 @@ const createTanStackQueryAgentController = (queryClient) => {
284
262
  return {
285
263
  ...(0, exports.buildTanStackQueryCacheSummary)(queryClient),
286
264
  total: queries.length,
287
- ...paginate(queries.map(getQuerySummary), 'queries', cursorState.queriesGeneration, input),
265
+ ...(0, agent_shared_1.paginateArray)(queries.map(getQuerySummary), {
266
+ keyOf: (row) => row.queryHash,
267
+ limit: input.limit,
268
+ cursor: input.cursor,
269
+ scope: 'queries',
270
+ }),
288
271
  };
289
272
  },
290
- getQueryDetails({ queryHash }) {
273
+ getQueryDetails({ queryHash, ...boundArgs }) {
274
+ const bounder = createValueBounder(QUERY_VALUE_FIELDS, boundArgs);
291
275
  const query = resolveQuery(queryClient, queryHash);
292
276
  return {
293
277
  summary: (0, exports.buildTanStackQueryCacheSummary)(queryClient),
294
278
  query: {
295
279
  ...getQuerySummary(query),
296
- data: (0, exports.serializeForAgent)(query.state.data),
297
- error: (0, exports.serializeForAgent)(query.state.error),
280
+ data: bounder.bound('data', (0, exports.serializeForAgent)(query.state.data)),
281
+ error: bounder.bound('error', (0, exports.serializeForAgent)(query.state.error)),
298
282
  observers: query.observers.map((observer) => ({
299
283
  queryHash: query.queryHash,
300
284
  options: pickObserverOptionsSummary(observer.options),
301
285
  })),
302
286
  },
287
+ ...bounder.finish(),
303
288
  };
304
289
  },
305
290
  async refetchQuery({ queryHash }) {
@@ -348,22 +333,29 @@ const createTanStackQueryAgentController = (queryClient) => {
348
333
  return {
349
334
  ...(0, exports.buildTanStackQueryCacheSummary)(queryClient),
350
335
  total: mutations.length,
351
- ...paginate(mutations.map(getMutationSummary), 'mutations', cursorState.mutationsGeneration, input),
336
+ ...(0, agent_shared_1.paginateArray)(mutations.map(getMutationSummary), {
337
+ keyOf: (row) => row.mutationId,
338
+ limit: input.limit,
339
+ cursor: input.cursor,
340
+ scope: 'mutations',
341
+ }),
352
342
  };
353
343
  },
354
- getMutationDetails({ mutationId }) {
344
+ getMutationDetails({ mutationId, ...boundArgs }) {
345
+ const bounder = createValueBounder(MUTATION_VALUE_FIELDS, boundArgs);
355
346
  const mutation = resolveMutation(queryClient, mutationId);
356
347
  return {
357
348
  summary: (0, exports.buildTanStackQueryCacheSummary)(queryClient),
358
349
  mutation: {
359
350
  ...getMutationSummary(mutation),
360
- variables: (0, exports.serializeForAgent)(mutation.state.variables),
361
- data: (0, exports.serializeForAgent)(mutation.state.data),
362
- error: (0, exports.serializeForAgent)(mutation.state.error),
363
- context: (0, exports.serializeForAgent)(mutation.state.context),
364
- failureReason: (0, exports.serializeForAgent)(mutation.state.failureReason),
351
+ variables: bounder.bound('variables', (0, exports.serializeForAgent)(mutation.state.variables)),
352
+ data: bounder.bound('data', (0, exports.serializeForAgent)(mutation.state.data)),
353
+ error: bounder.bound('error', (0, exports.serializeForAgent)(mutation.state.error)),
354
+ context: bounder.bound('context', (0, exports.serializeForAgent)(mutation.state.context)),
355
+ failureReason: bounder.bound('failureReason', (0, exports.serializeForAgent)(mutation.state.failureReason)),
365
356
  options: pickMutationOptionsSummary(mutation.options),
366
357
  },
358
+ ...bounder.finish(),
367
359
  };
368
360
  },
369
361
  async clearMutationCache() {
@@ -7,18 +7,6 @@ const tanstack_query_agent_1 = require("./tanstack-query-agent");
7
7
  const agent_tools_1 = require("../../shared/agent-tools");
8
8
  const useTanStackQueryAgentTools = (queryClient) => {
9
9
  const controller = (0, react_1.useMemo)(() => (0, tanstack_query_agent_1.createTanStackQueryAgentController)(queryClient), [queryClient]);
10
- (0, react_1.useEffect)(() => {
11
- const unsubscribeQueryCache = queryClient
12
- .getQueryCache()
13
- .subscribe((event) => controller.handleQueryCacheEvent(event));
14
- const unsubscribeMutationCache = queryClient
15
- .getMutationCache()
16
- .subscribe((event) => controller.handleMutationCacheEvent(event));
17
- return () => {
18
- unsubscribeQueryCache();
19
- unsubscribeMutationCache();
20
- };
21
- }, [controller, queryClient]);
22
10
  (0, agent_bridge_1.useRozenitePluginAgentTool)({
23
11
  pluginId: agent_tools_1.TANSTACK_QUERY_AGENT_PLUGIN_ID,
24
12
  tool: agent_tools_1.tanstackQueryToolDefinitions.getCacheSummary,
@@ -22,7 +22,21 @@ const paginationProperties = {
22
22
  },
23
23
  cursor: {
24
24
  type: 'string',
25
- description: 'Opaque pagination cursor from a previous list call.',
25
+ description: 'Opaque cursor from a previous page; the next page starts after the last row returned.',
26
+ },
27
+ };
28
+ const boundedValueProperties = {
29
+ maxDepth: {
30
+ type: 'integer',
31
+ description: 'Levels of nesting expanded below each returned value. Deeper objects and arrays collapse to "[object(N keys)]" / "[array(N)]". Defaults to 4, max 64.',
32
+ },
33
+ maxValueLength: {
34
+ type: 'integer',
35
+ description: 'Truncate string values longer than this, marking the cut with "[+N chars]". Defaults to 512.',
36
+ },
37
+ maxItems: {
38
+ type: 'integer',
39
+ description: 'Most array items or object keys returned per level; the rest are marked with a last "[+N items]" item or "[+N keys]" key. Defaults to 100, max 10000.',
26
40
  },
27
41
  };
28
42
  const emptyInputSchema = {
@@ -75,15 +89,23 @@ exports.tanstackQueryToolDefinitions = {
75
89
  'hasData',
76
90
  'hasError',
77
91
  ],
78
- defaultFields: ['queryHash', 'queryKey', 'status', 'fetchStatus', 'hasError'],
92
+ defaultFields: ['queryHash', 'status', 'fetchStatus', 'hasError'],
93
+ meta: ['total'],
79
94
  },
80
95
  }),
81
96
  getQueryDetails: (0, agent_shared_1.defineAgentToolContract)({
82
97
  name: 'get-query-details',
83
- description: 'Return a JSON-safe TanStack Query query snapshot and observer summary.',
98
+ description: 'Return a JSON-safe TanStack Query query snapshot and observer summary. data and error are cut to maxDepth levels, maxValueLength characters per string and maxItems entries per array or object; use path to read a deeper sub-tree.',
84
99
  inputSchema: {
85
100
  type: 'object',
86
- properties: queryActionProperties,
101
+ properties: {
102
+ ...queryActionProperties,
103
+ path: {
104
+ type: 'string',
105
+ description: 'Dot path starting with "data" or "error" selecting the sub-tree to return, for example "data.items.0".',
106
+ },
107
+ ...boundedValueProperties,
108
+ },
87
109
  required: ['queryHash'],
88
110
  },
89
111
  }),
@@ -178,14 +200,22 @@ exports.tanstackQueryToolDefinitions = {
178
200
  'hasError',
179
201
  ],
180
202
  defaultFields: ['mutationId', 'mutationKey', 'status', 'hasError'],
203
+ meta: ['total'],
181
204
  },
182
205
  }),
183
206
  getMutationDetails: (0, agent_shared_1.defineAgentToolContract)({
184
207
  name: 'get-mutation-details',
185
- description: 'Return a JSON-safe TanStack Query mutation snapshot for a mutationId.',
208
+ description: 'Return a JSON-safe TanStack Query mutation snapshot for a mutationId. variables, data, error, context and failureReason are cut to maxDepth levels, maxValueLength characters per string and maxItems entries per array or object; use path to read a deeper sub-tree.',
186
209
  inputSchema: {
187
210
  type: 'object',
188
- properties: mutationActionProperties,
211
+ properties: {
212
+ ...mutationActionProperties,
213
+ path: {
214
+ type: 'string',
215
+ description: 'Dot path starting with "variables", "data", "error", "context" or "failureReason" selecting the sub-tree to return, for example "variables.id".',
216
+ },
217
+ ...boundedValueProperties,
218
+ },
189
219
  required: ['mutationId'],
190
220
  },
191
221
  }),
@@ -1,11 +1,12 @@
1
- import type { MutationCacheNotifyEvent, QueryCacheNotifyEvent, QueryClient } from '@tanstack/react-query';
1
+ import type { QueryClient } from '@tanstack/react-query';
2
+ import { type BoundedValueArgs } from '@rozenite/agent-shared';
2
3
  import { type TanStackQueryAgentMutationIdInput as MutationIdInput, type TanStackQueryAgentOnlineStatusInput as OnlineStatusInput, type TanStackQueryAgentPaginationInput as PaginationInput, type TanStackQueryAgentQueryHashInput as QueryHashInput, type TanStackQueryAgentQueryToggleInput as QueryToggleInput, type TanStackQueryAgentSafeValue as AgentSafeValue, type TanStackQueryMutationOptionsSummary, type TanStackQueryObserverOptionsSummary } from '../../shared/agent-tools';
3
4
  export declare const serializeForAgent: (value: unknown, seen?: WeakSet<object>) => AgentSafeValue;
4
5
  export declare const getCacheSummaryTool: import("@rozenite/agent-shared").AgentToolContract<undefined, import("../../shared/agent-tools").TanStackQueryCacheSummary>;
5
6
  export declare const getOnlineStatusTool: import("@rozenite/agent-shared").AgentToolContract<undefined, import("../../shared/agent-tools").TanStackQueryGetOnlineStatusResult>;
6
7
  export declare const setOnlineStatusTool: import("@rozenite/agent-shared").AgentToolContract<OnlineStatusInput, import("../../shared/agent-tools").TanStackQuerySetOnlineStatusResult>;
7
8
  export declare const listQueriesTool: import("@rozenite/agent-shared").AgentToolContract<PaginationInput, import("../../shared/agent-tools").TanStackQueryListQueriesResult>;
8
- export declare const getQueryDetailsTool: import("@rozenite/agent-shared").AgentToolContract<QueryHashInput, import("../../shared/agent-tools").TanStackQueryGetQueryDetailsResult>;
9
+ export declare const getQueryDetailsTool: import("@rozenite/agent-shared").AgentToolContract<import("../../shared/agent-tools").TanStackQueryGetQueryDetailsArgs, import("../../shared/agent-tools").TanStackQueryGetQueryDetailsResult>;
9
10
  export declare const refetchQueryTool: import("@rozenite/agent-shared").AgentToolContract<QueryHashInput, {
10
11
  applied: boolean;
11
12
  action: "CLEAR_QUERY_CACHE";
@@ -707,7 +708,7 @@ export declare const clearQueryCacheTool: import("@rozenite/agent-shared").Agent
707
708
  mutationCountAfter?: undefined;
708
709
  }>;
709
710
  export declare const listMutationsTool: import("@rozenite/agent-shared").AgentToolContract<PaginationInput, import("../../shared/agent-tools").TanStackQueryListMutationsResult>;
710
- export declare const getMutationDetailsTool: import("@rozenite/agent-shared").AgentToolContract<MutationIdInput, import("../../shared/agent-tools").TanStackQueryGetMutationDetailsResult>;
711
+ export declare const getMutationDetailsTool: import("@rozenite/agent-shared").AgentToolContract<import("../../shared/agent-tools").TanStackQueryGetMutationDetailsArgs, import("../../shared/agent-tools").TanStackQueryGetMutationDetailsResult>;
711
712
  export declare const clearMutationCacheTool: import("@rozenite/agent-shared").AgentToolContract<undefined, {
712
713
  applied: boolean;
713
714
  action: "CLEAR_QUERY_CACHE";
@@ -808,7 +809,7 @@ export declare const clearMutationCacheTool: import("@rozenite/agent-shared").Ag
808
809
  mutationCountBefore?: undefined;
809
810
  mutationCountAfter?: undefined;
810
811
  }>;
811
- export declare const TANSTACK_QUERY_AGENT_TOOLS: (import("@rozenite/agent-shared").AgentToolContract<undefined, import("../../shared/agent-tools").TanStackQueryCacheSummary> | import("@rozenite/agent-shared").AgentToolContract<undefined, import("../../shared/agent-tools").TanStackQueryGetOnlineStatusResult> | import("@rozenite/agent-shared").AgentToolContract<OnlineStatusInput, import("../../shared/agent-tools").TanStackQuerySetOnlineStatusResult> | import("@rozenite/agent-shared").AgentToolContract<PaginationInput, import("../../shared/agent-tools").TanStackQueryListQueriesResult> | import("@rozenite/agent-shared").AgentToolContract<QueryHashInput, import("../../shared/agent-tools").TanStackQueryGetQueryDetailsResult> | import("@rozenite/agent-shared").AgentToolContract<QueryHashInput, {
812
+ export declare const TANSTACK_QUERY_AGENT_TOOLS: (import("@rozenite/agent-shared").AgentToolContract<undefined, import("../../shared/agent-tools").TanStackQueryCacheSummary> | import("@rozenite/agent-shared").AgentToolContract<undefined, import("../../shared/agent-tools").TanStackQueryGetOnlineStatusResult> | import("@rozenite/agent-shared").AgentToolContract<OnlineStatusInput, import("../../shared/agent-tools").TanStackQuerySetOnlineStatusResult> | import("@rozenite/agent-shared").AgentToolContract<PaginationInput, import("../../shared/agent-tools").TanStackQueryListQueriesResult> | import("@rozenite/agent-shared").AgentToolContract<import("../../shared/agent-tools").TanStackQueryGetQueryDetailsArgs, import("../../shared/agent-tools").TanStackQueryGetQueryDetailsResult> | import("@rozenite/agent-shared").AgentToolContract<QueryHashInput, {
812
813
  applied: boolean;
813
814
  action: "CLEAR_QUERY_CACHE";
814
815
  cleared: boolean;
@@ -1105,7 +1106,7 @@ export declare const TANSTACK_QUERY_AGENT_TOOLS: (import("@rozenite/agent-shared
1105
1106
  queryCountAfter?: undefined;
1106
1107
  mutationCountBefore?: undefined;
1107
1108
  mutationCountAfter?: undefined;
1108
- }> | import("@rozenite/agent-shared").AgentToolContract<PaginationInput, import("../../shared/agent-tools").TanStackQueryListMutationsResult> | import("@rozenite/agent-shared").AgentToolContract<MutationIdInput, import("../../shared/agent-tools").TanStackQueryGetMutationDetailsResult>)[];
1109
+ }> | import("@rozenite/agent-shared").AgentToolContract<PaginationInput, import("../../shared/agent-tools").TanStackQueryListMutationsResult> | import("@rozenite/agent-shared").AgentToolContract<import("../../shared/agent-tools").TanStackQueryGetMutationDetailsArgs, import("../../shared/agent-tools").TanStackQueryGetMutationDetailsResult>)[];
1109
1110
  export declare const buildTanStackQueryCacheSummary: (queryClient: QueryClient) => {
1110
1111
  online: boolean;
1111
1112
  queries: {
@@ -1126,8 +1127,6 @@ export declare const buildTanStackQueryCacheSummary: (queryClient: QueryClient)
1126
1127
  };
1127
1128
  };
1128
1129
  export declare const createTanStackQueryAgentController: (queryClient: QueryClient) => {
1129
- handleQueryCacheEvent(event: QueryCacheNotifyEvent): void;
1130
- handleMutationCacheEvent(event: MutationCacheNotifyEvent): void;
1131
1130
  getCacheSummary(): {
1132
1131
  online: boolean;
1133
1132
  queries: {
@@ -1166,11 +1165,8 @@ export declare const createTanStackQueryAgentController: (queryClient: QueryClie
1166
1165
  hasData: boolean;
1167
1166
  hasError: boolean;
1168
1167
  }[];
1169
- page: {
1170
- nextCursor?: string | undefined;
1171
- limit: number;
1172
- hasMore: boolean;
1173
- };
1168
+ page: import("@rozenite/agent-shared").PageEnvelope;
1169
+ meta?: unknown;
1174
1170
  total: number;
1175
1171
  online: boolean;
1176
1172
  queries: {
@@ -1190,7 +1186,9 @@ export declare const createTanStackQueryAgentController: (queryClient: QueryClie
1190
1186
  paused: number;
1191
1187
  };
1192
1188
  };
1193
- getQueryDetails({ queryHash }: QueryHashInput): {
1189
+ getQueryDetails({ queryHash, ...boundArgs }: QueryHashInput & BoundedValueArgs): {
1190
+ truncated: boolean;
1191
+ path?: string | undefined;
1194
1192
  summary: {
1195
1193
  online: boolean;
1196
1194
  queries: {
@@ -1940,11 +1938,8 @@ export declare const createTanStackQueryAgentController: (queryClient: QueryClie
1940
1938
  hasData: boolean;
1941
1939
  hasError: boolean;
1942
1940
  }[];
1943
- page: {
1944
- nextCursor?: string | undefined;
1945
- limit: number;
1946
- hasMore: boolean;
1947
- };
1941
+ page: import("@rozenite/agent-shared").PageEnvelope;
1942
+ meta?: unknown;
1948
1943
  total: number;
1949
1944
  online: boolean;
1950
1945
  queries: {
@@ -1964,7 +1959,9 @@ export declare const createTanStackQueryAgentController: (queryClient: QueryClie
1964
1959
  paused: number;
1965
1960
  };
1966
1961
  };
1967
- getMutationDetails({ mutationId }: MutationIdInput): {
1962
+ getMutationDetails({ mutationId, ...boundArgs }: MutationIdInput & BoundedValueArgs): {
1963
+ truncated: boolean;
1964
+ path?: string | undefined;
1968
1965
  summary: {
1969
1966
  online: boolean;
1970
1967
  queries: {
@@ -1,8 +1,7 @@
1
1
  import { onlineManager } from '@tanstack/react-query';
2
+ import { boundValue, normalizeBoundedValueArgs, paginateArray, selectValuePath, } from '@rozenite/agent-shared';
2
3
  import { applyTanStackQueryDevtoolsAction } from '../devtools-actions';
3
4
  import { tanstackQueryToolDefinitions, } from '../../shared/agent-tools';
4
- const DEFAULT_PAGE_LIMIT = 20;
5
- const MAX_PAGE_LIMIT = 100;
6
5
  const isPlainObject = (value) => {
7
6
  return !!value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype;
8
7
  };
@@ -58,47 +57,6 @@ export const serializeForAgent = (value, seen = new WeakSet()) => {
58
57
  }
59
58
  return String(value);
60
59
  };
61
- const sanitizeLimit = (limit) => {
62
- if (typeof limit !== 'number' ||
63
- !Number.isFinite(limit) ||
64
- !Number.isInteger(limit) ||
65
- limit < 1) {
66
- return DEFAULT_PAGE_LIMIT;
67
- }
68
- return Math.min(limit, MAX_PAGE_LIMIT);
69
- };
70
- const encodeCursor = (kind, generation, offset) => {
71
- return `${kind}:${generation}:${offset}`;
72
- };
73
- const decodeCursor = (cursor, kind, generation) => {
74
- const [cursorKind, rawGeneration, rawOffset] = cursor.split(':', 3);
75
- if (cursorKind !== kind || !rawGeneration || !rawOffset) {
76
- throw new Error('Cursor does not match the requested listing. Run the command again.');
77
- }
78
- const cursorGeneration = Number(rawGeneration);
79
- const offset = Number(rawOffset);
80
- if (!Number.isInteger(cursorGeneration) || cursorGeneration !== generation) {
81
- throw new Error('Cursor does not match the requested listing. Run the command again.');
82
- }
83
- if (!Number.isInteger(offset) || offset < 0) {
84
- throw new Error('Cursor is invalid. Run the command again.');
85
- }
86
- return offset;
87
- };
88
- const paginate = (rows, kind, generation, input) => {
89
- const limit = sanitizeLimit(input.limit);
90
- const startIndex = input.cursor ? decodeCursor(input.cursor, kind, generation) : 0;
91
- const endIndex = Math.min(startIndex + limit, rows.length);
92
- const hasMore = endIndex < rows.length;
93
- return {
94
- items: rows.slice(startIndex, endIndex),
95
- page: {
96
- limit,
97
- hasMore,
98
- ...(hasMore ? { nextCursor: encodeCursor(kind, generation, endIndex) } : {}),
99
- },
100
- };
101
- };
102
60
  export const getCacheSummaryTool = tanstackQueryToolDefinitions.getCacheSummary;
103
61
  export const getOnlineStatusTool = tanstackQueryToolDefinitions.getOnlineStatus;
104
62
  export const setOnlineStatusTool = tanstackQueryToolDefinitions.setOnlineStatus;
@@ -194,6 +152,40 @@ const getMutationSummary = (mutation) => {
194
152
  hasError: mutation.state.error != null,
195
153
  };
196
154
  };
155
+ /**
156
+ * Applies `path`, `maxDepth`, `maxValueLength` and `maxItems` to the named value fields
157
+ * of a details result. `path` must start with one of `fields`.
158
+ */
159
+ const createValueBounder = (fields, args) => {
160
+ const bounds = normalizeBoundedValueArgs(args);
161
+ const pathField = bounds.path?.[0];
162
+ if (bounds.path && !fields.includes(pathField)) {
163
+ throw new Error(`"path" must start with ${fields.map((field) => `"${field}"`).join(', ')}.`);
164
+ }
165
+ let truncated = false;
166
+ return {
167
+ bound(field, value) {
168
+ const selected = bounds.path && pathField === field
169
+ ? selectValuePath(value, bounds.path.slice(1), [field])
170
+ : value;
171
+ const result = boundValue(selected, {
172
+ maxDepth: bounds.maxDepth,
173
+ maxValueLength: bounds.maxValueLength,
174
+ maxItems: bounds.maxItems,
175
+ });
176
+ truncated = truncated || result.truncated;
177
+ return result.value;
178
+ },
179
+ finish() {
180
+ return {
181
+ ...(bounds.path ? { path: bounds.path.join('.') } : {}),
182
+ truncated,
183
+ };
184
+ },
185
+ };
186
+ };
187
+ const QUERY_VALUE_FIELDS = ['data', 'error'];
188
+ const MUTATION_VALUE_FIELDS = ['variables', 'data', 'error', 'context', 'failureReason'];
197
189
  const resolveQuery = (queryClient, queryHash) => {
198
190
  const query = queryClient.getQueryCache().get(queryHash);
199
191
  if (!query) {
@@ -245,21 +237,7 @@ export const buildTanStackQueryCacheSummary = (queryClient) => {
245
237
  };
246
238
  };
247
239
  export const createTanStackQueryAgentController = (queryClient) => {
248
- const cursorState = {
249
- queriesGeneration: 0,
250
- mutationsGeneration: 0,
251
- };
252
240
  return {
253
- handleQueryCacheEvent(event) {
254
- if (event.type === 'added' || event.type === 'removed') {
255
- cursorState.queriesGeneration += 1;
256
- }
257
- },
258
- handleMutationCacheEvent(event) {
259
- if (event.type === 'added' || event.type === 'removed') {
260
- cursorState.mutationsGeneration += 1;
261
- }
262
- },
263
241
  getCacheSummary() {
264
242
  return buildTanStackQueryCacheSummary(queryClient);
265
243
  },
@@ -279,22 +257,29 @@ export const createTanStackQueryAgentController = (queryClient) => {
279
257
  return {
280
258
  ...buildTanStackQueryCacheSummary(queryClient),
281
259
  total: queries.length,
282
- ...paginate(queries.map(getQuerySummary), 'queries', cursorState.queriesGeneration, input),
260
+ ...paginateArray(queries.map(getQuerySummary), {
261
+ keyOf: (row) => row.queryHash,
262
+ limit: input.limit,
263
+ cursor: input.cursor,
264
+ scope: 'queries',
265
+ }),
283
266
  };
284
267
  },
285
- getQueryDetails({ queryHash }) {
268
+ getQueryDetails({ queryHash, ...boundArgs }) {
269
+ const bounder = createValueBounder(QUERY_VALUE_FIELDS, boundArgs);
286
270
  const query = resolveQuery(queryClient, queryHash);
287
271
  return {
288
272
  summary: buildTanStackQueryCacheSummary(queryClient),
289
273
  query: {
290
274
  ...getQuerySummary(query),
291
- data: serializeForAgent(query.state.data),
292
- error: serializeForAgent(query.state.error),
275
+ data: bounder.bound('data', serializeForAgent(query.state.data)),
276
+ error: bounder.bound('error', serializeForAgent(query.state.error)),
293
277
  observers: query.observers.map((observer) => ({
294
278
  queryHash: query.queryHash,
295
279
  options: pickObserverOptionsSummary(observer.options),
296
280
  })),
297
281
  },
282
+ ...bounder.finish(),
298
283
  };
299
284
  },
300
285
  async refetchQuery({ queryHash }) {
@@ -343,22 +328,29 @@ export const createTanStackQueryAgentController = (queryClient) => {
343
328
  return {
344
329
  ...buildTanStackQueryCacheSummary(queryClient),
345
330
  total: mutations.length,
346
- ...paginate(mutations.map(getMutationSummary), 'mutations', cursorState.mutationsGeneration, input),
331
+ ...paginateArray(mutations.map(getMutationSummary), {
332
+ keyOf: (row) => row.mutationId,
333
+ limit: input.limit,
334
+ cursor: input.cursor,
335
+ scope: 'mutations',
336
+ }),
347
337
  };
348
338
  },
349
- getMutationDetails({ mutationId }) {
339
+ getMutationDetails({ mutationId, ...boundArgs }) {
340
+ const bounder = createValueBounder(MUTATION_VALUE_FIELDS, boundArgs);
350
341
  const mutation = resolveMutation(queryClient, mutationId);
351
342
  return {
352
343
  summary: buildTanStackQueryCacheSummary(queryClient),
353
344
  mutation: {
354
345
  ...getMutationSummary(mutation),
355
- variables: serializeForAgent(mutation.state.variables),
356
- data: serializeForAgent(mutation.state.data),
357
- error: serializeForAgent(mutation.state.error),
358
- context: serializeForAgent(mutation.state.context),
359
- failureReason: serializeForAgent(mutation.state.failureReason),
346
+ variables: bounder.bound('variables', serializeForAgent(mutation.state.variables)),
347
+ data: bounder.bound('data', serializeForAgent(mutation.state.data)),
348
+ error: bounder.bound('error', serializeForAgent(mutation.state.error)),
349
+ context: bounder.bound('context', serializeForAgent(mutation.state.context)),
350
+ failureReason: bounder.bound('failureReason', serializeForAgent(mutation.state.failureReason)),
360
351
  options: pickMutationOptionsSummary(mutation.options),
361
352
  },
353
+ ...bounder.finish(),
362
354
  };
363
355
  },
364
356
  async clearMutationCache() {