@kubb/plugin-react-query 5.0.0-beta.99 → 5.1.0-canary.20260819T202657

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/dist/index.cjs CHANGED
@@ -19,259 +19,19 @@ var __copyProps = (to, from, except, desc) => {
19
19
  }
20
20
  return to;
21
21
  };
22
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
23
23
  value: mod,
24
24
  enumerable: true
25
25
  }) : target, mod));
26
26
  //#endregion
27
+ let kubb_kit = require("kubb/kit");
27
28
  let node_path = require("node:path");
28
29
  node_path = __toESM(node_path, 1);
29
- let kubb_kit = require("kubb/kit");
30
30
  let _kubb_plugin_ts = require("@kubb/plugin-ts");
31
31
  let kubb_jsx = require("kubb/jsx");
32
32
  let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
33
33
  let node_fs = require("node:fs");
34
34
  node_fs = __toESM(node_fs, 1);
35
- //#region ../../internals/utils/src/casing.ts
36
- /**
37
- * Shared implementation for camelCase and PascalCase conversion.
38
- * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
39
- * and capitalizes each word according to `pascal`.
40
- *
41
- * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
42
- */
43
- function toCamelOrPascal(text, pascal) {
44
- return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
45
- if (word.length > 1 && word === word.toUpperCase()) return word;
46
- return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
47
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
48
- }
49
- /**
50
- * Converts `text` to camelCase.
51
- *
52
- * @example Word boundaries
53
- * `camelCase('hello-world') // 'helloWorld'`
54
- *
55
- * @example With a prefix
56
- * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
57
- */
58
- function camelCase(text, { prefix = "", suffix = "" } = {}) {
59
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
60
- }
61
- /**
62
- * Uppercases only the first character of `text`, leaving the rest untouched.
63
- * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.
64
- *
65
- * @example
66
- * `capitalize('getPetById') // 'GetPetById'`
67
- */
68
- function capitalize(text) {
69
- return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
70
- }
71
- //#endregion
72
- //#region ../../internals/utils/src/reserved.ts
73
- /**
74
- * JavaScript and Java reserved words.
75
- * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
76
- */
77
- const reservedWords = /* @__PURE__ */ new Set([
78
- "abstract",
79
- "arguments",
80
- "boolean",
81
- "break",
82
- "byte",
83
- "case",
84
- "catch",
85
- "char",
86
- "class",
87
- "const",
88
- "continue",
89
- "debugger",
90
- "default",
91
- "delete",
92
- "do",
93
- "double",
94
- "else",
95
- "enum",
96
- "eval",
97
- "export",
98
- "extends",
99
- "false",
100
- "final",
101
- "finally",
102
- "float",
103
- "for",
104
- "function",
105
- "goto",
106
- "if",
107
- "implements",
108
- "import",
109
- "in",
110
- "instanceof",
111
- "int",
112
- "interface",
113
- "let",
114
- "long",
115
- "native",
116
- "new",
117
- "null",
118
- "package",
119
- "private",
120
- "protected",
121
- "public",
122
- "return",
123
- "short",
124
- "static",
125
- "super",
126
- "switch",
127
- "synchronized",
128
- "this",
129
- "throw",
130
- "throws",
131
- "transient",
132
- "true",
133
- "try",
134
- "typeof",
135
- "var",
136
- "void",
137
- "volatile",
138
- "while",
139
- "with",
140
- "yield",
141
- "Array",
142
- "Date",
143
- "hasOwnProperty",
144
- "Infinity",
145
- "isFinite",
146
- "isNaN",
147
- "isPrototypeOf",
148
- "length",
149
- "Math",
150
- "name",
151
- "NaN",
152
- "Number",
153
- "Object",
154
- "prototype",
155
- "String",
156
- "toString",
157
- "undefined",
158
- "valueOf"
159
- ]);
160
- /**
161
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
162
- *
163
- * @example
164
- * ```ts
165
- * isValidVarName('status') // true
166
- * isValidVarName('class') // false (reserved word)
167
- * isValidVarName('42foo') // false (starts with digit)
168
- * ```
169
- */
170
- function isValidVarName(name) {
171
- if (!name || reservedWords.has(name)) return false;
172
- return isIdentifier(name);
173
- }
174
- /**
175
- * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
176
- *
177
- * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
178
- * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
179
- * deciding whether an object key needs quoting.
180
- *
181
- * @example
182
- * ```ts
183
- * isIdentifier('name') // true
184
- * isIdentifier('x-total')// false
185
- * ```
186
- */
187
- function isIdentifier(name) {
188
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
189
- }
190
- //#endregion
191
- //#region ../../internals/utils/src/strings.ts
192
- /**
193
- * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
194
- * `accessor`. Returns `null` for an empty path.
195
- *
196
- * @example
197
- * ```ts
198
- * getNestedAccessor('pagination.next.id', 'lastPage')
199
- * // "lastPage?.['pagination']?.['next']?.['id']"
200
- * ```
201
- */
202
- function getNestedAccessor(param, accessor) {
203
- const parts = Array.isArray(param) ? param : param.split(".");
204
- if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
205
- return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
206
- }
207
- //#endregion
208
- //#region ../../internals/utils/src/url.ts
209
- /**
210
- * Keeps the OpenAPI parameter name as-is when it is already a valid JS identifier, and
211
- * camelCases it only enough to become one otherwise (for example a hyphenated path segment).
212
- */
213
- function transformParam(raw) {
214
- return isValidVarName(raw) ? raw : camelCase(raw);
215
- }
216
- /**
217
- * Helpers for OpenAPI/Swagger paths.
218
- */
219
- var Url = class Url {
220
- /**
221
- * Converts an OpenAPI/Swagger path to Express-style colon syntax.
222
- *
223
- * @example
224
- * Url.toPath('/pet/{petId}') // '/pet/:petId'
225
- */
226
- static toPath(path) {
227
- return path.replace(/\{([^}]+)\}/g, ":$1");
228
- }
229
- /**
230
- * Rewrites OpenAPI placeholder names while keeping the `{...}` braces, so the generated `url`
231
- * literal aligns with the grouped `path` request option that the runtime client interpolates by
232
- * key.
233
- *
234
- * @example
235
- * Url.toSafeTemplate('/user/{monetary-account-id}') // '/user/{monetaryAccountId}'
236
- */
237
- static toSafeTemplate(path) {
238
- return path.replace(/\{([^}]+)\}/g, (_, name) => `{${transformParam(name)}}`);
239
- }
240
- /**
241
- * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
242
- * `prefix` is prepended inside the literal, and `replacer` transforms each parameter name.
243
- *
244
- * @example
245
- * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
246
- *
247
- * @example
248
- * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
249
- */
250
- static toTemplateString(path, { prefix, replacer } = {}) {
251
- const result = path.split(/\{([^}]+)\}/).map((part, i) => {
252
- if (i % 2 === 0) return part;
253
- const param = transformParam(part);
254
- return `\${${replacer ? replacer(param) : param}}`;
255
- }).join("");
256
- return `\`${prefix ?? ""}${result}\``;
257
- }
258
- /**
259
- * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
260
- * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
261
- * names match the generated `path` type, and `prefix` is prepended inside the literal. Shared by
262
- * the client and cypress generators that pass a grouped `path` object.
263
- *
264
- * @example
265
- * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
266
- */
267
- static toGroupedTemplateString(path, { prefix } = {}) {
268
- return Url.toTemplateString(path, {
269
- prefix,
270
- replacer: (name) => `path.${name}`
271
- });
272
- }
273
- };
274
- //#endregion
275
35
  //#region ../../internals/shared/src/params.ts
