@kubb/plugin-react-query 5.11.0-canary.20261111T122007 → 5.11.0-canary.20261111T193820

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
@@ -23,14 +23,192 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  value: mod,
24
24
  enumerable: true
25
25
  }) : target, mod));
26
- let _kubb_kit = require("@kubb/kit");
27
26
  let node_path = require("node:path");
28
27
  node_path = __toESM(node_path, 1);
28
+ let _kubb_kit = require("@kubb/kit");
29
29
  let _kubb_plugin_ts = require("@kubb/plugin-ts");
30
30
  let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
31
31
  let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
32
32
  let node_fs = require("node:fs");
33
33
  node_fs = __toESM(node_fs, 1);
34
+ // ../../internals/utils/src/casing.ts
35
+ /**
36
+ * Uppercases only the first character of `text`, leaving the rest untouched.
37
+ * Unlike `pascalCase` it never re-splits word boundaries or strips characters.
38
+ *
39
+ * @example
40
+ * `capitalize('getPetById') // 'GetPetById'`
41
+ */
42
+ function capitalize(text) {
43
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
44
+ }
45
+ // ../../internals/utils/src/reserved.ts
46
+ /**
47
+ * JavaScript and Java reserved words.
48
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
49
+ */
50
+ const reservedWords = /* @__PURE__ */ new Set([
51
+ "abstract",
52
+ "arguments",
53
+ "await",
54
+ "boolean",
55
+ "break",
56
+ "byte",
57
+ "case",
58
+ "catch",
59
+ "char",
60
+ "class",
61
+ "const",
62
+ "continue",
63
+ "debugger",
64
+ "default",
65
+ "delete",
66
+ "do",
67
+ "double",
68
+ "else",
69
+ "enum",
70
+ "eval",
71
+ "export",
72
+ "extends",
73
+ "false",
74
+ "final",
75
+ "finally",
76
+ "float",
77
+ "for",
78
+ "function",
79
+ "goto",
80
+ "if",
81
+ "implements",
82
+ "import",
83
+ "in",
84
+ "instanceof",
85
+ "int",
86
+ "interface",
87
+ "let",
88
+ "long",
89
+ "native",
90
+ "new",
91
+ "null",
92
+ "package",
93
+ "private",
94
+ "protected",
95
+ "public",
96
+ "return",
97
+ "short",
98
+ "static",
99
+ "super",
100
+ "switch",
101
+ "synchronized",
102
+ "this",
103
+ "throw",
104
+ "throws",
105
+ "transient",
106
+ "true",
107
+ "try",
108
+ "typeof",
109
+ "var",
110
+ "void",
111
+ "volatile",
112
+ "while",
113
+ "with",
114
+ "yield",
115
+ "Array",
116
+ "Date",
117
+ "hasOwnProperty",
118
+ "Infinity",
119
+ "isFinite",
120
+ "isNaN",
121
+ "isPrototypeOf",
122
+ "length",
123
+ "Math",
124
+ "name",
125
+ "NaN",
126
+ "Number",
127
+ "Object",
128
+ "prototype",
129
+ "String",
130
+ "toString",
131
+ "undefined",
132
+ "valueOf"
133
+ ]);
134
+ /**
135
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * isValidVarName('status') // true
140
+ * isValidVarName('class') // false (reserved word)
141
+ * isValidVarName('42foo') // false (starts with digit)
142
+ * ```
143
+ */
144
+ function isValidVarName(name) {
145
+ if (!name || reservedWords.has(name)) return false;
146
+ return isIdentifier(name);
147
+ }
148
+ /**
149
+ * Returns `name` when it's a syntactically valid JavaScript variable name,
150
+ * otherwise prefixes it with `_` so the result is a valid identifier.
151
+ *
152
+ * Useful for sanitizing OpenAPI schema names or operation IDs that start with
153
+ * a digit (e.g. `409`, `504AccountCancel`) before using them as exported
154
+ * variable, type, or function names.
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * ensureValidVarName('409') // '_409'
159
+ * ensureValidVarName('504AccountCancel') // '_504AccountCancel'
160
+ * ensureValidVarName('Pet') // 'Pet'
161
+ * ensureValidVarName('class') // '_class'
162
+ * ```
163
+ */
164
+ function ensureValidVarName(name) {
165
+ if (!name || isValidVarName(name)) return name;
166
+ return `_${name}`;
167
+ }
168
+ /**
169
+ * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
170
+ *
171
+ * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
172
+ * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
173
+ * deciding whether an object key needs quoting.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * isIdentifier('name') // true
178
+ * isIdentifier('x-total')// false
179
+ * ```
180
+ */
181
+ function isIdentifier(name) {
182
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
183
+ }
184
+ // ../../internals/utils/src/strings.ts
185
+ /**
186
+ * Escapes an `@` at the start of a line, so a multi-line description can't start a new JSDoc tag.
187
+ * Editors render `\@` as `@` in hovers.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * jsDocEscape('intro\n@example value') // 'intro\n\\@example value'
192
+ * ```
193
+ */
194
+ function jsDocEscape(input) {
195
+ return `${input}`.replace(/^(\s*)@/gm, "$1\\@");
196
+ }
197
+ /**
198
+ * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
199
+ * `accessor`. Returns `null` for an empty path.
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * getNestedAccessor('pagination.next.id', 'lastPage')
204
+ * // "lastPage?.['pagination']?.['next']?.['id']"
205
+ * ```
206
+ */
207
+ function getNestedAccessor(param, accessor) {
208
+ const parts = Array.isArray(param) ? param : param.split(".");
209
+ if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
210
+ return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
211
+ }
34
212
  // ../../internals/shared/src/operation.ts
