@kubb/plugin-ts 5.0.0-alpha.24 → 5.0.0-alpha.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,11 +2,11 @@ import "./chunk--u3MIqq1.js";
2
2
  import path from "node:path";
3
3
  import { safePrint } from "@kubb/fabric-core/parsers/typescript";
4
4
  import { File } from "@kubb/react-fabric";
5
+ import { caseParams, collect, composeTransformers, createPrinterFactory, createProperty, createSchema, extractRefName, isStringType, narrowSchema, schemaTypes, syncSchemaRef, transform, walk } from "@kubb/ast";
5
6
  import { isNumber } from "remeda";
6
7
  import ts from "typescript";
7
8
  import { Fragment, jsx, jsxs } from "@kubb/react-fabric/jsx-runtime";
8
- import { caseParams, collect, composeTransformers, createPrinterFactory, createProperty, createSchema, isStringType, narrowSchema, schemaTypes, transform, walk } from "@kubb/ast";
9
- import { createPlugin, defineGenerator, definePresets, definePrinter, defineResolver, getBarrelFiles, getMode, getPreset, renderOperation, renderSchema } from "@kubb/core";
9
+ import { createPlugin, defineGenerator, definePresets, definePrinter, defineResolver, getBarrelFiles, getMode, getPreset, runGeneratorOperation, runGeneratorOperations, runGeneratorSchema } from "@kubb/core";
10
10
  //#region ../../internals/utils/src/casing.ts
11
11
  /**
12
12
  * Shared implementation for camelCase and PascalCase conversion.
@@ -176,6 +176,15 @@ const ENUM_TYPES_WITH_TYPE_ONLY = new Set([
176
176
  "literal",
177
177
  void 0
178
178
  ]);
179
+ /**
180
+ * Ordering priority for function parameters: lower = sorted earlier.
181
+ */
182
+ const PARAM_RANK = {
183
+ required: 0,
184
+ optional: 1,
185
+ withDefault: 2,
186
+ rest: 3
187
+ };
179
188
  //#endregion
180
189
  //#region src/factory.ts
181
190
  const { SyntaxKind, factory } = ts;
@@ -264,7 +273,7 @@ function createInterfaceDeclaration({ modifiers, name, typeParameters, members }
264
273
  function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
265
274
  if (syntax === "interface" && "members" in type) return appendJSDocToNode({
266
275
  node: createInterfaceDeclaration({
267
- members: type.members,
276
+ members: [...type.members],
268
277
  modifiers: isExportable ? [modifiers.export] : [],
269
278
  name,
270
279
  typeParameters: void 0
@@ -397,63 +406,6 @@ const createFalse = factory.createFalse;
397
406
  factory.createIndexedAccessTypeNode;
398
407
  factory.createTypeOperatorNode;
399
408
  const createPrefixUnaryExpression = factory.createPrefixUnaryExpression;
400
- //#endregion
401
- //#region src/components/Enum.tsx
402
- /**
403
- * Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
404
- *
405
- * The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
406
- * valid TypeScript identifier. The resolver normalizes it; for inline enum
407
- * properties the adapter already emits a PascalCase+suffix name so resolution is typically a no-op.
408
- */
409
- function getEnumNames({ node, enumType, enumTypeSuffix, resolver }) {
410
- const resolved = resolver.default(node.name, "type");
411
- return {
412
- enumName: enumType === "asPascalConst" ? resolved : camelCase(node.name),
413
- typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolved
414
- };
415
- }
416
- /**
417
- * Renders the enum declaration(s) for a single named `EnumSchemaNode`.
418
- *
419
- * Depending on `enumType` this may emit:
420
- * - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
421
- * - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
422
- * - A union literal type alias (`literal`)
423
- *
424
- * The emitted `File.Source` nodes carry the resolved names so that the barrel
425
- * index picks up the correct export identifiers.
426
- */
427
- function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
428
- const { enumName, typeName } = getEnumNames({
429
- node,
430
- enumType,
431
- enumTypeSuffix,
432
- resolver
433
- });
434
- const [nameNode, typeNode] = createEnumDeclaration({
435
- name: enumName,
436
- typeName,
437
- 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]) ?? [],
438
- type: enumType,
439
- enumKeyCasing
440
- });
441
- return /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
442
- name: enumName,
443
- isExportable: true,
444
- isIndexable: true,
445
- isTypeOnly: false,
446
- children: safePrint(nameNode)
447
- }), /* @__PURE__ */ jsx(File.Source, {
448
- name: typeName,
449
- isIndexable: true,
450
- isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
451
- isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
452
- children: safePrint(typeNode)
453
- })] });
454
- }
455
- //#endregion
456
- //#region src/printers/printerTs.ts
457
409
  /**
458
410
  * Converts a primitive const value to a TypeScript literal type node.
459
411
  * Handles negative numbers via a prefix unary expression.
@@ -499,28 +451,13 @@ function buildTupleNode(node, print) {
499
451
  */
500
452
  function buildPropertyType(schema, baseType, optionalType) {
501
453
  const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType);
454
+ const meta = syncSchemaRef(schema);
502
455
  let type = baseType;
