@kubb/plugin-ts 5.0.0-beta.56 → 5.0.0-beta.73
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/README.md +2 -2
- package/dist/index.cjs +624 -156
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +377 -36
- package/dist/index.js +611 -159
- package/dist/index.js.map +1 -1
- package/dist/rolldown-runtime-CNktS9qV.js +17 -0
- package/package.json +8 -10
- package/dist/chunk-C0LytTxp.js +0 -8
- package/src/components/Enum.tsx +0 -87
- package/src/components/Type.tsx +0 -55
- package/src/constants.ts +0 -39
- package/src/factory.ts +0 -970
- package/src/generators/typeGenerator.tsx +0 -274
- package/src/index.ts +0 -9
- package/src/plugin.ts +0 -95
- package/src/printers/functionPrinter.ts +0 -197
- package/src/printers/printerTs.ts +0 -315
- package/src/resolvers/resolverTs.ts +0 -69
- package/src/types.ts +0 -335
- package/src/utils.ts +0 -140
package/dist/index.cjs
CHANGED
|
@@ -13,6 +13,15 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
13
13
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
14
|
var __getProtoOf = Object.getPrototypeOf;
|
|
15
15
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __exportAll = (all, no_symbols) => {
|
|
17
|
+
let target = {};
|
|
18
|
+
for (var name in all) __defProp(target, name, {
|
|
19
|
+
get: all[name],
|
|
20
|
+
enumerable: true
|
|
21
|
+
});
|
|
22
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
23
|
+
return target;
|
|
24
|
+
};
|
|
16
25
|
var __copyProps = (to, from, except, desc) => {
|
|
17
26
|
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
18
27
|
key = keys[i];
|
|
@@ -31,10 +40,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
40
|
let _kubb_ast_utils = require("@kubb/ast/utils");
|
|
32
41
|
let _kubb_parser_ts = require("@kubb/parser-ts");
|
|
33
42
|
let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
|
|
34
|
-
let _kubb_core = require("@kubb/core");
|
|
35
43
|
let typescript = require("typescript");
|
|
36
44
|
typescript = __toESM(typescript, 1);
|
|
37
45
|
let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
|
|
46
|
+
let _kubb_core = require("@kubb/core");
|
|
38
47
|
//#region ../../internals/utils/src/casing.ts
|
|
39
48
|
/**
|
|
40
49
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -288,7 +297,59 @@ const PARAM_RANK = {
|
|
|
288
297
|
};
|
|
289
298
|
//#endregion
|
|
290
299
|
//#region src/factory.ts
|
|
300
|
+
var factory_exports = /* @__PURE__ */ __exportAll({
|
|
301
|
+
SyntaxKind: () => SyntaxKind,
|
|
302
|
+
appendJSDocToNode: () => appendJSDocToNode,
|
|
303
|
+
buildIndexSignatures: () => buildIndexSignatures,
|
|
304
|
+
buildMemberNodes: () => buildMemberNodes,
|
|
305
|
+
buildPropertyType: () => buildPropertyType,
|
|
306
|
+
buildTupleNode: () => buildTupleNode,
|
|
307
|
+
constToTypeNode: () => constToTypeNode,
|
|
308
|
+
createArrayDeclaration: () => createArrayDeclaration,
|
|
309
|
+
createArrayTypeNode: () => createArrayTypeNode,
|
|
310
|
+
createEnumDeclaration: () => createEnumDeclaration,
|
|
311
|
+
createExportDeclaration: () => createExportDeclaration,
|
|
312
|
+
createFalse: () => createFalse,
|
|
313
|
+
createIdentifier: () => createIdentifier,
|
|
314
|
+
createImportDeclaration: () => createImportDeclaration,
|
|
315
|
+
createIndexSignature: () => createIndexSignature,
|
|
316
|
+
createInterfaceDeclaration: () => createInterfaceDeclaration,
|
|
317
|
+
createIntersectionDeclaration: () => createIntersectionDeclaration,
|
|
318
|
+
createJSDoc: () => createJSDoc,
|
|
319
|
+
createLiteralTypeNode: () => createLiteralTypeNode,
|
|
320
|
+
createNumericLiteral: () => createNumericLiteral,
|
|
321
|
+
createOmitDeclaration: () => createOmitDeclaration,
|
|
322
|
+
createOptionalTypeNode: () => createOptionalTypeNode,
|
|
323
|
+
createParameterSignature: () => createParameterSignature,
|
|
324
|
+
createPrefixUnaryExpression: () => createPrefixUnaryExpression,
|
|
325
|
+
createPropertySignature: () => createPropertySignature,
|
|
326
|
+
createQuestionToken: () => createQuestionToken,
|
|
327
|
+
createRestTypeNode: () => createRestTypeNode,
|
|
328
|
+
createStringLiteral: () => createStringLiteral,
|
|
329
|
+
createTrue: () => createTrue,
|
|
330
|
+
createTupleTypeNode: () => createTupleTypeNode,
|
|
331
|
+
createTypeAliasDeclaration: () => createTypeAliasDeclaration,
|
|
332
|
+
createTypeDeclaration: () => createTypeDeclaration,
|
|
333
|
+
createTypeLiteralNode: () => createTypeLiteralNode,
|
|
334
|
+
createTypeReferenceNode: () => createTypeReferenceNode,
|
|
335
|
+
createUnionDeclaration: () => createUnionDeclaration,
|
|
336
|
+
createUrlTemplateType: () => createUrlTemplateType,
|
|
337
|
+
dateOrStringNode: () => dateOrStringNode,
|
|
338
|
+
isNonNullable: () => isNonNullable$1,
|
|
339
|
+
keywordTypeNodes: () => keywordTypeNodes,
|
|
340
|
+
modifiers: () => modifiers,
|
|
341
|
+
syntaxKind: () => syntaxKind
|
|
342
|
+
});
|
|
291
343
|
const { SyntaxKind, factory } = typescript.default;
|
|
344
|
+
/**
|
|
345
|
+
* Compares two strings by UTF-16 code unit, keeping sorted output identical across platforms
|
|
346
|
+
* regardless of locale.
|
|
347
|
+
*/
|
|
348
|
+
function compareStrings(a, b) {
|
|
349
|
+
if (a < b) return -1;
|
|
350
|
+
if (a > b) return 1;
|
|
351
|
+
return 0;
|
|
352
|
+
}
|
|
292
353
|
function isNumber(value) {
|
|
293
354
|
return typeof value === "number" && !Number.isNaN(value);
|
|
294
355
|
}
|
|
@@ -396,6 +457,17 @@ function createParameterSignature(name, { modifiers, dotDotDotToken, questionTok
|
|
|
396
457
|
return factory.createParameterDeclaration(modifiers, dotDotDotToken, name, createQuestionToken(questionToken), type, initializer);
|
|
397
458
|
}
|
|
398
459
|
/**
|
|
460
|
+
* Creates a JSDoc comment node from an array of comment strings.
|
|
461
|
+
* Returns null if no comments are provided.
|
|
462
|
+
*/
|
|
463
|
+
function createJSDoc({ comments }) {
|
|
464
|
+
if (!comments.length) return null;
|
|
465
|
+
return factory.createJSDocComment(factory.createNodeArray(comments.map((comment, i) => {
|
|
466
|
+
if (i === comments.length - 1) return factory.createJSDocText(comment);
|
|
467
|
+
return factory.createJSDocText(`${comment}\n`);
|
|
468
|
+
})));
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
399
471
|
* Attaches JSDoc comments to an AST node as synthetic leading comments.
|
|
400
472
|
* Filters out undefined comments before attaching.
|
|
401
473
|
*
|
|
@@ -453,6 +525,50 @@ function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
|
|
|
453
525
|
});
|
|
454
526
|
}
|
|
455
527
|
/**
|
|
528
|
+
* Creates an import declaration with support for default imports, named imports, namespace imports, and type-only imports.
|
|
529
|
+
* Optionally rename imported members with `propertyName` and `name` pairs.
|
|
530
|
+
*
|
|
531
|
+
* @example Default import
|
|
532
|
+
* `import Pet from './Pet'`
|
|
533
|
+
*
|
|
534
|
+
* @example Named imports with rename
|
|
535
|
+
* `import { Pet as Cat } from './Pet'`
|
|
536
|
+
*
|
|
537
|
+
* @example Namespace import
|
|
538
|
+
* `import * as Pet from './Pet'`
|
|
539
|
+
*/
|
|
540
|
+
function createImportDeclaration({ name, path, isTypeOnly = false, isNameSpace = false }) {
|
|
541
|
+
if (!Array.isArray(name)) {
|
|
542
|
+
const importPropertyName = isNameSpace ? void 0 : factory.createIdentifier(name);
|
|
543
|
+
const importName = isNameSpace ? factory.createNamespaceImport(factory.createIdentifier(name)) : void 0;
|
|
544
|
+
return factory.createImportDeclaration(void 0, factory.createImportClause(isTypeOnly, importPropertyName, importName), factory.createStringLiteral(path), void 0);
|
|
545
|
+
}
|
|
546
|
+
const sortedName = name.toSorted((a, b) => compareStrings(typeof a === "object" ? a.propertyName : a, typeof b === "object" ? b.propertyName : b));
|
|
547
|
+
return factory.createImportDeclaration(void 0, factory.createImportClause(isTypeOnly, void 0, factory.createNamedImports(sortedName.map((item) => {
|
|
548
|
+
if (typeof item === "object") {
|
|
549
|
+
const obj = item;
|
|
550
|
+
if (obj.name) return factory.createImportSpecifier(false, factory.createIdentifier(obj.propertyName), factory.createIdentifier(obj.name));
|
|
551
|
+
return factory.createImportSpecifier(false, void 0, factory.createIdentifier(obj.propertyName));
|
|
552
|
+
}
|
|
553
|
+
return factory.createImportSpecifier(false, void 0, factory.createIdentifier(item));
|
|
554
|
+
}))), factory.createStringLiteral(path), void 0);
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Creates an export declaration with support for named exports, namespace exports, and type-only exports.
|
|
558
|
+
* Sorts export names alphabetically for consistent output across platforms.
|
|
559
|
+
*/
|
|
560
|
+
function createExportDeclaration({ path, asAlias, isTypeOnly = false, name }) {
|
|
561
|
+
if (name && !Array.isArray(name) && !asAlias) console.warn(`When using name as string, asAlias should be true ${name}`);
|
|
562
|
+
if (!Array.isArray(name)) {
|
|
563
|
+
const parsedName = name?.match(/^\d/) ? `_${name?.slice(1)}` : name;
|
|
564
|
+
return factory.createExportDeclaration(void 0, isTypeOnly, asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : void 0, factory.createStringLiteral(path), void 0);
|
|
565
|
+
}
|
|
566
|
+
const sortedName = name.toSorted((a, b) => compareStrings(typeof a === "string" ? a : a.text, typeof b === "string" ? b : b.text));
|
|
567
|
+
return factory.createExportDeclaration(void 0, isTypeOnly, factory.createNamedExports(sortedName.map((propertyName) => {
|
|
568
|
+
return factory.createExportSpecifier(false, void 0, typeof propertyName === "string" ? factory.createIdentifier(propertyName) : propertyName);
|
|
569
|
+
})), factory.createStringLiteral(path), void 0);
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
456
572
|
* Apply casing transformation to enum keys
|
|
457
573
|
*/
|
|
458
574
|
function applyEnumKeyCasing(key, casing = "none") {
|
|
@@ -484,7 +600,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
484
600
|
return factory.createLiteralTypeNode(factory.createNumericLiteral(value?.toString()));
|
|
485
601
|
}
|
|
486
602
|
if (typeof value === "boolean") return factory.createLiteralTypeNode(value ? factory.createTrue() : factory.createFalse());
|
|
487
|
-
if (value) return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString()));
|
|
603
|
+
if (value !== null && value !== void 0) return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString()));
|
|
488
604
|
}).filter((node) => node !== void 0)))];
|
|
489
605
|
if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(typescript.default.SyntaxKind.ConstKeyword) : void 0].filter((modifier) => modifier !== void 0), factory.createIdentifier(typeName), enums.map(([key, value]) => {
|
|
490
606
|
let initializer = factory.createStringLiteral(value?.toString());
|
|
@@ -495,7 +611,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
495
611
|
const casingKey = applyEnumKeyCasing(`${typeName}_${key}`, enumKeyCasing);
|
|
496
612
|
return factory.createEnumMember(propertyName(casingKey), initializer);
|
|
497
613
|
}
|
|
498
|
-
if (key) {
|
|
614
|
+
if (key !== null && key !== void 0) {
|
|
499
615
|
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
500
616
|
return factory.createEnumMember(propertyName(casingKey), initializer);
|
|
501
617
|
}
|
|
@@ -507,7 +623,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
507
623
|
if (isNumber(value)) if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
508
624
|
else initializer = factory.createNumericLiteral(value);
|
|
509
625
|
if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
|
|
510
|
-
if (key) {
|
|
626
|
+
if (key !== null && key !== void 0) {
|
|
511
627
|
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
512
628
|
return factory.createPropertyAssignment(propertyName(casingKey), initializer);
|
|
513
629
|
}
|
|
@@ -668,12 +784,12 @@ function buildTupleNode(node, print) {
|
|
|
668
784
|
/**
|
|
669
785
|
* Applies `nullable` and optional/nullish `| undefined` union modifiers to a property's resolved base type.
|
|
670
786
|
*/
|
|
671
|
-
function buildPropertyType(schema, baseType, optionalType) {
|
|
787
|
+
function buildPropertyType(schema, baseType, optionalType, optional) {
|
|
672
788
|
const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType);
|
|
673
|
-
const meta =
|
|
789
|
+
const meta = (0, _kubb_ast_utils.syncSchemaRef)(schema);
|
|
674
790
|
let type = baseType;
|
|
675
791
|
if (meta.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
|
|
676
|
-
if ((meta.nullish || meta.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
792
|
+
if ((optional || meta.nullish || meta.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
677
793
|
return type;
|
|
678
794
|
}
|
|
679
795
|
/**
|
|
@@ -787,6 +903,27 @@ function Type({ name, node, printer, enum: enumOptions, resolver }) {
|
|
|
787
903
|
})] });
|
|
788
904
|
}
|
|
789
905
|
//#endregion
|
|
906
|
+
//#region ../../internals/shared/src/params.ts
|
|
907
|
+
const caseParamsCache = /* @__PURE__ */ new WeakMap();
|
|
908
|
+
/**
|
|
909
|
+
* Applies camelCase to parameter names and returns a new array without mutating the input.
|
|
910
|
+
*
|
|
911
|
+
* Run it before handing parameters to schema builders so output property keys get the right casing
|
|
912
|
+
* while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
|
|
913
|
+
* original array is returned unchanged. Results are cached per input array.
|
|
914
|
+
*/
|
|
915
|
+
function caseParams(params, casing) {
|
|
916
|
+
if (!casing) return params;
|
|
917
|
+
const cached = caseParamsCache.get(params);
|
|
918
|
+
if (cached) return cached;
|
|
919
|
+
const result = params.map((param) => ({
|
|
920
|
+
...param,
|
|
921
|
+
name: camelCase(param.name)
|
|
922
|
+
}));
|
|
923
|
+
caseParamsCache.set(params, result);
|
|
924
|
+
return result;
|
|
925
|
+
}
|
|
926
|
+
//#endregion
|
|
790
927
|
//#region ../../internals/shared/src/operation.ts
|
|
791
928
|
/**
|
|
792
929
|
* Maps a content type to the PascalCase suffix used to name per-content-type variants
|
|
@@ -837,7 +974,7 @@ function resolveContentTypeVariants(entries, baseName) {
|
|
|
837
974
|
});
|
|
838
975
|
}
|
|
839
976
|
function getOperationParameters(node, options = {}) {
|
|
840
|
-
const params =
|
|
977
|
+
const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
|
|
841
978
|
return {
|
|
842
979
|
path: params.filter((param) => param.in === "path"),
|
|
843
980
|
query: params.filter((param) => param.in === "query"),
|
|
@@ -885,11 +1022,15 @@ function createGroupConfig(group) {
|
|
|
885
1022
|
* Constraint metadata (min/max length, pattern, multipleOf, min/maxProperties) is emitted as plain-text lines.
|
|
886
1023
|
|
|
887
1024
|
*/
|
|
888
|
-
function
|
|
889
|
-
|
|
1025
|
+
function isSchemaOptional(schema) {
|
|
1026
|
+
return Boolean("optional" in schema && schema.optional || "nullish" in schema && schema.nullish);
|
|
1027
|
+
}
|
|
1028
|
+
function buildPropertyJSDocComments(schema, optional) {
|
|
1029
|
+
const meta = (0, _kubb_ast_utils.syncSchemaRef)(schema);
|
|
890
1030
|
const isArray = meta?.primitive === "array";
|
|
891
1031
|
const hasDescription = meta && "description" in meta && meta.description;
|
|
892
1032
|
const formatComment = meta && "format" in meta && meta.format ? hasDescription ? [" ", `Format: \`${meta.format}\``] : ["@description", `Format: \`${meta.format}\``] : [];
|
|
1033
|
+
const exampleValues = meta?.examples ?? [];
|
|
893
1034
|
return [
|
|
894
1035
|
hasDescription ? `@description ${(0, _kubb_ast_utils.jsStringEscape)(meta.description)}` : null,
|
|
895
1036
|
...formatComment,
|
|
@@ -898,99 +1039,102 @@ function buildPropertyJSDocComments(schema) {
|
|
|
898
1039
|
!isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : null,
|
|
899
1040
|
meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : null,
|
|
900
1041
|
meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? (0, _kubb_ast_utils.stringify)(meta.default) : meta.default}` : null,
|
|
901
|
-
|
|
902
|
-
meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`,
|
|
1042
|
+
...exampleValues.map((example) => `@example ${example}`),
|
|
1043
|
+
meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, optional ?? isSchemaOptional(schema) ? " | undefined" : null].filter(Boolean).join("") : null
|
|
903
1044
|
].filter(Boolean);
|
|
904
1045
|
}
|
|
905
1046
|
function buildParams(node, { params, resolver }) {
|
|
906
|
-
return _kubb_core.ast.createSchema({
|
|
1047
|
+
return _kubb_core.ast.factory.createSchema({
|
|
907
1048
|
type: "object",
|
|
908
|
-
properties: params.map((param) => _kubb_core.ast.createProperty({
|
|
1049
|
+
properties: params.map((param) => _kubb_core.ast.factory.createProperty({
|
|
909
1050
|
name: param.name,
|
|
910
1051
|
required: param.required,
|
|
911
|
-
schema: _kubb_core.ast.createSchema({
|
|
1052
|
+
schema: _kubb_core.ast.factory.createSchema({
|
|
912
1053
|
type: "ref",
|
|
913
|
-
name: resolver.resolveParamName(node, param)
|
|
1054
|
+
name: resolver.resolveParamName(node, param),
|
|
1055
|
+
optional: !param.required
|
|
914
1056
|
})
|
|
915
1057
|
}))
|
|
916
1058
|
});
|
|
917
1059
|
}
|
|
918
1060
|
function buildData(node, { resolver }) {
|
|
919
|
-
const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node);
|
|
920
|
-
|
|
1061
|
+
const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node, { paramsCasing: "original" });
|
|
1062
|
+
const hasBody = Boolean(node.requestBody?.content?.[0]?.schema);
|
|
1063
|
+
const hasRequiredPath = pathParams.some((param) => param.required);
|
|
1064
|
+
const hasRequiredQuery = queryParams.some((param) => param.required);
|
|
1065
|
+
const hasRequiredHeader = headerParams.some((param) => param.required);
|
|
1066
|
+
return _kubb_core.ast.factory.createSchema({
|
|
921
1067
|
type: "object",
|
|
922
1068
|
deprecated: node.deprecated,
|
|
923
1069
|
properties: [
|
|
924
|
-
_kubb_core.ast.createProperty({
|
|
925
|
-
name: "
|
|
926
|
-
|
|
1070
|
+
_kubb_core.ast.factory.createProperty({
|
|
1071
|
+
name: "body",
|
|
1072
|
+
required: hasBody,
|
|
1073
|
+
schema: hasBody ? _kubb_core.ast.factory.createSchema({
|
|
927
1074
|
type: "ref",
|
|
928
|
-
name: resolver.resolveDataName(node)
|
|
929
|
-
|
|
930
|
-
}) : _kubb_core.ast.createSchema({
|
|
1075
|
+
name: resolver.resolveDataName(node)
|
|
1076
|
+
}) : _kubb_core.ast.factory.createSchema({
|
|
931
1077
|
type: "never",
|
|
932
1078
|
primitive: void 0,
|
|
933
1079
|
optional: true
|
|
934
1080
|
})
|
|
935
1081
|
}),
|
|
936
|
-
_kubb_core.ast.createProperty({
|
|
937
|
-
name: "
|
|
938
|
-
required:
|
|
939
|
-
schema: pathParams.length > 0 ?
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1082
|
+
_kubb_core.ast.factory.createProperty({
|
|
1083
|
+
name: "path",
|
|
1084
|
+
required: hasRequiredPath,
|
|
1085
|
+
schema: pathParams.length > 0 ? _kubb_core.ast.factory.createSchema({
|
|
1086
|
+
...buildParams(node, {
|
|
1087
|
+
params: pathParams,
|
|
1088
|
+
resolver
|
|
1089
|
+
}),
|
|
1090
|
+
optional: !hasRequiredPath
|
|
1091
|
+
}) : _kubb_core.ast.factory.createSchema({
|
|
943
1092
|
type: "never",
|
|
944
|
-
primitive: void 0
|
|
1093
|
+
primitive: void 0,
|
|
1094
|
+
optional: true
|
|
945
1095
|
})
|
|
946
1096
|
}),
|
|
947
|
-
_kubb_core.ast.createProperty({
|
|
948
|
-
name: "
|
|
949
|
-
|
|
1097
|
+
_kubb_core.ast.factory.createProperty({
|
|
1098
|
+
name: "query",
|
|
1099
|
+
required: hasRequiredQuery,
|
|
1100
|
+
schema: queryParams.length > 0 ? _kubb_core.ast.factory.createSchema({
|
|
950
1101
|
...buildParams(node, {
|
|
951
1102
|
params: queryParams,
|
|
952
1103
|
resolver
|
|
953
1104
|
}),
|
|
954
|
-
optional:
|
|
955
|
-
}) : _kubb_core.ast.createSchema({
|
|
1105
|
+
optional: !hasRequiredQuery
|
|
1106
|
+
}) : _kubb_core.ast.factory.createSchema({
|
|
956
1107
|
type: "never",
|
|
957
1108
|
primitive: void 0,
|
|
958
1109
|
optional: true
|
|
959
1110
|
})
|
|
960
1111
|
}),
|
|
961
|
-
_kubb_core.ast.createProperty({
|
|
962
|
-
name: "
|
|
963
|
-
|
|
1112
|
+
_kubb_core.ast.factory.createProperty({
|
|
1113
|
+
name: "headers",
|
|
1114
|
+
required: hasRequiredHeader,
|
|
1115
|
+
schema: headerParams.length > 0 ? _kubb_core.ast.factory.createSchema({
|
|
964
1116
|
...buildParams(node, {
|
|
965
1117
|
params: headerParams,
|
|
966
1118
|
resolver
|
|
967
1119
|
}),
|
|
968
|
-
optional:
|
|
969
|
-
}) : _kubb_core.ast.createSchema({
|
|
1120
|
+
optional: !hasRequiredHeader
|
|
1121
|
+
}) : _kubb_core.ast.factory.createSchema({
|
|
970
1122
|
type: "never",
|
|
971
1123
|
primitive: void 0,
|
|
972
1124
|
optional: true
|
|
973
1125
|
})
|
|
974
|
-
}),
|
|
975
|
-
_kubb_core.ast.createProperty({
|
|
976
|
-
name: "url",
|
|
977
|
-
required: true,
|
|
978
|
-
schema: _kubb_core.ast.createSchema({
|
|
979
|
-
type: "url",
|
|
980
|
-
path: node.path
|
|
981
|
-
})
|
|
982
1126
|
})
|
|
983
1127
|
]
|
|
984
1128
|
});
|
|
985
1129
|
}
|
|
986
1130
|
function buildResponses(node, { resolver }) {
|
|
987
1131
|
if (node.responses.length === 0) return null;
|
|
988
|
-
return _kubb_core.ast.createSchema({
|
|
1132
|
+
return _kubb_core.ast.factory.createSchema({
|
|
989
1133
|
type: "object",
|
|
990
|
-
properties: node.responses.map((res) => _kubb_core.ast.createProperty({
|
|
1134
|
+
properties: node.responses.map((res) => _kubb_core.ast.factory.createProperty({
|
|
991
1135
|
name: String(res.statusCode),
|
|
992
1136
|
required: true,
|
|
993
|
-
schema: _kubb_core.ast.createSchema({
|
|
1137
|
+
schema: _kubb_core.ast.factory.createSchema({
|
|
994
1138
|
type: "ref",
|
|
995
1139
|
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
996
1140
|
})
|
|
@@ -1000,9 +1144,9 @@ function buildResponses(node, { resolver }) {
|
|
|
1000
1144
|
function buildResponseUnion(node, { resolver }) {
|
|
1001
1145
|
const responsesWithSchema = node.responses.filter((res) => res.content?.some((entry) => entry.schema));
|
|
1002
1146
|
if (responsesWithSchema.length === 0) return null;
|
|
1003
|
-
return _kubb_core.ast.createSchema({
|
|
1147
|
+
return _kubb_core.ast.factory.createSchema({
|
|
1004
1148
|
type: "union",
|
|
1005
|
-
members: responsesWithSchema.map((res) => _kubb_core.ast.createSchema({
|
|
1149
|
+
members: responsesWithSchema.map((res) => _kubb_core.ast.factory.createSchema({
|
|
1006
1150
|
type: "ref",
|
|
1007
1151
|
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1008
1152
|
}))
|
|
@@ -1010,9 +1154,7 @@ function buildResponseUnion(node, { resolver }) {
|
|
|
1010
1154
|
}
|
|
1011
1155
|
//#endregion
|
|
1012
1156
|
//#region src/printers/printerTs.ts
|
|
1013
|
-
|
|
1014
|
-
return value !== null && value !== void 0;
|
|
1015
|
-
}
|
|
1157
|
+
const { isNonNullable } = factory_exports;
|
|
1016
1158
|
/**
|
|
1017
1159
|
* TypeScript type printer built with `definePrinter`.
|
|
1018
1160
|
*
|
|
@@ -1036,7 +1178,7 @@ function isNonNullable(value) {
|
|
|
1036
1178
|
* const declaration = printer.print(schemaNode) // ts.TypeAliasDeclaration | ts.InterfaceDeclaration
|
|
1037
1179
|
* ```
|
|
1038
1180
|
*/
|
|
1039
|
-
const printerTs = _kubb_core.ast.
|
|
1181
|
+
const printerTs = _kubb_core.ast.createPrinter((options) => {
|
|
1040
1182
|
const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(options.optionalType);
|
|
1041
1183
|
return {
|
|
1042
1184
|
name: "typescript",
|
|
@@ -1082,11 +1224,11 @@ const printerTs = _kubb_core.ast.definePrinter((options) => {
|
|
|
1082
1224
|
const hasStringLiteral = members.some((m) => {
|
|
1083
1225
|
return _kubb_core.ast.narrowSchema(m, _kubb_core.ast.schemaTypes.enum)?.primitive === "string";
|
|
1084
1226
|
});
|
|
1085
|
-
const hasPlainString = members.some((m) =>
|
|
1227
|
+
const hasPlainString = members.some((m) => (0, _kubb_ast_utils.isStringType)(m));
|
|
1086
1228
|
if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
|
|
1087
1229
|
withParentheses: true,
|
|
1088
1230
|
nodes: members.map((m) => {
|
|
1089
|
-
if (
|
|
1231
|
+
if ((0, _kubb_ast_utils.isStringType)(m)) return createIntersectionDeclaration({
|
|
1090
1232
|
nodes: [keywordTypeNodes.string, createTypeLiteralNode([])],
|
|
1091
1233
|
withParentheses: true
|
|
1092
1234
|
});
|
|
@@ -1106,7 +1248,7 @@ const printerTs = _kubb_core.ast.definePrinter((options) => {
|
|
|
1106
1248
|
},
|
|
1107
1249
|
array(node) {
|
|
1108
1250
|
return createArrayDeclaration({
|
|
1109
|
-
nodes: (
|
|
1251
|
+
nodes: (0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(isNonNullable),
|
|
1110
1252
|
arrayType: this.options.arrayType
|
|
1111
1253
|
}) ?? null;
|
|
1112
1254
|
},
|
|
@@ -1116,18 +1258,19 @@ const printerTs = _kubb_core.ast.definePrinter((options) => {
|
|
|
1116
1258
|
object(node) {
|
|
1117
1259
|
const { transform, options } = this;
|
|
1118
1260
|
const addsQuestionToken = OPTIONAL_ADDS_QUESTION_TOKEN.has(options.optionalType);
|
|
1119
|
-
const propertyNodes = node.
|
|
1120
|
-
const baseType =
|
|
1121
|
-
const
|
|
1122
|
-
const
|
|
1261
|
+
const propertyNodes = (0, _kubb_ast_utils.mapSchemaProperties)(node, (schema) => transform(schema)).map(({ name, property, output }) => {
|
|
1262
|
+
const baseType = output ?? keywordTypeNodes.unknown;
|
|
1263
|
+
const optional = !property.required || !!property.schema.optional || !!property.schema.nullish;
|
|
1264
|
+
const type = buildPropertyType(property.schema, baseType, options.optionalType, optional);
|
|
1265
|
+
const propMeta = (0, _kubb_ast_utils.syncSchemaRef)(property.schema);
|
|
1123
1266
|
return appendJSDocToNode({
|
|
1124
1267
|
node: createPropertySignature({
|
|
1125
|
-
questionToken:
|
|
1126
|
-
name
|
|
1268
|
+
questionToken: optional ? addsQuestionToken : false,
|
|
1269
|
+
name,
|
|
1127
1270
|
type,
|
|
1128
1271
|
readOnly: propMeta?.readOnly
|
|
1129
1272
|
}),
|
|
1130
|
-
comments: buildPropertyJSDocComments(
|
|
1273
|
+
comments: buildPropertyJSDocComments(property.schema, optional)
|
|
1131
1274
|
});
|
|
1132
1275
|
});
|
|
1133
1276
|
const allElements = [...propertyNodes, ...buildIndexSignatures(node, propertyNodes.length, transform)];
|
|
@@ -1140,7 +1283,7 @@ const printerTs = _kubb_core.ast.definePrinter((options) => {
|
|
|
1140
1283
|
const { name, syntaxType = "type", description, keysToOmit } = this.options;
|
|
1141
1284
|
const transformed = this.transform(node);
|
|
1142
1285
|
if (!transformed) return null;
|
|
1143
|
-
const meta =
|
|
1286
|
+
const meta = (0, _kubb_ast_utils.syncSchemaRef)(node);
|
|
1144
1287
|
if (!name) {
|
|
1145
1288
|
const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [transformed, keywordTypeNodes.null] }) : transformed;
|
|
1146
1289
|
const result = (meta.nullish || meta.optional) && addsUndefined ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
@@ -1262,9 +1405,9 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1262
1405
|
});
|
|
1263
1406
|
},
|
|
1264
1407
|
operation(node, ctx) {
|
|
1265
|
-
const { enum: enumOptions, optionalType, arrayType, syntaxType,
|
|
1408
|
+
const { enum: enumOptions, optionalType, arrayType, syntaxType, group, output, printer } = ctx.options;
|
|
1266
1409
|
const { adapter, config, resolver, root } = ctx;
|
|
1267
|
-
const params =
|
|
1410
|
+
const params = caseParams(node.parameters, "camelcase");
|
|
1268
1411
|
const meta = { file: resolver.resolveFile({
|
|
1269
1412
|
name: node.operationId,
|
|
1270
1413
|
extname: ".ts",
|
|
@@ -1328,9 +1471,9 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1328
1471
|
*/
|
|
1329
1472
|
function buildContentTypeVariants(entries, baseName, decorate) {
|
|
1330
1473
|
const variants = resolveContentTypeVariants(entries, baseName);
|
|
1331
|
-
const unionSchema = _kubb_core.ast.createSchema({
|
|
1474
|
+
const unionSchema = _kubb_core.ast.factory.createSchema({
|
|
1332
1475
|
type: "union",
|
|
1333
|
-
members: variants.map((variant) => _kubb_core.ast.createSchema({
|
|
1476
|
+
members: variants.map((variant) => _kubb_core.ast.factory.createSchema({
|
|
1334
1477
|
type: "ref",
|
|
1335
1478
|
name: variant.name
|
|
1336
1479
|
}))
|
|
@@ -1345,7 +1488,10 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1345
1488
|
})] });
|
|
1346
1489
|
}
|
|
1347
1490
|
const paramTypes = params.map((param) => renderSchemaType({
|
|
1348
|
-
schema:
|
|
1491
|
+
schema: {
|
|
1492
|
+
...param.schema,
|
|
1493
|
+
optional: !param.required
|
|
1494
|
+
},
|
|
1349
1495
|
name: resolver.resolveParamName(node, param)
|
|
1350
1496
|
}));
|
|
1351
1497
|
const requestBodyContent = node.requestBody?.content ?? [];
|
|
@@ -1541,7 +1687,7 @@ const pluginTs = (0, _kubb_core.definePlugin)((options) => {
|
|
|
1541
1687
|
const { output = {
|
|
1542
1688
|
path: "types",
|
|
1543
1689
|
barrel: { type: "named" }
|
|
1544
|
-
}, group, exclude = [], include, override = [], enum: enumOptions = {}, optionalType = "questionToken", arrayType = "array", syntaxType = "type",
|
|
1690
|
+
}, group, exclude = [], include, override = [], enum: enumOptions = {}, optionalType = "questionToken", arrayType = "array", syntaxType = "type", printer, resolver: userResolver, macros: userMacros } = options;
|
|
1545
1691
|
const groupConfig = createGroupConfig(group);
|
|
1546
1692
|
const resolvedEnum = {
|
|
1547
1693
|
type: enumOptions.type ?? "asConst",
|
|
@@ -1563,52 +1709,237 @@ const pluginTs = (0, _kubb_core.definePlugin)((options) => {
|
|
|
1563
1709
|
arrayType,
|
|
1564
1710
|
enum: resolvedEnum,
|
|
1565
1711
|
syntaxType,
|
|
1566
|
-
paramsCasing,
|
|
1567
1712
|
printer
|
|
1568
1713
|
});
|
|
1569
1714
|
ctx.setResolver(userResolver ? {
|
|
1570
1715
|
...resolverTs,
|
|
1571
1716
|
...userResolver
|
|
1572
1717
|
} : resolverTs);
|
|
1573
|
-
if (
|
|
1718
|
+
if (userMacros?.length) ctx.setMacros(userMacros);
|
|
1574
1719
|
ctx.addGenerator(typeGenerator);
|
|
1575
|
-
for (const gen of userGenerators) ctx.addGenerator(gen);
|
|
1576
1720
|
} }
|
|
1577
1721
|
};
|
|
1578
1722
|
});
|
|
1579
1723
|
//#endregion
|
|
1724
|
+
//#region src/printers/functionParams.ts
|
|
1725
|
+
/**
|
|
1726
|
+
* Narrows a {@link TypeExpression} to a {@link TypeLiteralNode}.
|
|
1727
|
+
*/
|
|
1728
|
+
function isTypeLiteral(type) {
|
|
1729
|
+
return typeof type !== "string" && type.kind === "TypeLiteral";
|
|
1730
|
+
}
|
|
1731
|
+
/**
|
|
1732
|
+
* Narrows a {@link TypeExpression} to an {@link IndexedAccessTypeNode}.
|
|
1733
|
+
*/
|
|
1734
|
+
function isIndexedAccessType(type) {
|
|
1735
|
+
return typeof type !== "string" && type.kind === "IndexedAccessType";
|
|
1736
|
+
}
|
|
1737
|
+
/**
|
|
1738
|
+
* Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
|
|
1739
|
+
*
|
|
1740
|
+
* @example
|
|
1741
|
+
* ```ts
|
|
1742
|
+
* createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
|
|
1743
|
+
* // { petId: string }
|
|
1744
|
+
* ```
|
|
1745
|
+
*/
|
|
1746
|
+
function createTypeLiteral(props) {
|
|
1747
|
+
return {
|
|
1748
|
+
kind: "TypeLiteral",
|
|
1749
|
+
...props
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
* Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
|
|
1754
|
+
*
|
|
1755
|
+
* @example
|
|
1756
|
+
* ```ts
|
|
1757
|
+
* createIndexedAccessType({ target: 'DeletePetPathParams', key: 'petId' })
|
|
1758
|
+
* // DeletePetPathParams['petId']
|
|
1759
|
+
* ```
|
|
1760
|
+
*/
|
|
1761
|
+
function createIndexedAccessType(props) {
|
|
1762
|
+
return {
|
|
1763
|
+
kind: "IndexedAccessType",
|
|
1764
|
+
...props
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
/**
|
|
1768
|
+
* Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
|
|
1769
|
+
*
|
|
1770
|
+
* @example
|
|
1771
|
+
* ```ts
|
|
1772
|
+
* createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
|
|
1773
|
+
* // { id, name }
|
|
1774
|
+
* ```
|
|
1775
|
+
*/
|
|
1776
|
+
function createObjectBindingPattern(props) {
|
|
1777
|
+
return {
|
|
1778
|
+
kind: "ObjectBindingPattern",
|
|
1779
|
+
...props
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
/**
|
|
1783
|
+
* Creates a {@link FunctionParameterNode}. `optional` defaults to `false`.
|
|
1784
|
+
* Passing `properties` builds a destructured group: an {@link ObjectBindingPatternNode} name
|
|
1785
|
+
* paired with a {@link TypeLiteralNode} type.
|
|
1786
|
+
*
|
|
1787
|
+
* @example Optional param
|
|
1788
|
+
* ```ts
|
|
1789
|
+
* createFunctionParameter({ name: 'params', type: 'QueryParams', optional: true })
|
|
1790
|
+
* // → params?: QueryParams
|
|
1791
|
+
* ```
|
|
1792
|
+
*
|
|
1793
|
+
* @example Destructured group
|
|
1794
|
+
* ```ts
|
|
1795
|
+
* createFunctionParameter({ properties: [{ name: 'id', type: 'string' }, { name: 'name', type: 'string', optional: true }], default: '{}' })
|
|
1796
|
+
* // → { id, name }: { id: string; name?: string } = {}
|
|
1797
|
+
* ```
|
|
1798
|
+
*/
|
|
1799
|
+
function createFunctionParameter(input) {
|
|
1800
|
+
if ("properties" in input) return {
|
|
1801
|
+
kind: "FunctionParameter",
|
|
1802
|
+
name: createObjectBindingPattern({ elements: input.properties.map((p) => ({ name: p.name })) }),
|
|
1803
|
+
type: createTypeLiteral({ members: input.properties.map((p) => ({
|
|
1804
|
+
name: p.name,
|
|
1805
|
+
type: p.type,
|
|
1806
|
+
optional: p.optional ?? false
|
|
1807
|
+
})) }),
|
|
1808
|
+
optional: input.optional ?? false,
|
|
1809
|
+
...input.default !== void 0 ? { default: input.default } : {}
|
|
1810
|
+
};
|
|
1811
|
+
return {
|
|
1812
|
+
kind: "FunctionParameter",
|
|
1813
|
+
optional: false,
|
|
1814
|
+
...input
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
/**
|
|
1818
|
+
* Creates a {@link FunctionParametersNode} from an ordered list of parameters.
|
|
1819
|
+
*
|
|
1820
|
+
* @example
|
|
1821
|
+
* ```ts
|
|
1822
|
+
* const empty = createFunctionParameters()
|
|
1823
|
+
* // { params: [] }
|
|
1824
|
+
* ```
|
|
1825
|
+
*/
|
|
1826
|
+
function createFunctionParameters(props = {}) {
|
|
1827
|
+
return {
|
|
1828
|
+
kind: "FunctionParameters",
|
|
1829
|
+
params: [],
|
|
1830
|
+
...props
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
//#endregion
|
|
1580
1834
|
//#region src/printers/functionPrinter.ts
|
|
1581
|
-
const kindToHandlerKey = {
|
|
1582
|
-
FunctionParameter: "functionParameter",
|
|
1583
|
-
ParameterGroup: "parameterGroup",
|
|
1584
|
-
FunctionParameters: "functionParameters",
|
|
1585
|
-
ParamsType: "paramsType"
|
|
1586
|
-
};
|
|
1587
1835
|
/**
|
|
1588
|
-
*
|
|
1836
|
+
* Renders a {@link TypeExpression} to its TypeScript source.
|
|
1589
1837
|
*
|
|
1590
|
-
*
|
|
1591
|
-
*
|
|
1838
|
+
* - a `string` is a type reference, returned as-is
|
|
1839
|
+
* - an `IndexedAccessType` becomes `objectType['indexType']`
|
|
1840
|
+
* - a `TypeLiteral` becomes `{ key: Type; key?: Type }`
|
|
1841
|
+
*
|
|
1842
|
+
* `transformType` is applied once to the fully rendered type, matching how the
|
|
1843
|
+
* printer wrapped reference types before the `ts.factory` model.
|
|
1844
|
+
*/
|
|
1845
|
+
function renderType(type, transformType) {
|
|
1846
|
+
const rendered = renderTypeExpression(type);
|
|
1847
|
+
return transformType ? transformType(rendered) : rendered;
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Renders an object-type key, quoting it as a string literal when it is not a valid
|
|
1851
|
+
* identifier so `{ 'content-type': string }` stays valid TypeScript.
|
|
1592
1852
|
*/
|
|
1593
|
-
|
|
1853
|
+
function renderKey(name) {
|
|
1854
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
1855
|
+
}
|
|
1856
|
+
function renderTypeExpression(type) {
|
|
1857
|
+
if (typeof type === "string") return type;
|
|
1858
|
+
if (isIndexedAccessType(type)) return `${type.target}['${type.key}']`;
|
|
1859
|
+
return `{ ${type.members.map((member) => {
|
|
1860
|
+
const value = renderTypeExpression(member.type);
|
|
1861
|
+
return member.optional ? `${renderKey(member.name)}?: ${value}` : `${renderKey(member.name)}: ${value}`;
|
|
1862
|
+
}).join("; ")} }`;
|
|
1863
|
+
}
|
|
1864
|
+
function groupMembers(param) {
|
|
1865
|
+
if (typeof param.name === "string") return null;
|
|
1866
|
+
return param.type && isTypeLiteral(param.type) ? param.type.members : [];
|
|
1867
|
+
}
|
|
1594
1868
|
function rank(param) {
|
|
1595
|
-
if (param.kind === "ParameterGroup") {
|
|
1596
|
-
if (param.default) return PARAM_RANK.withDefault;
|
|
1597
|
-
return param.optional ?? param.properties.every((p) => p.optional || p.default !== void 0) ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
1598
|
-
}
|
|
1599
1869
|
if (param.rest) return PARAM_RANK.rest;
|
|
1600
1870
|
if (param.default) return PARAM_RANK.withDefault;
|
|
1871
|
+
const members = groupMembers(param);
|
|
1872
|
+
if (members) return members.every((m) => m.optional) ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
1601
1873
|
return param.optional ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
1602
1874
|
}
|
|
1603
1875
|
function sortParams(params) {
|
|
1604
1876
|
return params.toSorted((a, b) => rank(a) - rank(b));
|
|
1605
1877
|
}
|
|
1606
|
-
function
|
|
1607
|
-
|
|
1878
|
+
function sortedGroupMembers(name, type) {
|
|
1879
|
+
const members = type && isTypeLiteral(type) ? type.members : [];
|
|
1880
|
+
const memberRank = (optional) => optional ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
1881
|
+
return name.elements.map((element, index) => ({
|
|
1882
|
+
name: element.name,
|
|
1883
|
+
propertyName: element.propertyName,
|
|
1884
|
+
type: members[index]?.type,
|
|
1885
|
+
optional: members[index]?.optional
|
|
1886
|
+
})).toSorted((a, b) => memberRank(a.optional) - memberRank(b.optional));
|
|
1608
1887
|
}
|
|
1609
1888
|
/**
|
|
1610
|
-
*
|
|
1611
|
-
*
|
|
1889
|
+
* Renders one binding element: the local name, prefixed with its source key when the
|
|
1890
|
+
* binding renames the property, as in `{ petId: id }`.
|
|
1891
|
+
*/
|
|
1892
|
+
function renderBindingMember(member, transformName) {
|
|
1893
|
+
const local = transformName ? transformName(member.name) : member.name;
|
|
1894
|
+
return member.propertyName ? `${member.propertyName}: ${local}` : local;
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Renders the type annotation of a destructured group. An inline object type is
|
|
1898
|
+
* rendered from the already-sorted members so its key order matches the binding;
|
|
1899
|
+
* a reference type is rendered as-is.
|
|
1900
|
+
*/
|
|
1901
|
+
function renderGroupType(type, sorted, transformType) {
|
|
1902
|
+
if (!type) return void 0;
|
|
1903
|
+
if (!isTypeLiteral(type)) return renderType(type);
|
|
1904
|
+
const typed = sorted.filter((member) => member.type !== void 0);
|
|
1905
|
+
if (!typed.length) return void 0;
|
|
1906
|
+
return `{ ${typed.map((member) => {
|
|
1907
|
+
const key = renderKey(member.propertyName ?? member.name);
|
|
1908
|
+
const value = renderType(member.type, transformType);
|
|
1909
|
+
return member.optional ? `${key}?: ${value}` : `${key}: ${value}`;
|
|
1910
|
+
}).join("; ")} }`;
|
|
1911
|
+
}
|
|
1912
|
+
function printParameter(node, options) {
|
|
1913
|
+
const { mode, transformName, transformType } = options;
|
|
1914
|
+
const isGroup = typeof node.name !== "string";
|
|
1915
|
+
if (mode === "call") {
|
|
1916
|
+
if (isGroup) return `{ ${sortedGroupMembers(node.name, node.type).map((member) => renderBindingMember(member)).join(", ")} }`;
|
|
1917
|
+
const name = transformName ? transformName(node.name) : node.name;
|
|
1918
|
+
return node.rest ? `...${name}` : name;
|
|
1919
|
+
}
|
|
1920
|
+
if (isGroup) {
|
|
1921
|
+
const sorted = sortedGroupMembers(node.name, node.type);
|
|
1922
|
+
const binding = `{ ${sorted.map((member) => renderBindingMember(member, transformName)).join(", ")} }`;
|
|
1923
|
+
const allOptional = sorted.every((member) => member.optional);
|
|
1924
|
+
const type = renderGroupType(node.type, sorted, transformType);
|
|
1925
|
+
if (type) {
|
|
1926
|
+
if (allOptional) return `${binding}: ${type} = ${node.default ?? "{}"}`;
|
|
1927
|
+
return node.default ? `${binding}: ${type} = ${node.default}` : `${binding}: ${type}`;
|
|
1928
|
+
}
|
|
1929
|
+
return node.default ? `${binding} = ${node.default}` : binding;
|
|
1930
|
+
}
|
|
1931
|
+
const name = transformName ? transformName(node.name) : node.name;
|
|
1932
|
+
const type = node.type ? renderType(node.type, transformType) : void 0;
|
|
1933
|
+
if (node.rest) return type ? `...${name}: ${type}` : `...${name}`;
|
|
1934
|
+
if (type) {
|
|
1935
|
+
if (node.optional) return `${name}?: ${type}`;
|
|
1936
|
+
return node.default ? `${name}: ${type} = ${node.default}` : `${name}: ${type}`;
|
|
1937
|
+
}
|
|
1938
|
+
return node.default ? `${name} = ${node.default}` : name;
|
|
1939
|
+
}
|
|
1940
|
+
/**
|
|
1941
|
+
* Default function-signature printer. Renders a parameter list in one of two modes:
|
|
1942
|
+
* `declaration` for the function signature and `call` for the call arguments.
|
|
1612
1943
|
*
|
|
1613
1944
|
* @example
|
|
1614
1945
|
* ```ts
|
|
@@ -1624,75 +1955,212 @@ function sortChildParams(params) {
|
|
|
1624
1955
|
* printer.print(sig) // → "petId: string, config: Config = {}"
|
|
1625
1956
|
* ```
|
|
1626
1957
|
*/
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1958
|
+
function functionPrinter(options) {
|
|
1959
|
+
return {
|
|
1960
|
+
name: "functionParameters",
|
|
1961
|
+
options,
|
|
1962
|
+
print(node) {
|
|
1963
|
+
return sortParams(node.params).map((p) => printParameter(p, options)).filter(Boolean).join(", ");
|
|
1964
|
+
}
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1967
|
+
//#endregion
|
|
1968
|
+
//#region src/printers/operationParams.ts
|
|
1969
|
+
/**
|
|
1970
|
+
* Resolves the {@link TypeExpression} for an individual parameter.
|
|
1971
|
+
*
|
|
1972
|
+
* Without a resolver, it falls back to the schema primitive (a plain type-name string). When the
|
|
1973
|
+
* parameter belongs to a named group, it emits an `IndexedAccessType` like `GroupParams['petId']`,
|
|
1974
|
+
* otherwise the resolved individual name.
|
|
1975
|
+
*/
|
|
1976
|
+
function resolveParamType({ node, param, resolver }) {
|
|
1977
|
+
if (!resolver) return param.schema.primitive ?? "unknown";
|
|
1978
|
+
const individualName = resolver.resolveParamName(node, param);
|
|
1979
|
+
const groupLocation = param.in === "path" || param.in === "query" || param.in === "header" ? param.in : void 0;
|
|
1980
|
+
const groupResolvers = {
|
|
1981
|
+
path: resolver.resolvePathParamsName,
|
|
1982
|
+
query: resolver.resolveQueryParamsName,
|
|
1983
|
+
header: resolver.resolveHeaderParamsName
|
|
1984
|
+
};
|
|
1985
|
+
const groupName = groupLocation ? groupResolvers[groupLocation].call(resolver, node, param) : void 0;
|
|
1986
|
+
if (groupName && groupName !== individualName) return createIndexedAccessType({
|
|
1987
|
+
target: groupName,
|
|
1988
|
+
key: param.name
|
|
1989
|
+
});
|
|
1990
|
+
return individualName;
|
|
1991
|
+
}
|
|
1992
|
+
/**
|
|
1993
|
+
* Derives a {@link ParamGroupType} for a query or header group from the resolver.
|
|
1994
|
+
*
|
|
1995
|
+
* Returns `null` when there is no resolver, no params, or the group name equals the
|
|
1996
|
+
* individual param name (so there is no real group to emit).
|
|
1997
|
+
*/
|
|
1998
|
+
function resolveGroupType({ node, params, group, resolver }) {
|
|
1999
|
+
if (!resolver || !params.length) return null;
|
|
2000
|
+
const firstParam = params[0];
|
|
2001
|
+
const groupName = (group === "query" ? resolver.resolveQueryParamsName : resolver.resolveHeaderParamsName).call(resolver, node, firstParam);
|
|
2002
|
+
if (groupName === resolver.resolveParamName(node, firstParam)) return null;
|
|
2003
|
+
return {
|
|
2004
|
+
type: groupName,
|
|
2005
|
+
optional: params.every((p) => !p.required)
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Converts an `OperationNode` into function parameters for code generation.
|
|
2010
|
+
*
|
|
2011
|
+
* Centralizes parameter grouping logic for all plugins. `paramsType` chooses between one
|
|
2012
|
+
* destructured object parameter (`object`) and separate top-level parameters (`inline`), while
|
|
2013
|
+
* `pathParamsType` controls how path params render in inline mode. Provide a `resolver` for type
|
|
2014
|
+
* name resolution and `extraParams` for plugin-specific trailing parameters such as an `options` object.
|
|
2015
|
+
*/
|
|
2016
|
+
function createOperationParams(node, options) {
|
|
2017
|
+
const { paramsType, pathParamsType, paramsCasing, resolver, pathParamsDefault, extraParams = [], paramNames, typeWrapper } = options;
|
|
2018
|
+
const dataName = paramNames?.data ?? "data";
|
|
2019
|
+
const paramsName = paramNames?.params ?? "params";
|
|
2020
|
+
const headersName = paramNames?.headers ?? "headers";
|
|
2021
|
+
const pathName = paramNames?.path ?? "pathParams";
|
|
2022
|
+
const wrapType = (type) => typeWrapper ? typeWrapper(type) : type;
|
|
2023
|
+
const wrapTypeExpression = (type) => typeof type === "string" ? wrapType(type) : type;
|
|
2024
|
+
const casedParams = caseParams(node.parameters, paramsCasing);
|
|
2025
|
+
const pathParams = casedParams.filter((p) => p.in === "path");
|
|
2026
|
+
const queryParams = casedParams.filter((p) => p.in === "query");
|
|
2027
|
+
const headerParams = casedParams.filter((p) => p.in === "header");
|
|
2028
|
+
const toProperty = (param) => ({
|
|
2029
|
+
name: param.name,
|
|
2030
|
+
type: wrapTypeExpression(resolveParamType({
|
|
2031
|
+
node,
|
|
2032
|
+
param,
|
|
2033
|
+
resolver
|
|
2034
|
+
})),
|
|
2035
|
+
optional: !param.required
|
|
2036
|
+
});
|
|
2037
|
+
const emptyObjectDefault = (props) => props.every((p) => p.optional) ? "{}" : void 0;
|
|
2038
|
+
const bodyType = node.requestBody?.content?.[0]?.schema ? wrapType(resolver?.resolveDataName(node) ?? "unknown") : void 0;
|
|
2039
|
+
const bodyProperty = bodyType ? [{
|
|
2040
|
+
name: dataName,
|
|
2041
|
+
type: bodyType,
|
|
2042
|
+
optional: !(node.requestBody?.required ?? false)
|
|
2043
|
+
}] : [];
|
|
2044
|
+
const trailingGroups = [{
|
|
2045
|
+
name: paramsName,
|
|
2046
|
+
node,
|
|
2047
|
+
params: queryParams,
|
|
2048
|
+
groupType: resolveGroupType({
|
|
2049
|
+
node,
|
|
2050
|
+
params: queryParams,
|
|
2051
|
+
group: "query",
|
|
2052
|
+
resolver
|
|
2053
|
+
}),
|
|
2054
|
+
resolver,
|
|
2055
|
+
wrapType
|
|
2056
|
+
}, {
|
|
2057
|
+
name: headersName,
|
|
2058
|
+
node,
|
|
2059
|
+
params: headerParams,
|
|
2060
|
+
groupType: resolveGroupType({
|
|
2061
|
+
node,
|
|
2062
|
+
params: headerParams,
|
|
2063
|
+
group: "header",
|
|
2064
|
+
resolver
|
|
2065
|
+
}),
|
|
2066
|
+
resolver,
|
|
2067
|
+
wrapType
|
|
2068
|
+
}];
|
|
2069
|
+
const params = [];
|
|
2070
|
+
if (paramsType === "object") {
|
|
2071
|
+
const children = [
|
|
2072
|
+
...pathParams.map(toProperty),
|
|
2073
|
+
...bodyProperty,
|
|
2074
|
+
...trailingGroups.flatMap(buildGroupProperty)
|
|
2075
|
+
];
|
|
2076
|
+
if (children.length) params.push(createFunctionParameter({
|
|
2077
|
+
properties: children,
|
|
2078
|
+
default: emptyObjectDefault(children)
|
|
2079
|
+
}));
|
|
2080
|
+
} else {
|
|
2081
|
+
if (pathParamsType === "inlineSpread" && pathParams.length) {
|
|
2082
|
+
const spreadType = resolver?.resolvePathParamsName(node, pathParams[0]);
|
|
2083
|
+
params.push(createFunctionParameter({
|
|
2084
|
+
name: pathName,
|
|
2085
|
+
type: spreadType ? wrapType(spreadType) : void 0,
|
|
2086
|
+
rest: true
|
|
2087
|
+
}));
|
|
2088
|
+
} else if (pathParamsType === "inline") params.push(...pathParams.map((p) => createFunctionParameter(toProperty(p))));
|
|
2089
|
+
else if (pathParams.length) {
|
|
2090
|
+
const pathChildren = pathParams.map(toProperty);
|
|
2091
|
+
params.push(createFunctionParameter({
|
|
2092
|
+
properties: pathChildren,
|
|
2093
|
+
default: pathParamsDefault ?? emptyObjectDefault(pathChildren)
|
|
2094
|
+
}));
|
|
1685
2095
|
}
|
|
2096
|
+
params.push(...bodyProperty.map((p) => createFunctionParameter(p)));
|
|
2097
|
+
params.push(...trailingGroups.flatMap(buildGroupParam));
|
|
1686
2098
|
}
|
|
1687
|
-
|
|
2099
|
+
params.push(...extraParams);
|
|
2100
|
+
return createFunctionParameters({ params });
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* Builds the property descriptor for a query or header group.
|
|
2104
|
+
* Returns an empty array when there are no params to emit.
|
|
2105
|
+
*
|
|
2106
|
+
* A pre-resolved `groupType` emits `name: GroupType`. Otherwise it builds an inline
|
|
2107
|
+
* {@link TypeLiteralNode} from the individual params.
|
|
2108
|
+
*/
|
|
2109
|
+
function buildGroupProperty({ name, node, params, groupType, resolver, wrapType }) {
|
|
2110
|
+
if (groupType) return [{
|
|
2111
|
+
name,
|
|
2112
|
+
type: typeof groupType.type === "string" ? wrapType(groupType.type) : groupType.type,
|
|
2113
|
+
optional: groupType.optional
|
|
2114
|
+
}];
|
|
2115
|
+
if (params.length) return [{
|
|
2116
|
+
name,
|
|
2117
|
+
type: buildTypeLiteral({
|
|
2118
|
+
node,
|
|
2119
|
+
params,
|
|
2120
|
+
resolver
|
|
2121
|
+
}),
|
|
2122
|
+
optional: params.every((p) => !p.required)
|
|
2123
|
+
}];
|
|
2124
|
+
return [];
|
|
2125
|
+
}
|
|
2126
|
+
/**
|
|
2127
|
+
* Builds a single {@link FunctionParameterNode} for a query or header group.
|
|
2128
|
+
* Returns an empty array when there are no params to emit.
|
|
2129
|
+
*/
|
|
2130
|
+
function buildGroupParam(args) {
|
|
2131
|
+
return buildGroupProperty(args).map((p) => createFunctionParameter(p));
|
|
2132
|
+
}
|
|
2133
|
+
/**
|
|
2134
|
+
* Builds a {@link TypeLiteralNode} for an inline anonymous type grouping named fields.
|
|
2135
|
+
*
|
|
2136
|
+
* Used when query or header parameters have no dedicated group type name.
|
|
2137
|
+
*/
|
|
2138
|
+
function buildTypeLiteral({ node, params, resolver }) {
|
|
2139
|
+
return createTypeLiteral({ members: params.map((p) => ({
|
|
2140
|
+
name: p.name,
|
|
2141
|
+
type: resolveParamType({
|
|
2142
|
+
node,
|
|
2143
|
+
param: p,
|
|
2144
|
+
resolver
|
|
2145
|
+
}),
|
|
2146
|
+
optional: !p.required
|
|
2147
|
+
})) });
|
|
2148
|
+
}
|
|
1688
2149
|
//#endregion
|
|
1689
2150
|
exports.Enum = Enum;
|
|
1690
2151
|
exports.Type = Type;
|
|
2152
|
+
exports.createFunctionParameter = createFunctionParameter;
|
|
2153
|
+
exports.createFunctionParameters = createFunctionParameters;
|
|
2154
|
+
exports.createIndexedAccessType = createIndexedAccessType;
|
|
2155
|
+
exports.createObjectBindingPattern = createObjectBindingPattern;
|
|
2156
|
+
exports.createOperationParams = createOperationParams;
|
|
2157
|
+
exports.createTypeLiteral = createTypeLiteral;
|
|
1691
2158
|
exports.default = pluginTs;
|
|
1692
2159
|
exports.functionPrinter = functionPrinter;
|
|
1693
2160
|
exports.pluginTs = pluginTs;
|
|
1694
2161
|
exports.pluginTsName = pluginTsName;
|
|
1695
2162
|
exports.printerTs = printerTs;
|
|
2163
|
+
exports.renderType = renderType;
|
|
1696
2164
|
exports.resolverTs = resolverTs;
|
|
1697
2165
|
exports.typeGenerator = typeGenerator;
|
|
1698
2166
|
|