@kubb/plugin-react-query 5.11.0-canary.20261111T120000 → 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.
@@ -526,6 +585,9 @@ function resolveOperationName(name) {
526
585
  * it is, so two of them never share an allocation even when a custom resolver gives both the same
527
586
  * name. Leave `scope` empty for the operation's own declaration.
528
587
  *
588
+ * The key starts from the operation's input `pointer`, which macros keep, so a plugin whose macro
589
+ * rewrites the method or path still resolves another plugin's names for the same operation.
590
+ *
529
591
  * @example
530
592
  * ```ts
531
593
  * resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
@@ -534,8 +596,7 @@ function resolveOperationName(name) {
534
596
  function operationKey(node, ...scope) {
535
597
  return [
536
598
  "operation",
537
- node.method,
538
- node.path,
599
+ ...node.pointer ? [node.pointer] : [node.method, node.path],
539
600
  ...scope.map(String)
540
601
  ];
541
602
  }
@@ -545,7 +606,8 @@ function operationKey(node, ...scope) {
545
606
  * shared default naming so every plugin groups output consistently:
546
607
  *
547
608
  * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
548
- * - 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`).
549
611
  *
550
612
  * A user-provided `group.name` always wins over the default namer, so callers stay in
551
613
  * control of their output folders. Returns `null` when grouping is disabled, matching the