35
213
  /**
36
214
  * Builds the `ResolverFileParams` every operation generator passes to
@@ -126,16 +304,19 @@ function getContentTypeInfo(node) {
126
304
  function getResponseContentTypeInfo(node) {
127
305
  return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? []);
128
306
  }
307
+ /**
308
+ * The media type without its parameters, in lower case: `Text/Plain; charset=utf-8` gives `text/plain`.
309
+ */
129
310
  function baseContentType(contentType) {
130
311
  return contentType.split(";")[0].trim().toLowerCase();
131
312
  }
132
313
  /**
133
314
  * Whether a content entry is a sequence of JSON values the adapter marks as a stream, such as `application/jsonl`,
134
- * `application/x-ndjson`, `application/json-seq`, or any media type with an OpenAPI 3.2 `itemSchema`.
315
+ * `application/x-ndjson` or `application/json-seq`.
135
316
  */
136
317
  function isJsonLines(entry) {
137
318
  const baseType = baseContentType(entry.contentType);
138
- return Boolean(entry.stream) && baseType !== "text/event-stream" && !baseType.startsWith("multipart/");
319
+ return Boolean(entry.stream) && baseType !== "text/event-stream" && isStreamContentType(baseType);
139
320
  }
140
321
  /**
141
322
  * How an operation streams its primary success response item by item, when that response declares one content type:
@@ -160,6 +341,25 @@ function getEventStream(node) {
160
341
  function isEventStream(node) {
161
342
  return getEventStream(node) !== null;
162
343
  }
344
+ const streamContentTypes = /* @__PURE__ */ new Set([
345
+ "text/event-stream",
346
+ "application/jsonl",
347
+ "application/x-ndjson",
348
+ "application/json-seq"
349
+ ]);
350
+ function isStreamContentType(baseType) {
351
+ return streamContentTypes.has(baseType) || baseType.startsWith("application/") && baseType.endsWith("+json-seq");
352
+ }
353
+ /**
354
+ * Whether a success response offers a stream media type next to other content types. The client returns that variant's
355
+ * body as a `ReadableStream`, so the stream runtime is registered and a hook's data type includes the stream.
356
+ */
357
+ function hasStreamVariant(node) {
358
+ return getSuccessResponses(node.responses).some((response) => {
359
+ const variants = (response.content ?? []).filter((entry) => entry.schema);
360
+ return variants.length > 1 && variants.some((entry) => isStreamContentType(baseContentType(entry.contentType)));
361
+ });
362
+ }
163
363
  /**
164
364
  * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
165
365
  * `useInfiniteQuery`, `useSWR`, ...): `RequestConfig` minus what the
@@ -235,7 +435,8 @@ function buildOperationComments(node, options = {}) {
235
435
  getOperationRequestLine(node),
236
436
  node.description && `@description ${node.description}`,
237
437
  node.summary && `@summary ${node.summary}`,
238
- node.deprecated && "@deprecated"
438
+ node.deprecated && "@deprecated",
439
+ node.externalDocs && `@see ${jsDocEscape([node.externalDocs.url, node.externalDocs.description].filter(Boolean).join(" "))}`
239
440
  ].filter((comment) => Boolean(comment));
240
441
  if (!splitLines) return filteredComments;
241
442
  return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
@@ -243,19 +444,25 @@ function buildOperationComments(node, options = {}) {
243
444
  const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
244
445
  /**
245
446
  * An OpenAPI 3.2 `querystring` parameter is the whole query string, so a form-encoded object becomes one query parameter
246
- * per property, typed and serialized like any other.
447
+ * per property, typed and serialized like any other, with the `style` and `explode` its `encoding` entry declares.
247
448
  * Another content type, such as JSON, stays one parameter named after it, and the runtime sends its value as the whole query string.
248
449
  */
