@kubb/plugin-ts 5.0.0-alpha.5 → 5.0.0-alpha.6

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.
@@ -1,5 +1,5 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import { A as keywordTypeNodes, C as createTypeDeclaration, D as createUnionDeclaration, E as createTypeReferenceNode, F as camelCase, I as pascalCase, M as syntaxKind, N as jsStringEscape, O as createUrlTemplateType, P as trimQuotes, S as createTypeAliasDeclaration, T as createTypeOperatorNode, _ as createPropertySignature, a as createArrayTypeNode, b as createTrue, c as createIdentifier, d as createIntersectionDeclaration, f as createLiteralTypeNode, g as createPrefixUnaryExpression, h as createOptionalTypeNode, i as createArrayDeclaration, j as modifiers, k as getUnknownType, l as createIndexSignature, m as createOmitDeclaration, n as SyntaxKind, o as createEnumDeclaration, p as createNumericLiteral, r as appendJSDocToNode, s as createFalse, t as Type$1, u as createIndexedAccessTypeNode, v as createRestTypeNode, w as createTypeLiteralNode, x as createTupleTypeNode, y as createStringLiteral } from "./components-Cwn1rflQ.js";
2
+ import { A as keywordTypeNodes, C as createTypeDeclaration, D as createUnionDeclaration, E as createTypeReferenceNode, F as camelCase, I as pascalCase, M as syntaxKind, N as jsStringEscape, O as createUrlTemplateType, P as trimQuotes, S as createTypeAliasDeclaration, T as createTypeOperatorNode, _ as createPropertySignature, a as createArrayTypeNode, b as createTrue, c as createIdentifier, d as createIntersectionDeclaration, f as createLiteralTypeNode, g as createPrefixUnaryExpression, h as createOptionalTypeNode, i as createArrayDeclaration, j as modifiers, k as getUnknownType, l as createIndexSignature, m as createOmitDeclaration, n as SyntaxKind, o as createEnumDeclaration, p as createNumericLiteral, r as appendJSDocToNode, s as createFalse, t as Type$1, u as createIndexedAccessTypeNode, v as createRestTypeNode, w as createTypeLiteralNode, x as createTupleTypeNode, y as createStringLiteral } from "./components-CRu8IKY3.js";
3
3
  import path from "node:path";
4
4
  import { applyParamsCasing, collect, createProperty, createSchema, isPlainStringType, walk } from "@kubb/ast";
5
5
  import { defineGenerator, definePlugin, definePrinter, getBarrelFiles, getMode, resolveOptions } from "@kubb/core";
