@kubb/plugin-react-query 5.7.0-canary.20261025T201031 → 5.7.1

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.js CHANGED
@@ -1,12 +1,11 @@
1
- import { Diagnostics, Resolver, Url, addGenerator, ast, createResolver, defineExtension, defineGenerator, setMacros, setResolver, useConfig } from "kubb/kit";
1
+ import { Diagnostics, Resolver, Url, addGenerator, ast, camelCase, createResolver, defineExtension, defineGenerator, setMacros, setResolver, useConfig } from "kubb/kit";
2
2
  import path from "node:path";
3
3
  import { pluginZodName } from "@kubb/plugin-zod";
4
4
  import { File, Function, Type, jsxRenderer } from "kubb/jsx";
5
5
  import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, createTypeLiteral, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
6
6
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
7
7
  import fs from "node:fs";
8
- //#endregion
9
- //#region ../../internals/shared/src/operation.ts
8
+ // ../../internals/shared/src/operation.ts
10
9
  /**
11
10
  * Builds the `ResolverFileParams` every operation generator passes to
12
11
  * `resolver.file`: a file named `name`, tagged by the operation's first
@@ -75,6 +74,24 @@ function getContentTypeInfo(node) {
75
74
  function getResponseContentTypeInfo(node) {
76
75
  return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? []);
77
76
  }
77
+ /**
78
+ * Reads the single base content type of an operation's primary success response, lowercased and
79
+ * stripped of any `; charset=...` suffix. Returns `undefined` when the response declares zero or
80
+ * more than one content type, since neither case has a single type to act on.
81
+ */
82
+ function getPrimarySuccessContentType(node) {
83
+ const contentTypes = getPrimarySuccessResponse(node)?.content?.map((entry) => entry.contentType) ?? [];
84
+ if (contentTypes.length !== 1) return void 0;
85
+ return contentTypes[0].split(";")[0].trim().toLowerCase();
86
+ }
87
+ /**
88
+ * Whether an operation streams its primary success response as Server-Sent Events
89
+ * (`text/event-stream`). The client generator uses this to return a typed event stream instead of a
90
+ * one-shot `RequestResult`.
91
+ */
92
+ function isEventStream(node) {
93
+ return getPrimarySuccessContentType(node) === "text/event-stream";
94
+ }
78
95
  const requestConfigBaseType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