249
450
  function spreadQuerystring(param) {
250
451
  const schema = param.schema.type === "ref" ? param.schema.schema : param.schema;
251
- const formEncoded = !param.contentType || param.contentType.split(";")[0].trim().toLowerCase() === "application/x-www-form-urlencoded";
452
+ const formEncoded = !param.contentType || baseContentType(param.contentType) === "application/x-www-form-urlencoded";
252
453
  if (schema?.type !== "object" || !formEncoded) return [param];
253
- return schema.properties.map((property) => _kubb_kit.ast.factory.createParameter({
254
- name: property.name,
255
- in: "query",
256
- schema: property.schema,
257
- required: param.required && property.required
258
- }));
454
+ return schema.properties.map((property) => {
455
+ const { style, explode, allowReserved } = param.encoding?.[property.name] ?? {};
456
+ return _kubb_kit.ast.factory.createParameter({
457
+ name: property.name,
458
+ in: "query",
459
+ schema: property.schema,
460
+ required: param.required && property.required,
461
+ ...style !== void 0 && { style },
462
+ ...explode !== void 0 && { explode },
463
+ ...allowReserved !== void 0 && { allowReserved }
464
+ });
465
+ });
259
466
  }
260
467
  /**
261
468
  * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
@@ -294,13 +501,28 @@ function getStatusCodeNumber(statusCode) {
294
501
  const code = Number(statusCode);
295
502
  return Number.isNaN(code) ? null : code;
296
503
  }
297
- function isSuccessStatusCode(statusCode) {
504
+ const statusClassByRange = /* @__PURE__ */ new Map([
505
+ ["1xx", 1],
506
+ ["2xx", 2],
507
+ ["3xx", 3],
508
+ ["4xx", 4],
509
+ ["5xx", 5]
510
+ ]);
511
+ /**
512
+ * The class digit of a status code or range, such as `2` for `201` and `2xx`, or `null` for `default`.
513
+ */
514
+ function getStatusClass(statusCode) {
515
+ const rangeClass = statusClassByRange.get(String(statusCode));
516
+ if (rangeClass) return rangeClass;
298
517
  const code = getStatusCodeNumber(statusCode);
299
- return code !== null && code >= 200 && code < 300;
518
+ return code === null ? null : Math.floor(code / 100);
519
+ }
520
+ function isSuccessStatusCode(statusCode) {
521
+ return getStatusClass(statusCode) === 2;
300
522
  }
301
523
  function isErrorStatusCode(statusCode) {
302
- const code = getStatusCodeNumber(statusCode);
303
- return code !== null && code >= 400;
524
+ const statusClass = getStatusClass(statusCode);
525
+ return statusClass !== null && statusClass >= 4;
304
526
  }
305
527
  function getSuccessResponses(responses) {
306
528
  return responses.filter((response) => isSuccessStatusCode(response.statusCode));
@@ -309,7 +531,10 @@ function getOperationSuccessResponses(node) {
309
531
  return getSuccessResponses(node.responses);
310
532
  }
311
533
  function getPrimarySuccessResponse(node) {
312
- return getOperationSuccessResponses(node)[0] ?? null;
534
+ const responses = getOperationSuccessResponses(node);
535
+ const withBody = responses.filter((response) => response.content?.length);
536
+ const candidates = withBody.length ? withBody : responses;
537
+ return candidates.find((response) => getStatusCodeNumber(response.statusCode) !== null) ?? candidates[0] ?? null;
313
538
  }
314
539
  function resolveErrorNames(node, resolver) {
315
540
  return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode));
