@kubb/plugin-ts 5.0.0-alpha.23 → 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,64 +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
- refName: resolved
415
- };
416
- }
417
- /**
418
- * Renders the enum declaration(s) for a single named `EnumSchemaNode`.
419
- *
420
- * Depending on `enumType` this may emit:
421
- * - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
422
- * - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
423
- * - A union literal type alias (`literal`)
424
- *
425
- * The emitted `File.Source` nodes carry the resolved names so that the barrel
426
- * index picks up the correct export identifiers.
427
- */
428
- function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
429
- const { enumName, typeName } = getEnumNames({
430
- node,
431
- enumType,
432
- enumTypeSuffix,
433
- resolver
434
- });
435
- const [nameNode, typeNode] = createEnumDeclaration({
436
- name: enumName,
437
- typeName,
438
- 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]) ?? [],
439
- type: enumType,
440
- enumKeyCasing
441
- });
442
- return /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
443
- name: enumName,
444
- isExportable: true,
445
- isIndexable: true,
446
- isTypeOnly: false,
447
- children: safePrint(nameNode)
448
- }), /* @__PURE__ */ jsx(File.Source, {
449
- name: typeName,
450
- isIndexable: true,
451
- isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
452
- isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
453
- children: safePrint(typeNode)
454
- })] });
455
- }
456
- //#endregion
457
- //#region src/printers/printerTs.ts
458
409
  /**
459
410
  * Converts a primitive const value to a TypeScript literal type node.
460
411
  * Handles negative numbers via a prefix unary expression.
@@ -500,28 +451,13 @@ function buildTupleNode(node, print) {
500
451
  */
501
452
  function buildPropertyType(schema, baseType, optionalType) {
502
453
  const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType);
454
+ const meta = syncSchemaRef(schema);
503
455
  let type = baseType;
504
- if (schema.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
505
- 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] });
506
458
  return type;
507
459
  }
508
460
  /**
509
- * Collects JSDoc annotation strings (description, deprecated, min/max, pattern, default, example, type) for a schema node.
510
- */
511
- function buildPropertyJSDocComments(schema) {
512
- const isArray = schema.type === "array";
513
- return [
514
- "description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
515
- "deprecated" in schema && schema.deprecated ? "@deprecated" : void 0,
516
- !isArray && "min" in schema && schema.min !== void 0 ? `@minLength ${schema.min}` : void 0,
517
- !isArray && "max" in schema && schema.max !== void 0 ? `@maxLength ${schema.max}` : void 0,
518
- "pattern" in schema && schema.pattern ? `@pattern ${schema.pattern}` : void 0,
519
- "default" in schema && schema.default !== void 0 ? `@default ${"primitive" in schema && schema.primitive === "string" ? stringify(schema.default) : schema.default}` : void 0,
520
- "example" in schema && schema.example !== void 0 ? `@example ${schema.example}` : void 0,
521
- "primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
522
- ];
523
- }
524
- /**
525
461
  * Creates TypeScript index signatures for `additionalProperties` and `patternProperties` on an object schema node.
526
462
  */