79
96
  function buildRequestConfigType(node) {
80
97
  const request = getContentTypeInfo(node);
@@ -166,6 +183,22 @@ function getOperationParameters(node) {
166
183
  operationParameterGroupsByNode.set(node, groups);
167
184
  return groups;
168
185
  }
186
+ /**
187
+ * Builds the combined `{ body, path, query, headers }` options object schema for an operation,
188
+ * referencing the already-resolved body and grouped param names. Shared by `@kubb/plugin-ts`'s
189
+ * `Options` type and `@kubb/plugin-zod`'s inferred options schema, so both printers emit the same
190
+ * shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod
191
+ * printer to emit `z.object(…)` rather than a record.
192
+ */
193
+ function hasRequestContentTypeChoice(node) {
194
+ return (node.requestBody?.content ?? []).filter((entry) => entry.schema).length > 1;
195
+ }
196
+ /**
197
+ * Casts a call argument to the client's parameter type; a `'plain'` client is non-generic.
198
+ */
199
+ function castToClientOptions(callArg, clientName, returnType = "full") {
200
+ return `${callArg} as Parameters<typeof ${clientName}${returnType === "plain" ? "" : "<true>"}>[0]`;
201
+ }
169
202
  function getStatusCodeNumber(statusCode) {
170
203
  const code = Number(statusCode);
171
204
  return Number.isNaN(code) ? null : code;
@@ -196,88 +229,184 @@ function resolveSuccessNames(node, resolver) {
196
229
  function resolveStatusCodeNames(node, resolver) {
197
230
  return node.responses.map((response) => resolver.response.status(node, response.statusCode));
198
231
  }
199
- const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
232
+ /**
233
+ * Lists the type names an operation's types file declares, computed once per resolver and `options` so every
234
+ * dependent reads the same list.
235
+ */
200
236
  function resolveOperationTypeNames(node, resolver, options = {}) {
201
- const cacheKey = `${node.operationId}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
202
- let byResolver = typeNamesByResolver.get(resolver);
203
- if (byResolver) {
204
- const cached = byResolver.get(cacheKey);
205
- if (cached) return cached;
206
- } else {
207
- byResolver = /* @__PURE__ */ new Map();
208
- typeNamesByResolver.set(resolver, byResolver);
209
- }
210
- const { path, query, header } = getOperationParameters(node);
211
- const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
212
- const exclude = new Set(options.exclude ?? []);
213
- const paramNames = options.includeParams === false ? [] : [
214
- ...path.map((param) => resolver.param.path(node, param)),
215
- ...query.map((param) => resolver.param.query(node, param)),
216
- ...header.map((param) => resolver.param.headers(node, param))
217
- ];
218
- const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)];
219
- const result = (options.order === "body-response-first" ? [
220
- ...bodyAndResponseNames,
221
- ...paramNames,
222
- ...responseStatusNames
223
- ] : [
224
- ...paramNames,
225
- ...bodyAndResponseNames,
226
- ...responseStatusNames
227
- ]).filter((name) => Boolean(name) && !exclude.has(name));
228
- byResolver.set(cacheKey, result);
229
- return result;
237
+ const key = `${node.operationId}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
238
+ return resolver.memo(`operationTypeNames:${key}`, () => {
239
+ const { path, query, header } = getOperationParameters(node);
240
+ const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
241
+ const exclude = new Set(options.exclude ?? []);
242
+ const paramNames = options.includeParams === false ? [] : [
243
+ ...path.map((param) => resolver.param.path(node, param)),
244
+ ...query.map((param) => resolver.param.query(node, param)),
245
+ ...header.map((param) => resolver.param.headers(node, param))
246
+ ];
247
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)];
248
+ return (options.order === "body-response-first" ? [
249
+ ...bodyAndResponseNames,
250
+ ...paramNames,
251
+ ...responseStatusNames
252
+ ] : [
253
+ ...paramNames,
254
+ ...bodyAndResponseNames,
255
+ ...responseStatusNames
256
+ ]).filter((name) => Boolean(name) && !exclude.has(name));
257
+ });
230
258
  }
231
- //#endregion
232
- //#region ../../internals/utils/src/casing.ts
259
+ // ../../internals/utils/src/casing.ts
233
260
  /**
234
- * Shared implementation for camelCase and PascalCase conversion.
235
- * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
236
- * and capitalizes each word according to `pascal`.
261
+ * Uppercases only the first character of `text`, leaving the rest untouched.
262
+ * Unlike `pascalCase` it never re-splits word boundaries or strips characters.
237
263
  *
238
- * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
239
- */
240
- function convert(text, pascal) {
241
- 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) => {
242
- if (word.length > 1 && word === word.toUpperCase()) return word;
243
- return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
244
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
245
- }
246
- const cache = /* @__PURE__ */ new Map();
247
- const cacheLimit = 1e4;
248
- function toCamelOrPascal(text, pascal) {
249
- const key = `${pascal ? "P" : "c"}${text}`;
250
- const cached = cache.get(key);
251
- if (cached !== void 0) return cached;
252
- const result = convert(text, pascal);
253
- if (cache.size >= cacheLimit) cache.clear();
254
- cache.set(key, result);
255
- return result;
264
+ * @example
265
+ * `capitalize('getPetById') // 'GetPetById'`
266
+ */
267
+ function capitalize(text) {
268
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
256
269
  }
270
+ // ../../internals/utils/src/reserved.ts
257
271
  /**
258
- * Converts `text` to camelCase.
272
+ * JavaScript and Java reserved words.
273
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
274
+ */
275
+ const reservedWords = /* @__PURE__ */ new Set([
276
+ "abstract",
277
+ "arguments",
278
+ "await",
279
+ "boolean",
280
+ "break",
281
+ "byte",
282
+ "case",
283
+ "catch",
284
+ "char",
285
+ "class",
286
+ "const",
287
+ "continue",
288
+ "debugger",
289
+ "default",
290
+ "delete",
291
+ "do",
292
+ "double",
293
+ "else",
294
+ "enum",
295
+ "eval",
296
+ "export",
297
+ "extends",
298
+ "false",
299
+ "final",
300
+ "finally",
301
+ "float",
302
+ "for",
303
+ "function",
304
+ "goto",
305
+ "if",
306
+ "implements",
307
+ "import",
308
+ "in",
309
+ "instanceof",
310
+ "int",
311
+ "interface",
312
+ "let",
313
+ "long",
314
+ "native",
315
+ "new",
316
+ "null",
317
+ "package",
318
+ "private",
319
+ "protected",
320
+ "public",
321
+ "return",
322
+ "short",
323
+ "static",
324
+ "super",
325
+ "switch",
326
+ "synchronized",
327
+ "this",
328
+ "throw",
329
+ "throws",
330
+ "transient",
331
+ "true",
332
+ "try",
333
+ "typeof",
334
+ "var",
335
+ "void",
336
+ "volatile",
337
+ "while",
338
+ "with",
339
+ "yield",
340
+ "Array",
341
+ "Date",
342
+ "hasOwnProperty",
343
+ "Infinity",
344
+ "isFinite",
345
+ "isNaN",
346
+ "isPrototypeOf",
347
+ "length",
348
+ "Math",
349
+ "name",
350
+ "NaN",
351
+ "Number",
352
+ "Object",
353
+ "prototype",
354
+ "String",
355
+ "toString",
356
+ "undefined",
357
+ "valueOf"
358
+ ]);
359
+ /**
360
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
259
361
  *
260
- * @example Word boundaries
261
- * `camelCase('hello-world') // 'helloWorld'`
362
+ * @example
363
+ * ```ts
364
+ * isValidVarName('status') // true
365
+ * isValidVarName('class') // false (reserved word)
366
+ * isValidVarName('42foo') // false (starts with digit)
367
+ * ```
368
+ */
369
+ function isValidVarName(name) {
370
+ if (!name || reservedWords.has(name)) return false;
371
+ return isIdentifier(name);
372
+ }
373
+ /**
374
+ * Returns `name` when it's a syntactically valid JavaScript variable name,
375
+ * otherwise prefixes it with `_` so the result is a valid identifier.
262
376
  *
263
- * @example With a prefix
264
- * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
377
+ * Useful for sanitizing OpenAPI schema names or operation IDs that start with
378
+ * a digit (e.g. `409`, `504AccountCancel`) before using them as exported
379
+ * variable, type, or function names.
380
+ *
381
+ * @example
382
+ * ```ts
383
+ * ensureValidVarName('409') // '_409'
384
+ * ensureValidVarName('504AccountCancel') // '_504AccountCancel'
385
+ * ensureValidVarName('Pet') // 'Pet'
386
+ * ensureValidVarName('class') // '_class'
387
+ * ```
265
388
  */
266
- function camelCase(text, { prefix = "", suffix = "" } = {}) {
267
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
389
+ function ensureValidVarName(name) {
390
+ if (!name || isValidVarName(name)) return name;
391
+ return `_${name}`;
268
392
  }
269
393
  /**
270
- * Uppercases only the first character of `text`, leaving the rest untouched.
271
- * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.
394
+ * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
395
+ *
396
+ * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
397
+ * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
398
+ * deciding whether an object key needs quoting.
272
399
  *
273
400
  * @example
274
- * `capitalize('getPetById') // 'GetPetById'`
401
+ * ```ts
402
+ * isIdentifier('name') // true
403
+ * isIdentifier('x-total')// false
404
+ * ```
275
405
  */
276
- function capitalize(text) {
277
- return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
406
+ function isIdentifier(name) {
407
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
278
408
  }
279
- //#endregion
280
- //#region ../../internals/utils/src/strings.ts
409
+ // ../../internals/utils/src/strings.ts
281
410
  /**
282
411
  * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
283
412
  * `accessor`. Returns `null` for an empty path.
@@ -293,8 +422,32 @@ function getNestedAccessor(param, accessor) {
293
422
  if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
294
423
  return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
295
424
  }
296
- //#endregion
297
- //#region ../../internals/shared/src/group.ts
425
+ // ../../internals/shared/src/resolver.ts
426
+ /**
427
+ * The shared top-level `name` of the operation plugins, computed once per operation name and build.
428
+ */
429
+ function resolveOperationName(name) {
430
+ return this.memo(`operation:${name}`, () => ensureValidVarName(camelCase(name)));
431
+ }
432
+ /**
433
+ * Builds the allocation key for a declaration an operation owns. `scope` names which declaration
434
+ * it is, so two of them never share an allocation even when a custom resolver gives both the same
435
+ * name. Leave `scope` empty for the operation's own declaration.
436
+ *
437
+ * @example
438
+ * ```ts
439
+ * resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
440
+ * ```
441
+ */
442
+ function operationKey(node, ...scope) {
443
+ return [
444
+ "operation",
445
+ node.method,
446
+ node.path,
447
+ ...scope.map(String)
448
+ ];
449
+ }
450
+ // ../../internals/shared/src/group.ts
298
451
  /**
299
452
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
300
453
  * shared default naming so every plugin groups output consistently:
@@ -324,17 +477,14 @@ function createGroupConfig(group) {
324
477
  name: group.name ? group.name : defaultName
325
478
  };
326
479
  }
327
- //#endregion
328
- //#region kubb-extension.json
480
+ // kubb-extension.json
329
481
  var compatibility = {
330
- "kubb": ">=5.8.3",
482
+ "kubb": ">=5.14.6",
331
483
  "node": ">=22.22"
332
484
  };
333
- //#endregion
334
- //#region package.json
335
- var version = "5.7.0-canary.20261025T201031";
336
- //#endregion
337
- //#region ../../internals/client/src/resolveOperationTypes.ts
485
+ // package.json
486
+ var version = "5.7.1";
487
+ // ../../internals/client/src/resolveOperationTypes.ts
338
488
  /**
339
489
  * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
340
490
  * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
@@ -344,6 +494,7 @@ function toZodTypeResolver(resolver) {
344
494
  return {
345
495
  ...resolver,
346
496
  file: resolver.file.bind(resolver),
497
+ memo: (key, compute) => resolver.memo(`zodTypes:${key}`, compute),
347
498
  param: {
348
499
  name: (node, p) => type(resolver.param.name(node, p)),
349
500
  path: (node, p) => type(resolver.param.path(node, p)),
@@ -400,8 +551,7 @@ function resolveOperationTypes(driver, pluginName) {
400
551
  group: pluginZod.options.group ?? void 0
401
552
  };
402
553
  }
403
- //#endregion
404
- //#region ../../internals/client/src/resolveClient.ts
554
+ // ../../internals/client/src/resolveClient.ts
405
555
  /**
406
556
  * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
407
557
  * operation, shared so the selection rules and diagnostics stay in one place.
@@ -511,8 +661,7 @@ function resolveContractClient(options) {
511
661
  }
512
662
  return resolved;
513
663
  }
514
- //#endregion
515
- //#region ../../internals/client/src/resolveClientOperation.ts
664
+ // ../../internals/client/src/resolveClientOperation.ts
516
665
  function isRelativeImport(importPath) {
517
666
  return importPath.startsWith(".");
518
667
  }
@@ -559,8 +708,12 @@ function resolveClientOperation(options) {
559
708
  group: operationOptions.group ?? void 0
560
709
  });
561
710
  const { importPath } = operationOptions;
711
+ const name = resolver.name(node.operationId);
562
712
  return {
563
- name: resolver.name(node.operationId),
713
+ name: resolver.resolveName({
714
+ key: operationKey(node),
715
+ name
716
+ }),
564
717
  path: file.path,
565
718
  clientPath: importPath === void 0 ? path.resolve(root, ".kubb/client.ts") : resolveImportPath({
566
719
  importPath,
@@ -571,8 +724,7 @@ function resolveClientOperation(options) {
571
724
  };
572
725
  });
573
726
  }
574
- //#endregion
575
- //#region ../../internals/tanstack-query/src/components/HookFile.tsx
727
+ // ../../internals/tanstack-query/src/components/HookFile.tsx
576
728
  /**
577
729
  * Resolves what every TanStack hook file shares: its file, the operation types file and names (`@kubb/plugin-ts`, or
578
730
  * `pluginZod({ inferred: 'codec' })`), banner and footer.
@@ -661,8 +813,7 @@ function HookFile({ hook, imports, children }) {
661
813
  ]
662
814
  });
663
815
  }
664
- //#endregion
665
- //#region ../../internals/tanstack-query/src/utils.ts
816
+ // ../../internals/tanstack-query/src/utils.ts
666
817
  /**
667
818
  * The grouped request options, ordered for both the destructured signature and the
668
819
  * call passed to the underlying client.
@@ -688,7 +839,7 @@ function maybeValueOrGetter(type) {
688
839
  * `MaybeRefOrGetter` per group.
689
840
  */
690
841
  function buildGroupedRequestParam(node, options) {
691
- const { resolver, keys = requestGroupOrder, memberTypeWrapper } = options;
842
+ const { resolver, keys = requestGroupOrder, memberTypeWrapper, withContentType = false } = options;
692
843
  const { groups, hasRequiredPath, hasRequiredQuery, hasRequiredHeader } = getRequestGroupOptionality(node);
693
844
  const names = keys.filter((key) => groups[key]);
694
845
  if (names.length === 0) return null;
@@ -700,6 +851,11 @@ function buildGroupedRequestParam(node, options) {
700
851
  };
701
852
  const isOptional = names.every((name) => !requiredByGroup[name]);
702
853
  const optionsName = resolver.response.options(node);
854
+ if (withContentType && hasRequestContentTypeChoice(node)) return createFunctionParameter({
855
+ name: "variables",
856
+ type: optionsName,
857
+ optional: false
858
+ });
703
859
  const omittedKeys = requestGroupOrder.filter((key) => !keys.includes(key));
704
860
  const optionsType = omittedKeys.length > 0 ? `Omit<${optionsName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : optionsName;
705
861
  if (memberTypeWrapper) {
@@ -757,14 +913,17 @@ function buildQueryOptionsParams(node, options) {
757
913
  * ```
758
914
  */
759
915
  function buildClientCall(node, options) {
760
- const { clientName, signal = false, unwrapName } = options;
916
+ const { clientName, signal = false, unwrapName, withContentType = false, returnType = "full" } = options;
761
917
  const { groups } = getRequestGroupOptionality(node);
762
- return `${clientName}({ ${[
918
+ const names = requestGroupOrder.filter((key) => groups[key]);
919
+ const args = [
763
920
  "...config",
764
- ...requestGroupOrder.filter((key) => groups[key]).map((name) => unwrapName ? `${name}: ${unwrapName(name)}` : name),
921
+ ...withContentType && hasRequestContentTypeChoice(node) ? ["...variables"] : names.map((name) => unwrapName ? `${name}: ${unwrapName(name)}` : name),
765
922
  signal ? "signal: config.signal ?? signal" : null,
766
923
  "throwOnError: true"
767
- ].filter((part) => part !== null).join(", ")} })`;
924
+ ].filter((part) => part !== null);
925
+ if (withContentType && hasRequestContentTypeChoice(node)) return `${clientName}(${castToClientOptions(`{ ${args.join(", ")} }`, clientName, returnType)})`;
926
+ return `${clientName}({ ${args.join(", ")} })`;
768
927
  }
769
928
  /**
770
929
  * Builds the query/mutation body that resolves a `buildClientCall` expression down to the bare
@@ -860,9 +1019,14 @@ function resolveMutationConfig(mutation, options) {
860
1019
  /**
861
1020
  * Classifies an operation as a query or a mutation from the resolved `query` / `mutation` method lists.
862
1021
  * Disabled query and mutation configs do not claim operations, and a method already claimed by an
863
- * enabled query config never counts as a mutation.
1022
+ * enabled query config never counts as a mutation. Event streams are consumed through the client
1023
+ * directly, so they do not generate query or mutation hooks.
864
1024
  */
865
1025
  function classifyOperation(node, { query, mutation }) {
1026
+ if (isEventStream(node)) return {
1027
+ isQuery: false,
1028
+ isMutation: false
1029
+ };
866
1030
  const isQuery = !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
867
1031
  const queryMethods = new Set(query ? query.methods : []);
868
1032
  return {
@@ -1015,8 +1179,7 @@ function buildResolvedRequestParams(node) {
1015
1179
  if (names.length === 0) return null;
1016
1180
  return `{ ${names.map((name) => `${name}: typeof ${name} === 'function' ? ${name}() : ${name}`).join(", ")} }`;
1017
1181
  }
1018
- //#endregion
1019
- //#region ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
1182
+ // ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
1020
1183
  const declarationPrinter$6 = functionPrinter({ mode: "declaration" });
1021
1184
  const callPrinter$3 = functionPrinter({ mode: "call" });
1022
1185
  function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, returnType = "full" }) {
@@ -1092,8 +1255,7 @@ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${que
1092
1255
  })
1093
1256
  });
1094
1257
  }
1095
- //#endregion
1096
- //#region ../../internals/tanstack-query/src/components/MutationKey.tsx
1258
+ // ../../internals/tanstack-query/src/components/MutationKey.tsx
1097
1259
  const declarationPrinter$5 = functionPrinter({ mode: "declaration" });
1098
1260
  /**
1099
1261
  * Default `mutationKey` builder. Call it from a custom builder to extend the default key.
@@ -1140,8 +1302,7 @@ function MutationKey({ name, node, transformer, typeName }) {
1140
1302
  })
1141
1303
  })] });
1142
1304
  }
1143
- //#endregion
1144
- //#region ../../internals/tanstack-query/src/resolver.ts
1305
+ // ../../internals/tanstack-query/src/resolver.ts
1145
1306
  /**
1146
1307
  * Builds the shared query namespace for a variant. Spread the result into
1147
1308
  * `createResolver` once per variant the plugin supports.
@@ -1157,19 +1318,39 @@ function MutationKey({ name, node, transformer, typeName }) {
1157
1318
  function createQueryResolver(variant = "") {
1158
1319
  return {
1159
1320
  name(node) {
1160
- return `use${capitalize(this.name(node.operationId))}${variant}`;
1321
+ const name = `use${capitalize(this.name(node.operationId))}${variant}`;
1322
+ return this.resolveName({
1323
+ key: operationKey(node, "query", variant, "name"),
1324
+ name
1325
+ });
1161
1326
  },
1162
1327
  optionsName(node) {
1163
- return `${this.name(node.operationId)}${variant}QueryOptions`;
1328
+ const name = `${this.name(node.operationId)}${variant}QueryOptions`;
1329
+ return this.resolveName({
1330
+ key: operationKey(node, "query", variant, "optionsName"),
1331
+ name
1332
+ });
1164
1333
  },
1165
1334
  keyName(node) {
1166
- return `${this.name(node.operationId)}${variant}QueryKey`;
1335
+ const name = `${this.name(node.operationId)}${variant}QueryKey`;
1336
+ return this.resolveName({
1337
+ key: operationKey(node, "query", variant, "keyName"),
1338
+ name
1339
+ });
1167
1340
  },
1168
1341
  keyTypeName(node) {
1169
- return `${capitalize(this.name(node.operationId))}${variant}QueryKey`;
1342
+ const name = `${capitalize(this.name(node.operationId))}${variant}QueryKey`;
1343
+ return this.resolveName({
1344
+ key: operationKey(node, "query", variant, "keyTypeName"),
1345
+ name
1346
+ });
1170
1347
  },
1171
1348
  clientName(node) {
1172
- return `${this.name(node.operationId)}${variant}`;
1349
+ const name = `${this.name(node.operationId)}${variant}`;
1350
+ return this.resolveName({
1351
+ key: operationKey(node, "query", variant, "clientName"),
1352
+ name
1353
+ });
1173
1354
  }
1174
1355
  };
1175
1356
  }
@@ -1186,15 +1367,22 @@ function createQueryResolver(variant = "") {
1186
1367
  function createMutationResolver() {
1187
1368
  return {
1188
1369
  name(node) {
1189
- return `use${capitalize(this.name(node.operationId))}`;
1370
+ const name = `use${capitalize(this.name(node.operationId))}`;
1371
+ return this.resolveName({
1372
+ key: operationKey(node, "mutation", "name"),
1373
+ name
1374
+ });
1190
1375
  },
1191
1376
  keyName(node) {
1192
- return `${this.name(node.operationId)}MutationKey`;
1377
+ const name = `${this.name(node.operationId)}MutationKey`;
1378
+ return this.resolveName({
1379
+ key: operationKey(node, "mutation", "keyName"),
1380
+ name
1381
+ });
1193
1382
  }
1194
1383
  };
1195
1384
  }
1196
- //#endregion
1197
- //#region ../../internals/tanstack-query/src/components/QueryKey.tsx
1385
+ // ../../internals/tanstack-query/src/components/QueryKey.tsx
1198
1386
  const declarationPrinter$4 = functionPrinter({ mode: "declaration" });
1199
1387
  /**
1200
1388
  * Default `queryKey` builder. Call it from a custom builder to extend the default key.
@@ -1252,8 +1440,7 @@ function QueryKey({ name, node, tsResolver, typeName, transformer, variant = "qu
1252
1440
  })
1253
1441
  })] });
1254
1442
  }
1255
- //#endregion
1256
- //#region src/generators/customHookOptionsFileGenerator.tsx
1443
+ // src/generators/customHookOptionsFileGenerator.tsx
1257
1444
  /**
1258
1445
  * Scaffolds the user-editable `useCustomHookOptions` file when
1259
1446
  * `pluginReactQuery({ customOptions: { ... }, hooks: true })` is configured. The file is
@@ -1350,8 +1537,7 @@ const customHookOptionsFileGenerator = defineGenerator({
1350
1537
  });
1351
1538
  }
1352
1539
  });
1353
- //#endregion
1354
- //#region src/generators/hookOptionsGenerator.tsx
1540
+ // src/generators/hookOptionsGenerator.tsx
1355
1541
  /**
1356
1542
  * Emits the `HookOptions` type used by `customOptions`. Enabled when
1357
1543
  * `pluginReactQuery({ customOptions: { ... } })`. The generated type lists
@@ -1510,8 +1696,7 @@ const hookOptionsGenerator = defineGenerator({
1510
1696
  });
1511
1697
  }
1512
1698
  });
1513
- //#endregion
1514
- //#region src/components/Query.tsx
1699
+ // src/components/Query.tsx
1515
1700
  const declarationPrinter$3 = functionPrinter({ mode: "declaration" });
1516
1701
  const OBSERVER_OPTIONS_NAMES = {
1517
1702
  infinite: {
@@ -1621,8 +1806,7 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
1621
1806
  })
1622
1807
  });
1623
1808
  }
1624
- //#endregion
1625
- //#region src/components/QueryOptions.tsx
1809
+ // src/components/QueryOptions.tsx
1626
1810
  const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
1627
1811
  const callPrinter$2 = functionPrinter({ mode: "call" });
1628
1812
  function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, returnType = "full" }) {
@@ -1655,8 +1839,7 @@ function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, return
1655
1839
  })
1656
1840
  });
1657
1841
  }
1658
- //#endregion
1659
- //#region src/generators/createQueryGenerator.tsx
1842
+ // src/generators/createQueryGenerator.tsx
1660
1843
  const OBSERVER_IMPORTS = {
1661
1844
  query: ["QueryObserverOptions", "UseQueryResult"],
1662
1845
  suspenseQuery: ["UseSuspenseQueryOptions", "UseSuspenseQueryResult"],
@@ -1815,8 +1998,7 @@ function createQueryGenerator({ name, variant }) {
1815
1998
  }
1816
1999
  });
1817
2000
  }
1818
- //#endregion
1819
- //#region src/generators/infiniteQueryGenerator.tsx
2001
+ // src/generators/infiniteQueryGenerator.tsx
1820
2002
  /**
1821
2003
  * Built-in generator for `useInfiniteQuery` hooks. Enabled when
1822
2004
  * `pluginReactQuery({ infinite: { ... }, hooks: true })`. Emits one
@@ -1828,8 +2010,7 @@ const infiniteQueryGenerator = createQueryGenerator({
1828
2010
  name: "react-infinite-query",
1829
2011
  variant: "infiniteQuery"
1830
2012
  });
1831
- //#endregion
1832
- //#region src/components/MutationOptions.tsx
2013
+ // src/components/MutationOptions.tsx
1833
2014
  const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
1834
2015
  const callPrinter$1 = functionPrinter({ mode: "call" });
1835
2016
  function buildMutationConfigParamsNode(node) {
@@ -1843,14 +2024,19 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
1843
2024
  const { TData, TError } = buildResponseTypes(node, tsResolver);
1844
2025
  const configParamsNode = buildMutationConfigParamsNode(node);
1845
2026
  const paramsSignature = declarationPrinter$1.print(configParamsNode) ?? "";
1846
- const groupedParam = buildGroupedRequestParam(node, { resolver: tsResolver });
2027
+ const groupedParam = buildGroupedRequestParam(node, {
2028
+ resolver: tsResolver,
2029
+ withContentType: true
2030
+ });
1847
2031
  const hasMutationParams = groupedParam !== null;
1848
2032
  const groupedParamsNode = createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
1849
2033
  const TRequest = hasMutationParams ? tsResolver.response.options(node) : "undefined";
1850
2034
  const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "_";
1851
2035
  const mutationFnBody = buildCallResultBody(buildClientCall(node, {
1852
2036
  clientName,
1853
- signal: false
2037
+ signal: false,
2038
+ withContentType: true,
2039
+ returnType
1854
2040
  }), { returnType });
1855
2041
  return /* @__PURE__ */ jsx(File.Source, {
1856
2042
  name,
@@ -1873,8 +2059,7 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
1873
2059
  })
1874
2060
  });