@@ -348,172 +573,6 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
348
573
  ]).filter((name) => Boolean(name) && !exclude.has(name));
349
574
  });
350
575
  }
351
- // ../../internals/utils/src/casing.ts
352
- /**
353
- * Uppercases only the first character of `text`, leaving the rest untouched.
354
- * Unlike `pascalCase` it never re-splits word boundaries or strips characters.
355
- *
356
- * @example
357
- * `capitalize('getPetById') // 'GetPetById'`
358
- */
359
- function capitalize(text) {
360
- return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
361
- }
362
- // ../../internals/utils/src/reserved.ts
363
- /**
364
- * JavaScript and Java reserved words.
365
- * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
366
- */
367
- const reservedWords = /* @__PURE__ */ new Set([
368
- "abstract",
369
- "arguments",
370
- "await",
371
- "boolean",
372
- "break",
373
- "byte",
374
- "case",
375
- "catch",
376
- "char",
377
- "class",
378
- "const",
379
- "continue",
380
- "debugger",
381
- "default",
382
- "delete",
383
- "do",
384
- "double",
385
- "else",
386
- "enum",
387
- "eval",
388
- "export",
389
- "extends",
390
- "false",
391
- "final",
392
- "finally",
393
- "float",
394
- "for",
395
- "function",
396
- "goto",
397
- "if",
398
- "implements",
399
- "import",
400
- "in",
401
- "instanceof",
402
- "int",
403
- "interface",
404
- "let",
405
- "long",
406
- "native",
407
- "new",
408
- "null",
409
- "package",
410
- "private",
411
- "protected",
412
- "public",
413
- "return",
414
- "short",
415
- "static",
416
- "super",
417
- "switch",
418
- "synchronized",
419
- "this",
420
- "throw",
421
- "throws",
422
- "transient",
423
- "true",
424
- "try",
425
- "typeof",
426
- "var",
427
- "void",
428
- "volatile",
429
- "while",
430
- "with",
431
- "yield",
432
- "Array",
433
- "Date",
434
- "hasOwnProperty",
435
- "Infinity",
436
- "isFinite",
437
- "isNaN",
438
- "isPrototypeOf",
439
- "length",
440
- "Math",
441
- "name",
442
- "NaN",
443
- "Number",
444
- "Object",
445
- "prototype",
446
- "String",
447
- "toString",
448
- "undefined",
449
- "valueOf"
450
- ]);
451
- /**
452
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
453
- *
454
- * @example
455
- * ```ts
456
- * isValidVarName('status') // true
457
- * isValidVarName('class') // false (reserved word)
458
- * isValidVarName('42foo') // false (starts with digit)
459
- * ```
460
- */
461
- function isValidVarName(name) {
462
- if (!name || reservedWords.has(name)) return false;
463
- return isIdentifier(name);
464
- }
465
- /**
466
- * Returns `name` when it's a syntactically valid JavaScript variable name,
467
- * otherwise prefixes it with `_` so the result is a valid identifier.
468
- *
469
- * Useful for sanitizing OpenAPI schema names or operation IDs that start with
470
- * a digit (e.g. `409`, `504AccountCancel`) before using them as exported
471
- * variable, type, or function names.
472
- *
473
- * @example
474
- * ```ts
475
- * ensureValidVarName('409') // '_409'
476
- * ensureValidVarName('504AccountCancel') // '_504AccountCancel'
477
- * ensureValidVarName('Pet') // 'Pet'
478
- * ensureValidVarName('class') // '_class'
479
- * ```
480
- */
481
- function ensureValidVarName(name) {
482
- if (!name || isValidVarName(name)) return name;
483
- return `_${name}`;
484
- }
485
- /**
486
- * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
487
- *
488
- * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
489
- * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
490
- * deciding whether an object key needs quoting.
491
- *
492
- * @example
493
- * ```ts
494
- * isIdentifier('name') // true
495
- * isIdentifier('x-total')// false
496
- * ```
497
- */
498
- function isIdentifier(name) {
499
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
500
- }
501
- // ../../internals/utils/src/strings.ts
502
- /**
503
- * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
504
- * `accessor`. Returns `null` for an empty path.
505
- *
506
- * @example
507
- * ```ts
508
- * getNestedAccessor('pagination.next.id', 'lastPage')
509
- * // "lastPage?.['pagination']?.['next']?.['id']"
510
- * ```
511
- */
512
- function getNestedAccessor(param, accessor) {
513
- const parts = Array.isArray(param) ? param : param.split(".");
514
- if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
515
- return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
516
- }
517
576
  // ../../internals/shared/src/resolver.ts