527
463
  function buildIndexSignatures(node, propertyCount, print) {
@@ -540,6 +476,194 @@ function buildIndexSignatures(node, propertyCount, print) {
540
476
  }
541
477
  return elements;
542
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
543
667
  /**
544
668
  * TypeScript type printer built with `definePrinter`.
545
669
  *
@@ -583,6 +707,8 @@ const printerTs = definePrinter((options) => {
583
707
  if (node.path) return createUrlTemplateType(node.path);
584
708
  return keywordTypeNodes.string;
585
709
  },
710
+ ipv4: () => keywordTypeNodes.string,
711
+ ipv6: () => keywordTypeNodes.string,
586
712
  datetime: () => keywordTypeNodes.string,
587
713
  number: () => keywordTypeNodes.number,
588
714
  integer: () => keywordTypeNodes.number,
@@ -591,14 +717,14 @@ const printerTs = definePrinter((options) => {
591
717
  time: dateOrStringNode,
592
718
  ref(node) {
593
719
  if (!node.name) return;
594
- const refName = node.ref ? node.ref.split("/").at(-1) ?? node.name : node.name;
595
- return createTypeReferenceNode(node.ref ? this.options.resolver.default(refName, "type") : refName, void 0);
720
+ const refName = node.ref ? extractRefName(node.ref) ?? node.name : node.name;
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);
596
722
  },
597
723
  enum(node) {
598
724
  const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
599
725
  if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
600
726
  withParentheses: true,
601
- 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)
602
728
  }) ?? void 0;
603
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);
604
730
  },
@@ -644,12 +770,13 @@ const printerTs = definePrinter((options) => {
644
770
  const propertyNodes = node.properties.map((prop) => {
645
771
  const baseType = transform(prop.schema) ?? keywordTypeNodes.unknown;
646
772
  const type = buildPropertyType(prop.schema, baseType, options.optionalType);
773
+ const propMeta = syncSchemaRef(prop.schema);
647
774
  return appendJSDocToNode({
648
775
  node: createPropertySignature({
649
776
  questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
650
777
  name: prop.name,
651
778
  type,
652
- readOnly: prop.schema.readOnly
779
+ readOnly: propMeta?.readOnly
653
780
  }),
654
781
  comments: buildPropertyJSDocComments(prop.schema)
655
782
  });
@@ -660,39 +787,39 @@ const printerTs = definePrinter((options) => {
660
787
  }
661
788
  },
662
789
  print(node) {
663
- let type = this.transform(node);
664
- if (!type) return null;
665
- if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
666
- if ((node.nullish || node.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
667
790
  const { name, syntaxType = "type", description, keysToOmit } = this.options;
668
- if (!name) return safePrint(type);
669
- 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;
670
807
  return safePrint(createTypeDeclaration({
671
808
  name,
672
809
  isExportable: true,
673
- type: keysToOmit?.length ? createOmitDeclaration({
674
- keys: keysToOmit,
675
- type,
676
- nonNullable: true
677
- }) : type,
810
+ type: inner,
678
811
  syntax: useTypeGeneration ? "type" : "interface",
679
- comments: [
680
- node?.title ? jsStringEscape(node.title) : void 0,
681
- description ? `@description ${jsStringEscape(description)}` : void 0,
682
- node?.deprecated ? "@deprecated" : void 0,
683
- node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
684
- node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
685
- node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
686
- node?.default ? `@default ${node.default}` : void 0,
687
- node?.example ? `@example ${node.example}` : void 0
688
- ]
812
+ comments: buildPropertyJSDocComments({
813
+ ...meta,
814
+ description
815
+ })
689
816
  }));
690
817
  }
691
818
  };
692
819
  });
693
820
  //#endregion
694
821
  //#region src/components/Type.tsx
695
- function Type({ name, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumTypeSuffix, enumKeyCasing, description, resolver }) {
822
+ function Type({ name, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumTypeSuffix, enumKeyCasing, description, resolver, enumSchemaNames }) {
696
823
  const resolvedDescription = description || node?.description;
697
824
  const enumSchemaNodes = collect(node, { schema(n) {
698
825
  const enumNode = narrowSchema(n, schemaTypes.enum);
@@ -707,7 +834,8 @@ function Type({ name, node, keysToOmit, optionalType, arrayType, syntaxType, enu
707
834
  syntaxType,
708
835
  description: resolvedDescription,
709
836
  keysToOmit,
710
- resolver
837
+ resolver,
838
+ enumSchemaNames
711
839
  }).print(node);
712
840
  if (!output) return;
713
841
  const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((node) => {
@@ -731,144 +859,111 @@ function Type({ name, node, keysToOmit, optionalType, arrayType, syntaxType, enu
731
859
  resolver
732
860
  })), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
733
861
  name,
734
- isTypeOnly: true,
735
- isExportable: true,
736
- isIndexable: true,
737
- children: output
738
- })] });
739
- }
740
- //#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)
832
- })
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
- });
862
+ isTypeOnly: true,
863
+ isExportable: true,
864
+ isIndexable: true,
865
+ children: output
866
+ })] });
846
867
  }
847
868
  //#endregion
848
869
  //#region src/generators/typeGenerator.tsx
849
870
  const typeGenerator = defineGenerator({
850
871
  name: "typescript",
851
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
905
+ })
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);
867
- function renderSchemaType({ node: schemaNode, name, description, keysToOmit }) {
868
- if (!schemaNode) return null;
869
- const transformedNode = transform(schemaNode, composeTransformers(...transformers));
870
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
871
- name: resolver.default(schemaName, "type"),
957
+ }) };
958
+ const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name));
959
+ function resolveImportName(schemaName) {
960
+ if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
961
+ return resolver.default(schemaName, "type");
962
+ }
963
+ function renderSchemaType({ schema, name, keysToOmit }) {
964
+ if (!schema) return null;
965
+ const imports = adapter.getImports(schema, (schemaName) => ({
966
+ name: resolveImportName(schemaName),
872
967
  path: resolver.resolveFile({
873
968
  name: schemaName,
874
969
  extname: ".ts"
@@ -879,7 +974,7 @@ const typeGenerator = defineGenerator({
879
974
  }).path
880
975
  }));
881
976
  return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
882
- root: file.path,
977
+ root: meta.file.path,
883
978
  path: imp.path,
884
979
  name: imp.name,
885
980
  isTypeOnly: true
@@ -889,8 +984,7 @@ const typeGenerator = defineGenerator({
889
984
  imp.isTypeOnly
890
985
  ].join("-"))), /* @__PURE__ */ jsx(Type, {
891
986
  name,
892
- node: transformedNode,
893
- description,
987
+ node: schema,
894
988
  enumType,
895
989
  enumTypeSuffix,
896
990
  enumKeyCasing,
@@ -898,54 +992,49 @@ const typeGenerator = defineGenerator({
898
992
  arrayType,
899
993
  syntaxType,
900
994
  resolver,
901
- keysToOmit
995
+ keysToOmit,
996
+ enumSchemaNames
902
997
  })] });
