@kubb/plugin-ts 5.0.0-beta.75 → 5.0.0-beta.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +88 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +88 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -550,7 +550,7 @@ function applyEnumKeyCasing(key, casing = "none") {
|
|
|
550
550
|
* type: 'enum',
|
|
551
551
|
* name: 'petType',
|
|
552
552
|
* typeName: 'PetType',
|
|
553
|
-
* enums: [['cat', 'cat'], ['dog', 'dog']],
|
|
553
|
+
* enums: [['cat', 'cat', 'A cat'], ['dog', 'dog']],
|
|
554
554
|
* })
|
|
555
555
|
* ```
|
|
556
556
|
*/
|
|
@@ -563,30 +563,39 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
563
563
|
if (typeof value === "boolean") return factory.createLiteralTypeNode(value ? factory.createTrue() : factory.createFalse());
|
|
564
564
|
if (value !== null && value !== void 0) return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString()));
|
|
565
565
|
}).filter((node) => node !== void 0)))];
|
|
566
|
-
if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(ts.SyntaxKind.ConstKeyword) : void 0].filter((modifier) => modifier !== void 0), factory.createIdentifier(typeName), enums.map(([key, value]) => {
|
|
566
|
+
if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(ts.SyntaxKind.ConstKeyword) : void 0].filter((modifier) => modifier !== void 0), factory.createIdentifier(typeName), enums.map(([key, value, description]) => {
|
|
567
567
|
let initializer = factory.createStringLiteral(value?.toString());
|
|
568
568
|
if (Number.parseInt(value.toString(), 10) === value && isNumber(Number.parseInt(value.toString(), 10))) if (value < 0) initializer = factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
569
569
|
else initializer = factory.createNumericLiteral(value);
|
|
570
570
|
if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
|
|
571
571
|
if (isNumber(Number.parseInt(key.toString(), 10))) {
|
|
572
572
|
const casingKey = applyEnumKeyCasing(`${typeName}_${key}`, enumKeyCasing);
|
|
573
|
-
return
|
|
573
|
+
return appendJSDocToNode({
|
|
574
|
+
node: factory.createEnumMember(propertyName(casingKey), initializer),
|
|
575
|
+
comments: [description]
|
|
576
|
+
});
|
|
574
577
|
}
|
|
575
578
|
if (key !== null && key !== void 0) {
|
|
576
579
|
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
577
|
-
return
|
|
580
|
+
return appendJSDocToNode({
|
|
581
|
+
node: factory.createEnumMember(propertyName(casingKey), initializer),
|
|
582
|
+
comments: [description]
|
|
583
|
+
});
|
|
578
584
|
}
|
|
579
585
|
}).filter((member) => member !== void 0))];
|
|
580
586
|
const identifierName = name;
|
|
581
587
|
if (enums.length === 0) return [void 0, factory.createTypeAliasDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword))];
|
|
582
|
-
return [factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(identifierName), void 0, void 0, factory.createAsExpression(factory.createObjectLiteralExpression(enums.map(([key, value]) => {
|
|
588
|
+
return [factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(identifierName), void 0, void 0, factory.createAsExpression(factory.createObjectLiteralExpression(enums.map(([key, value, description]) => {
|
|
583
589
|
let initializer = factory.createStringLiteral(value?.toString());
|
|
584
590
|
if (isNumber(value)) if (value < 0) initializer = factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
585
591
|
else initializer = factory.createNumericLiteral(value);
|
|
586
592
|
if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
|
|
587
593
|
if (key !== null && key !== void 0) {
|
|
588
594
|
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
589
|
-
return
|
|
595
|
+
return appendJSDocToNode({
|
|
596
|
+
node: factory.createPropertyAssignment(propertyName(casingKey), initializer),
|
|
597
|
+
comments: [description]
|
|
598
|
+
});
|
|
590
599
|
}
|
|
591
600
|
}).filter((property) => property !== void 0), true), factory.createTypeReferenceNode(factory.createIdentifier("const"), void 0)))], ts.NodeFlags.Const)), factory.createTypeAliasDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createIndexedAccessTypeNode(factory.createParenthesizedType(factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0)), factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0))))];
|
|
592
601
|
}
|
|
@@ -753,24 +762,30 @@ function buildPropertyType(schema, baseType, optionalType, optional) {
|
|
|
753
762
|
if ((optional || meta.nullish || meta.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
754
763
|
return type;
|
|
755
764
|
}
|
|
765
|
+
const indexSignaturePrinter = ts.createPrinter();
|
|
766
|
+
const indexSignatureSource = ts.createSourceFile("", "", ts.ScriptTarget.Latest);
|
|
756
767
|
/**
|
|
757
|
-
* Creates TypeScript index
|
|
768
|
+
* Creates a TypeScript index signature for `additionalProperties` and `patternProperties` on an
|
|
769
|
+
* object schema node. TypeScript allows only one string index signature and its value must be
|
|
770
|
+
* assignable from every named property, so both keywords collapse into a single signature: the
|
|
771
|
+
* union of all value types (deduplicated), or `unknown` when the object also has fixed properties.
|
|
772
|
+
* The key regex of `patternProperties` cannot be expressed by an index signature and is dropped.
|
|
758
773
|
*/
|
|
759
774
|
function buildIndexSignatures(node, propertyCount, print) {
|
|
760
|
-
const
|
|
761
|
-
if (node.additionalProperties && node.additionalProperties !== true)
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const first = Object.values(node.patternProperties)[0];
|
|
767
|
-
if (first) {
|
|
768
|
-
let patternType = print(first) ?? keywordTypeNodes.unknown;
|
|
769
|
-
if (first.nullable) patternType = createUnionDeclaration({ nodes: [patternType, keywordTypeNodes.null] });
|
|
770
|
-
elements.push(createIndexSignature(patternType));
|
|
771
|
-
}
|
|
775
|
+
const valueTypes = [];
|
|
776
|
+
if (node.additionalProperties && node.additionalProperties !== true) valueTypes.push(print(node.additionalProperties) ?? keywordTypeNodes.unknown);
|
|
777
|
+
else if (node.additionalProperties === true) valueTypes.push(keywordTypeNodes.unknown);
|
|
778
|
+
for (const schema of Object.values(node.patternProperties ?? {})) {
|
|
779
|
+
const patternType = print(schema) ?? keywordTypeNodes.unknown;
|
|
780
|
+
valueTypes.push(schema.nullable ? createUnionDeclaration({ nodes: [patternType, keywordTypeNodes.null] }) : patternType);
|
|
772
781
|
}
|
|
773
|
-
return
|
|
782
|
+
if (valueTypes.length === 0) return [];
|
|
783
|
+
const seen = /* @__PURE__ */ new Set();
|
|
784
|
+
const distinct = valueTypes.filter((type) => {
|
|
785
|
+
const key = indexSignaturePrinter.printNode(ts.EmitHint.Unspecified, type, indexSignatureSource);
|
|
786
|
+
return seen.has(key) ? false : (seen.add(key), true);
|
|
787
|
+
});
|
|
788
|
+
return [createIndexSignature(propertyCount > 0 ? keywordTypeNodes.unknown : createUnionDeclaration({ nodes: distinct }))];
|
|
774
789
|
}
|
|
775
790
|
//#endregion
|
|
776
791
|
//#region src/components/Enum.tsx
|
|
@@ -811,7 +826,11 @@ function Enum({ node, enum: enumOptions, resolver }) {
|
|
|
811
826
|
const [nameNode, typeNode] = createEnumDeclaration({
|
|
812
827
|
name: enumName,
|
|
813
828
|
typeName,
|
|
814
|
-
enums: node.namedEnumValues?.map((v) => [
|
|
829
|
+
enums: node.namedEnumValues?.map((v) => [
|
|
830
|
+
trimQuotes(v.name.toString()),
|
|
831
|
+
v.value,
|
|
832
|
+
v.description
|
|
833
|
+
]) ?? node.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [trimQuotes(v.toString()), v]) ?? [],
|
|
815
834
|
type: enumOptions.type,
|
|
816
835
|
enumKeyCasing: enumOptions.keyCasing
|
|
817
836
|
});
|
|
@@ -831,39 +850,6 @@ function Enum({ node, enum: enumOptions, resolver }) {
|
|
|
831
850
|
})] });
|
|
832
851
|
}
|
|
833
852
|
//#endregion
|
|
834
|
-
//#region src/components/Type.tsx
|
|
835
|
-
function Type({ name, node, printer, enum: enumOptions, resolver }) {
|
|
836
|
-
const enumSchemaNodes = ast.collect(node, { schema(n) {
|
|
837
|
-
const enumNode = ast.narrowSchema(n, ast.schemaTypes.enum);
|
|
838
|
-
if (enumNode?.name) return enumNode;
|
|
839
|
-
} });
|
|
840
|
-
const output = printer.print(node);
|
|
841
|
-
if (!output) return;
|
|
842
|
-
const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((node) => {
|
|
843
|
-
return {
|
|
844
|
-
node,
|
|
845
|
-
...getEnumNames({
|
|
846
|
-
node,
|
|
847
|
-
enum: enumOptions,
|
|
848
|
-
resolver
|
|
849
|
-
})
|
|
850
|
-
};
|
|
851
|
-
});
|
|
852
|
-
const shouldExportEnums = enumOptions.type !== "inlineLiteral";
|
|
853
|
-
const shouldExportType = enumOptions.type === "inlineLiteral" || enums.every((item) => item.typeName !== name);
|
|
854
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [shouldExportEnums && enums.map(({ node }) => /* @__PURE__ */ jsx(Enum, {
|
|
855
|
-
node,
|
|
856
|
-
enum: enumOptions,
|
|
857
|
-
resolver
|
|
858
|
-
}, node.name)), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
|
|
859
|
-
name,
|
|
860
|
-
isTypeOnly: true,
|
|
861
|
-
isExportable: true,
|
|
862
|
-
isIndexable: true,
|
|
863
|
-
children: output
|
|
864
|
-
})] });
|
|
865
|
-
}
|
|
866
|
-
//#endregion
|
|
867
853
|
//#region ../../internals/shared/src/params.ts
|
|
868
854
|
const caseParamsCache = /* @__PURE__ */ new WeakMap();
|
|
869
855
|
/**
|
|
@@ -977,6 +963,18 @@ function createGroupConfig(group) {
|
|
|
977
963
|
//#endregion
|
|
978
964
|
//#region src/utils.ts
|
|
979
965
|
/**
|
|
966
|
+
* Tells whether a `const` (single-value enum) should render as a bare literal type (`'active'`)
|
|
967
|
+
* rather than a named enum reference or a runtime enum declaration.
|
|
968
|
+
*
|
|
969
|
+
* The parser folds `const` into a single-value enum node. The adapter decides which schemas are
|
|
970
|
+
* named enums and lists them in `enumSchemaNames`, and references to those names get suffixed (for
|
|
971
|
+
* example `StatusKey`). A const renders as a literal only when the adapter has not registered it as
|
|
972
|
+
* a named enum, which keeps the declaration and its references in sync across adapter versions.
|
|
973
|
+
*/
|
|
974
|
+
function isInlineConstEnum(node, enumSchemaNames) {
|
|
975
|
+
return (node.namedEnumValues ?? node.enumValues ?? []).length === 1 && !(node.name && enumSchemaNames?.has(node.name));
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
980
978
|
* Collects JSDoc annotation strings for a schema node.
|
|
981
979
|
*
|
|
982
980
|
* Only uses official JSDoc tags from https://jsdoc.app/: `@description`, `@deprecated`, `@default`, `@example`, `@type`.
|
|
@@ -1114,6 +1112,39 @@ function buildResponseUnion(node, { resolver }) {
|
|
|
1114
1112
|
});
|
|
1115
1113
|
}
|
|
1116
1114
|
//#endregion
|
|
1115
|
+
//#region src/components/Type.tsx
|
|
1116
|
+
function Type({ name, node, printer, enum: enumOptions, resolver }) {
|
|
1117
|
+
const enumSchemaNodes = ast.collect(node, { schema(n) {
|
|
1118
|
+
const enumNode = ast.narrowSchema(n, ast.schemaTypes.enum);
|
|
1119
|
+
if (enumNode?.name && !isInlineConstEnum(enumNode, printer.options.enumSchemaNames)) return enumNode;
|
|
1120
|
+
} });
|
|
1121
|
+
const output = printer.print(node);
|
|
1122
|
+
if (!output) return;
|
|
1123
|
+
const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((node) => {
|
|
1124
|
+
return {
|
|
1125
|
+
node,
|
|
1126
|
+
...getEnumNames({
|
|
1127
|
+
node,
|
|
1128
|
+
enum: enumOptions,
|
|
1129
|
+
resolver
|
|
1130
|
+
})
|
|
1131
|
+
};
|
|
1132
|
+
});
|
|
1133
|
+
const shouldExportEnums = enumOptions.type !== "inlineLiteral";
|
|
1134
|
+
const shouldExportType = enumOptions.type === "inlineLiteral" || enums.every((item) => item.typeName !== name);
|
|
1135
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [shouldExportEnums && enums.map(({ node }) => /* @__PURE__ */ jsx(Enum, {
|
|
1136
|
+
node,
|
|
1137
|
+
enum: enumOptions,
|
|
1138
|
+
resolver
|
|
1139
|
+
}, node.name)), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
|
|
1140
|
+
name,
|
|
1141
|
+
isTypeOnly: true,
|
|
1142
|
+
isExportable: true,
|
|
1143
|
+
isIndexable: true,
|
|
1144
|
+
children: output
|
|
1145
|
+
})] });
|
|
1146
|
+
}
|
|
1147
|
+
//#endregion
|
|
1117
1148
|
//#region src/printers/printerTs.ts
|
|
1118
1149
|
const { isNonNullable } = factory_exports;
|
|
1119
1150
|
/**
|
|
@@ -1174,7 +1205,7 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1174
1205
|
},
|
|
1175
1206
|
enum(node) {
|
|
1176
1207
|
const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
|
|
1177
|
-
if (this.options.enum.type === "inlineLiteral" || !node.name) return createUnionDeclaration({
|
|
1208
|
+
if (this.options.enum.type === "inlineLiteral" || !node.name || isInlineConstEnum(node, this.options.enumSchemaNames)) return createUnionDeclaration({
|
|
1178
1209
|
withParentheses: true,
|
|
1179
1210
|
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(isNonNullable)
|
|
1180
1211
|
}) ?? void 0;
|
|
@@ -1304,7 +1335,8 @@ const typeGenerator = defineGenerator({
|
|
|
1304
1335
|
group: group ?? void 0
|
|
1305
1336
|
}).path
|
|
1306
1337
|
}));
|
|
1307
|
-
const
|
|
1338
|
+
const enumNode = ast.narrowSchema(node, ast.schemaTypes.enum);
|
|
1339
|
+
const isEnumSchema = !!enumNode && !isInlineConstEnum(enumNode, enumSchemaNames);
|
|
1308
1340
|
const meta = {
|
|
1309
1341
|
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumOptions.typeSuffix) : resolver.resolveTypeName(node.name),
|
|
1310
1342
|
file: resolver.resolveFile({
|