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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import { A as keywordTypeNodes, C as createTypeDeclaration, D as createUnionDeclaration, E as createTypeReferenceNode, F as camelCase, I as pascalCase, M as syntaxKind, N as jsStringEscape, O as createUrlTemplateType, P as trimQuotes, S as createTypeAliasDeclaration, T as createTypeOperatorNode, _ as createPropertySignature, a as createArrayTypeNode, b as createTrue, c as createIdentifier, d as createIntersectionDeclaration, f as createLiteralTypeNode, g as createPrefixUnaryExpression, h as createOptionalTypeNode, i as createArrayDeclaration, j as modifiers, k as getUnknownType, l as createIndexSignature, m as createOmitDeclaration, n as SyntaxKind, o as createEnumDeclaration, p as createNumericLiteral, r as appendJSDocToNode, s as createFalse, t as Type$1, u as createIndexedAccessTypeNode, v as createRestTypeNode, w as createTypeLiteralNode, x as createTupleTypeNode, y as createStringLiteral } from "./components-CRjwjdyE.js";
2
+ import { A as keywordTypeNodes, C as createTypeDeclaration, D as createUnionDeclaration, E as createTypeReferenceNode, F as camelCase, I as pascalCase, M as syntaxKind, N as jsStringEscape, O as createUrlTemplateType, P as trimQuotes, S as createTypeAliasDeclaration, T as createTypeOperatorNode, _ as createPropertySignature, a as createArrayTypeNode, b as createTrue, c as createIdentifier, d as createIntersectionDeclaration, f as createLiteralTypeNode, g as createPrefixUnaryExpression, h as createOptionalTypeNode, i as createArrayDeclaration, j as modifiers, k as getUnknownType, l as createIndexSignature, m as createOmitDeclaration, n as SyntaxKind, o as createEnumDeclaration, p as createNumericLiteral, r as appendJSDocToNode, s as createFalse, t as Type$1, u as createIndexedAccessTypeNode, v as createRestTypeNode, w as createTypeLiteralNode, x as createTupleTypeNode, y as createStringLiteral } from "./components-Cwn1rflQ.js";
3
3
  import path from "node:path";
4
- import { collect, isPlainStringType, walk } from "@kubb/ast";
5
- import { definePlugin, definePrinter, getBarrelFiles, getMode } from "@kubb/core";
4
+ import { applyParamsCasing, collect, createProperty, createSchema, isPlainStringType, walk } from "@kubb/ast";
5
+ import { defineGenerator, definePlugin, definePrinter, getBarrelFiles, getMode, resolveOptions } from "@kubb/core";
6
6
  import { OperationGenerator, SchemaGenerator, buildOperation, buildSchema, isKeyword, pluginOasName, schemaKeywords } from "@kubb/plugin-oas";
7
7
  import { useKubb, useMode, usePluginManager } from "@kubb/core/hooks";
8
8
  import { safePrint } from "@kubb/fabric-core/parsers/typescript";
9
9
  import { createReactGenerator } from "@kubb/plugin-oas/generators";
10
10
  import { useOas, useOperationManager, useSchemaManager } from "@kubb/plugin-oas/hooks";
11
- import { applyParamsCasing, getBanner, getFooter, getImports, isParameterSchema } from "@kubb/plugin-oas/utils";
11
+ import { applyParamsCasing as applyParamsCasing$1, getBanner, getFooter, getImports, isParameterSchema } from "@kubb/plugin-oas/utils";
12
12
  import { File } from "@kubb/react-fabric";
13
13
  import ts from "typescript";
14
14
  import { Fragment, jsx, jsxs } from "@kubb/react-fabric/jsx-runtime";
@@ -201,7 +201,6 @@ function printResponseSchema({ baseName, schemas, pluginManager, unknownType })
201
201
  }