518
577
  /**
519
578
  * The shared top-level `name` of the operation plugins, computed once per operation name and build.
@@ -547,7 +606,8 @@ function operationKey(node, ...scope) {
547
606
  * shared default naming so every plugin groups output consistently:
548
607
  *
549
608
  * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
550
- * - other groups use the camelCased group (`pet store` → `petStore`).
609
+ * - `tag` groups get no name here, so Kubb names them itself: the camelCased tag (`pet store` → `petStore`), nested in
610
+ * the folders of its OpenAPI 3.2 `parent` tags (`payment` with parent `store` → `store/payment`).
551
611
  *
552
612
  * A user-provided `group.name` always wins over the default namer, so callers stay in
553
613
  * control of their output folders. Returns `null` when grouping is disabled, matching the
@@ -562,22 +622,19 @@ function operationKey(node, ...scope) {
562
622
  */
563
623
  function createGroupConfig(group) {
564
624
  if (!group) return null;
565
- const defaultName = (ctx) => {
566
- if (group.type === "path") return `${ctx.group.split("/")[1]}`;
567
- return (0, _kubb_kit.camelCase)(ctx.group);
568
- };
625
+ if (group.name || group.type !== "path") return group;
569
626
  return {
570
627
  ...group,
571
- name: group.name ? group.name : defaultName
628
+ name: (ctx) => `${ctx.group.split("/")[1]}`
572
629
  };
573
630
  }
574
631
  // kubb-extension.json
575
632
  var compatibility = {
576
- "kubb": ">=5.16.0",
633
+ "kubb": ">=5.18.4",
577
634
  "node": ">=22.22"
578
635
  };
579
636
  // package.json
580
- var version = "5.11.0-canary.20261111T122007";
637
+ var version = "5.11.0-canary.20261111T193820";
581
638
  // ../../internals/client/src/resolveClient.ts