276
36
  /**
277
37
  * Drops parameters that share the same name, keeping the first.
@@ -310,11 +70,30 @@ function operationFileEntry(node, name, extname = ".ts") {
310
70
  path: node.path
311
71
  };
312
72
  }
73
+ /**
74
+ * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the
75
+ * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the
76
+ * same dependency for the same operation in one pass (a query plugin's several hook generators, the
77
+ * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.
78
+ *
79
+ * @example Cache `plugin-ts`'s file for the current operation
80
+ * ```ts
81
+ * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })
82
+ * ```
83
+ */
84
+ function resolveDependencyOperationFile(options) {
85
+ const { cache, node, resolver, root, output, group } = options;
86
+ return cache.ensureItem(`${resolver.pluginName}:operationFile`, () => resolver.file({
87
+ ...operationFileEntry(node, node.operationId),
88
+ root,
89
+ output,
90
+ group: group ?? void 0
91
+ }));
92
+ }
313
93
  function getOperationLink(node, link) {
314
94
  if (!link) return null;
315
95
  if (typeof link === "function") return link(node) ?? null;
316
- if (link === "urlPath") return node.path ? `{@link ${Url.toPath(node.path)}}` : null;
317
- return node.path ? `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}` : null;
96
+ return node.path ? `{@link ${kubb_kit.Url.toPath(node.path)}}` : null;
318
97
  }
319
98
  /**
320
99
  * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several
@@ -404,16 +183,24 @@ function buildOperationComments(node, options = {}) {
404
183
  if (!splitLines) return filteredComments;
405
184
  return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
406
185
  }
186
+ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
187
+ /**
188
+ * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
189
+ * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
190
+ * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
191
+ * same parameters once per plugin.
192
+ */
407
193
  function getOperationParameters(node) {
408
- return {
409
- path: dedupeParams(node.parameters.filter((param) => param.in === "path").map((param) => isValidVarName(param.name) ? param : {
410
- ...param,
411
- name: camelCase(param.name)
412
- })),
194
+ const cached = operationParameterGroupsByNode.get(node);
195
+ if (cached) return cached;
196
+ const groups = {
197
+ path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
413
198
  query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
414
199
  header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
415
200
  cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
416
201
  };
202
+ operationParameterGroupsByNode.set(node, groups);
203
+ return groups;
417
204
  }
418
205
  function getStatusCodeNumber(statusCode) {
419
206
  const code = Number(statusCode);
@@ -478,6 +265,60 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
478
265
  return result;
479
266
  }
480
267
  //#endregion
268
+ //#region ../../internals/utils/src/casing.ts
269
+ /**
270
+ * Shared implementation for camelCase and PascalCase conversion.
271
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
272
+ * and capitalizes each word according to `pascal`.
273
+ *
274
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
275
+ */
276
+ function toCamelOrPascal(text, pascal) {
277
+ return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
278
+ if (word.length > 1 && word === word.toUpperCase()) return word;
279
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
280
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
281
+ }
282
+ /**
283
+ * Converts `text` to camelCase.
284
+ *
285
+ * @example Word boundaries
286
+ * `camelCase('hello-world') // 'helloWorld'`
287
+ *
288
+ * @example With a prefix
289
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
290
+ */
291
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
292
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
293
+ }
294
+ /**
295
+ * Uppercases only the first character of `text`, leaving the rest untouched.
296
+ * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.
297
+ *
298
+ * @example
299
+ * `capitalize('getPetById') // 'GetPetById'`
300
+ */
301
+ function capitalize(text) {
302
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
303
+ }
304
+ //#endregion
305
+ //#region ../../internals/utils/src/strings.ts
306
+ /**
307
+ * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
308
+ * `accessor`. Returns `null` for an empty path.
309
+ *
310
+ * @example
311
+ * ```ts
312
+ * getNestedAccessor('pagination.next.id', 'lastPage')
313
+ * // "lastPage?.['pagination']?.['next']?.['id']"
314
+ * ```
315
+ */
316
+ function getNestedAccessor(param, accessor) {
317
+ const parts = Array.isArray(param) ? param : param.split(".");
318
+ if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
319
+ return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
320
+ }
321
+ //#endregion
481
322
  //#region ../../internals/shared/src/group.ts