503
- if (schema.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
504
- if ((schema.nullish || schema.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
456
+ if (meta.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
457
+ if ((meta.nullish || meta.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
505
458
  return type;
506
459
  }
507
460
  /**
508
- * Collects JSDoc annotation strings (description, deprecated, min/max, pattern, default, example, type) for a schema node.
509
- */
510
- function buildPropertyJSDocComments(schema) {
511
- const isArray = schema.type === "array";
512
- return [
513
- "description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
514
- "deprecated" in schema && schema.deprecated ? "@deprecated" : void 0,
515
- !isArray && "min" in schema && schema.min !== void 0 ? `@minLength ${schema.min}` : void 0,
516
- !isArray && "max" in schema && schema.max !== void 0 ? `@maxLength ${schema.max}` : void 0,
517
- "pattern" in schema && schema.pattern ? `@pattern ${schema.pattern}` : void 0,
518
- "default" in schema && schema.default !== void 0 ? `@default ${"primitive" in schema && schema.primitive === "string" ? stringify(schema.default) : schema.default}` : void 0,
519
- "example" in schema && schema.example !== void 0 ? `@example ${schema.example}` : void 0,
520
- "primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
521
- ];
522
- }
523
- /**
524
461
  * Creates TypeScript index signatures for `additionalProperties` and `patternProperties` on an object schema node.
525
462
  */
526
463
  function buildIndexSignatures(node, propertyCount, print) {
@@ -539,6 +476,194 @@ function buildIndexSignatures(node, propertyCount, print) {
539
476
  }
540
477
  return elements;
541
478
  }
479
+ //#endregion
480
+ //#region src/components/Enum.tsx
481
+ /**
482
+ * Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
483
+ *
484
+ * The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
485
+ * valid TypeScript identifier. The resolver normalizes it; for inline enum
486
+ * properties the adapter already emits a PascalCase+suffix name so resolution is typically a no-op.
487
+ */
488
+ function getEnumNames({ node, enumType, enumTypeSuffix, resolver }) {
489
+ const resolved = resolver.default(node.name, "type");
490
+ return {
491
+ enumName: enumType === "asPascalConst" ? resolved : camelCase(node.name),
492
+ typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolved
493
+ };
494
+ }
495
+ /**
496
+ * Renders the enum declaration(s) for a single named `EnumSchemaNode`.
497
+ *
498
+ * Depending on `enumType` this may emit:
499
+ * - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
500
+ * - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
501
+ * - A union literal type alias (`literal`)
502
+ *
503
+ * The emitted `File.Source` nodes carry the resolved names so that the barrel
504
+ * index picks up the correct export identifiers.
505
+ */
506
+ function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
507
+ const { enumName, typeName } = getEnumNames({
508
+ node,
509
+ enumType,
510
+ enumTypeSuffix,
511
+ resolver
512
+ });
513
+ const [nameNode, typeNode] = createEnumDeclaration({
514
+ name: enumName,
515
+ typeName,
516
+ 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]) ?? [],
517
+ type: enumType,
518
+ enumKeyCasing
519
+ });
520
+ return /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
521
+ name: enumName,
522
+ isExportable: true,
523
+ isIndexable: true,
524
+ isTypeOnly: false,
525
+ children: safePrint(nameNode)
526
+ }), /* @__PURE__ */ jsx(File.Source, {
527
+ name: typeName,
528
+ isIndexable: true,
529
+ isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
530
+ isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
531
+ children: safePrint(typeNode)
532
+ })] });
533
+ }
534
+ //#endregion
535
+ //#region src/utils.ts
536
+ /**
537
+ * Collects JSDoc annotation strings for a schema node.
538
+ *
539
+ * Only uses official JSDoc tags from https://jsdoc.app/: `@description`, `@deprecated`, `@default`, `@example`, `@type`.
540
+ * Constraint metadata (min/max length, pattern, multipleOf, min/maxProperties) is emitted as plain-text lines.
541
+
542
+ */
543
+ function buildPropertyJSDocComments(schema) {
544
+ const meta = syncSchemaRef(schema);
545
+ const isArray = meta?.primitive === "array";
546
+ return [
547
+ meta && "description" in meta && meta.description ? `@description ${jsStringEscape(meta.description)}` : void 0,
548
+ meta && "deprecated" in meta && meta.deprecated ? "@deprecated" : void 0,
549
+ !isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` : void 0,
550
+ !isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : void 0,
551
+ meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : void 0,
552
+ meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` : void 0,
553
+ meta && "example" in meta && meta.example !== void 0 ? `@example ${meta.example}` : void 0,
554
+ meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
555
+ ].filter(Boolean);
556
+ }
557
+ function buildParams(node, { params, resolver }) {
558
+ return createSchema({
559
+ type: "object",
560
+ properties: params.map((param) => createProperty({
561
+ name: param.name,
562
+ required: param.required,
563
+ schema: createSchema({
564
+ type: "ref",
565
+ name: resolver.resolveParamName(node, param)
566
+ })
567
+ }))
568
+ });
569
+ }
570
+ function buildData(node, { resolver }) {
571
+ const pathParams = node.parameters.filter((p) => p.in === "path");
572
+ const queryParams = node.parameters.filter((p) => p.in === "query");
573
+ const headerParams = node.parameters.filter((p) => p.in === "header");
574
+ return createSchema({
575
+ type: "object",
576
+ deprecated: node.deprecated,
577
+ properties: [
578
+ createProperty({
579
+ name: "data",
580
+ schema: node.requestBody?.schema ? createSchema({
581
+ type: "ref",
582
+ name: resolver.resolveDataName(node),
583
+ optional: true
584
+ }) : createSchema({
585
+ type: "never",
586
+ primitive: void 0,
587
+ optional: true
588
+ })
589
+ }),
590
+ createProperty({
591
+ name: "pathParams",
592
+ required: pathParams.length > 0,
593
+ schema: pathParams.length > 0 ? buildParams(node, {
594
+ params: pathParams,
595
+ resolver
596
+ }) : createSchema({
597
+ type: "never",
598
+ primitive: void 0
599
+ })
600
+ }),
601
+ createProperty({
602
+ name: "queryParams",
603
+ schema: queryParams.length > 0 ? createSchema({
604
+ ...buildParams(node, {
605
+ params: queryParams,
606
+ resolver
607
+ }),
608
+ optional: true
609
+ }) : createSchema({
610
+ type: "never",
611
+ primitive: void 0,
612
+ optional: true
613
+ })
614
+ }),
615
+ createProperty({
616
+ name: "headerParams",
617
+ schema: headerParams.length > 0 ? createSchema({
618
+ ...buildParams(node, {
619
+ params: headerParams,
620
+ resolver
621
+ }),
622
+ optional: true
623
+ }) : createSchema({
624
+ type: "never",
625
+ primitive: void 0,
626
+ optional: true
627
+ })
628
+ }),
629
+ createProperty({
630
+ name: "url",
631
+ required: true,
632
+ schema: createSchema({
633
+ type: "url",
634
+ path: node.path
635
+ })
636
+ })
637
+ ]
638
+ });
639
+ }
640
+ function buildResponses(node, { resolver }) {
641
+ if (node.responses.length === 0) return null;
642
+ return createSchema({
643
+ type: "object",
644
+ properties: node.responses.map((res) => createProperty({
645
+ name: String(res.statusCode),
646
+ required: true,
647
+ schema: createSchema({
648
+ type: "ref",
649
+ name: resolver.resolveResponseStatusName(node, res.statusCode)
650
+ })
651
+ }))
652
+ });
653
+ }
654
+ function buildResponseUnion(node, { resolver }) {
655
+ const responsesWithSchema = node.responses.filter((res) => res.schema);
656
+ if (responsesWithSchema.length === 0) return null;
657
+ return createSchema({
658
+ type: "union",
659
+ members: responsesWithSchema.map((res) => createSchema({
660
+ type: "ref",
661
+ name: resolver.resolveResponseStatusName(node, res.statusCode)
662
+ }))
663
+ });
664
+ }
665
+ //#endregion
666
+ //#region src/printers/printerTs.ts
542
667
  /**
543
668
  * TypeScript type printer built with `definePrinter`.
544
669
  *
@@ -582,6 +707,8 @@ const printerTs = definePrinter((options) => {
582
707
  if (node.path) return createUrlTemplateType(node.path);
583
708
  return keywordTypeNodes.string;
584
709
  },
710
+ ipv4: () => keywordTypeNodes.string,
711
+ ipv6: () => keywordTypeNodes.string,
585
712
  datetime: () => keywordTypeNodes.string,
586
713
  number: () => keywordTypeNodes.number,
587
714
  integer: () => keywordTypeNodes.number,
@@ -590,14 +717,14 @@ const printerTs = definePrinter((options) => {
590
717
  time: dateOrStringNode,
591
718
  ref(node) {
592
719
  if (!node.name) return;
593
- const refName = node.ref ? node.ref.split("/").at(-1) ?? node.name : node.name;
720
+ const refName = node.ref ? extractRefName(node.ref) ?? node.name : node.name;
594
721
  return createTypeReferenceNode(node.ref && ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) && this.options.enumTypeSuffix && this.options.enumSchemaNames?.has(refName) ? this.options.resolver.resolveEnumKeyName({ name: refName }, this.options.enumTypeSuffix) : node.ref ? this.options.resolver.default(refName, "type") : refName, void 0);
595
722
  },
596
723
  enum(node) {
597
724
  const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
598
725
  if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
599
726
  withParentheses: true,
600
- nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value)).filter(Boolean)
727
+ nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(Boolean)
601
728
  }) ?? void 0;
602
729
  return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) && this.options.enumTypeSuffix ? this.options.resolver.resolveEnumKeyName(node, this.options.enumTypeSuffix) : this.options.resolver.default(node.name, "type"), void 0);
603
730
  },
@@ -643,12 +770,13 @@ const printerTs = definePrinter((options) => {
643
770
  const propertyNodes = node.properties.map((prop) => {
644
771
  const baseType = transform(prop.schema) ?? keywordTypeNodes.unknown;
645
772
  const type = buildPropertyType(prop.schema, baseType, options.optionalType);
773
+ const propMeta = syncSchemaRef(prop.schema);
646
774
  return appendJSDocToNode({
647
775
  node: createPropertySignature({
648
776
  questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
649
777
  name: prop.name,
650
778
  type,
651
- readOnly: prop.schema.readOnly
779
+ readOnly: propMeta?.readOnly
652
780
  }),
653
781
  comments: buildPropertyJSDocComments(prop.schema)
654
782
  });
@@ -659,32 +787,32 @@ const printerTs = definePrinter((options) => {
659
787
  }
660
788
  },
661
789
  print(node) {
662
- let type = this.transform(node);
663
- if (!type) return null;
664
- if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
665
- if ((node.nullish || node.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
666
790
  const { name, syntaxType = "type", description, keysToOmit } = this.options;
667
- if (!name) return safePrint(type);
668
- const useTypeGeneration = syntaxType === "type" || type.kind === syntaxKind.union || !!keysToOmit?.length;
791
+ let base = this.transform(node);
792
+ if (!base) return null;
793
+ const meta = syncSchemaRef(node);
794
+ if (!name) {
795
+ if (meta.nullable) base = createUnionDeclaration({ nodes: [base, keywordTypeNodes.null] });
796
+ if ((meta.nullish || meta.optional) && addsUndefined) base = createUnionDeclaration({ nodes: [base, keywordTypeNodes.undefined] });
797
+ return safePrint(base);
798
+ }
799
+ let inner = keysToOmit?.length ? createOmitDeclaration({
800
+ keys: keysToOmit,
801
+ type: base,
802
+ nonNullable: true
803
+ }) : base;
804
+ if (meta.nullable) inner = createUnionDeclaration({ nodes: [inner, keywordTypeNodes.null] });
805
+ if (meta.nullish || meta.optional) inner = createUnionDeclaration({ nodes: [inner, keywordTypeNodes.undefined] });
806
+ const useTypeGeneration = syntaxType === "type" || inner.kind === syntaxKind.union || !!keysToOmit?.length;
669
807
  return safePrint(createTypeDeclaration({
670
808
  name,
671
809
  isExportable: true,
672
- type: keysToOmit?.length ? createOmitDeclaration({
673
- keys: keysToOmit,
674
- type,
675
- nonNullable: true
676
- }) : type,
810
+ type: inner,
677
811
  syntax: useTypeGeneration ? "type" : "interface",
678
- comments: [
679
- node?.title ? jsStringEscape(node.title) : void 0,
680
- description ? `@description ${jsStringEscape(description)}` : void 0,
681
- node?.deprecated ? "@deprecated" : void 0,
682
- node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
683
- node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
684
- node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
685
- node?.default ? `@default ${node.default}` : void 0,
686
- node?.example ? `@example ${node.example}` : void 0
687
- ]
812
+ comments: buildPropertyJSDocComments({
813
+ ...meta,
814
+ description
815
+ })
688
816
  }));
689
817
  }
690
818
  };
@@ -738,141 +866,103 @@ function Type({ name, node, keysToOmit, optionalType, arrayType, syntaxType, enu
738
866
  })] });
739
867
  }
740
868
  //#endregion
741
- //#region src/utils.ts
742
- function buildParams({ params, node, resolver }) {
743
- return createSchema({
744
- type: "object",
745
- properties: params.map((param) => createProperty({
746
- name: param.name,
747
- required: param.required,
748
- schema: createSchema({
749
- type: "ref",
750
- name: resolver.resolveParamName(node, param)
751
- })
752
- }))
753
- });
754
- }
755
- function buildData({ node, resolver }) {
756
- const pathParams = node.parameters.filter((p) => p.in === "path");
757
- const queryParams = node.parameters.filter((p) => p.in === "query");
758
- const headerParams = node.parameters.filter((p) => p.in === "header");
759
- return createSchema({
760
- type: "object",
761
- deprecated: node.deprecated,
762
- properties: [
763
- createProperty({
764
- name: "data",
765
- schema: node.requestBody?.schema ? createSchema({
766
- type: "ref",
767
- name: resolver.resolveDataName(node),
768
- optional: true
769
- }) : createSchema({
770
- type: "never",
771
- optional: true
772
- })
773
- }),
774
- createProperty({
775
- name: "pathParams",
776
- required: pathParams.length > 0,
777
- schema: pathParams.length > 0 ? buildParams({
778
- params: pathParams,
779
- node,
780
- resolver
781
- }) : createSchema({ type: "never" })
782
- }),
783
- createProperty({
784
- name: "queryParams",
785
- schema: queryParams.length > 0 ? createSchema({
786
- ...buildParams({
787
- params: queryParams,
788
- node,
789
- resolver
790
- }),
791
- optional: true
792
- }) : createSchema({
793
- type: "never",
794
- optional: true
795
- })
796
- }),
797
- createProperty({
798
- name: "headerParams",
799
- schema: headerParams.length > 0 ? createSchema({
800
- ...buildParams({
801
- params: headerParams,
802
- node,
803
- resolver
804
- }),
805
- optional: true
806
- }) : createSchema({
807
- type: "never",
808
- optional: true
809
- })
810
- }),
811
- createProperty({
812
- name: "url",
813
- required: true,
814
- schema: createSchema({
815
- type: "url",
816
- path: node.path
817
- })
818
- })
819
- ]
820
- });
821
- }
822
- function buildResponses({ node, resolver }) {
823
- if (node.responses.length === 0) return null;
824
- return createSchema({
825
- type: "object",
826
- properties: node.responses.map((res) => createProperty({
827
- name: String(res.statusCode),
828
- required: true,
829
- schema: createSchema({
830
- type: "ref",
831
- name: resolver.resolveResponseStatusName(node, res.statusCode)
869
+ //#region src/generators/typeGenerator.tsx
870
+ const typeGenerator = defineGenerator({
871
+ name: "typescript",
872
+ type: "react",
873
+ Schema({ node, adapter, options, config, resolver }) {
874
+ const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
875
+ const transformedNode = transform(node, composeTransformers(...transformers));
876
+ if (!transformedNode.name) return;
877
+ const root = path.resolve(config.root, config.output.path);
878
+ const mode = getMode(path.resolve(root, output.path));
879
+ const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name));
880
+ function resolveImportName(schemaName) {
881
+ if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
882
+ return resolver.default(schemaName, "type");
883
+ }
884
+ const imports = adapter.getImports(transformedNode, (schemaName) => ({
885
+ name: resolveImportName(schemaName),
886
+ path: resolver.resolveFile({
887
+ name: schemaName,
888
+ extname: ".ts"
889
+ }, {
890
+ root,
891
+ output,
892
+ group
893
+ }).path
894
+ }));
895
+ const isEnumSchema = !!narrowSchema(transformedNode, schemaTypes.enum);
896
+ const meta = {
897
+ name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(transformedNode, enumTypeSuffix) : resolver.resolveName(transformedNode.name),
898
+ file: resolver.resolveFile({
899
+ name: transformedNode.name,
900
+ extname: ".ts"
901
+ }, {
902
+ root,
903
+ output,
904
+ group
832
905
  })
833
- }))
834
- });
835
- }
836
- function buildResponseUnion({ node, resolver }) {
837
- const responsesWithSchema = node.responses.filter((res) => res.schema);
838
- if (responsesWithSchema.length === 0) return null;
839
- return createSchema({
840
- type: "union",
841
- members: responsesWithSchema.map((res) => createSchema({
842
- type: "ref",
843
- name: resolver.resolveResponseStatusName(node, res.statusCode)
844
- }))
845
- });
846
- }
847
- //#endregion
848
- //#region src/generators/typeGenerator.tsx
849
- const typeGenerator = defineGenerator({
850
- name: "typescript",
851
- type: "react",
906
+ };
907
+ return /* @__PURE__ */ jsxs(File, {
908
+ baseName: meta.file.baseName,
909
+ path: meta.file.path,
910
+ meta: meta.file.meta,
911
+ banner: resolver.resolveBanner(adapter.rootNode, {
912
+ output,
913
+ config
914
+ }),
915
+ footer: resolver.resolveFooter(adapter.rootNode, {
916
+ output,
917
+ config
918
+ }),
919
+ children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
920
+ root: meta.file.path,
921
+ path: imp.path,
922
+ name: imp.name,
923
+ isTypeOnly: true
924
+ }, [
925
+ transformedNode.name,
926
+ imp.path,
927
+ imp.isTypeOnly
928
+ ].join("-"))), /* @__PURE__ */ jsx(Type, {
929
+ name: meta.name,
930
+ node: transformedNode,
931
+ enumType,
932
+ enumTypeSuffix,
933
+ enumKeyCasing,
934
+ optionalType,
935
+ arrayType,
936
+ syntaxType,
937
+ resolver,
938
+ enumSchemaNames
939
+ })]
940
+ });
941
+ },
852
942
  Operation({ node, adapter, options, config, resolver }) {
853
943
  const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options;
944
+ const transformedNode = transform(node, composeTransformers(...transformers));
854
945
  const root = path.resolve(config.root, config.output.path);
855
946
  const mode = getMode(path.resolve(root, output.path));
856
- const file = resolver.resolveFile({
857
- name: node.operationId,
947
+ const params = caseParams(transformedNode.parameters, paramsCasing);
948
+ const meta = { file: resolver.resolveFile({
949
+ name: transformedNode.operationId,
858
950
  extname: ".ts",
859
- tag: node.tags[0] ?? "default",
860
- path: node.path
951
+ tag: transformedNode.tags[0] ?? "default",
952
+ path: transformedNode.path
861
953
  }, {
862
954
  root,
863
955
  output,
864
956
  group
865
- });
866
- const params = caseParams(node.parameters, paramsCasing);
957
+ }) };
867
958
  const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name));