@@ -202,7 +202,7 @@ function printResponseSchema({ baseName, schemas, pluginManager, unknownType })
202
202
  const typeGenerator$1 = createReactGenerator({
203
203
  name: "typescript",
204
204
  Operation({ operation, generator, plugin }) {
205
- const { options, options: { mapper, enumType, enumKeyCasing, syntaxType, optionalType, arrayType, unknownType, paramsCasing } } = plugin;
205
+ const { options, options: { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, unknownType, paramsCasing } } = plugin;
206
206
  const mode = useMode();
207
207
  const pluginManager = usePluginManager();
208
208
  const oas = useOas();
@@ -261,7 +261,6 @@ const typeGenerator$1 = createReactGenerator({
261
261
  description,
262
262
  tree,
263
263
  schema: transformedSchema,
264
- mapper,
265
264
  enumType,
266
265
  enumKeyCasing,
267
266
  optionalType,
@@ -321,7 +320,7 @@ const typeGenerator$1 = createReactGenerator({
321
320
  });
322
321
  },
323
322
  Schema({ schema, plugin }) {
324
- const { options: { mapper, enumType, enumKeyCasing, syntaxType, optionalType, arrayType, output } } = plugin;
323
+ const { options: { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, output } } = plugin;
325
324
  const mode = useMode();
326
325
  const oas = useOas();
327
326
  const pluginManager = usePluginManager();
@@ -363,7 +362,6 @@ const typeGenerator$1 = createReactGenerator({
363
362
  description: schema.value.description,
364
363
  tree: schema.tree,
365
364
  schema: schema.value,
366
- mapper,
367
365
  enumType,
368
366
  enumKeyCasing,
369
367
  optionalType,
@@ -374,7 +372,45 @@ const typeGenerator$1 = createReactGenerator({
374
372
  }
375
373
  });
376
374
  //#endregion
375
+ //#region src/constants.ts
376
+ /**
377
+ * `optionalType` values that cause a property's type to include `| undefined`.
378
+ */
379
+ const OPTIONAL_ADDS_UNDEFINED = new Set(["undefined", "questionTokenAndUndefined"]);
380
+ /**
381
+ * `optionalType` values that render the property key with a `?` token.
382
+ */
383
+ const OPTIONAL_ADDS_QUESTION_TOKEN = new Set(["questionToken", "questionTokenAndUndefined"]);
384
+ /**
385
+ * `enumType` values that append a `Key` suffix to the generated enum type alias.
386
+ */
387
+ const ENUM_TYPES_WITH_KEY_SUFFIX = new Set(["asConst", "asPascalConst"]);
388
+ /**
389
+ * `enumType` values that require a runtime value declaration (object, enum, or literal).
390
+ */
391
+ const ENUM_TYPES_WITH_RUNTIME_VALUE = new Set([
392
+ "enum",
393
+ "asConst",
394
+ "asPascalConst",
395
+ "constEnum",
396
+ "literal",
397
+ void 0
398
+ ]);
399
+ /**
400
+ * `enumType` values whose type declaration is type-only (no runtime value emitted for the type alias).
401
+ */
402
+ const ENUM_TYPES_WITH_TYPE_ONLY = new Set([
403
+ "asConst",
404
+ "asPascalConst",
405
+ "literal",
406
+ void 0
407
+ ]);
408
+ //#endregion
377
409
  //#region src/printer.ts
410
+ /**
411
+ * Converts a primitive const value to a TypeScript literal type node.
412
+ * Handles negative numbers via a prefix unary expression.
413
+ */
378
414
  function constToTypeNode(value, format) {
379
415
  if (format === "boolean") return createLiteralTypeNode(value === true ? createTrue() : createFalse());
380
416
  if (format === "number" && typeof value === "number") {
@@ -383,12 +419,22 @@ function constToTypeNode(value, format) {
383
419
  }
384
420
  return createLiteralTypeNode(createStringLiteral(String(value)));
385
421
  }
422
+ /**
423
+ * Returns a `Date` reference type node when `representation` is `'date'`, otherwise falls back to `string`.
424
+ */
386
425
  function dateOrStringNode(node) {
387
426
  return node.representation === "date" ? createTypeReferenceNode(createIdentifier("Date")) : keywordTypeNodes.string;
388
427
  }
428
+ /**
429
+ * Maps an array of `SchemaNode`s through the printer, filtering out `null` and `undefined` results.
430
+ */
389
431
  function buildMemberNodes(members, print) {
390
432
  return (members ?? []).map(print).filter(Boolean);
391
433
  }
434
+ /**
435
+ * Builds a TypeScript tuple type node from an array schema's `items`,
436
+ * applying min/max slice and optional/rest element rules.
437
+ */
392
438
  function buildTupleNode(node, print) {
393
439
  let items = (node.items ?? []).map(print).filter(Boolean);
394
440
  const restNode = node.rest ? print(node.rest) ?? void 0 : void 0;
@@ -401,13 +447,19 @@ function buildTupleNode(node, print) {
401
447
  if (max === void 0 && restNode) items.push(createRestTypeNode(createArrayTypeNode(restNode)));
402
448
  return createTupleTypeNode(items);
403
449
  }
450
+ /**
451
+ * Applies `nullable` and optional/nullish `| undefined` union modifiers to a property's resolved base type.
452
+ */
404
453
  function buildPropertyType(schema, baseType, optionalType) {
405
- const addsUndefined = ["undefined", "questionTokenAndUndefined"].includes(optionalType);
454
+ const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType);
406
455
  let type = baseType;
407
456
  if (schema.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
408
457
  if ((schema.nullish || schema.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
409
458
  return type;
410
459
  }
460
+ /**
461
+ * Collects JSDoc annotation strings (description, deprecated, min/max, pattern, default, example, type) for a schema node.
462
+ */
411
463
  function buildPropertyJSDocComments(schema) {
412
464
  return [
413
465
  "description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
@@ -420,6 +472,9 @@ function buildPropertyJSDocComments(schema) {
420
472
  "primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
421
473
  ];
422
474
  }
475
+ /**
476
+ * Creates TypeScript index signatures for `additionalProperties` and `patternProperties` on an object schema node.
477
+ */
423
478
  function buildIndexSignatures(node, propertyCount, print) {
424
479
  const elements = [];
425
480
  if (node.additionalProperties && node.additionalProperties !== true) {
@@ -437,204 +492,238 @@ function buildIndexSignatures(node, propertyCount, print) {
437
492
  return elements;
438
493
  }
439
494
  /**
440
- * Converts a `SchemaNode` AST node into a TypeScript `ts.TypeNode`.
495
+ * TypeScript type printer built with `definePrinter`.
496
+ *
497
+ * Converts a `SchemaNode` AST node into a TypeScript AST node:
498
+ * - **`printer.print(node)`** — when `options.typeName` is set, returns a full
499
+ * `type Name = …` or `interface Name { … }` declaration (`ts.Node`).
500
+ * Without `typeName`, returns the raw `ts.TypeNode` for the schema.
501
+ *
502
+ * Dispatches on `node.type` to the appropriate handler in `nodes`. Options are closed
503
+ * over per printer instance, so each call to `printerTs(options)` produces an independent printer.
441
504
  *
442
- * Built on `definePrinter` dispatches on `node.type`, with options closed over
443
- * per printer instance. Produces the same `ts.TypeNode` output as the keyword-based
444
- * `parse` in `parser.ts`.
505
+ * @example Raw type node (no `typeName`)
506
+ * ```ts
507
+ * const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enumType: 'inlineLiteral' })
508
+ * const typeNode = printer.print(schemaNode) // ts.TypeNode
509
+ * ```
510
+ *
511
+ * @example Full declaration (with `typeName`)
512
+ * ```ts
513
+ * const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enumType: 'inlineLiteral', typeName: 'MyType' })
514
+ * const declaration = printer.print(schemaNode) // ts.TypeAliasDeclaration | ts.InterfaceDeclaration
515
+ * ```
445
516
  */
446
- const printerTs = definePrinter((options) => ({
447
- name: "typescript",
448
- options,
449
- nodes: {
450
- any: () => keywordTypeNodes.any,
451
- unknown: () => keywordTypeNodes.unknown,
452
- void: () => keywordTypeNodes.void,
453
- never: () => keywordTypeNodes.never,
454
- boolean: () => keywordTypeNodes.boolean,
455
- null: () => keywordTypeNodes.null,
456
- blob: () => createTypeReferenceNode("Blob", []),
457
- string: () => keywordTypeNodes.string,
458
- uuid: () => keywordTypeNodes.string,
459
- email: () => keywordTypeNodes.string,
460
- url: (node) => {
461
- if (node.path) return createUrlTemplateType(node.path);
462
- return keywordTypeNodes.string;
463
- },
464
- datetime: () => keywordTypeNodes.string,
465
- number: () => keywordTypeNodes.number,
466
- integer: () => keywordTypeNodes.number,
467
- bigint: () => keywordTypeNodes.bigint,
468
- date: (node) => dateOrStringNode(node),
469
- time: (node) => dateOrStringNode(node),
470
- ref(node) {
471
- if (!node.name) return;
472
- return createTypeReferenceNode(node.name, void 0);
473
- },
474
- enum(node) {
475
- const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
476
- if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
477
- withParentheses: true,
478
- nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string")).filter(Boolean)
479
- }) ?? void 0;
480
- return createTypeReferenceNode(["asConst", "asPascalConst"].includes(this.options.enumType) ? `${node.name}Key` : node.name, void 0);
481
- },
482
- union(node) {
483
- const members = node.members ?? [];
484
- const hasStringLiteral = members.some((m) => m.type === "enum" && m.enumType === "string");
485
- const hasPlainString = members.some((m) => isPlainStringType(m));
486
- if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
487
- withParentheses: true,
488
- nodes: members.map((m) => {
489
- if (isPlainStringType(m)) return createIntersectionDeclaration({
490
- nodes: [keywordTypeNodes.string, createTypeLiteralNode([])],
491
- withParentheses: true
517
+ const printerTs = definePrinter((options) => {
518
+ const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(options.optionalType);
519
+ return {
520
+ name: "typescript",
521
+ options,
522
+ nodes: {
523
+ any: () => keywordTypeNodes.any,
524
+ unknown: () => keywordTypeNodes.unknown,
525
+ void: () => keywordTypeNodes.void,
526
+ never: () => keywordTypeNodes.never,
527
+ boolean: () => keywordTypeNodes.boolean,
528
+ null: () => keywordTypeNodes.null,
529
+ blob: () => createTypeReferenceNode("Blob", []),
530
+ string: () => keywordTypeNodes.string,
531
+ uuid: () => keywordTypeNodes.string,
532
+ email: () => keywordTypeNodes.string,
533
+ url: (node) => {
534
+ if (node.path) return createUrlTemplateType(node.path);
535
+ return keywordTypeNodes.string;
536
+ },
537
+ datetime: () => keywordTypeNodes.string,
538
+ number: () => keywordTypeNodes.number,
539
+ integer: () => keywordTypeNodes.number,
540
+ bigint: () => keywordTypeNodes.bigint,
541
+ date: dateOrStringNode,
542
+ time: dateOrStringNode,
543
+ ref(node) {
544
+ if (!node.name) return;
545
+ return createTypeReferenceNode(node.name, void 0);
546
+ },
547
+ enum(node) {
548
+ const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
549
+ if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
550
+ withParentheses: true,
551
+ nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value)).filter(Boolean)
552
+ }) ?? void 0;
553
+ const resolvedName = pascalCase(node.name);
554
+ return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) ? `${resolvedName}Key` : resolvedName, void 0);
555
+ },
556
+ union(node) {
557
+ const members = node.members ?? [];
558
+ const hasStringLiteral = members.some((m) => m.type === "enum" && m.enumType === "string");
559
+ const hasPlainString = members.some((m) => isPlainStringType(m));
560
+ if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
561
+ withParentheses: true,
562
+ nodes: members.map((m) => {
563
+ if (isPlainStringType(m)) return createIntersectionDeclaration({
564
+ nodes: [keywordTypeNodes.string, createTypeLiteralNode([])],
565
+ withParentheses: true
566
+ });
567
+ return this.print(m);
568
+ }).filter(Boolean)
569
+ }) ?? void 0;
570
+ return createUnionDeclaration({
571
+ withParentheses: true,
572
+ nodes: buildMemberNodes(members, this.print)
573
+ }) ?? void 0;
574
+ },
575
+ intersection(node) {
576
+ return createIntersectionDeclaration({
577
+ withParentheses: true,
578
+ nodes: buildMemberNodes(node.members, this.print)
579
+ }) ?? void 0;
580
+ },
581
+ array(node) {
582
+ return createArrayDeclaration({
583
+ nodes: (node.items ?? []).map((item) => this.print(item)).filter(Boolean),
584
+ arrayType: this.options.arrayType
585
+ }) ?? void 0;
586
+ },
587
+ tuple(node) {
588
+ return buildTupleNode(node, this.print);
589
+ },
590
+ object(node) {
591
+ const { print, options } = this;
592
+ const addsQuestionToken = OPTIONAL_ADDS_QUESTION_TOKEN.has(options.optionalType);
593
+ const propertyNodes = node.properties.map((prop) => {
594
+ const baseType = print(prop.schema) ?? keywordTypeNodes.unknown;
595
+ const type = buildPropertyType(prop.schema, baseType, options.optionalType);
596
+ return appendJSDocToNode({
597
+ node: createPropertySignature({
598
+ questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
599
+ name: prop.name,
600
+ type,
601
+ readOnly: prop.schema.readOnly
602
+ }),
603
+ comments: buildPropertyJSDocComments(prop.schema)
492
604
  });
493
- return this.print(m);
494
- }).filter(Boolean)
495
- }) ?? void 0;
496
- return createUnionDeclaration({
497
- withParentheses: true,
498
- nodes: buildMemberNodes(members, this.print)
499
- }) ?? void 0;
500
- },
501
- intersection(node) {
502
- return createIntersectionDeclaration({
503
- withParentheses: true,
504
- nodes: buildMemberNodes(node.members, this.print)
505
- }) ?? void 0;
506
- },
507
- array(node) {
508
- return createArrayDeclaration({
509
- nodes: (node.items ?? []).map((item) => this.print(item)).filter(Boolean),
510
- arrayType: this.options.arrayType
511
- }) ?? void 0;
512
- },
513
- tuple(node) {
514
- return buildTupleNode(node, this.print);
515
- },
516
- object(node) {
517
- const addsQuestionToken = ["questionToken", "questionTokenAndUndefined"].includes(this.options.optionalType);
518
- const { print } = this;
519
- const propertyNodes = node.properties.map((prop) => {
520
- if (this.options.mapper && Object.hasOwn(this.options.mapper, prop.name)) return this.options.mapper[prop.name];
521
- const baseType = print(prop.schema) ?? keywordTypeNodes.unknown;
522
- const type = buildPropertyType(prop.schema, baseType, this.options.optionalType);
523
- return appendJSDocToNode({
524
- node: createPropertySignature({
525
- questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
526
- name: prop.name,
527
- type,
528
- readOnly: prop.schema.readOnly
529
- }),
530
- comments: buildPropertyJSDocComments(prop.schema)
531
605
  });
606
+ const allElements = [...propertyNodes, ...buildIndexSignatures(node, propertyNodes.length, print)];
607
+ if (!allElements.length) return keywordTypeNodes.object;
608
+ return createTypeLiteralNode(allElements);
609
+ }
610
+ },
611
+ print(node) {
612
+ let type = this.print(node);
613
+ if (!type) return;
614
+ if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
615
+ if ((node.nullish || node.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
616
+ const { typeName, syntaxType = "type", description, keysToOmit } = this.options;
617
+ if (!typeName) return type;
618
+ const useTypeGeneration = syntaxType === "type" || type.kind === syntaxKind.union || !!keysToOmit?.length;
619
+ return createTypeDeclaration({
620
+ name: typeName,
621
+ isExportable: true,
622
+ type: keysToOmit?.length ? createOmitDeclaration({
623
+ keys: keysToOmit,
624
+ type,
625
+ nonNullable: true
626
+ }) : type,
627
+ syntax: useTypeGeneration ? "type" : "interface",
628
+ comments: [
629
+ node?.title ? jsStringEscape(node.title) : void 0,
630
+ description ? `@description ${jsStringEscape(description)}` : void 0,
631
+ node?.deprecated ? "@deprecated" : void 0,
632
+ node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
633
+ node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
634
+ node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
635
+ node?.default ? `@default ${node.default}` : void 0,
636
+ node?.example ? `@example ${node.example}` : void 0
637
+ ]
532
638
  });
533
- const allElements = [...propertyNodes, ...buildIndexSignatures(node, propertyNodes.length, print)];
534
- if (!allElements.length) return keywordTypeNodes.object;
535
- return createTypeLiteralNode(allElements);
536
639
  }
537
- }
538
- }));
640
+ };
641
+ });
642
+ //#endregion
643
+ //#region src/components/v2/Enum.tsx
644
+ /**
645
+ * Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
646
+ *
647
+ * The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
648
+ * valid TypeScript identifier. `pascalCase` normalizes it unconditionally; for inline enum
649
+ * properties the adapter already emits a PascalCase+suffix name so `pascalCase` is a no-op.
650
+ */
651
+ function getEnumNames(node, enumType) {
652
+ const resolved = pascalCase(node.name);
653
+ return {
654
+ enumName: enumType === "asPascalConst" ? resolved : camelCase(node.name),
655
+ typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? `${resolved}Key` : resolved
656
+ };
657
+ }
658
+ /**
659
+ * Renders the enum declaration(s) for a single named `EnumSchemaNode`.
660
+ *
661
+ * Depending on `enumType` this may emit:
662
+ * - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
663
+ * - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
664
+ * - A union literal type alias (`literal`)
665
+ *
666
+ * The emitted `File.Source` nodes carry the resolved names so that the barrel
667
+ * index picks up the correct export identifiers.
668
+ */
669
+ function Enum({ node, enumType, enumKeyCasing }) {
670
+ const { enumName, typeName } = getEnumNames(node, enumType);
671
+ const [nameNode, typeNode] = createEnumDeclaration({
672
+ name: enumName,
673
+ typeName,
674
+ enums: node.namedEnumValues?.map((v) => [trimQuotes(v.name.toString()), v.value]) ?? node.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [trimQuotes(v.toString()), v]) ?? [],
675
+ type: enumType,
676
+ enumKeyCasing
677
+ });
678
+ return /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
679
+ name: enumName,
680
+ isExportable: true,
681
+ isIndexable: true,
682
+ isTypeOnly: false,
683
+ children: safePrint(nameNode)
684
+ }), /* @__PURE__ */ jsx(File.Source, {
685
+ name: typeName,
686
+ isIndexable: true,
687
+ isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
688
+ isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
689
+ children: safePrint(typeNode)
690
+ })] });
691
+ }
539
692
  //#endregion
540
693
  //#region src/components/v2/Type.tsx
541
- function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumKeyCasing, mapper, ...rest }) {
542
- const typeNodes = [];
543
- const description = rest.description || node?.description;
694
+ function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumKeyCasing, description }) {
695
+ const resolvedDescription = description || node?.description;
544
696
  const enumSchemaNodes = collect(node, { schema(n) {
545
697
  if (n.type === "enum" && n.name) return n;
546
698
  } });
547
- let type = printerTs({
699
+ const typeNode = printerTs({
548
700
  optionalType,
549
701
  arrayType,
550
702
  enumType,
551
- mapper
703
+ typeName: name,
704
+ syntaxType,
705
+ description: resolvedDescription,
706
+ keysToOmit
552
707
  }).print(node);
553
- if (!type) return;
554
- if (["asConst", "asPascalConst"].includes(enumType) && enumSchemaNodes.length > 0) {
555
- const isDirectEnum = node.type === "array" && node.items !== void 0;
556
- const isEnumOnly = "enum" in node && node.enum;
557
- if (isDirectEnum || isEnumOnly) {
558
- type = createTypeReferenceNode(`${enumSchemaNodes[0].name}Key`);
559
- if (isDirectEnum) if (arrayType === "generic") type = createTypeReferenceNode(createIdentifier("Array"), [type]);
560
- else type = createArrayTypeNode(type);
561
- }
562
- }
563
- if (node) {
564
- if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
565
- if (node.nullish && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
566
- if (node.optional && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
567
- }
568
- const useTypeGeneration = syntaxType === "type" || [syntaxKind.union].includes(type.kind) || !!keysToOmit?.length;
569
- typeNodes.push(createTypeDeclaration({
570
- name,
571
- isExportable: true,
572
- type: keysToOmit?.length ? createOmitDeclaration({
573
- keys: keysToOmit,
574
- type,
575
- nonNullable: true
576
- }) : type,
577
- syntax: useTypeGeneration ? "type" : "interface",
578
- comments: [
579
- node?.title ? `${jsStringEscape(node.title)}` : void 0,
580
- description ? `@description ${jsStringEscape(description)}` : void 0,
581
- node?.deprecated ? "@deprecated" : void 0,
582
- node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
583
- node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
584
- node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
585
- node?.default ? `@default ${node.default}` : void 0,
586
- node?.example ? `@example ${node.example}` : void 0
587
- ]
588
- }));
589
- const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((enumSchemaNode) => {
590
- const enumName = enumType === "asPascalConst" ? pascalCase(enumSchemaNode.name) : camelCase(enumSchemaNode.name);
591
- const typeName = ["asConst", "asPascalConst"].includes(enumType) ? `${enumSchemaNode.name}Key` : enumSchemaNode.name;
592
- const [nameNode, typeNode] = createEnumDeclaration({
593
- name: enumName,
594
- typeName,
595
- enums: enumSchemaNode.namedEnumValues?.map((v) => [trimQuotes(v.name.toString()), v.value]) ?? enumSchemaNode.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [trimQuotes(v.toString()), v]) ?? [],
596
- type: enumType,
597
- enumKeyCasing
598
- });
708
+ if (!typeNode) return;
709
+ const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((node) => {
599
710
  return {
600
- nameNode,
601
- typeNode,
602
- name: enumName,
603
- typeName
711
+ node,
712
+ ...getEnumNames(node, enumType)
604
713
  };
605
714
  });
606
715
  const shouldExportEnums = enumType !== "inlineLiteral";
607
716
  const shouldExportType = enumType === "inlineLiteral" || enums.every((item) => item.typeName !== name);
608
- return /* @__PURE__ */ jsxs(Fragment, { children: [shouldExportEnums && enums.map(({ name: enumName, nameNode, typeName, typeNode }) => /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
609
- name: enumName,
610
- isExportable: true,
611
- isIndexable: true,
612
- isTypeOnly: false,
613
- children: safePrint(nameNode)
614
- }), /* @__PURE__ */ jsx(File.Source, {
615
- name: typeName,
616
- isIndexable: true,
617
- isExportable: [
618
- "enum",
619
- "asConst",
620
- "asPascalConst",
621
- "constEnum",
622
- "literal",
623
- void 0
624
- ].includes(enumType),
625
- isTypeOnly: [
626
- "asConst",
627
- "asPascalConst",
628
- "literal",
629
- void 0
630
- ].includes(enumType),
631
- children: safePrint(typeNode)
632
- })] })), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
717
+ return /* @__PURE__ */ jsxs(Fragment, { children: [shouldExportEnums && enums.map(({ node }) => /* @__PURE__ */ jsx(Enum, {
718
+ node,
719
+ enumType,
720
+ enumKeyCasing
721
+ })), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
633
722
  name: typedName,
634
723
  isTypeOnly: true,
635
724
  isExportable: true,
636
725
  isIndexable: true,
637
- children: safePrint(...typeNodes)
726
+ children: safePrint(typeNode)
638
727
  })] });
639
728
  }
640
729
  //#endregion
@@ -642,6 +731,8 @@ function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, synt
642
731
  /**
643
732
  * Builds an `ObjectSchemaNode` for a group of parameters (path/query/header).
644
733
  * Each property is a `ref` schema pointing to the individually-resolved parameter type.
734
+ * The ref name includes the parameter location so generated type names follow
735
+ * the `<OperationId><Location><ParamName>` convention.
645
736
  */
646
737
  function buildParamsSchema({ params, operationId, resolveName }) {
647
738
  return createSchema({
@@ -651,7 +742,7 @@ function buildParamsSchema({ params, operationId, resolveName }) {
651
742
  schema: createSchema({
652
743
  type: "ref",
653
744
  name: resolveName({
654
- name: `${operationId} ${param.name}`,
745
+ name: `${operationId} ${pascalCase(param.in)} ${param.name}`,
655
746
  type: "function"
656
747
  }),
657
748
  optional: !param.required
@@ -660,7 +751,7 @@ function buildParamsSchema({ params, operationId, resolveName }) {
660
751
  });
661
752
  }
662
753
  /**
663
- * Builds an `ObjectSchemaNode` representing the `<OperationId>Data` type:
754
+ * Builds an `ObjectSchemaNode` representing the `<OperationId>RequestConfig` type:
664
755
  * - `data` → request body ref (optional) or `never`
665
756
  * - `pathParams` → inline object of path param refs, or `never`
666
757
  * - `queryParams` → inline object of query param refs (optional), or `never`
@@ -679,7 +770,7 @@ function buildDataSchemaNode({ node, resolveName }) {
679
770
  schema: node.requestBody ? createSchema({
680
771
  type: "ref",
681
772
  name: resolveName({
682
- name: `${node.operationId} MutationRequest`,
773
+ name: `${node.operationId} Data`,
683
774
  type: "function"
684
775
  }),
685
776
  optional: true
@@ -739,11 +830,7 @@ function buildDataSchemaNode({ node, resolveName }) {
739
830
  }
740
831
  /**
741
832
  * Builds an `ObjectSchemaNode` representing `<OperationId>Responses` — keyed by HTTP status code.
742
- *
743
- * Example output:
744
- * ```ts
745
- * export type PlaceOrderPatchResponses = { 200: PlaceOrderPatch200; 405: PlaceOrderPatch405 }
746
- * ```
833
+ * Numeric status codes produce unquoted numeric keys (e.g. `200:`).
747
834
  */
748
835
  function buildResponsesSchemaNode({ node, resolveName }) {
749
836
  const responsesWithSchema = node.responses.filter((res) => res.schema);
@@ -755,7 +842,7 @@ function buildResponsesSchemaNode({ node, resolveName }) {
755
842
  schema: createSchema({
756
843
  type: "ref",
757
844
  name: resolveName({
758
- name: `${node.operationId} ${res.statusCode}`,
845
+ name: `${node.operationId} Status ${res.statusCode}`,
759
846
  type: "function"
760
847
  })
761
848
  })
@@ -764,11 +851,7 @@ function buildResponsesSchemaNode({ node, resolveName }) {
764
851
  }
765
852
  /**
766
853
  * Builds a `UnionSchemaNode` representing `<OperationId>Response` — all response types in union format.
767
- *
768
- * Example output:
769
- * ```ts
770
- * export type PlaceOrderPatchResponse = PlaceOrderPatch200 | PlaceOrderPatch405
771
- * ```
854
+ * Returns `null` when the operation has no responses with schemas.
772
855
  */
773
856
  function buildResponseUnionSchemaNode({ node, resolveName }) {
774
857
  const responsesWithSchema = node.responses.filter((res) => res.schema);
@@ -778,7 +861,7 @@ function buildResponseUnionSchemaNode({ node, resolveName }) {
778
861
  members: responsesWithSchema.map((res) => createSchema({
779
862
  type: "ref",
780
863
  name: resolveName({
781
- name: `${node.operationId} ${res.statusCode}`,
864
+ name: `${node.operationId} Status ${res.statusCode}`,
782
865
  type: "function"
783
866
  })
784
867
  }))
@@ -790,12 +873,13 @@ const typeGenerator = defineGenerator({
790
873
  name: "typescript",
791
874
  type: "react",
792
875
  Operation({ node, adapter, options }) {
793
- const { enumType, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, mapper } = options;
876
+ const { enumType, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group } = options;
794
877
  const { mode, getFile, resolveName } = useKubb();
795
878
  const file = getFile({
796
879
  name: node.operationId,
797
880
  extname: ".ts",
798
- mode
881
+ mode,
882
+ options: { group: group ? group.type === "tag" ? { tag: node.tags[0] } : { path: node.path } : void 0 }
799
883
  });
800
884
  const params = applyParamsCasing(node.parameters, paramsCasing);
801
885
  function renderSchemaType({ node: schemaNode, name, typedName, description }) {
@@ -829,29 +913,28 @@ const typeGenerator = defineGenerator({
829
913
  enumKeyCasing,
830
914
  optionalType,
831
915
  arrayType,
832
- syntaxType,
833
- mapper
916
+ syntaxType
834
917
  })] });
835
918
  }
836
919
  const paramTypes = params.map((param) => renderSchemaType({
837
920
  node: param.schema,
838
921
  name: resolveName({
839
- name: `${node.operationId} ${param.name}`,
922
+ name: `${node.operationId} ${pascalCase(param.in)} ${param.name}`,
840
923
  type: "function"
841
924
  }),
842
925
  typedName: resolveName({
843
- name: `${node.operationId} ${param.name}`,
926
+ name: `${node.operationId} ${pascalCase(param.in)} ${param.name}`,
844
927
  type: "type"
845
928
  })
846
929
  }));
847
930
  const responseTypes = node.responses.filter((res) => res.schema).map((res) => renderSchemaType({
848
931
  node: res.schema,
849
932
  name: resolveName({
850
- name: `${node.operationId} ${res.statusCode}`,
933
+ name: `${node.operationId} Status ${res.statusCode}`,
851
934
  type: "function"
852
935
  }),
853
936
  typedName: resolveName({
854
- name: `${node.operationId} ${res.statusCode}`,
937
+ name: `${node.operationId} Status ${res.statusCode}`,
855
938
  type: "type"
856
939
  }),
857
940
  description: res.description
@@ -859,11 +942,11 @@ const typeGenerator = defineGenerator({
859
942
  const requestType = node.requestBody ? renderSchemaType({
860
943
  node: node.requestBody,
861
944
  name: resolveName({
862
- name: `${node.operationId} MutationRequest`,
945
+ name: `${node.operationId} Data`,
863
946
  type: "function"
864
947
  }),
865
948
  typedName: resolveName({
866
- name: `${node.operationId} MutationRequest`,
949
+ name: `${node.operationId} Data`,
867
950
  type: "type"
868
951
  }),
869
952
  description: node.requestBody.description
@@ -877,11 +960,11 @@ const typeGenerator = defineGenerator({
877
960
  resolveName
878
961
  }),
879
962
  name: resolveName({
880
- name: `${node.operationId} Data`,
963
+ name: `${node.operationId} RequestConfig`,
881
964
  type: "function"
882
965
  }),
883
966
  typedName: resolveName({
884
- name: `${node.operationId} Data`,
967
+ name: `${node.operationId} RequestConfig`,
885
968
  type: "type"
886
969
  })
887
970
  });
@@ -911,7 +994,8 @@ const typeGenerator = defineGenerator({
911
994
  typedName: resolveName({
912
995
  name: `${node.operationId} Response`,
913
996
  type: "type"
914
- })
997
+ }),
998
+ description: "Union of all possible responses"
915
999
  });
916
1000
  return /* @__PURE__ */ jsxs(File, {
917
1001
  baseName: file.baseName,
@@ -928,7 +1012,7 @@ const typeGenerator = defineGenerator({
928
1012
  });
929
1013
  },
930
1014
  Schema({ node, adapter, options }) {
931
- const { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, mapper } = options;
1015
+ const { enumType, enumKeyCasing, syntaxType, optionalType, arrayType } = options;
932
1016
  const { mode, resolveName, getFile } = useKubb();
933
1017
  if (!node.name) return;
934
1018
  const imports = adapter.getImports(node, (schemaName) => ({
@@ -947,7 +1031,7 @@ const typeGenerator = defineGenerator({
947
1031
  name: node.name,
948
1032
  type: "type"
949
1033
  });
950
- if (["asConst", "asPascalConst"].includes(enumType) && isEnumSchema) typedName += "Key";
1034
+ if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema) typedName += "Key";
951
1035
  const type = {
952
1036
  name: resolveName({
953
1037
  name: node.name,
@@ -981,8 +1065,7 @@ const typeGenerator = defineGenerator({
981
1065
  enumKeyCasing,
982
1066
  optionalType,
983
1067
  arrayType,
984
- syntaxType,
985
- mapper
1068
+ syntaxType
986
1069
  })]
987
1070
  });
988
1071
  }
@@ -994,7 +1077,7 @@ const pluginTs = definePlugin((options) => {
994
1077
  const { output = {
995
1078
  path: "types",
996
1079
  barrelType: "named"
997
- }, group, exclude = [], include, override = [], enumType = "asConst", enumKeyCasing = "none", enumSuffix = "enum", dateType = "string", integerType = "number", unknownType = "any", optionalType = "questionToken", arrayType = "array", emptySchemaType = unknownType, syntaxType = "type", transformers = {}, mapper = {}, paramsCasing, generators = [typeGenerator$1, typeGenerator].filter(Boolean), contentType, UNSTABLE_NAMING } = options;
1080
+ }, group, exclude = [], include, override = [], enumType = "asConst", enumKeyCasing = "none", enumSuffix = "enum", dateType = "string", integerType = "number", unknownType = "any", optionalType = "questionToken", arrayType = "array", emptySchemaType = unknownType, syntaxType = "type", transformers = {}, paramsCasing, generators = [typeGenerator$1, typeGenerator].filter(Boolean), contentType, UNSTABLE_NAMING } = options;
998
1081
  return {
999
1082
  name: pluginTsName,
1000
1083
  options: {
@@ -1012,7 +1095,6 @@ const pluginTs = definePlugin((options) => {
1012
1095
  syntaxType,
1013
1096
  group,
1014
1097
  override,
1015
- mapper,
1016
1098
  paramsCasing,
1017
1099
  usedEnumNames: {}
1018
1100
  },
@@ -1147,4 +1229,4 @@ const pluginTs = definePlugin((options) => {
1147
1229
  //#endregion
1148
1230
  export { typeGenerator$1 as i, pluginTsName as n, typeGenerator as r, pluginTs as t };
1149
1231
 
1150
- //# sourceMappingURL=plugin-kdQ5D2cW.js.map
1232
+ //# sourceMappingURL=plugin-BcK4SBA0.js.map