482
323
  /**
483
324
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -597,23 +438,30 @@ function resolveContractClient(options) {
597
438
  * (plugin-fetch or plugin-axios). Returns `null` when no contract plugin is in play (the inline
598
439
  * path). The plugin injects `.kubb/client.ts` at the global output root, the same path consumers
599
440
  * read `RequestConfig` / `ResponseErrorConfig` from.
441
+ *
442
+ * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,
443
+ * so several dependents reading the same client plugin for one operation in a single pass
444
+ * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share
445
+ * one computed result instead of each re-deriving the name and path.
600
446
  */
601
447
  function resolveClientOperation(options) {
602
- const { clientPlugin, driver, node, root, output } = options;
448
+ const { clientPlugin, driver, node, root, output, cache } = options;
603
449
  if (!clientPlugin) return null;
604
- const resolver = driver.getResolver(clientPlugin.pluginName);
605
- const plugin = driver.getPlugin(clientPlugin.pluginName);
606
- const file = resolver.file({
607
- ...operationFileEntry(node, node.operationId),
608
- root,
609
- output: plugin?.options?.output ?? output,
610
- group: plugin?.options?.group ?? void 0
450
+ return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {
451
+ const resolver = driver.getResolver(clientPlugin.pluginName);
452
+ const plugin = driver.getPlugin(clientPlugin.pluginName);
453
+ const file = resolver.file({
454
+ ...operationFileEntry(node, node.operationId),
455
+ root,
456
+ output: plugin?.options?.output ?? output,
457
+ group: plugin?.options?.group ?? void 0
458
+ });
459
+ return {
460
+ name: resolver.name(node.operationId),
461
+ path: file.path,
462
+ clientPath: node_path.default.resolve(root, ".kubb/client.ts")
463
+ };
611
464
  });
612
- return {
613
- name: resolver.name(node.operationId),
614
- path: file.path,
615
- clientPath: node_path.default.resolve(root, ".kubb/client.ts")
616
- };
617
465
  }
618
466
  //#endregion
619
467
  //#region ../../internals/tanstack-query/src/utils.ts
@@ -684,14 +532,16 @@ function buildGroupedRequestParam(node, options) {
684
532
  */
685
533
  function buildQueryOptionsParams(node, options) {
686
534
  const { resolver, memberTypeWrapper } = options;
687
- return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
535
+ const groupedParam = buildGroupedRequestParam(node, {
688
536
  resolver,
689
537
  memberTypeWrapper
690
- }), (0, _kubb_plugin_ts.createFunctionParameter)({
538
+ });
539
+ const configParam = (0, _kubb_plugin_ts.createFunctionParameter)({
691
540
  name: "config",
692
541
  type: `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`,
693
542
  default: "{}"
694
- })].filter((param) => param !== null) });
543
+ });
544
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [groupedParam, configParam].filter((param) => param !== null) });
695
545
  }
696
546
  /**
697
547
  * Builds the call to a client `<op>` function inside a query/mutation hook body. The function takes
@@ -789,6 +639,19 @@ function resolveMutationConfig(mutation, options) {
789
639
  };
790
640
  }
791
641
  /**
642
+ * Classifies an operation as a query or a mutation from the resolved `query` / `mutation` method lists.
643
+ * `query: false` still marks the operation as a query so the query-family generators keep matching it,
644
+ * and a method already claimed by `query` never counts as a mutation.
645
+ */
646
+ function classifyOperation(node, { query, mutation }) {
647
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
648
+ const queryMethods = new Set(query ? query.methods : []);
649
+ return {
650
+ isQuery,
651
+ isMutation: mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase())
652
+ };
653
+ }
654
+ /**
792
655
  * Applies the shared infinite-query defaults during plugin setup: a falsy value disables infinite
793
656
  * queries, and an object merges over `queryParam: 'id'` and `initialPageParam: 0` with the cursor
794
657
  * paths cleared.
@@ -923,7 +786,7 @@ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${que
923
786
  const declarationPrinter$6 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
924
787
  const mutationKeyTransformer = ({ node }) => {
925
788
  if (!node.path) return [];
926
- return [`{ url: '${Url.toPath(node.path)}' }`];
789
+ return [`{ url: '${kubb_kit.Url.toPath(node.path)}' }`];
927
790
  };
928
791
  function MutationKey({ name, node, transformer }) {
929
792
  const paramsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: [] });
@@ -1007,7 +870,7 @@ const queryKeyTransformer = ({ node }) => {
1007
870
  const hasQueryParams = getOperationParameters(node).query.length > 0;
1008
871
  const hasRequestBody = !!node.requestBody?.content?.[0]?.schema;
1009
872
  return [
1010
- hasPathParams ? `{ url: '${Url.toPath(node.path)}', params: path }` : `{ url: '${Url.toPath(node.path)}' }`,
873
+ hasPathParams ? `{ url: '${kubb_kit.Url.toPath(node.path)}', params: path }` : `{ url: '${kubb_kit.Url.toPath(node.path)}' }`,
1011
874
  hasQueryParams ? "...(query ? [query] : [])" : null,
1012
875
  hasRequestBody ? "...(body ? [body] : [])" : null
1013
876
  ].filter(Boolean);
@@ -1158,19 +1021,6 @@ function buildResolvedRequestParams(node) {
1158
1021
  if (names.length === 0) return null;
1159
1022
  return `{ ${names.map((name) => `${name}: typeof ${name} === 'function' ? ${name}() : ${name}`).join(", ")} }`;
1160
1023
  }
1161
- /**
1162
- * Classifies an operation as a query or a mutation from the resolved `query` / `mutation` method lists.
1163
- * `query: false` still marks the operation as a query so the query-family generators keep matching it,
1164
- * and a method already claimed by `query` never counts as a mutation.
1165
- */
1166
- function classifyOperation(node, { query, mutation }) {
1167
- const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1168
- const queryMethods = new Set(query ? query.methods : []);
1169
- return {
1170
- isQuery,
1171
- isMutation: mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase())
1172
- };
1173
- }
1174
1024
  //#endregion