582
639
  /**
583
640
  * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
@@ -747,12 +804,53 @@ function resolveClientOperation(options) {
747
804
  operationFile: file.path
748
805
  }),
749
806
  clientPathIsFile: importPath === void 0 || isRelativeImport(importPath),
750
- returnType: operationOptions.returnType ?? "full"
807
+ returnType: operationOptions.returnType ?? "full",
808
+ typedHeaders: importPath === void 0
751
809
  };
752
810
  });
753
811
  }
754
812
  // ../../internals/client/src/resolveOperationTypes.ts
755
813
  const pluginZodName = "plugin-zod";
814
+ function getResponseHeadersEntries({ node, types }) {
815
+ const resolve = types.response.headers;
816
+ if (!resolve) return [];
817
+ return node.responses.filter((response) => response.headers?.length).map((response) => [response.statusCode, resolve.call(types.response, node, response.statusCode)]);
818
+ }
819
+ /**
820
+ * The headers type argument of `RequestResult`, such as `{ '200': LoginUserStatus200Headers }`, or `null` when no response declares headers.
821
+ */
822
+ function buildResponseHeadersType({ node, types }) {
823
+ const entries = getResponseHeadersEntries({
824
+ node,
825
+ types
826
+ }).map(([statusCode, name]) => `'${statusCode}': ${name}`);
827
+ return entries.length ? `{ ${entries.join("; ")} }` : null;
828
+ }
829
+ /**
830
+ * A runtime result type, such as `RequestResult`, in its `WithHeaders` form when `headers` is set.
831
+ */
832
+ function resultTypeName(name, headers) {
833
+ return headers ? `${name}WithHeaders` : name;
834
+ }
835
+ /**
836
+ * A runtime result type with its arguments, such as `RequestResultWithHeaders<Responses, Headers, ThrowOnError>`.
837
+ */
838
+ function buildResultTypeRef(name, responses, headers, rest = []) {
839
+ return `${resultTypeName(name, headers !== null)}<${[
840
+ responses,
841
+ headers,
842
+ ...rest
843
+ ].filter(Boolean).join(", ")}>`;
844
+ }
845
+ /**
846
+ * The names of the headers types `buildResponseHeadersType` references, for the file's imports.
847
+ */
848
+ function getResponseHeadersTypeNames({ node, types }) {
849
+ return getResponseHeadersEntries({
850
+ node,
851
+ types
852
+ }).map(([, name]) => name);
853
+ }
756
854
  /**
757
855
  * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
758
856
  * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
@@ -775,6 +873,7 @@ function toZodTypeResolver(resolver) {
775
873
  status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
776
874
  response: (node) => type(resolver.response.response(node)),
777
875
  responses: (node) => type(resolver.response.responses(node)),
876
+ headers: (node, statusCode) => type(resolver.response.headers(node, statusCode)),
778
877
  options: (node) => resolver.response.options(node)
779
878
  }
780
879
  };
@@ -840,6 +939,10 @@ function resolveHookFile(node, ctx, options) {
840
939
  });
841
940
  const types = resolveOperationTypes(ctx.driver, resolver.pluginName);
842
941
  const tsResolver = types.resolver;
942
+ const headerTypeNames = returnType === "data" || !contractOp.typedHeaders ? [] : getResponseHeadersTypeNames({
943
+ node,
944
+ types: tsResolver
945
+ });
843
946
  const file = resolver.file({
844
947
  ...operationFileEntry(node, name),
845
948
  root,
@@ -857,6 +960,7 @@ function resolveHookFile(node, ctx, options) {
857
960
  const importedTypeNames = [
858
961
  tsResolver.response.options(node),
859
962
  tsResolver.response.responses(node),
963
+ ...headerTypeNames,
860
964
  ...extraTypeNames,
861
965
  ...resolveOperationTypeNames(node, tsResolver, {
862
966
  exclude: [keyTypeName, returnType !== "data" ? tsResolver.response.response(node) : null].filter((name) => Boolean(name)),
@@ -874,6 +978,7 @@ function resolveHookFile(node, ctx, options) {
874
978
  tsResolver,
875
979
  contractOp,
876
980
  importedTypeNames,
981
+ resultTypeName: headerTypeNames.length ? "RequestResultWithHeaders" : "RequestResult",
877
982
  returnType,
878
983
  banner: resolver.default.banner(ctx.meta, {
879
984
  output,
@@ -891,7 +996,7 @@ function resolveHookFile(node, ctx, options) {
891
996
  * The `<File>` shell shared by the TanStack hook generators; renders `children` after the imports.
892
997
  */