903
998
  }
904
999
  const paramTypes = params.map((param) => renderSchemaType({
905
- node: param.schema,
906
- name: resolver.resolveParamName(node, param)
1000
+ schema: param.schema,
1001
+ name: resolver.resolveParamName(transformedNode, param)
907
1002
  }));
908
- const requestType = node.requestBody?.schema ? renderSchemaType({
909
- node: node.requestBody.schema,
910
- name: resolver.resolveDataName(node),
911
- description: node.requestBody.description ?? node.requestBody.schema.description,
912
- 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
913
1010
  }) : null;
914
- const responseTypes = node.responses.map((res) => renderSchemaType({
915
- node: res.schema,
916
- name: resolver.resolveResponseStatusName(node, res.statusCode),
917
- description: res.description,
1011
+ const responseTypes = transformedNode.responses.map((res) => renderSchemaType({
1012
+ schema: res.schema,
1013
+ name: resolver.resolveResponseStatusName(transformedNode, res.statusCode),
918
1014
  keysToOmit: res.keysToOmit
919
1015
  }));
920
1016
  const dataType = renderSchemaType({
921
- node: buildData({
922
- node: {
923
- ...node,
924
- parameters: params
925
- },
926
- resolver
927
- }),
928
- name: resolver.resolveRequestConfigName(node)
1017
+ schema: buildData({
1018
+ ...transformedNode,
1019
+ parameters: params
1020
+ }, { resolver }),
1021
+ name: resolver.resolveRequestConfigName(transformedNode)
929
1022
  });
930
1023
  const responsesType = renderSchemaType({
931
- node: buildResponses({
932
- node,
933
- resolver
934
- }),
935
- name: resolver.resolveResponsesName(node)
1024
+ schema: buildResponses(transformedNode, { resolver }),
1025
+ name: resolver.resolveResponsesName(transformedNode)
936
1026
  });
937
1027
  const responseType = renderSchemaType({
938
- node: buildResponseUnion({
939
- node,
940
- resolver
941
- }),
942
- name: resolver.resolveResponseName(node),
943
- 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)
944
1033
  });
945
1034
  return /* @__PURE__ */ jsxs(File, {
946
- baseName: file.baseName,
947
- path: file.path,
948
- meta: file.meta,
1035
+ baseName: meta.file.baseName,
1036
+ path: meta.file.path,
1037
+ meta: meta.file.meta,
949
1038
  banner: resolver.resolveBanner(adapter.rootNode, {
950
1039
  output,
951
1040
  config
@@ -963,74 +1052,11 @@ const typeGenerator = defineGenerator({
963
1052
  responseType
964
1053
  ]
965
1054
  });
966
- },
967
- Schema({ node, adapter, options, config, resolver }) {
968
- const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
969
- const root = path.resolve(config.root, config.output.path);
970
- const mode = getMode(path.resolve(root, output.path));
971
- if (!node.name) return;
972
- const transformedNode = transform(node, composeTransformers(...transformers));
973
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
974
- name: resolver.default(schemaName, "type"),
975
- path: resolver.resolveFile({
976
- name: schemaName,
977
- extname: ".ts"
978
- }, {
979
- root,
980
- output,
981
- group
982
- }).path
983
- }));
984
- const isEnumSchema = !!narrowSchema(node, schemaTypes.enum);
985
- const type = {
986
- name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
987
- file: resolver.resolveFile({
988
- name: node.name,
989
- extname: ".ts"
990
- }, {
991
- root,
992
- output,
993
- group
994
- })
995
- };
996
- return /* @__PURE__ */ jsxs(File, {
997
- baseName: type.file.baseName,
998
- path: type.file.path,
999
- meta: type.file.meta,
1000
- banner: resolver.resolveBanner(adapter.rootNode, {
1001
- output,
1002
- config
1003
- }),
1004
- footer: resolver.resolveFooter(adapter.rootNode, {
1005
- output,
1006
- config
1007
- }),
1008
- children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1009
- root: type.file.path,
1010
- path: imp.path,
1011
- name: imp.name,
1012
- isTypeOnly: true
1013
- }, [
1014
- node.name,
1015
- imp.path,
1016
- imp.isTypeOnly
1017
- ].join("-"))), /* @__PURE__ */ jsx(Type, {
1018
- name: type.name,
1019
- node: transformedNode,
1020
- enumType,
1021
- enumTypeSuffix,
1022
- enumKeyCasing,
1023
- optionalType,
1024
- arrayType,
1025
- syntaxType,
1026
- resolver
1027
- })]
1028
- });
1029
1055
  }