1175
1025
  //#region src/generators/hookOptionsGenerator.tsx
1176
1026
  /**
@@ -1345,10 +1195,11 @@ function buildInfiniteQueryParamsNode(node, options) {
1345
1195
  }`,
1346
1196
  default: "{}"
1347
1197
  });
1348
- return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
1198
+ const groupedParam = buildGroupedRequestParam(node, {
1349
1199
  resolver,
1350
1200
  memberTypeWrapper: maybeValueOrGetter
1351
- }), optionsParam].filter((param) => param !== null) });
1201
+ });
1202
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
1352
1203
  }
1353
1204
  function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, initialPageParam, queryParam, customOptions, suspense }) {
1354
1205
  const { TData: responseType, TError: errorType } = buildResponseTypes(node, tsResolver);
@@ -1461,15 +1312,16 @@ function resolveMutationRequestType(node, resolver) {
1461
1312
  function buildMutationParamsNode(node, options) {
1462
1313
  const { resolver } = options;
1463
1314
  const { TData, TError } = buildResponseTypes(node, resolver);
1315
+ const generics = [
1316
+ TData,
1317
+ TError,
1318
+ resolveMutationRequestType(node, resolver),
1319
+ "TContext"
1320
+ ].join(", ");
1464
1321
  return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
1465
1322
  name: "options",
1466
1323
  type: `{
1467
- mutation?: UseMutationOptions<${[
1468
- TData,
1469
- TError,
1470
- resolveMutationRequestType(node, resolver),
1471
- "TContext"
1472
- ].join(", ")}> & { client?: QueryClient },
1324
+ mutation?: UseMutationOptions<${generics}> & { client?: QueryClient },
1473
1325
  client?: ${buildRequestConfigType(node)},
1474
1326
  }`,
1475
1327
  default: "{}"
@@ -1527,10 +1379,11 @@ function buildQueryParamsNode(node, options) {
1527
1379
  }`,
1528
1380
  default: "{}"
1529
1381
  });
1530
- return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
1382
+ const groupedParam = buildGroupedRequestParam(node, {
1531
1383
  resolver,
1532
1384
  memberTypeWrapper: maybeValueOrGetter
1533
- }), optionsParam].filter((param) => param !== null) });
1385
+ });
1386
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
1534
1387
  }
1535
1388
  function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense }) {
1536
1389
  const { TData, TError } = buildResponseTypes(node, tsResolver);
@@ -1595,14 +1448,11 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
1595
1448
  //#region src/components/QueryOptions.tsx
1596
1449
  const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1597
1450
  const callPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1598
- function getQueryOptionsParams(node, options) {
1599
- return buildQueryOptionsParams(node, options);
1600
- }
1601
1451
  function QueryOptions({ name, clientName, node, tsResolver, queryKeyName }) {
1602
1452
  const { TData, TError } = buildResponseTypes(node, tsResolver);
1603
1453
  const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
1604
1454
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? "";
1605
- const paramsNode = getQueryOptionsParams(node, { resolver: tsResolver });
1455
+ const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
1606
1456
  const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
1607
1457
  const queryFnBody = `const { data } = await ${buildClientCall(node, {
1608
1458
  clientName,
@@ -1633,36 +1483,44 @@ function QueryOptions({ name, clientName, node, tsResolver, queryKeyName }) {
1633
1483
  //#region src/generators/infiniteQueryGenerator.tsx
1634
1484
  /**
1635
1485
  * Built-in generator for `useInfiniteQuery` hooks. Enabled when
1636
- * `pluginReactQuery({ infinite: { ... } })`. Emits one `useFooInfiniteQuery`
1637
- * hook per query operation, wiring the configured `nextParam` /
1638
- * `previousParam` paths into TanStack Query's cursor-based pagination.
1486
+ * `pluginReactQuery({ infinite: { ... }, hooks: true })`. Emits one
1487
+ * `useFooInfiniteQuery` hook per query operation, wiring the configured
1488
+ * `nextParam` / `previousParam` paths into TanStack Query's cursor-based
1489
+ * pagination.
1639
1490
  */
1640
1491
  const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1641