868
959
  function resolveImportName(schemaName) {
869
960
  if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
870
961
  return resolver.default(schemaName, "type");
871
962
  }
872
- function renderSchemaType({ node: schemaNode, name, description, keysToOmit }) {
873
- if (!schemaNode) return null;
874
- const transformedNode = transform(schemaNode, composeTransformers(...transformers));
875
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
963
+ function renderSchemaType({ schema, name, keysToOmit }) {
964
+ if (!schema) return null;
965
+ const imports = adapter.getImports(schema, (schemaName) => ({
876
966
  name: resolveImportName(schemaName),
877
967
  path: resolver.resolveFile({
878
968
  name: schemaName,
@@ -884,7 +974,7 @@ const typeGenerator = defineGenerator({
884
974
  }).path
885
975
  }));
886
976
  return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
887
- root: file.path,
977
+ root: meta.file.path,
888
978
  path: imp.path,
889
979
  name: imp.name,
890
980
  isTypeOnly: true
@@ -894,8 +984,7 @@ const typeGenerator = defineGenerator({
894
984
  imp.isTypeOnly
895
985
  ].join("-"))), /* @__PURE__ */ jsx(Type, {
896
986
  name,
897
- node: transformedNode,
898
- description,
987
+ node: schema,
899
988
  enumType,
900
989
  enumTypeSuffix,
901
990
  enumKeyCasing,
@@ -908,50 +997,44 @@ const typeGenerator = defineGenerator({
908
997
  })] });
909
998
  }
910
999
  const paramTypes = params.map((param) => renderSchemaType({
911
- node: param.schema,
912
- name: resolver.resolveParamName(node, param)
1000
+ schema: param.schema,
1001
+ name: resolver.resolveParamName(transformedNode, param)
913
1002
  }));
914
- const requestType = node.requestBody?.schema ? renderSchemaType({
915
- node: node.requestBody.schema,
916
- name: resolver.resolveDataName(node),
917
- description: node.requestBody.description ?? node.requestBody.schema.description,
918
- keysToOmit: node.requestBody.keysToOmit
1003
+ const requestType = transformedNode.requestBody?.schema ? renderSchemaType({
1004
+ schema: {
1005
+ ...transformedNode.requestBody.schema,
1006
+ description: transformedNode.requestBody.description ?? transformedNode.requestBody.schema.description
1007
+ },
1008
+ name: resolver.resolveDataName(transformedNode),
1009
+ keysToOmit: transformedNode.requestBody.keysToOmit
919
1010
  }) : null;
920
- const responseTypes = node.responses.map((res) => renderSchemaType({
921
- node: res.schema,
922
- name: resolver.resolveResponseStatusName(node, res.statusCode),
923
- description: res.description,
1011
+ const responseTypes = transformedNode.responses.map((res) => renderSchemaType({
1012
+ schema: res.schema,
1013
+ name: resolver.resolveResponseStatusName(transformedNode, res.statusCode),
924
1014
  keysToOmit: res.keysToOmit
925
1015
  }));
926
1016
  const dataType = renderSchemaType({
927
- node: buildData({
928
- node: {
929
- ...node,
930
- parameters: params
931
- },
932
- resolver
933
- }),
934
- name: resolver.resolveRequestConfigName(node)
1017
+ schema: buildData({
1018
+ ...transformedNode,
1019
+ parameters: params
1020
+ }, { resolver }),
1021
+ name: resolver.resolveRequestConfigName(transformedNode)
935
1022
  });
936
1023
  const responsesType = renderSchemaType({
937
- node: buildResponses({
938
- node,
939
- resolver
940
- }),
941
- name: resolver.resolveResponsesName(node)
1024
+ schema: buildResponses(transformedNode, { resolver }),
1025
+ name: resolver.resolveResponsesName(transformedNode)
942
1026
  });
943
1027
  const responseType = renderSchemaType({
944
- node: buildResponseUnion({
945
- node,
946
- resolver
947
- }),
948
- name: resolver.resolveResponseName(node),
949
- description: "Union of all possible responses"
1028
+ schema: transformedNode.responses.some((res) => res.schema) ? {
1029
+ ...buildResponseUnion(transformedNode, { resolver }),
1030
+ description: "Union of all possible responses"
1031
+ } : null,
1032
+ name: resolver.resolveResponseName(transformedNode)
950
1033
  });
951
1034
  return /* @__PURE__ */ jsxs(File, {
952
- baseName: file.baseName,
953
- path: file.path,
954
- meta: file.meta,
1035
+ baseName: meta.file.baseName,
1036
+ path: meta.file.path,
1037
+ meta: meta.file.meta,
955
1038
  banner: resolver.resolveBanner(adapter.rootNode, {
956
1039
  output,
957
1040
  config
@@ -969,80 +1052,11 @@ const typeGenerator = defineGenerator({
969
1052
  responseType
970
1053
  ]
971
1054
  });
972
- },
973
- Schema({ node, adapter, options, config, resolver }) {
974
- const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
975
- const root = path.resolve(config.root, config.output.path);
976
- const mode = getMode(path.resolve(root, output.path));
977
- if (!node.name) return;
978
- const transformedNode = transform(node, composeTransformers(...transformers));
979
- const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name));
980
- function resolveImportName(schemaName) {
981
- if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
982
- return resolver.default(schemaName, "type");
983
- }
984
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
985
- name: resolveImportName(schemaName),
986
- path: resolver.resolveFile({
987
- name: schemaName,
988
- extname: ".ts"
989
- }, {
990
- root,
991
- output,
992
- group
993
- }).path
994
- }));
995
- const isEnumSchema = !!narrowSchema(node, schemaTypes.enum);
996
- const type = {
997
- name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
998
- file: resolver.resolveFile({
999
- name: node.name,
1000
- extname: ".ts"
1001
- }, {
1002
- root,
1003
- output,
1004
- group
1005
- })
1006
- };
1007
- return /* @__PURE__ */ jsxs(File, {
1008
- baseName: type.file.baseName,
1009
- path: type.file.path,
1010
- meta: type.file.meta,
1011
- banner: resolver.resolveBanner(adapter.rootNode, {
1012
- output,
1013
- config
1014
- }),
1015
- footer: resolver.resolveFooter(adapter.rootNode, {
1016
- output,
1017
- config
1018
- }),
1019
- children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1020
- root: type.file.path,
1021
- path: imp.path,
1022
- name: imp.name,
1023
- isTypeOnly: true
1024
- }, [
1025
- node.name,
1026
- imp.path,
1027
- imp.isTypeOnly
1028
- ].join("-"))), /* @__PURE__ */ jsx(Type, {
1029
- name: type.name,
1030
- node: transformedNode,
1031
- enumType,
1032
- enumTypeSuffix,
1033
- enumKeyCasing,
1034
- optionalType,
1035
- arrayType,
1036
- syntaxType,
1037
- resolver,
1038
- enumSchemaNames
1039
- })]
1040
- });
1041
1055
  }