1875
2061
  }
1876
- //#endregion
1877
- //#region src/components/Mutation.tsx
2062
+ // src/components/Mutation.tsx
1878
2063
  const declarationPrinter = functionPrinter({ mode: "declaration" });
1879
2064
  const callPrinter = functionPrinter({ mode: "call" });
1880
2065
  function buildMutationParamsNode(node, options) {
@@ -1933,8 +2118,7 @@ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName
1933
2118
  })
1934
2119
  });
1935
2120
  }
1936
- //#endregion
1937
- //#region src/generators/mutationGenerator.tsx
2121
+ // src/generators/mutationGenerator.tsx
1938
2122
  /**
1939
2123
  * Built-in generator for `useMutation` hooks. Emits one `useFooMutation` hook
1940
2124
  * per POST/PUT/DELETE operation (configurable via `mutation.methods`) plus
@@ -2027,8 +2211,7 @@ const mutationGenerator = defineGenerator({
2027
2211
  });
2028
2212
  }
2029
2213
  });
2030
- //#endregion
2031
- //#region src/generators/queryGenerator.tsx
2214
+ // src/generators/queryGenerator.tsx
2032
2215
  /**
2033
2216
  * Built-in generator for `useQuery` hooks. Emits one `useFooQuery` hook per
2034
2217
  * GET and QUERY operation (configurable via `query.methods`) plus the matching
@@ -2038,8 +2221,7 @@ const queryGenerator = createQueryGenerator({
2038
2221
  name: "react-query",
2039
2222
  variant: "query"
2040
2223
  });
2041
- //#endregion
2042
- //#region src/generators/suspenseInfiniteQueryGenerator.tsx
2224
+ // src/generators/suspenseInfiniteQueryGenerator.tsx
2043
2225
  /**
2044
2226
  * Built-in generator for `useSuspenseInfiniteQuery` hooks. Enabled when
2045
2227
  * `suspense`, `infinite`, and `hooks` are all configured. Combines suspense
@@ -2050,8 +2232,7 @@ const suspenseInfiniteQueryGenerator = createQueryGenerator({
2050
2232
  name: "react-suspense-infinite-query",
2051
2233
  variant: "suspenseInfiniteQuery"
2052
2234
  });
2053
- //#endregion
2054
- //#region src/generators/suspenseQueryGenerator.tsx
2235
+ // src/generators/suspenseQueryGenerator.tsx
2055
2236
  /**
2056
2237
  * Built-in generator for `useSuspenseQuery` hooks. Enabled when
2057
2238
  * `pluginReactQuery({ suspense: {}, hooks: true })`. Emits one
@@ -2063,15 +2244,14 @@ const suspenseQueryGenerator = createQueryGenerator({
2063
2244
  name: "react-suspense-query",
2064
2245
  variant: "suspenseQuery"
2065
2246
  });
2066
- //#endregion
2067
- //#region src/resolvers/resolverReactQuery.ts
2247
+ // src/resolvers/resolverReactQuery.ts
2068
2248
  /**
2069
2249
  * Default resolver used by `@kubb/plugin-react-query`. Decides the names and
2070
2250
  * file paths for every generated TanStack Query hook (`useFoo`,
2071
2251
  * `useFooSuspense`, `useFooInfinite`, ...) and its companion helpers
2072
2252
  * (`fooQueryKey`, `fooQueryOptions`).
2073
2253
  *
2074
- * Functions and files use the built-in camelCase casing; hooks get the `use`
2254
+ * Functions use safe camelCase identifiers; hooks get the `use`
2075
2255
  * prefix; suspense and infinite variants are suffixed with `Suspense`/`Infinite`.
2076
2256
  *
2077
2257
  * @example Resolve hook and helper names
@@ -2086,6 +2266,7 @@ const suspenseQueryGenerator = createQueryGenerator({
2086
2266
  */