1492
  name: "react-infinite-query",
1642
1493
  renderer: kubb_jsx.jsxRenderer,
1494
+ match(node, ctx) {
1495
+ const operationNode = node;
1496
+ if (!kubb_kit.ast.isHttpOperationNode(operationNode)) return false;
1497
+ const { query, mutation, infinite, hooks } = ctx.options;
1498
+ const { isQuery, isMutation } = classifyOperation(operationNode, {
1499
+ query,
1500
+ mutation
1501
+ });
1502
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1503
+ if (!isQuery || isMutation || !infiniteOptions || !hooks) return false;
1504
+ const queryParamKeys = getOperationParameters(operationNode).query.map((p) => p.name);
1505
+ return infiniteOptions.queryParam ? queryParamKeys.includes(infiniteOptions.queryParam) || queryParamKeys.includes(`${infiniteOptions.queryParam}?`) : false;
1506
+ },
1643
1507
  operation(node, ctx) {
1644
1508
  if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
1645
1509
  const { config, driver, resolver, root } = ctx;
1646
- const { output, query, mutation, infinite, client, group, customOptions, hooks } = ctx.options;
1510
+ const { output, query, infinite, client, group, customOptions } = ctx.options;
1647
1511
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1648
1512
  if (!pluginTs) return null;
1649
1513
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1650
- const { isQuery, isMutation } = classifyOperation(node, {
1651
- query,
1652
- mutation
1653
- });
1654
1514
  const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1655
- if (!isQuery || isMutation || !infiniteOptions) return null;
1656
- const normalizeKey = (key) => key.replace(/\?$/, "");
1657
- const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
1658
- if (!(infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false)) return null;
1515
+ if (!infiniteOptions) return null;
1659
1516
  const importPath = query ? query.importPath : "@tanstack/react-query";
1660
1517
  const contractOp = resolveClientOperation({
1661
1518
  clientPlugin: { pluginName: client.pluginName },
1662
1519
  driver,
1663
1520
  node,
1664
1521
  root,
1665
- output
1522
+ output,
1523
+ cache: ctx.cache
1666
1524
  });
1667
1525
  if (!contractOp) return null;
1668
1526
  const queryName = resolver.infiniteQuery.name(node);
@@ -1676,15 +1534,20 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1676
1534
  output,
1677
1535
  group: group ?? void 0
1678
1536
  }),
1679
- fileTs: tsResolver.file({
1680
- ...operationFileEntry(node, node.operationId),
1537
+ fileTs: resolveDependencyOperationFile({
1538
+ cache: ctx.cache,
1539
+ node,
1540
+ resolver: tsResolver,
1681
1541
  root,
1682
1542
  output: pluginTs.options?.output ?? output,
1683
- group: pluginTs.options?.group ?? void 0
1543
+ group: pluginTs.options?.group
1684
1544
  })
1685
1545
  };
1686
- const rawQueryParams = getOperationParameters(node).query;
1687
- const queryParamsTypeName = rawQueryParams.length > 0 && tsResolver.param.query(node, rawQueryParams[0]) !== tsResolver.param.name(node, rawQueryParams[0]) ? tsResolver.param.query(node, rawQueryParams[0]) : null;
1546
+ const { queryParamsTypeName } = resolvePageParamType(node, {
1547
+ resolver: tsResolver,
1548
+ initialPageParam: infiniteOptions.initialPageParam,
1549
+ queryParam: infiniteOptions.queryParam
1550
+ });
1688
1551
  const importedTypeNames = [
1689
1552
  tsResolver.response.options(node),
1690
1553
  queryParamsTypeName,
@@ -1765,33 +1628,31 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1765
1628
  initialPageParam: infiniteOptions.initialPageParam,
1766
1629
  queryParam: infiniteOptions.queryParam
1767
1630
  }),
1768
- hooks && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [
1769
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1770
- name: ["useInfiniteQuery"],
1771
- path: importPath
1772
- }),
1773
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1774
- name: [
1775
- "QueryKey",
1776
- "QueryClient",
1777
- "InfiniteQueryObserverOptions",
1778
- "UseInfiniteQueryResult"
1779
- ],
1780
- path: importPath,
1781
- isTypeOnly: true
1782
- }),
1783
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
1784
- name: queryName,
1785
- queryOptionsName,
1786
- queryKeyName,
1787
- queryKeyTypeName,
1788
- node,
1789
- tsResolver,
1790
- initialPageParam: infiniteOptions.initialPageParam,
1791
- queryParam: infiniteOptions.queryParam,
1792
- customOptions
1793
- })
1794
- ] })
1631
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1632
+ name: ["useInfiniteQuery"],
1633
+ path: importPath
1634
+ }),
1635
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1636
+ name: [
1637
+ "QueryKey",
1638
+ "QueryClient",
1639
+ "InfiniteQueryObserverOptions",
1640
+ "UseInfiniteQueryResult"
1641
+ ],
1642
+ path: importPath,
1643
+ isTypeOnly: true
1644
+ }),
1645
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
1646
+ name: queryName,
1647
+ queryOptionsName,
1648
+ queryKeyName,
1649
+ queryKeyTypeName,
1650
+ node,
1651
+ tsResolver,
1652
+ initialPageParam: infiniteOptions.initialPageParam,
1653
+ queryParam: infiniteOptions.queryParam,
1654
+ customOptions
1655
+ })
1795
1656
  ]
1796
1657
  });
1797
1658
  }