1042
1056
  });
1043
1057
  //#endregion
1044
1058
  //#region src/resolvers/resolverTs.ts
1045
- function resolveName(name, type) {
1059
+ function toTypeName(name, type) {
1046
1060
  return pascalCase(name, { isFile: type === "file" });
1047
1061
  }
1048
1062
  /**
@@ -1067,7 +1081,7 @@ const resolverTs = defineResolver(() => {
1067
1081
  name: "default",
1068
1082
  pluginName: "plugin-ts",
1069
1083
  default(name, type) {
1070
- return resolveName(name, type);
1084
+ return toTypeName(name, type);
1071
1085
  },
1072
1086
  resolveName(name) {
1073
1087
  return this.default(name, "function");
@@ -1186,7 +1200,7 @@ function buildGroupedParamsSchema({ params, parentName }) {
1186
1200
  })
1187
1201
  });
1188
1202
  }
1189
- function buildLegacyResponsesSchemaNode({ node, resolver }) {
1203
+ function buildLegacyResponsesSchemaNode(node, { resolver }) {
1190
1204
  const isGet = node.method.toLowerCase() === "get";
1191
1205
  const successResponses = node.responses.filter((res) => {
1192
1206
  const code = Number(res.statusCode);
@@ -1202,7 +1216,10 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
1202
1216
  type: "ref",
1203
1217
  name: resolver.resolveResponseStatusName(node, res.statusCode)
1204
1218
  }))
1205
- }) : createSchema({ type: "any" });
1219
+ }) : createSchema({
1220
+ type: "any",
1221
+ primitive: void 0
1222
+ });
1206
1223
  const errorsSchema = errorResponses.length > 0 ? errorResponses.length === 1 ? createSchema({
1207
1224
  type: "ref",
1208
1225
  name: resolver.resolveResponseStatusName(node, errorResponses[0].statusCode)
@@ -1212,7 +1229,10 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
1212
1229
  type: "ref",
1213
1230
  name: resolver.resolveResponseStatusName(node, res.statusCode)
1214
1231
  }))
1215
- }) : createSchema({ type: "any" });
1232
+ }) : createSchema({
1233
+ type: "any",
1234
+ primitive: void 0
1235
+ });
1216
1236
  const properties = [createProperty({
1217
1237
  name: "Response",
1218
1238
  required: true,
@@ -1263,12 +1283,15 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
1263
1283
  properties
1264
1284
  });
1265
1285
  }
1266
- function buildLegacyResponseUnionSchemaNode({ node, resolver }) {
1286
+ function buildLegacyResponseUnionSchemaNode(node, { resolver }) {
1267
1287
  const successResponses = node.responses.filter((res) => {
1268
1288
  const code = Number(res.statusCode);
1269
1289
  return !Number.isNaN(code) && code >= 200 && code < 300;
1270
1290
  });
1271
- if (successResponses.length === 0) return createSchema({ type: "any" });
1291
+ if (successResponses.length === 0) return createSchema({
1292
+ type: "any",
1293
+ primitive: void 0
1294
+ });
1272
1295
  if (successResponses.length === 1) return createSchema({
1273
1296
  type: "ref",
1274
1297
  name: resolver.resolveResponseStatusName(node, successResponses[0].statusCode)
@@ -1309,25 +1332,88 @@ function nameUnnamedEnums(node, parentName) {
1309
1332
  const typeGeneratorLegacy = defineGenerator({
1310
1333
  name: "typescript-legacy",
1311
1334
  type: "react",
1335
+ Schema({ node, adapter, options, config, resolver }) {
1336
+ const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
1337
+ const transformedNode = transform(node, composeTransformers(...transformers));
1338
+ if (!transformedNode.name) return;
1339
+ const root = path.resolve(config.root, config.output.path);
1340
+ const mode = getMode(path.resolve(root, output.path));
1341
+ const imports = adapter.getImports(transformedNode, (schemaName) => ({
1342
+ name: resolver.default(schemaName, "type"),
1343
+ path: resolver.resolveFile({
1344
+ name: schemaName,
1345
+ extname: ".ts"
1346
+ }, {
1347
+ root,
1348
+ output,
1349
+ group
1350
+ }).path
1351
+ }));
1352
+ const isEnumSchema = !!narrowSchema(transformedNode, schemaTypes.enum);
1353
+ const meta = {
1354
+ name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(transformedNode, enumTypeSuffix) : resolver.resolveName(transformedNode.name),
1355
+ file: resolver.resolveFile({
1356
+ name: transformedNode.name,
1357
+ extname: ".ts"
1358
+ }, {
1359
+ root,
1360
+ output,
1361
+ group
1362
+ })
1363
+ };
1364
+ return /* @__PURE__ */ jsxs(File, {
1365
+ baseName: meta.file.baseName,
1366
+ path: meta.file.path,
1367
+ meta: meta.file.meta,
1368
+ banner: resolver.resolveBanner(adapter.rootNode, {
1369
+ output,
1370
+ config
1371
+ }),
1372
+ footer: resolver.resolveFooter(adapter.rootNode, {
1373
+ output,
1374
+ config
1375
+ }),
1376
+ children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1377
+ root: meta.file.path,
1378
+ path: imp.path,
1379
+ name: imp.name,
1380
+ isTypeOnly: true
1381
+ }, [
1382
+ transformedNode.name,
1383
+ imp.path,
1384
+ imp.isTypeOnly
1385
+ ].join("-"))), /* @__PURE__ */ jsx(Type, {
1386
+ name: meta.name,
1387
+ node: transformedNode,
1388
+ enumType,
1389
+ enumTypeSuffix,
1390
+ enumKeyCasing,
1391
+ optionalType,
1392
+ arrayType,
1393
+ syntaxType,
1394
+ resolver
1395
+ })]
1396
+ });
1397
+ },
1312
1398
  Operation({ node, adapter, options, config, resolver }) {
1313
1399
  const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options;
1400
+ const transformedNode = transform(node, composeTransformers(...transformers));
1314
1401
  const root = path.resolve(config.root, config.output.path);
1315
1402
  const mode = getMode(path.resolve(root, output.path));
1316
- const file = resolver.resolveFile({
1317
- name: node.operationId,
1403
+ const params = caseParams(node.parameters, paramsCasing);
1404
+ const meta = { file: resolver.resolveFile({
1405
+ name: transformedNode.operationId,
1318
1406
  extname: ".ts",
1319
- tag: node.tags[0] ?? "default",
1320
- path: node.path
1407
+ tag: transformedNode.tags[0] ?? "default",
1408
+ path: transformedNode.path
1321
1409
  }, {
1322
1410
  root,
1323
1411
  output,
1324
1412
  group
1325
- });
1326
- const params = caseParams(node.parameters, paramsCasing);
1327
- function renderSchemaType({ node: schemaNode, name, description, keysToOmit }) {
1328
- if (!schemaNode) return null;
1329
- const transformedNode = transform(schemaNode, composeTransformers(...transformers));
1330
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
1413
+ }) };
1414
+ function renderSchemaType({ schema, name, description, keysToOmit }) {
1415
+ if (!schema) return null;
1416
+ const imports = adapter.getImports(schema, (schemaName) => ({
1331
1417
  name: resolver.default(schemaName, "type"),
1332
1418
  path: resolver.resolveFile({
1333
1419
  name: schemaName,
@@ -1339,7 +1425,7 @@ const typeGeneratorLegacy = defineGenerator({
1339
1425
  }).path
1340
1426
  }));
1341
1427
  return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1342
- root: file.path,
1428
+ root: meta.file.path,
1343
1429
  path: imp.path,
1344
1430
  name: imp.name,
1345
1431
  isTypeOnly: true
@@ -1349,7 +1435,7 @@ const typeGeneratorLegacy = defineGenerator({
1349
1435
  imp.isTypeOnly
1350
1436
  ].join("-"))), /* @__PURE__ */ jsx(Type, {
1351
1437
  name,
1352
- node: transformedNode,
1438
+ node: schema,
1353
1439
  description,
1354
1440
  enumType,
1355
1441
  enumTypeSuffix,
@@ -1368,35 +1454,35 @@ const typeGeneratorLegacy = defineGenerator({
1368
1454
  const responseName = resolver.resolveResponseStatusName(node, res.statusCode);
1369
1455
  const baseResponseName = resolverTsLegacy.resolveResponseStatusName(node, res.statusCode);
1370
1456
  return renderSchemaType({
1371
- node: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
1457
+ schema: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
1372
1458
  name: responseName,
1373
1459
  description: res.description,
1374
1460
  keysToOmit: res.keysToOmit
1375
1461
  });
1376
1462
  });
1377
1463
  const requestType = node.requestBody?.schema ? renderSchemaType({
1378
- node: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
1464
+ schema: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
1379
1465
  name: resolver.resolveDataName(node),
1380
1466
  description: node.requestBody.description ?? node.requestBody.schema.description,
1381
1467
  keysToOmit: node.requestBody.keysToOmit
1382
1468
  }) : null;
1383
1469
  const legacyParamTypes = [
1384
1470
  pathParams.length > 0 ? renderSchemaType({
1385
- node: buildGroupedParamsSchema({
1471
+ schema: buildGroupedParamsSchema({
1386
1472
  params: pathParams,
1387
1473
  parentName: resolverTsLegacy.resolvePathParamsName(node, pathParams[0])
1388
1474
  }),
1389
1475
  name: resolver.resolvePathParamsName(node, pathParams[0])
1390
1476
  }) : null,
1391
1477
  queryParams.length > 0 ? renderSchemaType({
1392
- node: buildGroupedParamsSchema({
1478
+ schema: buildGroupedParamsSchema({
1393
1479
  params: queryParams,
1394
1480
  parentName: resolverTsLegacy.resolveQueryParamsName(node, queryParams[0])
1395
1481
  }),
1396
1482
  name: resolver.resolveQueryParamsName(node, queryParams[0])
1397
1483
  }) : null,
1398
1484
  headerParams.length > 0 ? renderSchemaType({
1399
- node: buildGroupedParamsSchema({
1485
+ schema: buildGroupedParamsSchema({
1400
1486
  params: headerParams,
1401
1487
  parentName: resolverTsLegacy.resolveHeaderParamsName(node, headerParams[0])
1402
1488
  }),
@@ -1404,23 +1490,17 @@ const typeGeneratorLegacy = defineGenerator({
1404
1490
  }) : null
1405
1491
  ];
1406
1492
  const legacyResponsesType = renderSchemaType({
1407
- node: buildLegacyResponsesSchemaNode({
1408
- node,
1409
- resolver
1410
- }),
1493
+ schema: buildLegacyResponsesSchemaNode(node, { resolver }),
1411
1494
  name: resolver.resolveResponsesName(node)
1412
1495
  });
1413
1496
  const legacyResponseType = renderSchemaType({
1414
- node: buildLegacyResponseUnionSchemaNode({
1415
- node,
1416
- resolver
1417
- }),
1497
+ schema: buildLegacyResponseUnionSchemaNode(node, { resolver }),
1418
1498
  name: resolver.resolveResponseName(node)
1419
1499
  });
1420
1500
  return /* @__PURE__ */ jsxs(File, {
1421
- baseName: file.baseName,
1422
- path: file.path,
1423
- meta: file.meta,
1501
+ baseName: meta.file.baseName,
1502
+ path: meta.file.path,
1503
+ meta: meta.file.meta,
1424
1504
  banner: resolver.resolveBanner(adapter.rootNode, {
1425
1505
  output,
1426
1506
  config
@@ -1437,69 +1517,6 @@ const typeGeneratorLegacy = defineGenerator({
1437
1517
  legacyResponsesType
1438
1518
  ]
1439
1519
  });
1440
- },
1441
- Schema({ node, adapter, options, config, resolver }) {
1442
- const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
1443
- const root = path.resolve(config.root, config.output.path);
1444
- const mode = getMode(path.resolve(root, output.path));
1445
- if (!node.name) return;
1446
- const transformedNode = transform(node, composeTransformers(...transformers));
1447
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
1448
- name: resolver.default(schemaName, "type"),
1449
- path: resolver.resolveFile({
1450
- name: schemaName,
1451
- extname: ".ts"
1452
- }, {
1453
- root,
1454
- output,
1455
- group
1456
- }).path
1457
- }));
1458
- const isEnumSchema = !!narrowSchema(node, schemaTypes.enum);
1459
- const type = {
1460
- name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
1461
- file: resolver.resolveFile({
1462
- name: node.name,
1463
- extname: ".ts"
1464
- }, {
1465
- root,
1466
- output,
1467
- group
1468
- })
1469
- };
1470
- return /* @__PURE__ */ jsxs(File, {
1471
- baseName: type.file.baseName,
1472
- path: type.file.path,
1473
- meta: type.file.meta,
1474
- banner: resolver.resolveBanner(adapter.rootNode, {
1475
- output,
1476
- config
1477
- }),
1478
- footer: resolver.resolveFooter(adapter.rootNode, {
1479
- output,
1480
- config
1481
- }),
1482
- children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1483
- root: type.file.path,
1484
- path: imp.path,
1485
- name: imp.name,
1486
- isTypeOnly: true
1487
- }, [
1488
- node.name,
1489
- imp.path,
1490
- imp.isTypeOnly
1491
- ].join("-"))), /* @__PURE__ */ jsx(Type, {
1492
- name: type.name,
1493
- node: transformedNode,
1494
- enumType,
1495
- enumTypeSuffix,
1496
- enumKeyCasing,
1497
- optionalType,
1498
- arrayType,
1499
- syntaxType,
1500
- resolver
1501
- })]
1502
- });
1503
1520
  }
1504
1521
  });
1505
1522
  //#endregion
@@ -1568,9 +1585,9 @@ const pluginTs = createPlugin((options) => {
1568
1585
  output,
1569
1586
  optionalType,
1570
1587
  group: group ? {
1571
- ...options.group,
1588
+ ...group,
1572
1589
  name: (ctx) => {
1573
- if (options.group?.type === "path") return `${ctx.group.split("/")[1]}`;
1590
+ if (group.type === "path") return `${ctx.group.split("/")[1]}`;
1574
1591
  return `${camelCase(ctx.group)}Controller`;
1575
1592
  }
1576
1593
  } : void 0,
@@ -1609,59 +1626,37 @@ const pluginTs = createPlugin((options) => {
1609
1626
  async install() {
1610
1627
  const { config, fabric, plugin, adapter, rootNode, driver, openInStudio, resolver } = this;
1611
1628
  const root = path.resolve(config.root, config.output.path);
1612
- if (!adapter) throw new Error("Plugin cannot work without adapter being set");
1629
+ if (!adapter) throw new Error(`[${pluginTsName}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
1613
1630
  await openInStudio({ ast: true });
1631
+ const collectedOperations = [];
1632
+ const generatorContext = {
1633
+ generators: preset.generators,
1634
+ plugin,
1635
+ resolver,
1636
+ exclude,
1637
+ include,
1638
+ override,
1639
+ fabric,
1640
+ adapter,
1641
+ config,
1642
+ driver
1643
+ };
1614
1644
  await walk(rootNode, {
1615
1645
  depth: "shallow",
1616
1646
  async schema(schemaNode) {
1617
- const writeTasks = preset.generators.map(async (generator) => {
1618
- if (generator.type === "react" && generator.version === "2") {
1619
- const options = resolver.resolveOptions(schemaNode, {
1620
- options: plugin.options,
1621
- exclude,
1622
- include,
1623
- override
1624
- });
1625
- if (options === null) return;
1626
- await renderSchema(schemaNode, {
1627
- options,
1628
- resolver,
1629
- adapter,
1630
- config,
1631
- fabric,
1632
- Component: generator.Schema,
1633
- plugin,
1634
- driver
1635
- });
1636
- }
1637
- });
1638
- await Promise.all(writeTasks);
1647
+ await runGeneratorSchema(schemaNode, generatorContext);
1639
1648
  },
1640
1649
  async operation(operationNode) {
1641
- const writeTasks = preset.generators.map(async (generator) => {
1642
- if (generator.type === "react" && generator.version === "2") {
1643
- const options = resolver.resolveOptions(operationNode, {
1644
- options: plugin.options,
1645
- exclude,
1646
- include,
1647
- override
1648
- });
1649
- if (options === null) return;
1650
- await renderOperation(operationNode, {
1651
- options,
1652
- resolver,
1653
- adapter,
1654
- config,
1655
- fabric,
1656
- Component: generator.Operation,
1657
- plugin,
1658
- driver
1659
- });
1660
- }
1661
- });
1662
- await Promise.all(writeTasks);
1650
+ if (resolver.resolveOptions(operationNode, {
1651
+ options: plugin.options,
1652
+ exclude,
1653
+ include,
1654
+ override
1655
+ }) !== null) collectedOperations.push(operationNode);
1656
+ await runGeneratorOperation(operationNode, generatorContext);
1663
1657
  }
1664
1658
  });
1659
+ await runGeneratorOperations(collectedOperations, generatorContext);
1665
1660
  const barrelFiles = await getBarrelFiles(this.fabric.files, {
1666
1661
  type: output.barrelType ?? "named",
1667
1662
  root,
@@ -1689,12 +1684,12 @@ const kindToHandlerKey = {
1689
1684
  const defineFunctionPrinter = createPrinterFactory((node) => kindToHandlerKey[node.kind]);
1690
1685
  function rank(param) {
1691
1686
  if (param.kind === "ParameterGroup") {
1692
- if (param.default) return 2;
1693
- return param.optional ?? param.properties.every((p) => p.optional || p.default !== void 0) ? 1 : 0;
1687
+ if (param.default) return PARAM_RANK.withDefault;
1688
+ return param.optional ?? param.properties.every((p) => p.optional || p.default !== void 0) ? PARAM_RANK.optional : PARAM_RANK.required;
1694
1689
  }
1695
- if (param.rest) return 3;
1696
- if (param.default) return 2;
1697
- return param.optional ? 1 : 0;
1690
+ if (param.rest) return PARAM_RANK.rest;
1691
+ if (param.default) return PARAM_RANK.withDefault;
1692
+ return param.optional ? PARAM_RANK.optional : PARAM_RANK.required;
1698
1693
  }
1699
1694
  function sortParams(params) {
1700
1695
  return [...params].sort((a, b) => rank(a) - rank(b));