1030
1056
  });
1031
1057
  //#endregion
1032
1058
  //#region src/resolvers/resolverTs.ts
1033
- function resolveName(name, type) {
1059
+ function toTypeName(name, type) {
1034
1060
  return pascalCase(name, { isFile: type === "file" });
1035
1061
  }
1036
1062
  /**
@@ -1055,7 +1081,7 @@ const resolverTs = defineResolver(() => {
1055
1081
  name: "default",
1056
1082
  pluginName: "plugin-ts",
1057
1083
  default(name, type) {
1058
- return resolveName(name, type);
1084
+ return toTypeName(name, type);
1059
1085
  },
1060
1086
  resolveName(name) {
1061
1087
  return this.default(name, "function");
@@ -1174,7 +1200,7 @@ function buildGroupedParamsSchema({ params, parentName }) {
1174
1200
  })
1175
1201
  });
1176
1202
  }
1177
- function buildLegacyResponsesSchemaNode({ node, resolver }) {
1203
+ function buildLegacyResponsesSchemaNode(node, { resolver }) {
1178
1204
  const isGet = node.method.toLowerCase() === "get";
1179
1205
  const successResponses = node.responses.filter((res) => {
1180
1206
  const code = Number(res.statusCode);
@@ -1190,7 +1216,10 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
1190
1216
  type: "ref",
1191
1217
  name: resolver.resolveResponseStatusName(node, res.statusCode)
1192
1218
  }))
1193
- }) : createSchema({ type: "any" });
1219
+ }) : createSchema({
1220
+ type: "any",
1221
+ primitive: void 0
1222
+ });
1194
1223
  const errorsSchema = errorResponses.length > 0 ? errorResponses.length === 1 ? createSchema({
1195
1224
  type: "ref",
1196
1225
  name: resolver.resolveResponseStatusName(node, errorResponses[0].statusCode)
@@ -1200,7 +1229,10 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
1200
1229
  type: "ref",
1201
1230
  name: resolver.resolveResponseStatusName(node, res.statusCode)
1202
1231
  }))
1203
- }) : createSchema({ type: "any" });
1232
+ }) : createSchema({
1233
+ type: "any",
1234
+ primitive: void 0
1235
+ });
1204
1236
  const properties = [createProperty({
1205
1237
  name: "Response",
1206
1238
  required: true,
@@ -1251,12 +1283,15 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
1251
1283
  properties
1252
1284
  });
1253
1285
  }
1254
- function buildLegacyResponseUnionSchemaNode({ node, resolver }) {
1286
+ function buildLegacyResponseUnionSchemaNode(node, { resolver }) {
1255
1287
  const successResponses = node.responses.filter((res) => {
1256
1288
  const code = Number(res.statusCode);
1257
1289
  return !Number.isNaN(code) && code >= 200 && code < 300;
1258
1290
  });
1259
- if (successResponses.length === 0) return createSchema({ type: "any" });
1291
+ if (successResponses.length === 0) return createSchema({
1292
+ type: "any",
1293
+ primitive: void 0
1294
+ });
1260
1295
  if (successResponses.length === 1) return createSchema({
1261
1296
  type: "ref",
1262
1297
  name: resolver.resolveResponseStatusName(node, successResponses[0].statusCode)
@@ -1297,25 +1332,88 @@ function nameUnnamedEnums(node, parentName) {
1297
1332
  const typeGeneratorLegacy = defineGenerator({
1298
1333
  name: "typescript-legacy",
1299
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
+ },
1300
1398
  Operation({ node, adapter, options, config, resolver }) {
1301
1399
  const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options;
1400
+ const transformedNode = transform(node, composeTransformers(...transformers));
1302
1401
  const root = path.resolve(config.root, config.output.path);
1303
1402
  const mode = getMode(path.resolve(root, output.path));
1304
- const file = resolver.resolveFile({
1305
- name: node.operationId,
1403
+ const params = caseParams(node.parameters, paramsCasing);
1404
+ const meta = { file: resolver.resolveFile({
1405
+ name: transformedNode.operationId,
1306
1406
  extname: ".ts",
1307
- tag: node.tags[0] ?? "default",
1308
- path: node.path
1407
+ tag: transformedNode.tags[0] ?? "default",
1408
+ path: transformedNode.path
1309
1409
  }, {
1310
1410
  root,
1311
1411
  output,
1312
1412
  group
1313
- });
1314
- const params = caseParams(node.parameters, paramsCasing);
1315
- function renderSchemaType({ node: schemaNode, name, description, keysToOmit }) {
1316
- if (!schemaNode) return null;
1317
- const transformedNode = transform(schemaNode, composeTransformers(...transformers));
1318
- 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) => ({
1319
1417
  name: resolver.default(schemaName, "type"),
1320
1418
  path: resolver.resolveFile({
1321
1419
  name: schemaName,
@@ -1327,7 +1425,7 @@ const typeGeneratorLegacy = defineGenerator({
1327
1425
  }).path
1328
1426
  }));
1329
1427
  return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1330
- root: file.path,
1428
+ root: meta.file.path,
1331
1429
  path: imp.path,
1332
1430
  name: imp.name,
1333
1431
  isTypeOnly: true
@@ -1337,7 +1435,7 @@ const typeGeneratorLegacy = defineGenerator({
1337
1435
  imp.isTypeOnly
1338
1436
  ].join("-"))), /* @__PURE__ */ jsx(Type, {
1339
1437
  name,
1340
- node: transformedNode,
1438
+ node: schema,
1341
1439
  description,
1342
1440
  enumType,
1343
1441
  enumTypeSuffix,
@@ -1356,35 +1454,35 @@ const typeGeneratorLegacy = defineGenerator({
1356
1454
  const responseName = resolver.resolveResponseStatusName(node, res.statusCode);
1357
1455
  const baseResponseName = resolverTsLegacy.resolveResponseStatusName(node, res.statusCode);
1358
1456
  return renderSchemaType({
1359
- node: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
1457
+ schema: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
1360
1458
  name: responseName,
1361
1459
  description: res.description,
1362
1460
  keysToOmit: res.keysToOmit
1363
1461
  });
1364
1462
  });
1365
1463
  const requestType = node.requestBody?.schema ? renderSchemaType({
1366
- node: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
1464
+ schema: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
1367
1465
  name: resolver.resolveDataName(node),
1368
1466
  description: node.requestBody.description ?? node.requestBody.schema.description,
1369
1467
  keysToOmit: node.requestBody.keysToOmit
1370
1468
  }) : null;
1371
1469
  const legacyParamTypes = [
1372
1470
  pathParams.length > 0 ? renderSchemaType({
1373
- node: buildGroupedParamsSchema({
1471
+ schema: buildGroupedParamsSchema({
1374
1472
  params: pathParams,
1375
1473
  parentName: resolverTsLegacy.resolvePathParamsName(node, pathParams[0])
1376
1474
  }),
1377
1475
  name: resolver.resolvePathParamsName(node, pathParams[0])
1378
1476
  }) : null,
1379
1477
  queryParams.length > 0 ? renderSchemaType({
1380
- node: buildGroupedParamsSchema({
1478
+ schema: buildGroupedParamsSchema({
1381
1479
  params: queryParams,
1382
1480
  parentName: resolverTsLegacy.resolveQueryParamsName(node, queryParams[0])
1383
1481
  }),
1384
1482
  name: resolver.resolveQueryParamsName(node, queryParams[0])
1385
1483
  }) : null,
1386
1484
  headerParams.length > 0 ? renderSchemaType({
1387
- node: buildGroupedParamsSchema({
1485
+ schema: buildGroupedParamsSchema({
1388
1486
  params: headerParams,
1389
1487
  parentName: resolverTsLegacy.resolveHeaderParamsName(node, headerParams[0])
1390
1488
  }),
@@ -1392,23 +1490,17 @@ const typeGeneratorLegacy = defineGenerator({
1392
1490
  }) : null
1393
1491
  ];
1394
1492
  const legacyResponsesType = renderSchemaType({
1395
- node: buildLegacyResponsesSchemaNode({
1396
- node,
1397
- resolver
1398
- }),
1493
+ schema: buildLegacyResponsesSchemaNode(node, { resolver }),
1399
1494
  name: resolver.resolveResponsesName(node)
1400
1495
  });
1401
1496
  const legacyResponseType = renderSchemaType({
1402
- node: buildLegacyResponseUnionSchemaNode({
1403
- node,
1404
- resolver
1405
- }),
1497
+ schema: buildLegacyResponseUnionSchemaNode(node, { resolver }),
1406
1498
  name: resolver.resolveResponseName(node)
1407
1499
  });
1408
1500
  return /* @__PURE__ */ jsxs(File, {
1409
- baseName: file.baseName,
1410
- path: file.path,
1411
- meta: file.meta,
1501
+ baseName: meta.file.baseName,
1502
+ path: meta.file.path,
1503
+ meta: meta.file.meta,
1412
1504
  banner: resolver.resolveBanner(adapter.rootNode, {
1413
1505
  output,
1414
1506
  config
@@ -1425,69 +1517,6 @@ const typeGeneratorLegacy = defineGenerator({
1425
1517
  legacyResponsesType
1426
1518
  ]
1427
1519
  });
1428
- },
1429
- Schema({ node, adapter, options, config, resolver }) {
1430
- const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
1431
- const root = path.resolve(config.root, config.output.path);
1432
- const mode = getMode(path.resolve(root, output.path));
1433
- if (!node.name) return;
1434
- const transformedNode = transform(node, composeTransformers(...transformers));
1435
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
1436
- name: resolver.default(schemaName, "type"),
1437
- path: resolver.resolveFile({
1438
- name: schemaName,
1439
- extname: ".ts"
1440
- }, {
1441
- root,
1442
- output,
1443
- group
1444
- }).path
1445
- }));
1446
- const isEnumSchema = !!narrowSchema(node, schemaTypes.enum);
1447
- const type = {
1448
- name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
1449
- file: resolver.resolveFile({
1450
- name: node.name,
1451
- extname: ".ts"
1452
- }, {
1453
- root,
1454
- output,
1455
- group
1456
- })
1457
- };
1458
- return /* @__PURE__ */ jsxs(File, {
1459
- baseName: type.file.baseName,
1460
- path: type.file.path,
1461
- meta: type.file.meta,
1462
- banner: resolver.resolveBanner(adapter.rootNode, {
1463
- output,
1464
- config
1465
- }),
1466
- footer: resolver.resolveFooter(adapter.rootNode, {
1467
- output,
1468
- config
1469
- }),
1470
- children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1471
- root: type.file.path,
1472
- path: imp.path,
1473
- name: imp.name,
1474
- isTypeOnly: true
1475
- }, [
1476
- node.name,
1477
- imp.path,
1478
- imp.isTypeOnly
1479
- ].join("-"))), /* @__PURE__ */ jsx(Type, {
1480
- name: type.name,
1481
- node: transformedNode,
1482
- enumType,
1483
- enumTypeSuffix,
1484
- enumKeyCasing,
1485
- optionalType,
1486
- arrayType,
1487
- syntaxType,
1488
- resolver
1489
- })]
1490
- });
1491
1520
  }
1492
1521
  });
1493
1522
  //#endregion
@@ -1556,9 +1585,9 @@ const pluginTs = createPlugin((options) => {
1556
1585
  output,
1557
1586
  optionalType,
1558
1587
  group: group ? {
1559
- ...options.group,
1588
+ ...group,
1560
1589
  name: (ctx) => {
1561
- if (options.group?.type === "path") return `${ctx.group.split("/")[1]}`;
1590
+ if (group.type === "path") return `${ctx.group.split("/")[1]}`;
1562
1591
  return `${camelCase(ctx.group)}Controller`;
1563
1592
  }
1564
1593
  } : void 0,
@@ -1597,59 +1626,37 @@ const pluginTs = createPlugin((options) => {
1597
1626
  async install() {
1598
1627
  const { config, fabric, plugin, adapter, rootNode, driver, openInStudio, resolver } = this;
1599
1628
  const root = path.resolve(config.root, config.output.path);
1600
- 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.`);
1601
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
+ };
1602
1644
  await walk(rootNode, {
1603
1645
  depth: "shallow",
1604
1646
  async schema(schemaNode) {
1605
- const writeTasks = preset.generators.map(async (generator) => {
1606
- if (generator.type === "react" && generator.version === "2") {
1607
- const options = resolver.resolveOptions(schemaNode, {
1608
- options: plugin.options,
1609
- exclude,
1610
- include,
1611
- override
1612
- });
1613
- if (options === null) return;
1614
- await renderSchema(schemaNode, {
1615
- options,
1616
- resolver,
1617
- adapter,
1618
- config,
1619
- fabric,
1620
- Component: generator.Schema,
1621
- plugin,
1622
- driver
1623
- });
1624
- }
1625
- });
1626
- await Promise.all(writeTasks);
1647
+ await runGeneratorSchema(schemaNode, generatorContext);
1627
1648
  },
1628
1649
  async operation(operationNode) {
1629
- const writeTasks = preset.generators.map(async (generator) => {
1630
- if (generator.type === "react" && generator.version === "2") {
1631
- const options = resolver.resolveOptions(operationNode, {
1632
- options: plugin.options,
1633
- exclude,
1634
- include,
1635
- override
1636
- });
1637
- if (options === null) return;
1638
- await renderOperation(operationNode, {
1639
- options,
1640
- resolver,
1641
- adapter,
1642
- config,
1643
- fabric,
1644
- Component: generator.Operation,
1645
- plugin,
1646
- driver
1647
- });
1648
- }
1649
- });
1650
- 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);
1651
1657
  }
1652
1658
  });
1659
+ await runGeneratorOperations(collectedOperations, generatorContext);
1653
1660
  const barrelFiles = await getBarrelFiles(this.fabric.files, {
1654
1661
  type: output.barrelType ?? "named",
1655
1662
  root,
@@ -1677,12 +1684,12 @@ const kindToHandlerKey = {
1677
1684
  const defineFunctionPrinter = createPrinterFactory((node) => kindToHandlerKey[node.kind]);
1678
1685
  function rank(param) {
1679
1686
  if (param.kind === "ParameterGroup") {
1680
- if (param.default) return 2;
1681
- 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;
1682
1689
  }
1683
- if (param.rest) return 3;
1684
- if (param.default) return 2;
1685
- 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;
1686
1693
  }
1687
1694
  function sortParams(params) {
1688
1695
  return [...params].sort((a, b) => rank(a) - rank(b));