@@ -1806,25 +1667,30 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1806
1667
  const mutationGenerator = (0, kubb_kit.defineGenerator)({
1807
1668
  name: "react-query-mutation",
1808
1669
  renderer: kubb_jsx.jsxRenderer,
1670
+ match(node, ctx) {
1671
+ const operationNode = node;
1672
+ if (!kubb_kit.ast.isHttpOperationNode(operationNode)) return false;
1673
+ const { query, mutation } = ctx.options;
1674
+ return classifyOperation(operationNode, {
1675
+ query,
1676
+ mutation
1677
+ }).isMutation;
1678
+ },
1809
1679
  operation(node, ctx) {
1810
1680
  if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
1811
1681
  const { config, driver, resolver, root } = ctx;
1812
- const { output, query, mutation, client, group, customOptions, hooks } = ctx.options;
1682
+ const { output, mutation, client, group, customOptions, hooks } = ctx.options;
1813
1683
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1814
1684
  if (!pluginTs) return null;
1815
1685
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1816
- const { isMutation } = classifyOperation(node, {
1817
- query,
1818
- mutation
1819
- });
1820
- if (!isMutation) return null;
1821
1686
  const importPath = mutation ? mutation.importPath : "@tanstack/react-query";
1822
1687
  const contractOp = resolveClientOperation({
1823
1688
  clientPlugin: { pluginName: client.pluginName },
1824
1689
  driver,
1825
1690
  node,
1826
1691
  root,
1827
- output
1692
+ output,
1693
+ cache: ctx.cache
1828
1694
  });
1829
1695
  if (!contractOp) return null;
1830
1696
  const mutationHookName = resolver.mutation.name(node);
@@ -1838,11 +1704,13 @@ const mutationGenerator = (0, kubb_kit.defineGenerator)({
1838
1704
  output,
1839
1705
  group: group ?? void 0
1840
1706
  }),
1841
- fileTs: tsResolver.file({
1842
- ...operationFileEntry(node, node.operationId),
1707
+ fileTs: resolveDependencyOperationFile({
1708
+ cache: ctx.cache,
1709
+ node,
1710
+ resolver: tsResolver,
1843
1711
  root,
1844
1712
  output: pluginTs.options?.output ?? output,
1845
- group: pluginTs.options?.group ?? void 0
1713
+ group: pluginTs.options?.group
1846
1714
  })
1847
1715
  };
1848
1716
  const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
@@ -1946,25 +1814,31 @@ const mutationGenerator = (0, kubb_kit.defineGenerator)({
1946
1814
  const queryGenerator = (0, kubb_kit.defineGenerator)({
1947
1815
  name: "react-query",
1948
1816
  renderer: kubb_jsx.jsxRenderer,
1817
+ match(node, ctx) {
1818
+ const operationNode = node;
1819
+ if (!kubb_kit.ast.isHttpOperationNode(operationNode)) return false;
1820
+ const { query, mutation } = ctx.options;
1821
+ const { isQuery, isMutation } = classifyOperation(operationNode, {
1822
+ query,
1823
+ mutation
1824
+ });
1825
+ return isQuery && !isMutation;
1826
+ },
1949
1827
  operation(node, ctx) {
1950
1828
  if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
1951
1829
  const { config, driver, resolver, root } = ctx;
1952
- const { output, query, mutation, client, group, customOptions, hooks } = ctx.options;
1830
+ const { output, query, client, group, customOptions, hooks } = ctx.options;
1953
1831
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1954
1832
  if (!pluginTs) return null;
1955
1833
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1956
- const { isQuery, isMutation } = classifyOperation(node, {
1957
- query,
1958
- mutation
1959
- });
1960
- if (!isQuery || isMutation) return null;
1961
1834
  const importPath = query ? query.importPath : "@tanstack/react-query";
1962
1835
  const contractOp = resolveClientOperation({
1963
1836
  clientPlugin: { pluginName: client.pluginName },
1964
1837
  driver,
1965
1838
  node,
1966
1839
  root,
1967
- output
1840
+ output,
1841
+ cache: ctx.cache
1968
1842
  });
1969
1843
  if (!contractOp) return null;
1970
1844
  const queryName = resolver.query.name(node);
@@ -1978,11 +1852,13 @@ const queryGenerator = (0, kubb_kit.defineGenerator)({
1978
1852
  output,
1979
1853
  group: group ?? void 0
1980
1854
  }),
1981
- fileTs: tsResolver.file({
1982
- ...operationFileEntry(node, node.operationId),
1855
+ fileTs: resolveDependencyOperationFile({
1856
+ cache: ctx.cache,
1857
+ node,
1858
+ resolver: tsResolver,
1983
1859
  root,
1984
1860
  output: pluginTs.options?.output ?? output,
1985
- group: pluginTs.options?.group ?? void 0
1861
+ group: pluginTs.options?.group
1986
1862
  })
1987
1863
  };
1988
1864
  const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
@@ -2083,38 +1959,44 @@ const queryGenerator = (0, kubb_kit.defineGenerator)({
2083
1959
  //#endregion
2084
1960
  //#region src/generators/suspenseInfiniteQueryGenerator.tsx
2085
1961
  /**
2086
- * Built-in generator for `useSuspenseInfiniteQuery` hooks. Enabled when both
2087
- * `suspense` and `infinite` are configured. Combines suspense semantics with
2088
- * cursor-based pagination. Handlers throw promises while loading and pull
2089
- * additional pages on demand.
1962
+ * Built-in generator for `useSuspenseInfiniteQuery` hooks. Enabled when
1963
+ * `suspense`, `infinite`, and `hooks` are all configured. Combines suspense
1964
+ * semantics with cursor-based pagination. Handlers throw promises while
1965
+ * loading and pull additional pages on demand.
2090
1966
  */
2091
1967
  const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
2092
1968
  name: "react-suspense-infinite-query",
2093
1969
  renderer: kubb_jsx.jsxRenderer,
1970
+ match(node, ctx) {
1971
+ const operationNode = node;
1972
+ if (!kubb_kit.ast.isHttpOperationNode(operationNode)) return false;
1973
+ const { query, mutation, infinite, suspense, hooks } = ctx.options;
1974
+ const { isQuery, isMutation } = classifyOperation(operationNode, {
1975
+ query,
1976
+ mutation
1977
+ });
1978
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1979
+ if (!isQuery || isMutation || !suspense || !infiniteOptions || !hooks) return false;
1980
+ const queryParamKeys = getOperationParameters(operationNode).query.map((p) => p.name);
1981
+ return infiniteOptions.queryParam ? queryParamKeys.includes(infiniteOptions.queryParam) || queryParamKeys.includes(`${infiniteOptions.queryParam}?`) : false;
1982
+ },
2094
1983
  operation(node, ctx) {
2095
1984
  if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
2096
1985
  const { config, driver, resolver, root } = ctx;
2097
- const { output, query, mutation, infinite, suspense, client, group, customOptions, hooks } = ctx.options;
1986
+ const { output, query, infinite, client, group, customOptions } = ctx.options;
2098
1987
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
2099
1988
  if (!pluginTs) return null;
2100
1989
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
2101
- const { isQuery, isMutation } = classifyOperation(node, {
2102
- query,
2103
- mutation
2104
- });
2105
- const isSuspense = !!suspense;
2106
1990
  const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
2107
- if (!isQuery || isMutation || !isSuspense || !infiniteOptions) return null;
2108
- const normalizeKey = (key) => key.replace(/\?$/, "");
2109
- const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
2110
- if (!(infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false)) return null;
1991
+ if (!infiniteOptions) return null;
2111
1992
  const importPath = query ? query.importPath : "@tanstack/react-query";
2112
1993
  const contractOp = resolveClientOperation({
2113
1994
  clientPlugin: { pluginName: client.pluginName },
2114
1995
  driver,
2115
1996
  node,
2116
1997
  root,
2117
- output
1998
+ output,
1999
+ cache: ctx.cache
2118
2000
  });
2119
2001
  if (!contractOp) return null;
2120
2002
  const queryName = resolver.suspenseInfiniteQuery.name(node);
@@ -2128,11 +2010,13 @@ const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
2128
2010
  output,
2129
2011
  group: group ?? void 0
2130
2012
  }),
2131
- fileTs: tsResolver.file({
2132
- ...operationFileEntry(node, node.operationId),
2013
+ fileTs: resolveDependencyOperationFile({
2014
+ cache: ctx.cache,
2015
+ node,
2016
+ resolver: tsResolver,
2133
2017
  root,
2134
2018
  output: pluginTs.options?.output ?? output,
2135
- group: pluginTs.options?.group ?? void 0
2019
+ group: pluginTs.options?.group
2136
2020
  })
2137
2021
  };
2138
2022
  const rawQueryParams = getOperationParameters(node).query;
@@ -2216,34 +2100,32 @@ const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
2216
2100
  initialPageParam: infiniteOptions.initialPageParam,
2217
2101
  queryParam: infiniteOptions.queryParam
2218
2102
  }),
2219
- hooks && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [
2220
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2221
- name: ["useSuspenseInfiniteQuery"],
2222
- path: importPath
2223
- }),
2224
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2225
- name: [
2226
- "QueryKey",
2227
- "QueryClient",
2228
- "UseSuspenseInfiniteQueryOptions",
2229
- "UseSuspenseInfiniteQueryResult"
2230
- ],
2231
- path: importPath,
2232
- isTypeOnly: true
2233
- }),
2234
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
2235
- name: queryName,
2236
- queryOptionsName,
2237
- queryKeyName,
2238
- queryKeyTypeName,
2239
- node,
2240
- tsResolver,
2241
- initialPageParam: infiniteOptions.initialPageParam,
2242
- queryParam: infiniteOptions.queryParam,
2243
- customOptions,
2244
- suspense: true
2245
- })
2246
- ] })
2103
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2104
+ name: ["useSuspenseInfiniteQuery"],
2105
+ path: importPath
2106
+ }),
2107
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2108
+ name: [
2109
+ "QueryKey",
2110
+ "QueryClient",
2111
+ "UseSuspenseInfiniteQueryOptions",
2112
+ "UseSuspenseInfiniteQueryResult"
2113
+ ],
2114
+ path: importPath,
2115
+ isTypeOnly: true
2116
+ }),
2117
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
2118
+ name: queryName,
2119
+ queryOptionsName,
2120
+ queryKeyName,
2121
+ queryKeyTypeName,
2122
+ node,
2123
+ tsResolver,
2124
+ initialPageParam: infiniteOptions.initialPageParam,
2125
+ queryParam: infiniteOptions.queryParam,
2126
+ customOptions,
2127
+ suspense: true
2128
+ })
2247
2129
  ]