202
202
  const typeGenerator$1 = createReactGenerator({
203
203
  name: "typescript",
204
- version: "1",
205
204
  Operation({ operation, generator, plugin }) {
206
205
  const { options, options: { mapper, enumType, enumKeyCasing, syntaxType, optionalType, arrayType, unknownType, paramsCasing } } = plugin;
207
206
  const mode = useMode();
@@ -233,7 +232,7 @@ const typeGenerator$1 = createReactGenerator({
233
232
  schemas.response
234
233
  ].flat().filter(Boolean);
235
234
  const mapOperationSchema = ({ name, schema, description, keysToOmit, ...options }) => {
236
- const transformedSchema = paramsCasing && isParameterSchema(name) ? applyParamsCasing(schema, paramsCasing) : schema;
235
+ const transformedSchema = paramsCasing && isParameterSchema(name) ? applyParamsCasing$1(schema, paramsCasing) : schema;
237
236
  const tree = schemaGenerator.parse({
238
237
  schema: transformedSchema,
239
238
  name,
@@ -451,13 +450,17 @@ const printerTs = definePrinter((options) => ({
451
450
  any: () => keywordTypeNodes.any,
452
451
  unknown: () => keywordTypeNodes.unknown,
453
452
  void: () => keywordTypeNodes.void,
453
+ never: () => keywordTypeNodes.never,
454
454
  boolean: () => keywordTypeNodes.boolean,
455
455
  null: () => keywordTypeNodes.null,
456
456
  blob: () => createTypeReferenceNode("Blob", []),
457
457
  string: () => keywordTypeNodes.string,
458
458
  uuid: () => keywordTypeNodes.string,
459
459
  email: () => keywordTypeNodes.string,
460
- url: () => keywordTypeNodes.string,
460
+ url: (node) => {
461
+ if (node.path) return createUrlTemplateType(node.path);
462
+ return keywordTypeNodes.string;
463
+ },
461
464
  datetime: () => keywordTypeNodes.string,
462
465
  number: () => keywordTypeNodes.number,
463
466
  integer: () => keywordTypeNodes.number,
@@ -514,6 +517,7 @@ const printerTs = definePrinter((options) => ({
514
517
  const addsQuestionToken = ["questionToken", "questionTokenAndUndefined"].includes(this.options.optionalType);
515
518
  const { print } = this;
516
519
  const propertyNodes = node.properties.map((prop) => {
520
+ if (this.options.mapper && Object.hasOwn(this.options.mapper, prop.name)) return this.options.mapper[prop.name];
517
521
  const baseType = print(prop.schema) ?? keywordTypeNodes.unknown;
518
522
  const type = buildPropertyType(prop.schema, baseType, this.options.optionalType);
519
523
  return appendJSDocToNode({
@@ -534,7 +538,7 @@ const printerTs = definePrinter((options) => ({
534
538
  }));
535
539
  //#endregion
536
540
  //#region src/components/v2/Type.tsx
537
- function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumKeyCasing, ...rest }) {
541
+ function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumKeyCasing, mapper, ...rest }) {
538
542
  const typeNodes = [];
539
543
  const description = rest.description || node?.description;
540
544
  const enumSchemaNodes = collect(node, { schema(n) {
@@ -543,7 +547,8 @@ function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, synt
543
547
  let type = printerTs({
544
548
  optionalType,
545
549
  arrayType,
546
- enumType
550
+ enumType,
551
+ mapper
547
552
  }).print(node);
548
553
  if (!type) return;
549
554
  if (["asConst", "asPascalConst"].includes(enumType) && enumSchemaNodes.length > 0) {
@@ -633,29 +638,175 @@ function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, synt
633
638
  })] });
634
639
  }
635
640
  //#endregion
641
+ //#region src/generators/v2/utils.ts
642
+ /**
643
+ * Builds an `ObjectSchemaNode` for a group of parameters (path/query/header).
644
+ * Each property is a `ref` schema pointing to the individually-resolved parameter type.
645
+ */
646
+ function buildParamsSchema({ params, operationId, resolveName }) {
647
+ return createSchema({
648
+ type: "object",
649
+ properties: params.map((param) => createProperty({
650
+ name: param.name,
651
+ schema: createSchema({
652
+ type: "ref",
653
+ name: resolveName({
654
+ name: `${operationId} ${param.name}`,
655
+ type: "function"
656
+ }),
657
+ optional: !param.required
658
+ })
659
+ }))
660
+ });
661
+ }
662
+ /**
663
+ * Builds an `ObjectSchemaNode` representing the `<OperationId>Data` type:
664
+ * - `data` → request body ref (optional) or `never`
665
+ * - `pathParams` → inline object of path param refs, or `never`
666
+ * - `queryParams` → inline object of query param refs (optional), or `never`
667
+ * - `headerParams` → inline object of header param refs (optional), or `never`
668
+ * - `url` → Express-style template literal (plugin-ts extension, handled by printer)
669
+ */
670
+ function buildDataSchemaNode({ node, resolveName }) {
671
+ const pathParams = node.parameters.filter((p) => p.in === "path");
672
+ const queryParams = node.parameters.filter((p) => p.in === "query");
673
+ const headerParams = node.parameters.filter((p) => p.in === "header");
674
+ return createSchema({
675
+ type: "object",
676
+ properties: [
677
+ createProperty({
678
+ name: "data",
679
+ schema: node.requestBody ? createSchema({
680
+ type: "ref",
681
+ name: resolveName({
682
+ name: `${node.operationId} MutationRequest`,
683
+ type: "function"
684
+ }),
685
+ optional: true
686
+ }) : createSchema({
687
+ type: "never",
688
+ optional: true
689
+ })
690
+ }),
691
+ createProperty({
692
+ name: "pathParams",
693
+ schema: pathParams.length > 0 ? buildParamsSchema({
694
+ params: pathParams,
695
+ operationId: node.operationId,
696
+ resolveName
697
+ }) : createSchema({
698
+ type: "never",
699
+ optional: true
700
+ })
701
+ }),
702
+ createProperty({
703
+ name: "queryParams",
704
+ schema: queryParams.length > 0 ? createSchema({
705
+ ...buildParamsSchema({
706
+ params: queryParams,
707
+ operationId: node.operationId,
708
+ resolveName
709
+ }),
710
+ optional: true
711
+ }) : createSchema({
712
+ type: "never",
713
+ optional: true
714
+ })
715
+ }),
716
+ createProperty({
717
+ name: "headerParams",
718
+ schema: headerParams.length > 0 ? createSchema({
719
+ ...buildParamsSchema({
720
+ params: headerParams,
721
+ operationId: node.operationId,
722
+ resolveName
723
+ }),
724
+ optional: true
725
+ }) : createSchema({
726
+ type: "never",
727
+ optional: true
728
+ })
729
+ }),
730
+ createProperty({
731
+ name: "url",
732
+ schema: createSchema({
733
+ type: "url",
734
+ path: node.path
735
+ })
736
+ })
737
+ ]
738
+ });
739
+ }
740
+ /**
741
+ * Builds an `ObjectSchemaNode` representing `<OperationId>Responses` — keyed by HTTP status code.
742
+ *
743
+ * Example output:
744
+ * ```ts
745
+ * export type PlaceOrderPatchResponses = { 200: PlaceOrderPatch200; 405: PlaceOrderPatch405 }
746
+ * ```
747
+ */
748
+ function buildResponsesSchemaNode({ node, resolveName }) {
749
+ const responsesWithSchema = node.responses.filter((res) => res.schema);
750
+ if (responsesWithSchema.length === 0) return null;
751
+ return createSchema({
752
+ type: "object",
753
+ properties: responsesWithSchema.map((res) => createProperty({
754
+ name: String(res.statusCode),
755
+ schema: createSchema({
756
+ type: "ref",
757
+ name: resolveName({
758
+ name: `${node.operationId} ${res.statusCode}`,
759
+ type: "function"
760
+ })
761
+ })
762
+ }))
763
+ });
764
+ }
765
+ /**
766
+ * Builds a `UnionSchemaNode` representing `<OperationId>Response` — all response types in union format.
767
+ *
768
+ * Example output:
769
+ * ```ts
770
+ * export type PlaceOrderPatchResponse = PlaceOrderPatch200 | PlaceOrderPatch405
771
+ * ```
772
+ */
773
+ function buildResponseUnionSchemaNode({ node, resolveName }) {
774
+ const responsesWithSchema = node.responses.filter((res) => res.schema);
775
+ if (responsesWithSchema.length === 0) return null;
776
+ return createSchema({
777
+ type: "union",
778
+ members: responsesWithSchema.map((res) => createSchema({
779
+ type: "ref",
780
+ name: resolveName({
781
+ name: `${node.operationId} ${res.statusCode}`,
782
+ type: "function"
783
+ })
784
+ }))
785
+ });
786
+ }
787
+ //#endregion
636
788
  //#region src/generators/v2/typeGenerator.tsx
637
- const typeGenerator = createReactGenerator({
789
+ const typeGenerator = defineGenerator({
638
790
  name: "typescript",
639
- version: "2",
791
+ type: "react",
640
792
  Operation({ node, adapter, options }) {
641
- const { enumType, enumKeyCasing, optionalType, arrayType, syntaxType } = options;
642
- const { plugin, mode, getFile, resolveName } = useKubb();
793
+ const { enumType, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, mapper } = options;
794
+ const { mode, getFile, resolveName } = useKubb();
643
795
  const file = getFile({
644
796
  name: node.operationId,
645
- pluginName: plugin.name,
646
797
  extname: ".ts",
647
798
  mode
648
799
  });
800
+ const params = applyParamsCasing(node.parameters, paramsCasing);
649
801
  function renderSchemaType({ node: schemaNode, name, typedName, description }) {
802
+ if (!schemaNode) return null;
650
803
  const imports = adapter.getImports(schemaNode, (schemaName) => ({
651
804
  name: resolveName({
652
805
  name: schemaName,
653
- pluginName: plugin.name,
654
806
  type: "type"
655
807
  }),
656
808
  path: getFile({
657
809
  name: schemaName,
658
- pluginName: plugin.name,
659
810
  extname: ".ts",
660
811
  mode
661
812
  }).path
@@ -678,63 +829,90 @@ const typeGenerator = createReactGenerator({
678
829
  enumKeyCasing,
679
830
  optionalType,
680
831
  arrayType,
681
- syntaxType
832
+ syntaxType,
833
+ mapper
682
834
  })] });
683
835
  }
684
- const paramTypes = node.parameters.map((param) => {
685
- const name = resolveName({
836
+ const paramTypes = params.map((param) => renderSchemaType({
837
+ node: param.schema,
838
+ name: resolveName({
686
839
  name: `${node.operationId} ${param.name}`,
687
- pluginName: plugin.name,
688
840
  type: "function"
689
- });
690
- const typedName = resolveName({
841
+ }),
842
+ typedName: resolveName({
691
843
  name: `${node.operationId} ${param.name}`,
692
- pluginName: plugin.name,
693
844
  type: "type"
694
- });
695
- return renderSchemaType({
696
- node: param.schema,
697
- name,
698
- typedName
699
- });
845
+ })
846
+ }));
847
+ const responseTypes = node.responses.filter((res) => res.schema).map((res) => renderSchemaType({
848
+ node: res.schema,
849
+ name: resolveName({
850
+ name: `${node.operationId} ${res.statusCode}`,
851
+ type: "function"
852
+ }),
853
+ typedName: resolveName({
854
+ name: `${node.operationId} ${res.statusCode}`,
855
+ type: "type"
856
+ }),
857
+ description: res.description
858
+ }));
859
+ const requestType = node.requestBody ? renderSchemaType({
860
+ node: node.requestBody,
861
+ name: resolveName({
862
+ name: `${node.operationId} MutationRequest`,
863
+ type: "function"
864
+ }),
865
+ typedName: resolveName({
866
+ name: `${node.operationId} MutationRequest`,
867
+ type: "type"
868
+ }),
869
+ description: node.requestBody.description
870
+ }) : null;
871
+ const dataType = renderSchemaType({
872
+ node: buildDataSchemaNode({
873
+ node: {
874
+ ...node,
875
+ parameters: params
876
+ },
877
+ resolveName
878
+ }),
879
+ name: resolveName({
880
+ name: `${node.operationId} Data`,
881
+ type: "function"
882
+ }),
883
+ typedName: resolveName({
884
+ name: `${node.operationId} Data`,
885
+ type: "type"
886
+ })
700
887
  });
701
- const responseTypes = node.responses.filter((res) => res.schema).map((res) => {
702
- const schemaNode = res.schema;
703
- const responseName = `${node.operationId} ${res.statusCode}`;
704
- return renderSchemaType({
705
- node: schemaNode,
706
- name: resolveName({
707
- name: responseName,
708
- pluginName: plugin.name,
709
- type: "function"
710
- }),
711
- typedName: resolveName({
712
- name: responseName,
713
- pluginName: plugin.name,
714
- type: "type"
715
- }),
716
- description: res.description
717
- });
888
+ const responsesType = renderSchemaType({
889
+ node: buildResponsesSchemaNode({
890
+ node,
891
+ resolveName
892
+ }),
893
+ name: resolveName({
894
+ name: `${node.operationId} Responses`,
895
+ type: "function"
896
+ }),
897
+ typedName: resolveName({
898
+ name: `${node.operationId} Responses`,
899
+ type: "type"
900
+ })
718
901
  });
719
- const requestType = node.requestBody ? (() => {
720
- const requestName = `${node.operationId} MutationRequest`;
721
- const resolvedName = resolveName({
722
- name: requestName,
723
- pluginName: plugin.name,
902
+ const responseType = renderSchemaType({
903
+ node: buildResponseUnionSchemaNode({
904
+ node,
905
+ resolveName
906
+ }),
907
+ name: resolveName({
908
+ name: `${node.operationId} Response`,
724
909
  type: "function"
725
- });
726
- const typedName = resolveName({
727
- name: requestName,
728
- pluginName: plugin.name,
910
+ }),
911
+ typedName: resolveName({
912
+ name: `${node.operationId} Response`,
729
913
  type: "type"
730
- });
731
- return renderSchemaType({
732
- node: node.requestBody,
733
- name: resolvedName,
734
- typedName,
735
- description: node.requestBody.description
736
- });
737
- })() : null;
914
+ })
915
+ });
738
916
  return /* @__PURE__ */ jsxs(File, {
739
917
  baseName: file.baseName,
740
918
  path: file.path,
@@ -742,23 +920,24 @@ const typeGenerator = createReactGenerator({
742
920
  children: [
743
921
  paramTypes,
744
922
  responseTypes,
745
- requestType
923
+ requestType,
924
+ dataType,
925
+ responsesType,
926
+ responseType
746
927
  ]
747
928
  });
748
929
  },
749
930
  Schema({ node, adapter, options }) {
750
- const { enumType, enumKeyCasing, syntaxType, optionalType, arrayType } = options;
751
- const { plugin, mode, resolveName, getFile } = useKubb();
931
+ const { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, mapper } = options;
932
+ const { mode, resolveName, getFile } = useKubb();
752
933
  if (!node.name) return;
753
934
  const imports = adapter.getImports(node, (schemaName) => ({
754
935
  name: resolveName({
755
936
  name: schemaName,
756
- pluginName: plugin.name,
757
937
  type: "type"
758
938
  }),
759
939
  path: getFile({
760
940
  name: schemaName,
761
- pluginName: plugin.name,
762
941
  extname: ".ts",
763
942
  mode
764
943
  }).path
@@ -766,20 +945,17 @@ const typeGenerator = createReactGenerator({
766
945
  const isEnumSchema = node.type === "enum";
767
946
  let typedName = resolveName({
768
947
  name: node.name,
769
- pluginName: plugin.name,
770
948
  type: "type"
771
949
  });
772
- if (["asConst", "asPascalConst"].includes(enumType) && isEnumSchema) typedName = typedName += "Key";
950
+ if (["asConst", "asPascalConst"].includes(enumType) && isEnumSchema) typedName += "Key";
773
951
  const type = {
774
952
  name: resolveName({
775
953
  name: node.name,
776
- pluginName: plugin.name,
777
954
  type: "function"
778
955
  }),
779
956
  typedName,
780
957
  file: getFile({
781
958
  name: node.name,
782
- pluginName: plugin.name,
783
959
  extname: ".ts",
784
960
  mode
785
961
  })
@@ -805,7 +981,8 @@ const typeGenerator = createReactGenerator({
805
981
  enumKeyCasing,
806
982
  optionalType,
807
983
  arrayType,
808
- syntaxType
984
+ syntaxType,
985
+ mapper
809
986
  })]
810
987
  });
811
988
  }
@@ -870,34 +1047,63 @@ const pluginTs = definePlugin((options) => {
870
1047
  await openInStudio({ ast: true });
871
1048
  await walk(rootNode, {
872
1049
  async schema(schemaNode) {
873
- await generators.map(async (generator) => {
874
- if (generator.type === "react" && generator.version === "2") await buildSchema(schemaNode, {
875
- adapter,
876
- config,
877
- fabric,
878
- Component: generator.Schema,
879
- plugin,
880
- pluginManager,
881
- mode,
882
- version: generator.version
883
- });
1050
+ const writeTasks = generators.map(async (generator) => {
1051
+ if (generator.type === "react" && generator.version === "2") {
1052
+ const options = resolveOptions(schemaNode, {
1053
+ options: plugin.options,
1054
+ exclude,
1055
+ include,
1056
+ override
1057
+ });
1058
+ if (options === null) return;
1059
+ await buildSchema(schemaNode, {
1060
+ options,
1061
+ adapter,
1062
+ config,
1063
+ fabric,
1064
+ Component: generator.Schema,
1065
+ plugin,
1066
+ pluginManager,
1067
+ mode,
1068
+ version: generator.version
1069
+ });
1070
+ }
884
1071
  });
1072
+ await Promise.all(writeTasks);
885
1073
  },
886
1074
  async operation(operationNode) {
887
- await generators.map(async (generator) => {
888
- if (generator.type === "react" && generator.version === "2") await buildOperation(operationNode, {
889
- adapter,
890
- config,
891
- fabric,
892
- Component: generator.Operation,
893
- plugin,
894
- pluginManager,
895
- mode,
896
- version: generator.version
897
- });
1075
+ const writeTasks = generators.map(async (generator) => {
1076
+ if (generator.type === "react" && generator.version === "2") {
1077
+ const options = resolveOptions(operationNode, {
1078
+ options: plugin.options,
1079
+ exclude,
1080
+ include,
1081
+ override
1082
+ });
1083
+ if (options === null) return;
1084
+ await buildOperation(operationNode, {
1085
+ options,
1086
+ adapter,
1087
+ config,
1088
+ fabric,
1089
+ Component: generator.Operation,
1090
+ plugin,
1091
+ pluginManager,
1092
+ mode,
1093
+ version: generator.version
1094
+ });
1095
+ }
898
1096
  });
1097
+ await Promise.all(writeTasks);
899
1098
  }
900
1099
  }, { depth: "shallow" });
1100
+ const barrelFiles = await getBarrelFiles(this.fabric.files, {
1101
+ type: output.barrelType ?? "named",
1102
+ root,
1103
+ output,
1104
+ meta: { pluginName: this.plugin.name }
1105
+ });
1106
+ await this.upsertFile(...barrelFiles);
901
1107
  return;
902
1108
  }
903
1109
  const oas = await this.getOas();
@@ -941,4 +1147,4 @@ const pluginTs = definePlugin((options) => {
941
1147
  //#endregion
942
1148
  export { typeGenerator$1 as i, pluginTsName as n, typeGenerator as r, pluginTs as t };
943
1149
 
944
- //# sourceMappingURL=plugin-DmwgRHK8.js.map
1150
+ //# sourceMappingURL=plugin-kdQ5D2cW.js.map