893
998
  function HookFile({ hook, imports, children }) {
894
- const { file, fileTs, contractOp, importedTypeNames, banner, footer } = hook;
999
+ const { file, fileTs, contractOp, importedTypeNames, resultTypeName, banner, footer } = hook;
895
1000
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
896
1001
  baseName: file.baseName,
897
1002
  path: file.path,
@@ -908,7 +1013,7 @@ function HookFile({ hook, imports, children }) {
908
1013
  name: [
909
1014
  "RequestConfig",
910
1015
  "ResponseErrorConfig",
911
- "RequestResult"
1016
+ resultTypeName
912
1017
  ],
913
1018
  root: contractOp.clientPathIsFile ? file.path : void 0,
914
1019
  path: contractOp.clientPath,
@@ -1053,19 +1158,28 @@ function buildCallResultBody(call, options = {}) {
1053
1158
  if (clientReturnType === "plain") return `return (await ${call}).data`;
1054
1159
  return `return ${call}.unwrap()`;
1055
1160
  }
1161
+ function buildResultType(node, resolver, typedHeaders) {
1162
+ const headers = typedHeaders ? buildResponseHeadersType({
1163
+ node,
1164
+ types: resolver
1165
+ }) : null;
1166
+ return buildResultTypeRef("RequestResult", resolver.response.responses(node), headers, ["true"]);
1167
+ }
1056
1168
  /**
1057
1169
  * Builds the `TData` / `TError` type expressions shared by every generated hook, joining the resolved
1058
1170
  * success responses into `TData` and wrapping the error responses in `ResponseErrorConfig<...>`.
1059
- * With `returnType` `'full'`, `TData` is the client's `RequestResult` over the operation's responses record.
1171
+ * With `returnType` `'full'`, `TData` is the client's `RequestResult` over the operation's responses record, with the
1172
+ * response headers the operation declares.
1060
1173
  */
1061
1174
  function buildResponseTypes(node, resolver, options = {}) {
1062
- const { returnType = "data" } = options;
1063
- return resolver.memo(`responseTypes:${returnType}:${node.method}\0${node.path}`, () => {
1175
+ const { returnType = "data", typedHeaders = true } = options;
1176
+ return resolver.memo(`responseTypes:${returnType}:${typedHeaders}:${node.method}\0${node.path}`, () => {
1064
1177
  const successNames = resolveSuccessNames(node, resolver);
1065
- const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.response.response(node);
1178
+ const bodyName = successNames.length > 0 ? successNames.join(" | ") : resolver.response.response(node);
1179
+ const responseName = hasStreamVariant(node) ? `${bodyName} | ReadableStream<Uint8Array>` : bodyName;
1066
1180
  const errorNames = resolveErrorNames(node, resolver);
1067
1181
  return {
1068
- TData: returnType !== "data" ? `RequestResult<${resolver.response.responses(node)}, true>` : responseName,
1182
+ TData: returnType === "data" ? responseName : buildResultType(node, resolver, typedHeaders),
1069
1183
  TError: `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`
1070
1184
  };
1071
1185
  });
@@ -1301,8 +1415,11 @@ function buildResolvedRequestParams(node) {
1301
1415
  // ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
1302
1416
  const declarationPrinter$6 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1303
1417
  const callPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1304
- function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, clientReturnType, returnType }) {
1305
- const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver, { returnType });
1418
+ function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, clientReturnType, returnType, typedHeaders }) {
1419
+ const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver, {
1420
+ returnType,
1421
+ typedHeaders
1422
+ });
1306
1423
  const dataSuffix = returnType === "data" ? "" : ".data";
1307
1424
  const { queryParamsTypeName, pageParamType } = resolvePageParamType(node, {
1308
1425
  resolver: tsResolver,
@@ -1803,8 +1920,11 @@ function buildHookTypes({ node, tsResolver, infinite, suspense, TData, TError, q
1803
1920
  resultType: `${resultTypeName}<TData, ${TError}> & { queryKey: TQueryKey }`
1804
1921
  };
1805
1922
  }
1806
- function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense, infinite, returnType }) {
1807
- const { TData, TError } = buildResponseTypes(node, tsResolver, { returnType });
1923
+ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense, infinite, returnType, typedHeaders }) {
1924
+ const { TData, TError } = buildResponseTypes(node, tsResolver, {
1925
+ returnType,
1926
+ typedHeaders
1927
+ });
1808
1928
  const prefix = suspense ? "UseSuspense" : "Use";
1809
1929
  const hookName = `${suspense ? "useSuspense" : "use"}${infinite ? "InfiniteQuery" : "Query"}`;
1810
1930
  const observerOptionsName = OBSERVER_OPTIONS_NAMES[infinite ? "infinite" : "plain"][suspense ? "suspense" : "standard"];
@@ -1864,8 +1984,11 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
1864
1984
  // src/components/QueryOptions.tsx
1865
1985
  const declarationPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1866
1986
  const callPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1867
- function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, clientReturnType, returnType }) {
1868
- const { TData, TError } = buildResponseTypes(node, tsResolver, { returnType });
1987
+ function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, clientReturnType, returnType, typedHeaders }) {
1988
+ const { TData, TError } = buildResponseTypes(node, tsResolver, {
1989
+ returnType,
1990
+ typedHeaders
1991
+ });
1869
1992
  const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
1870
1993
  const queryKeyParamsCall = callPrinter$2.print(queryKeyParamsNode) ?? "";
1871
1994
  const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
@@ -2011,7 +2134,8 @@ function createQueryGenerator({ name, variant }) {
2011
2134
  hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
2012
2135
  queryParam: infiniteOptions.queryParam,
2013
2136
  clientReturnType: contractOp.returnType,
2014
- returnType: hook.returnType
2137
+ returnType: hook.returnType,
2138
+ typedHeaders: hook.contractOp.typedHeaders
2015
2139
  })
2016
2140
  ] }) : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