2087
2267
  const resolverReactQuery = createResolver({
2088
2268
  pluginName: "plugin-react-query",
2269
+ name: resolveOperationName,
2089
2270
  query: createQueryResolver(),
2090
2271
  suspenseQuery: createQueryResolver("Suspense"),
2091
2272
  infiniteQuery: createQueryResolver("Infinite"),
@@ -2093,23 +2274,36 @@ const resolverReactQuery = createResolver({
2093
2274
  mutation: {
2094
2275
  ...createMutationResolver(),
2095
2276
  optionsName(node) {
2096
- return `${this.name(node.operationId)}MutationOptions`;
2277
+ const name = `${this.name(node.operationId)}MutationOptions`;
2278
+ return this.resolveName({
2279
+ key: operationKey(node, "mutation", "optionsName"),
2280
+ name
2281
+ });
2097
2282
  },
2098
2283
  typeName(node) {
2099
- return capitalize(this.name(node.operationId));
2284
+ const name = capitalize(this.name(node.operationId));
2285
+ return this.resolveName({
2286
+ key: operationKey(node, "mutation", "typeName"),
2287
+ name
2288
+ });
2100
2289
  }
2101
2290
  },
2102
2291
  hook: {
2103
2292
  optionsName() {
2104
- return "HookOptions";
2293
+ return this.resolveName({
2294
+ key: ["hook", "options"],
2295
+ name: "HookOptions"
2296
+ });
2105
2297
  },
2106
2298
  customOptionsName() {
2107
- return "getCustomHookOptions";
2299
+ return this.resolveName({
2300
+ key: ["hook", "custom-options"],
2301
+ name: "getCustomHookOptions"
2302
+ });
2108
2303
  }
2109
2304
  }
2110
2305
  });
2111
- //#endregion
2112
- //#region src/plugin.ts
2306
+ // src/plugin.ts
2113
2307
  /**
2114
2308
  * Canonical plugin name for `@kubb/plugin-react-query`. Used for driver lookups
2115
2309
  * and cross-plugin dependency references.
@@ -2183,7 +2377,6 @@ const pluginReactQuery = defineExtension({
2183
2377
  };
2184
2378
  }
2185
2379
  });
2186
- //#endregion
2187
2380
  export { pluginReactQuery as default, pluginReactQuery, definePageParam, mutationKeyTransformer, pluginReactQueryName, queryKeyTransformer, resolverReactQuery };
2188
2381
 
2189
2382
  //# sourceMappingURL=index.js.map