2248
2130
  });
2249
2131
  }
@@ -2252,32 +2134,39 @@ const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
2252
2134
  //#region src/generators/suspenseQueryGenerator.tsx
2253
2135
  /**
2254
2136
  * Built-in generator for `useSuspenseQuery` hooks. Enabled when
2255
- * `pluginReactQuery({ suspense: {} })`. Emits one `useFooSuspenseQuery` hook
2256
- * per query operation. Suspense queries throw promises while loading and
2257
- * require a `<Suspense>` boundary in the React tree. TanStack Query v5+ only.
2137
+ * `pluginReactQuery({ suspense: {}, hooks: true })`. Emits one
2138
+ * `useFooSuspenseQuery` hook per query operation. Suspense queries throw
2139
+ * promises while loading and require a `<Suspense>` boundary in the React
2140
+ * tree. TanStack Query v5+ only.
2258
2141
  */
2259
2142
  const suspenseQueryGenerator = (0, kubb_kit.defineGenerator)({
2260
2143
  name: "react-suspense-query",
2261
2144
  renderer: kubb_jsx.jsxRenderer,
2145
+ match(node, ctx) {
2146
+ const operationNode = node;
2147
+ if (!kubb_kit.ast.isHttpOperationNode(operationNode)) return false;
2148
+ const { query, mutation, suspense, hooks } = ctx.options;
2149
+ const { isQuery, isMutation } = classifyOperation(operationNode, {
2150
+ query,
2151
+ mutation
2152
+ });
2153
+ return isQuery && !isMutation && !!suspense && hooks;
2154
+ },
2262
2155
  operation(node, ctx) {
2263
2156
  if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
2264
2157
  const { config, driver, resolver, root } = ctx;
2265
- const { output, query, mutation, suspense, client, group, customOptions, hooks } = ctx.options;
2158
+ const { output, query, client, group, customOptions } = ctx.options;
2266
2159
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
2267
2160
  if (!pluginTs) return null;
2268
2161
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
2269
- const { isQuery, isMutation } = classifyOperation(node, {
2270
- query,
2271
- mutation
2272
- });
2273
- if (!isQuery || isMutation || !!!suspense) return null;
2274
2162
  const importPath = query ? query.importPath : "@tanstack/react-query";
2275
2163
  const contractOp = resolveClientOperation({
2276
2164
  clientPlugin: { pluginName: client.pluginName },
2277
2165
  driver,
2278
2166
  node,
2279
2167
  root,
2280
- output
2168
+ output,
2169
+ cache: ctx.cache
2281
2170
  });
2282
2171
  if (!contractOp) return null;
2283
2172
  const queryName = resolver.suspenseQuery.name(node);
@@ -2291,11 +2180,13 @@ const suspenseQueryGenerator = (0, kubb_kit.defineGenerator)({
2291
2180
  output,
2292
2181
  group: group ?? void 0
2293
2182
  }),
2294
- fileTs: tsResolver.file({
2295
- ...operationFileEntry(node, node.operationId),
2183
+ fileTs: resolveDependencyOperationFile({
2184
+ cache: ctx.cache,
2185
+ node,
2186
+ resolver: tsResolver,
2296
2187
  root,
2297
2188
  output: pluginTs.options?.output ?? output,
2298
- group: pluginTs.options?.group ?? void 0
2189
+ group: pluginTs.options?.group
2299
2190
  })
2300
2191
  };
2301
2192
  const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
@@ -2364,32 +2255,30 @@ const suspenseQueryGenerator = (0, kubb_kit.defineGenerator)({
2364
2255
  node,
2365
2256
  tsResolver
2366
2257
  }),
2367
- suspense && hooks && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [
2368
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2369
- name: ["useSuspenseQuery"],
2370
- path: importPath
2371
- }),
2372
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2373
- name: [
2374
- "QueryKey",
2375
- "QueryClient",
2376
- "UseSuspenseQueryOptions",
2377
- "UseSuspenseQueryResult"
2378
- ],
2379
- path: importPath,
2380
- isTypeOnly: true
2381
- }),
2382
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Query, {
2383
- name: queryName,
2384
- queryOptionsName,
2385
- queryKeyName,
2386
- queryKeyTypeName,
2387
- node,
2388
- tsResolver,
2389
- customOptions,
2390
- suspense: true
2391
- })
2392
- ] })
2258
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2259
+ name: ["useSuspenseQuery"],
2260
+ path: importPath
2261
+ }),
2262
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2263
+ name: [
2264
+ "QueryKey",
2265
+ "QueryClient",
2266
+ "UseSuspenseQueryOptions",
2267
+ "UseSuspenseQueryResult"
2268
+ ],
2269
+ path: importPath,
2270
+ isTypeOnly: true
2271
+ }),
2272
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Query, {
2273
+ name: queryName,
2274
+ queryOptionsName,
2275
+ queryKeyName,
2276
+ queryKeyTypeName,
2277
+ node,
2278
+ tsResolver,
2279
+ customOptions,
2280
+ suspense: true
2281
+ })
2393
2282
  ]
2394
2283
  });
2395
2284
  }
@@ -2475,7 +2364,7 @@ const pluginReactQuery = (0, kubb_kit.definePlugin)((options) => {
2475
2364
  const { output = {
2476
2365
  path: "hooks",
2477
2366
  barrel: { type: "named" }
2478
- }, group, exclude = [], include, override = [], suspense = {}, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, customOptions, hooks = false, client, resolver: userResolver, macros: userMacros } = options;
2367
+ }, group, exclude = [], include, override = [], suspense = false, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, customOptions, hooks = false, client, resolver: userResolver, macros: userMacros } = options;
2479
2368
  const selectedGenerators = [
2480
2369
  queryGenerator,
2481
2370
  suspenseQueryGenerator,