2017
2141
  name: ["queryOptions"],
@@ -2023,7 +2147,8 @@ function createQueryGenerator({ name, variant }) {
2023
2147
  node,
2024
2148
  tsResolver: hook.tsResolver,
2025
2149
  clientReturnType: contractOp.returnType,
2026
- returnType: hook.returnType
2150
+ returnType: hook.returnType,
2151
+ typedHeaders: hook.contractOp.typedHeaders
2027
2152
  })] }),
2028
2153
  (variant !== "query" || query && hooks) && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
2029
2154
  /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
@@ -2048,6 +2173,7 @@ function createQueryGenerator({ name, variant }) {
2048
2173
  tsResolver: hook.tsResolver,
2049
2174
  customOptions,
2050
2175
  returnType: hook.returnType,
2176
+ typedHeaders: hook.contractOp.typedHeaders,
2051
2177
  suspense,
2052
2178
  infinite: infiniteOptions ? {
2053
2179
  initialPageParam: infiniteOptions.initialPageParam,
@@ -2082,8 +2208,11 @@ function buildMutationConfigParamsNode(node) {
2082
2208
  default: "{}"
2083
2209
  })] });
2084
2210
  }
2085
- function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName, clientReturnType, returnType }) {
2086
- const { TData, TError } = buildResponseTypes(node, tsResolver, { returnType });
2211
+ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName, clientReturnType, returnType, typedHeaders }) {
2212
+ const { TData, TError } = buildResponseTypes(node, tsResolver, {
2213
+ returnType,
2214
+ typedHeaders
2215
+ });
2087
2216
  const configParamsNode = buildMutationConfigParamsNode(node);
2088
2217
  const paramsSignature = declarationPrinter$1.print(configParamsNode) ?? "";
2089
2218
  const groupedParam = buildGroupedRequestParam(node, {
@@ -2127,8 +2256,11 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
2127
2256
  const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
2128
2257
  const callPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
2129
2258
  function buildMutationParamsNode(node, options) {
2130
- const { resolver, returnType } = options;
2131
- const { TData, TError } = buildResponseTypes(node, resolver, { returnType });
2259
+ const { resolver, returnType, typedHeaders } = options;
2260
+ const { TData, TError } = buildResponseTypes(node, resolver, {
2261
+ returnType,
2262
+ typedHeaders
2263
+ });
2132
2264
  return buildHookParams(node, {
2133
2265
  resolver,
2134
2266
  withRequest: false,
@@ -2143,8 +2275,11 @@ function buildMutationParamsNode(node, options) {
2143
2275
  }`
2144
2276
  });
2145
2277
  }
2146
- function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName, customOptions, returnType }) {
2147
- const { TData, TError } = buildResponseTypes(node, tsResolver, { returnType });
2278
+ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName, customOptions, returnType, typedHeaders }) {
2279
+ const { TData, TError } = buildResponseTypes(node, tsResolver, {
2280
+ returnType,
2281
+ typedHeaders
2282
+ });
2148
2283
  const generics = [
2149
2284
  TData,
2150
2285
  TError,
@@ -2156,7 +2291,8 @@ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName
2156
2291
  const mutationOptionsParamsCall = callPrinter.print(mutationOptionsConfigNode) ?? "";
2157
2292
  const paramsNode = buildMutationParamsNode(node, {
2158
2293
  resolver: tsResolver,
2159
- returnType
2294
+ returnType,
2295
+ typedHeaders
2160
2296
  });
2161
2297
  const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
2162
2298
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
@@ -2251,7 +2387,8 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
2251
2387
  node,
2252
2388
  tsResolver,
2253
2389
  clientReturnType: contractOp.returnType,
2254
- returnType: hook.returnType
2390
+ returnType: hook.returnType,
2391
+ typedHeaders: hook.contractOp.typedHeaders
2255
2392
  }),
2256
2393
  mutation && hooks && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
2257
2394
  /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
@@ -2274,7 +2411,8 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
2274
2411
  node,
2275
2412
  tsResolver,
2276
2413
  customOptions,
2277
- returnType: hook.returnType
2414
+ returnType: hook.returnType,
2415
+ typedHeaders: hook.contractOp.typedHeaders
2278
2416
  })
2279
2417
  ] })
2280
2418
  ]