@@ -560,22 +622,19 @@ function operationKey(node, ...scope) {
560
622
  */
561
623
  function createGroupConfig(group) {
562
624
  if (!group) return null;
563
- const defaultName = (ctx) => {
564
- if (group.type === "path") return `${ctx.group.split("/")[1]}`;
565
- return (0, _kubb_kit.camelCase)(ctx.group);
566
- };
625
+ if (group.name || group.type !== "path") return group;
567
626
  return {
568
627
  ...group,
569
- name: group.name ? group.name : defaultName
628
+ name: (ctx) => `${ctx.group.split("/")[1]}`
570
629
  };
571
630
  }
572
631
  // kubb-extension.json
573
632
  var compatibility = {
574
- "kubb": ">=5.16.0",
633
+ "kubb": ">=5.18.4",
575
634
  "node": ">=22.22"
576
635
  };
577
636
  // package.json
578
- var version = "5.11.0-canary.20261111T120000";
637
+ var version = "5.11.0-canary.20261111T193820";
579
638
  // ../../internals/client/src/resolveClient.ts
580
639
  /**
581
640
  * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
@@ -745,12 +804,53 @@ function resolveClientOperation(options) {
745
804
  operationFile: file.path
746
805
  }),
747
806
  clientPathIsFile: importPath === void 0 || isRelativeImport(importPath),
748
- returnType: operationOptions.returnType ?? "full"
807
+ returnType: operationOptions.returnType ?? "full",
808
+ typedHeaders: importPath === void 0
749
809
  };
750
810
  });
751
811
  }
752
812
  // ../../internals/client/src/resolveOperationTypes.ts
753
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
+ }
754
854
  /**
755
855
  * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
756
856
  * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
@@ -773,6 +873,7 @@ function toZodTypeResolver(resolver) {
773
873
  status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
774
874
  response: (node) => type(resolver.response.response(node)),
775
875
  responses: (node) => type(resolver.response.responses(node)),
876
+ headers: (node, statusCode) => type(resolver.response.headers(node, statusCode)),
776
877
  options: (node) => resolver.response.options(node)
777
878
  }
778
879
  };
@@ -838,6 +939,10 @@ function resolveHookFile(node, ctx, options) {
838
939
  });
839
940
  const types = resolveOperationTypes(ctx.driver, resolver.pluginName);
840
941
  const tsResolver = types.resolver;
942
+ const headerTypeNames = returnType === "data" || !contractOp.typedHeaders ? [] : getResponseHeadersTypeNames({
943
+ node,
944
+ types: tsResolver
945
+ });
841
946
  const file = resolver.file({
842
947
  ...operationFileEntry(node, name),
843
948
  root,
@@ -855,6 +960,7 @@ function resolveHookFile(node, ctx, options) {
855
960
  const importedTypeNames = [
856
961
  tsResolver.response.options(node),
857
962
  tsResolver.response.responses(node),
963
+ ...headerTypeNames,
858
964
  ...extraTypeNames,
859
965
  ...resolveOperationTypeNames(node, tsResolver, {
860
966
  exclude: [keyTypeName, returnType !== "data" ? tsResolver.response.response(node) : null].filter((name) => Boolean(name)),
@@ -872,6 +978,7 @@ function resolveHookFile(node, ctx, options) {
872
978
  tsResolver,
873
979
  contractOp,
874
980
  importedTypeNames,
981
+ resultTypeName: headerTypeNames.length ? "RequestResultWithHeaders" : "RequestResult",
875
982
  returnType,
876
983
  banner: resolver.default.banner(ctx.meta, {
877
984
  output,
@@ -889,7 +996,7 @@ function resolveHookFile(node, ctx, options) {
889
996
  * The `<File>` shell shared by the TanStack hook generators; renders `children` after the imports.
890
997
  */
891
998
  function HookFile({ hook, imports, children }) {
892
- const { file, fileTs, contractOp, importedTypeNames, banner, footer } = hook;
999
+ const { file, fileTs, contractOp, importedTypeNames, resultTypeName, banner, footer } = hook;
893
1000
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
894
1001
  baseName: file.baseName,
895
1002
  path: file.path,
@@ -906,7 +1013,7 @@ function HookFile({ hook, imports, children }) {
906
1013
  name: [
907
1014
  "RequestConfig",
908
1015
  "ResponseErrorConfig",
909
- "RequestResult"
1016
+ resultTypeName
910
1017
  ],
911
1018
  root: contractOp.clientPathIsFile ? file.path : void 0,
912
1019
  path: contractOp.clientPath,
@@ -1051,19 +1158,28 @@ function buildCallResultBody(call, options = {}) {
1051
1158
  if (clientReturnType === "plain") return `return (await ${call}).data`;
1052
1159
  return `return ${call}.unwrap()`;
1053
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
+ }
1054
1168
  /**
1055
1169
  * Builds the `TData` / `TError` type expressions shared by every generated hook, joining the resolved
1056
1170
  * success responses into `TData` and wrapping the error responses in `ResponseErrorConfig<...>`.
1057
- * 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.
1058
1173
  */
1059
1174
  function buildResponseTypes(node, resolver, options = {}) {
1060
- const { returnType = "data" } = options;
1061
- 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}`, () => {
1062
1177
  const successNames = resolveSuccessNames(node, resolver);
1063
- 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;
1064
1180
  const errorNames = resolveErrorNames(node, resolver);
1065
1181
  return {
1066
- TData: returnType !== "data" ? `RequestResult<${resolver.response.responses(node)}, true>` : responseName,
1182
+ TData: returnType === "data" ? responseName : buildResultType(node, resolver, typedHeaders),
1067
1183
  TError: `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`
1068
1184
  };
1069
1185
  });
@@ -1299,8 +1415,11 @@ function buildResolvedRequestParams(node) {
1299
1415
  // ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
1300
1416
  const declarationPrinter$6 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1301
1417
  const callPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1302
- function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, clientReturnType, returnType }) {
1303
- 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
+ });
1304
1423
  const dataSuffix = returnType === "data" ? "" : ".data";
1305
1424
  const { queryParamsTypeName, pageParamType } = resolvePageParamType(node, {
1306
1425
  resolver: tsResolver,
@@ -1801,8 +1920,11 @@ function buildHookTypes({ node, tsResolver, infinite, suspense, TData, TError, q
1801
1920
  resultType: `${resultTypeName}<TData, ${TError}> & { queryKey: TQueryKey }`
1802
1921
  };
1803
1922
  }
1804
- function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense, infinite, returnType }) {
1805
- 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
+ });
1806
1928
  const prefix = suspense ? "UseSuspense" : "Use";
1807
1929
  const hookName = `${suspense ? "useSuspense" : "use"}${infinite ? "InfiniteQuery" : "Query"}`;
1808
1930
  const observerOptionsName = OBSERVER_OPTIONS_NAMES[infinite ? "infinite" : "plain"][suspense ? "suspense" : "standard"];
@@ -1862,8 +1984,11 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
1862
1984
  // src/components/QueryOptions.tsx
1863
1985
  const declarationPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1864
1986
  const callPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1865
- function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, clientReturnType, returnType }) {
1866
- 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
+ });
1867
1992
  const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
1868
1993
  const queryKeyParamsCall = callPrinter$2.print(queryKeyParamsNode) ?? "";
1869
1994
  const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
@@ -2009,7 +2134,8 @@ function createQueryGenerator({ name, variant }) {
2009
2134
  hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
2010
2135
  queryParam: infiniteOptions.queryParam,
2011
2136
  clientReturnType: contractOp.returnType,
2012
- returnType: hook.returnType
2137
+ returnType: hook.returnType,
2138
+ typedHeaders: hook.contractOp.typedHeaders
2013
2139
  })
2014
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, {
2015
2141
  name: ["queryOptions"],
@@ -2021,7 +2147,8 @@ function createQueryGenerator({ name, variant }) {
2021
2147
  node,
2022
2148
  tsResolver: hook.tsResolver,
2023
2149
  clientReturnType: contractOp.returnType,
2024
- returnType: hook.returnType
2150
+ returnType: hook.returnType,
2151
+ typedHeaders: hook.contractOp.typedHeaders
2025
2152
  })] }),
2026
2153
  (variant !== "query" || query && hooks) && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
2027
2154
  /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
@@ -2046,6 +2173,7 @@ function createQueryGenerator({ name, variant }) {
2046
2173
  tsResolver: hook.tsResolver,
2047
2174
  customOptions,
2048
2175
  returnType: hook.returnType,
2176
+ typedHeaders: hook.contractOp.typedHeaders,
2049
2177
  suspense,
2050
2178
  infinite: infiniteOptions ? {
2051
2179
  initialPageParam: infiniteOptions.initialPageParam,
@@ -2080,8 +2208,11 @@ function buildMutationConfigParamsNode(node) {
2080
2208
  default: "{}"
2081
2209
  })] });
2082
2210
  }
2083
- function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName, clientReturnType, returnType }) {
2084
- 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
+ });
2085
2216
  const configParamsNode = buildMutationConfigParamsNode(node);
2086
2217
  const paramsSignature = declarationPrinter$1.print(configParamsNode) ?? "";
2087
2218
  const groupedParam = buildGroupedRequestParam(node, {
@@ -2125,8 +2256,11 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
2125
2256
  const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
2126
2257
  const callPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
2127
2258
  function buildMutationParamsNode(node, options) {
2128
- const { resolver, returnType } = options;
2129
- 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
+ });
2130
2264
  return buildHookParams(node, {
2131
2265
  resolver,
2132
2266
  withRequest: false,
@@ -2141,8 +2275,11 @@ function buildMutationParamsNode(node, options) {
2141
2275
  }`
2142
2276
  });
2143
2277
  }
2144
- function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName, customOptions, returnType }) {
2145
- 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
+ });
2146
2283
  const generics = [
2147
2284
  TData,
2148
2285
  TError,
@@ -2154,7 +2291,8 @@ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName
2154
2291
  const mutationOptionsParamsCall = callPrinter.print(mutationOptionsConfigNode) ?? "";
2155
2292
  const paramsNode = buildMutationParamsNode(node, {
2156
2293
  resolver: tsResolver,
2157
- returnType
2294
+ returnType,
2295
+ typedHeaders
2158
2296
  });
2159
2297
  const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
2160
2298
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
@@ -2249,7 +2387,8 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
2249
2387
  node,
2250
2388
  tsResolver,
2251
2389
  clientReturnType: contractOp.returnType,
2252
- returnType: hook.returnType
2390
+ returnType: hook.returnType,
2391
+ typedHeaders: hook.contractOp.typedHeaders
2253
2392
  }),
2254
2393
  mutation && hooks && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
2255
2394
  /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
@@ -2272,7 +2411,8 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
2272
2411
  node,
2273
2412
  tsResolver,
2274
2413
  customOptions,
2275
- returnType: hook.returnType
2414
+ returnType: hook.returnType,
2415
+ typedHeaders: hook.contractOp.typedHeaders
2276
2416
  })
2277
2417
  ] })
2278
2418
  ]