@kubb/plugin-ts 5.0.10 → 5.0.12
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 +113 -495
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +18 -147
- package/dist/index.js +113 -495
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -292,47 +292,6 @@ function toFilePath(name, caseLast = camelCase) {
|
|
|
292
292
|
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
293
293
|
}
|
|
294
294
|
//#endregion
|
|
295
|
-
//#region src/constants.ts
|
|
296
|
-
/**
|
|
297
|
-
* `optionalType` values that cause a property's type to include `| undefined`.
|
|
298
|
-
*/
|
|
299
|
-
const OPTIONAL_ADDS_UNDEFINED = /* @__PURE__ */ new Set(["undefined", "questionTokenAndUndefined"]);
|
|
300
|
-
/**
|
|
301
|
-
* `optionalType` values that render the property key with a `?` token.
|
|
302
|
-
*/
|
|
303
|
-
const OPTIONAL_ADDS_QUESTION_TOKEN = /* @__PURE__ */ new Set(["questionToken", "questionTokenAndUndefined"]);
|
|
304
|
-
/**
|
|
305
|
-
* `enum.type` values that append a `typeSuffix` to the generated enum type alias.
|
|
306
|
-
*/
|
|
307
|
-
const ENUM_TYPES_WITH_KEY_SUFFIX = /* @__PURE__ */ new Set(["asConst"]);
|
|
308
|
-
/**
|
|
309
|
-
* `enum.type` values that require a runtime value declaration (object, enum, or literal).
|
|
310
|
-
*/
|
|
311
|
-
const ENUM_TYPES_WITH_RUNTIME_VALUE = /* @__PURE__ */ new Set([
|
|
312
|
-
"enum",
|
|
313
|
-
"asConst",
|
|
314
|
-
"constEnum",
|
|
315
|
-
"literal",
|
|
316
|
-
void 0
|
|
317
|
-
]);
|
|
318
|
-
/**
|
|
319
|
-
* `enum.type` values whose type declaration is type-only (no runtime value emitted for the type alias).
|
|
320
|
-
*/
|
|
321
|
-
const ENUM_TYPES_WITH_TYPE_ONLY = /* @__PURE__ */ new Set([
|
|
322
|
-
"asConst",
|
|
323
|
-
"literal",
|
|
324
|
-
void 0
|
|
325
|
-
]);
|
|
326
|
-
/**
|
|
327
|
-
* Ordering priority for function parameters: lower = sorted earlier.
|
|
328
|
-
*/
|
|
329
|
-
const PARAM_RANK = {
|
|
330
|
-
required: 0,
|
|
331
|
-
optional: 1,
|
|
332
|
-
withDefault: 2,
|
|
333
|
-
rest: 3
|
|
334
|
-
};
|
|
335
|
-
//#endregion
|
|
336
295
|
//#region src/factory.ts
|
|
337
296
|
var factory_exports = /* @__PURE__ */ __exportAll({
|
|
338
297
|
appendJSDocToNode: () => appendJSDocToNode,
|
|
@@ -343,14 +302,9 @@ var factory_exports = /* @__PURE__ */ __exportAll({
|
|
|
343
302
|
constToTypeNode: () => constToTypeNode,
|
|
344
303
|
createArrayDeclaration: () => createArrayDeclaration,
|
|
345
304
|
createEnumDeclaration: () => createEnumDeclaration,
|
|
346
|
-
createExportDeclaration: () => createExportDeclaration,
|
|
347
|
-
createImportDeclaration: () => createImportDeclaration,
|
|
348
305
|
createIntersectionDeclaration: () => createIntersectionDeclaration,
|
|
349
|
-
createJSDoc: () => createJSDoc,
|
|
350
306
|
createOmitDeclaration: () => createOmitDeclaration,
|
|
351
|
-
createParameterSignature: () => createParameterSignature,
|
|
352
307
|
createPropertySignature: () => createPropertySignature,
|
|
353
|
-
createQuestionToken: () => createQuestionToken,
|
|
354
308
|
createTypeDeclaration: () => createTypeDeclaration,
|
|
355
309
|
createTypeLiteralNode: () => createTypeLiteralNode,
|
|
356
310
|
createTypeReferenceNode: () => createTypeReferenceNode,
|
|
@@ -358,9 +312,10 @@ var factory_exports = /* @__PURE__ */ __exportAll({
|
|
|
358
312
|
createUrlTemplateType: () => createUrlTemplateType,
|
|
359
313
|
dateOrStringNode: () => dateOrStringNode,
|
|
360
314
|
isNonNullable: () => isNonNullable$1,
|
|
315
|
+
isUnionTypeNode: () => isUnionTypeNode,
|
|
361
316
|
keywordTypeNodes: () => keywordTypeNodes,
|
|
362
317
|
modifiers: () => modifiers,
|
|
363
|
-
|
|
318
|
+
wrapNullableOptional: () => wrapNullableOptional
|
|
364
319
|
});
|
|
365
320
|
/**
|
|
366
321
|
* Loaded with `require`, not `import`. When ESM imports a CommonJS package, Node keeps a second
|
|
@@ -368,35 +323,14 @@ var factory_exports = /* @__PURE__ */ __exportAll({
|
|
|
368
323
|
*/
|
|
369
324
|
const typescript = createRequire(import.meta.url)("typescript");
|
|
370
325
|
const { SyntaxKind, factory } = typescript;
|
|
371
|
-
/**
|
|
372
|
-
* Compares two strings by UTF-16 code unit, keeping sorted output identical across platforms
|
|
373
|
-
* regardless of locale.
|
|
374
|
-
*/
|
|
375
|
-
function compareStrings(a, b) {
|
|
376
|
-
if (a < b) return -1;
|
|
377
|
-
if (a > b) return 1;
|
|
378
|
-
return 0;
|
|
379
|
-
}
|
|
380
326
|
function isNumber(value) {
|
|
381
327
|
return typeof value === "number" && !Number.isNaN(value);
|
|
382
328
|
}
|
|
383
329
|
/**
|
|
384
|
-
* TypeScript AST modifiers for
|
|
330
|
+
* TypeScript AST modifiers for the `export` keyword.
|
|
385
331
|
*/
|
|
386
|
-
const modifiers = {
|
|
387
|
-
|
|
388
|
-
export: factory.createModifier(typescript.SyntaxKind.ExportKeyword),
|
|
389
|
-
const: factory.createModifier(typescript.SyntaxKind.ConstKeyword),
|
|
390
|
-
static: factory.createModifier(typescript.SyntaxKind.StaticKeyword)
|
|
391
|
-
};
|
|
392
|
-
/**
|
|
393
|
-
* TypeScript syntax kind constants for union, literal, and string types.
|
|
394
|
-
*/
|
|
395
|
-
const syntaxKind = {
|
|
396
|
-
union: SyntaxKind.UnionType,
|
|
397
|
-
literalType: SyntaxKind.LiteralType,
|
|
398
|
-
stringLiteral: SyntaxKind.StringLiteral
|
|
399
|
-
};
|
|
332
|
+
const modifiers = { export: factory.createModifier(typescript.SyntaxKind.ExportKeyword) };
|
|
333
|
+
const isUnionTypeNode = typescript.isUnionTypeNode;
|
|
400
334
|
function isNonNullable$1(value) {
|
|
401
335
|
return value !== null && value !== void 0;
|
|
402
336
|
}
|
|
@@ -450,7 +384,6 @@ function createArrayDeclaration({ nodes, arrayType = "array" }) {
|
|
|
450
384
|
if (!nodes.length) return factory.createTupleTypeNode([]);
|
|
451
385
|
if (nodes.length === 1) {
|
|
452
386
|
const node = nodes[0];
|
|
453
|
-
if (!node) return null;
|
|
454
387
|
if (arrayType === "generic") return factory.createTypeReferenceNode(factory.createIdentifier("Array"), [node]);
|
|
455
388
|
return factory.createArrayTypeNode(node);
|
|
456
389
|
}
|
|
@@ -478,23 +411,6 @@ function createPropertySignature({ readOnly, modifiers = [], name, questionToken
|
|
|
478
411
|
return factory.createPropertySignature([...modifiers, readOnly ? factory.createToken(typescript.SyntaxKind.ReadonlyKeyword) : void 0].filter((modifier) => modifier !== void 0), propertyName(name), createQuestionToken(questionToken), type);
|
|
479
412
|
}
|
|
480
413
|
/**
|
|
481
|
-
* Creates a function parameter declaration with optional markers, rest parameters, and type annotations.
|
|
482
|
-
*/
|
|
483
|
-
function createParameterSignature(name, { modifiers, dotDotDotToken, questionToken, type, initializer }) {
|
|
484
|
-
return factory.createParameterDeclaration(modifiers, dotDotDotToken, name, createQuestionToken(questionToken), type, initializer);
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Creates a JSDoc comment node from an array of comment strings.
|
|
488
|
-
* Returns null if no comments are provided.
|
|
489
|
-
*/
|
|
490
|
-
function createJSDoc({ comments }) {
|
|
491
|
-
if (!comments.length) return null;
|
|
492
|
-
return factory.createJSDocComment(factory.createNodeArray(comments.map((comment, i) => {
|
|
493
|
-
if (i === comments.length - 1) return factory.createJSDocText(comment);
|
|
494
|
-
return factory.createJSDocText(`${comment}\n`);
|
|
495
|
-
})));
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
414
|
* Attaches JSDoc comments to an AST node as synthetic leading comments.
|
|
499
415
|
* Filters out undefined comments before attaching.
|
|
500
416
|
*
|
|
@@ -513,19 +429,7 @@ function appendJSDocToNode({ node, comments }) {
|
|
|
513
429
|
* Defines the key type (default: `string`) and value type on an object.
|
|
514
430
|
*/
|
|
515
431
|
function createIndexSignature(type, { modifiers, indexName = "key", indexType = factory.createKeywordTypeNode(typescript.SyntaxKind.StringKeyword) } = {}) {
|
|
516
|
-
return factory.createIndexSignature(modifiers, [
|
|
517
|
-
}
|
|
518
|
-
/**
|
|
519
|
-
* Creates a TypeScript type alias declaration with optional modifiers and type parameters.
|
|
520
|
-
*/
|
|
521
|
-
function createTypeAliasDeclaration({ modifiers, name, typeParameters, type }) {
|
|
522
|
-
return factory.createTypeAliasDeclaration(modifiers, name, typeParameters, type);
|
|
523
|
-
}
|
|
524
|
-
/**
|
|
525
|
-
* Creates a TypeScript interface declaration with optional modifiers, type parameters, and members.
|
|
526
|
-
*/
|
|
527
|
-
function createInterfaceDeclaration({ modifiers, name, typeParameters, members }) {
|
|
528
|
-
return factory.createInterfaceDeclaration(modifiers, name, typeParameters, void 0, members);
|
|
432
|
+
return factory.createIndexSignature(modifiers, [factory.createParameterDeclaration(void 0, void 0, indexName, void 0, indexType)], type);
|
|
529
433
|
}
|
|
530
434
|
/**
|
|
531
435
|
* Creates a TypeScript type declaration as either a type alias or interface.
|
|
@@ -533,67 +437,22 @@ function createInterfaceDeclaration({ modifiers, name, typeParameters, members }
|
|
|
533
437
|
*/
|
|
534
438
|
function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
|
|
535
439
|
if (syntax === "interface" && typescript.isTypeLiteralNode(type)) return appendJSDocToNode({
|
|
536
|
-
node: createInterfaceDeclaration(
|
|
537
|
-
members: [...type.members],
|
|
538
|
-
modifiers: isExportable ? [modifiers.export] : [],
|
|
539
|
-
name,
|
|
540
|
-
typeParameters: void 0
|
|
541
|
-
}),
|
|
440
|
+
node: factory.createInterfaceDeclaration(isExportable ? [modifiers.export] : [], name, void 0, void 0, [...type.members]),
|
|
542
441
|
comments
|
|
543
442
|
});
|
|
544
443
|
return appendJSDocToNode({
|
|
545
|
-
node: createTypeAliasDeclaration(
|
|
546
|
-
type,
|
|
547
|
-
modifiers: isExportable ? [modifiers.export] : [],
|
|
548
|
-
name,
|
|
549
|
-
typeParameters: void 0
|
|
550
|
-
}),
|
|
444
|
+
node: factory.createTypeAliasDeclaration(isExportable ? [modifiers.export] : [], name, void 0, type),
|
|
551
445
|
comments
|
|
552
446
|
});
|
|
553
447
|
}
|
|
554
448
|
/**
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
* @example Default import
|
|
559
|
-
* `import Pet from './Pet'`
|
|
560
|
-
*
|
|
561
|
-
* @example Named imports with rename
|
|
562
|
-
* `import { Pet as Cat } from './Pet'`
|
|
563
|
-
*
|
|
564
|
-
* @example Namespace import
|
|
565
|
-
* `import * as Pet from './Pet'`
|
|
566
|
-
*/
|
|
567
|
-
function createImportDeclaration({ name, path, isTypeOnly = false, isNameSpace = false }) {
|
|
568
|
-
if (!Array.isArray(name)) {
|
|
569
|
-
const importPropertyName = isNameSpace ? void 0 : factory.createIdentifier(name);
|
|
570
|
-
const importName = isNameSpace ? factory.createNamespaceImport(factory.createIdentifier(name)) : void 0;
|
|
571
|
-
return factory.createImportDeclaration(void 0, factory.createImportClause(isTypeOnly, importPropertyName, importName), factory.createStringLiteral(path), void 0);
|
|
572
|
-
}
|
|
573
|
-
const sortedName = name.toSorted((a, b) => compareStrings(typeof a === "object" ? a.propertyName : a, typeof b === "object" ? b.propertyName : b));
|
|
574
|
-
return factory.createImportDeclaration(void 0, factory.createImportClause(isTypeOnly, void 0, factory.createNamedImports(sortedName.map((item) => {
|
|
575
|
-
if (typeof item === "object") {
|
|
576
|
-
const obj = item;
|
|
577
|
-
if (obj.name) return factory.createImportSpecifier(false, factory.createIdentifier(obj.propertyName), factory.createIdentifier(obj.name));
|
|
578
|
-
return factory.createImportSpecifier(false, void 0, factory.createIdentifier(obj.propertyName));
|
|
579
|
-
}
|
|
580
|
-
return factory.createImportSpecifier(false, void 0, factory.createIdentifier(item));
|
|
581
|
-
}))), factory.createStringLiteral(path), void 0);
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Creates an export declaration with support for named exports, namespace exports, and type-only exports.
|
|
585
|
-
* Sorts export names alphabetically for consistent output across platforms.
|
|
449
|
+
* Converts an enum member value to a literal expression. Numbers become numeric literals (negatives use a prefix
|
|
450
|
+
* minus, as `createNumericLiteral` rejects them) unless `asNumber` is `false`, which emits the string form.
|
|
586
451
|
*/
|
|
587
|
-
function
|
|
588
|
-
if (
|
|
589
|
-
if (
|
|
590
|
-
|
|
591
|
-
return factory.createExportDeclaration(void 0, isTypeOnly, asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : void 0, factory.createStringLiteral(path), void 0);
|
|
592
|
-
}
|
|
593
|
-
const sortedName = name.toSorted((a, b) => compareStrings(typeof a === "string" ? a : a.text, typeof b === "string" ? b : b.text));
|
|
594
|
-
return factory.createExportDeclaration(void 0, isTypeOnly, factory.createNamedExports(sortedName.map((propertyName) => {
|
|
595
|
-
return factory.createExportSpecifier(false, void 0, typeof propertyName === "string" ? factory.createIdentifier(propertyName) : propertyName);
|
|
596
|
-
})), factory.createStringLiteral(path), void 0);
|
|
452
|
+
function valueToExpression(value, asNumber = isNumber(value)) {
|
|
453
|
+
if (typeof value === "boolean") return value ? factory.createTrue() : factory.createFalse();
|
|
454
|
+
if (asNumber && isNumber(value)) return value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value))) : factory.createNumericLiteral(value);
|
|
455
|
+
return factory.createStringLiteral(value.toString());
|
|
597
456
|
}
|
|
598
457
|
/**
|
|
599
458
|
* Apply casing transformation to enum keys
|
|
@@ -630,12 +489,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
630
489
|
if (value !== null && value !== void 0) return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString()));
|
|
631
490
|
}).filter((node) => node !== void 0)))];
|
|
632
491
|
if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(typescript.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(typescript.SyntaxKind.ConstKeyword) : void 0].filter((modifier) => modifier !== void 0), factory.createIdentifier(typeName), enums.map(([key, value, description]) => {
|
|
633
|
-
|
|
634
|
-
if (Number.parseInt(value.toString(), 10) === value && isNumber(value)) {
|
|
635
|
-
if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
636
|
-
else initializer = factory.createNumericLiteral(value);
|
|
637
|
-
}
|
|
638
|
-
if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
|
|
492
|
+
const initializer = valueToExpression(value, Number.parseInt(value.toString(), 10) === value);
|
|
639
493
|
if (isNumber(Number.parseInt(key.toString(), 10))) {
|
|
640
494
|
const casingKey = applyEnumKeyCasing(`${typeName}_${key}`, enumKeyCasing);
|
|
641
495
|
return appendJSDocToNode({
|
|
@@ -654,12 +508,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
|
|
|
654
508
|
const identifierName = name;
|
|
655
509
|
if (enums.length === 0) return [void 0, factory.createTypeAliasDeclaration([factory.createToken(typescript.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createKeywordTypeNode(typescript.SyntaxKind.NeverKeyword))];
|
|
656
510
|
return [factory.createVariableStatement([factory.createToken(typescript.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(identifierName), void 0, void 0, factory.createAsExpression(factory.createObjectLiteralExpression(enums.map(([key, value, description]) => {
|
|
657
|
-
|
|
658
|
-
if (isNumber(value)) {
|
|
659
|
-
if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
660
|
-
else initializer = factory.createNumericLiteral(value);
|
|
661
|
-
}
|
|
662
|
-
if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
|
|
511
|
+
const initializer = valueToExpression(value);
|
|
663
512
|
if (key !== null && key !== void 0) {
|
|
664
513
|
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
665
514
|
return appendJSDocToNode({
|
|
@@ -738,66 +587,19 @@ const createTypeLiteralNode = factory.createTypeLiteralNode;
|
|
|
738
587
|
*/
|
|
739
588
|
const createTypeReferenceNode = factory.createTypeReferenceNode;
|
|
740
589
|
/**
|
|
741
|
-
* Creates a numeric literal type node.
|
|
742
|
-
*/
|
|
743
|
-
const createNumericLiteral = factory.createNumericLiteral;
|
|
744
|
-
/**
|
|
745
|
-
* Creates a string literal type node.
|
|
746
|
-
*/
|
|
747
|
-
const createStringLiteral = factory.createStringLiteral;
|
|
748
|
-
/**
|
|
749
|
-
* Creates an array type node (e.g., `T[]`).
|
|
750
|
-
*/
|
|
751
|
-
const createArrayTypeNode = factory.createArrayTypeNode;
|
|
752
|
-
/**
|
|
753
|
-
* Creates a literal type node (e.g., `'hello'`, `42`, `true`).
|
|
754
|
-
*/
|
|
755
|
-
const createLiteralTypeNode = factory.createLiteralTypeNode;
|
|
756
|
-
/**
|
|
757
|
-
* Creates an identifier node.
|
|
758
|
-
*/
|
|
759
|
-
const createIdentifier = factory.createIdentifier;
|
|
760
|
-
/**
|
|
761
|
-
* Creates an optional type node (e.g., `T | undefined`).
|
|
762
|
-
*/
|
|
763
|
-
const createOptionalTypeNode = factory.createOptionalTypeNode;
|
|
764
|
-
/**
|
|
765
|
-
* Creates a tuple type node (e.g., `[string, number]`).
|
|
766
|
-
*/
|
|
767
|
-
const createTupleTypeNode = factory.createTupleTypeNode;
|
|
768
|
-
/**
|
|
769
|
-
* Creates a rest type node for variadic tuple elements (e.g., `...T[]`).
|
|
770
|
-
*/
|
|
771
|
-
const createRestTypeNode = factory.createRestTypeNode;
|
|
772
|
-
/**
|
|
773
|
-
* Creates a boolean true literal type node.
|
|
774
|
-
*/
|
|
775
|
-
const createTrue = factory.createTrue;
|
|
776
|
-
/**
|
|
777
|
-
* Creates a boolean false literal type node.
|
|
778
|
-
*/
|
|
779
|
-
const createFalse = factory.createFalse;
|
|
780
|
-
/**
|
|
781
|
-
* Creates a prefix unary expression (e.g., negative numbers, logical not).
|
|
782
|
-
*/
|
|
783
|
-
const createPrefixUnaryExpression = factory.createPrefixUnaryExpression;
|
|
784
|
-
/**
|
|
785
590
|
* Converts a primitive const value to a TypeScript literal type node.
|
|
786
591
|
* Handles negative numbers via a prefix unary expression.
|
|
787
592
|
*/
|
|
788
593
|
function constToTypeNode(value, format) {
|
|
789
|
-
if (format === "boolean") return createLiteralTypeNode(value === true ? createTrue() : createFalse());
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
return createLiteralTypeNode(createNumericLiteral(value));
|
|
793
|
-
}
|
|
794
|
-
return createLiteralTypeNode(createStringLiteral(String(value)));
|
|
594
|
+
if (format === "boolean") return factory.createLiteralTypeNode(value === true ? factory.createTrue() : factory.createFalse());
|
|
595
|
+
const literal = format === "number" && typeof value === "number" ? value : String(value);
|
|
596
|
+
return factory.createLiteralTypeNode(valueToExpression(literal));
|
|
795
597
|
}
|
|
796
598
|
/**
|
|
797
599
|
* Returns a `Date` reference type node when `representation` is `'date'`, otherwise falls back to `string`.
|
|
798
600
|
*/
|
|
799
601
|
function dateOrStringNode(node) {
|
|
800
|
-
return node.representation === "date" ? createTypeReferenceNode(createIdentifier("Date")) : keywordTypeNodes.string;
|
|
602
|
+
return node.representation === "date" ? createTypeReferenceNode(factory.createIdentifier("Date")) : keywordTypeNodes.string;
|
|
801
603
|
}
|
|
802
604
|
/**
|
|
803
605
|
* Maps an array of `SchemaNode`s through the printer, filtering out `null` and `undefined` results.
|
|
@@ -817,20 +619,24 @@ function buildTupleNode(node, print) {
|
|
|
817
619
|
items = items.slice(0, max);
|
|
818
620
|
if (items.length < max && restNode) items = [...items, ...Array(max - items.length).fill(restNode)];
|
|
819
621
|
}
|
|
820
|
-
if (min !== void 0) items = items.map((item, i) => i >= min ? createOptionalTypeNode(item) : item);
|
|
821
|
-
if (max === void 0 && restNode) items.push(createRestTypeNode(createArrayTypeNode(restNode)));
|
|
822
|
-
return createTupleTypeNode(items);
|
|
622
|
+
if (min !== void 0) items = items.map((item, i) => i >= min ? factory.createOptionalTypeNode(item) : item);
|
|
623
|
+
if (max === void 0 && restNode) items.push(factory.createRestTypeNode(factory.createArrayTypeNode(restNode)));
|
|
624
|
+
return factory.createTupleTypeNode(items);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Appends `| null` and then `| undefined` to a type when requested.
|
|
628
|
+
*/
|
|
629
|
+
function wrapNullableOptional(type, nullable, addsUndefined) {
|
|
630
|
+
const withNullable = nullable ? createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] }) : type;
|
|
631
|
+
return addsUndefined ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
823
632
|
}
|
|
824
633
|
/**
|
|
825
634
|
* Applies `nullable` and optional/nullish `| undefined` union modifiers to a property's resolved base type.
|
|
826
635
|
*/
|
|
827
636
|
function buildPropertyType(schema, baseType, optionalType, optional) {
|
|
828
|
-
const addsUndefined =
|
|
637
|
+
const addsUndefined = optionalType === "undefined" || optionalType === "questionTokenAndUndefined";
|
|
829
638
|
const meta = syncSchemaRef(schema);
|
|
830
|
-
|
|
831
|
-
if (meta.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
|
|
832
|
-
if ((optional || meta.nullish || meta.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
833
|
-
return type;
|
|
639
|
+
return wrapNullableOptional(baseType, !!meta.nullable, addsUndefined && !!(optional || meta.nullish || meta.optional));
|
|
834
640
|
}
|
|
835
641
|
const indexSignaturePrinter = typescript.createPrinter();
|
|
836
642
|
const indexSignatureSource = typescript.createSourceFile("", "", typescript.ScriptTarget.Latest);
|
|
@@ -873,7 +679,7 @@ function getEnumNames({ node, enum: enumOptions, resolver }) {
|
|
|
873
679
|
const resolved = resolver.name(node.name);
|
|
874
680
|
return {
|
|
875
681
|
enumName: enumOptions.constCasing === "pascalCase" ? resolved : camelCase(node.name),
|
|
876
|
-
typeName:
|
|
682
|
+
typeName: enumOptions.type === "asConst" ? resolver.enum.keyName(node, enumOptions.typeSuffix) : resolved
|
|
877
683
|
};
|
|
878
684
|
}
|
|
879
685
|
/**
|
|
@@ -914,30 +720,16 @@ function Enum({ node, enum: enumOptions, resolver }) {
|
|
|
914
720
|
}), /* @__PURE__ */ jsx(File.Source, {
|
|
915
721
|
name: typeName,
|
|
916
722
|
isIndexable: !namesMerge,
|
|
917
|
-
isExportable: !namesMerge &&
|
|
918
|
-
isTypeOnly:
|
|
723
|
+
isExportable: !namesMerge && enumOptions.type !== "inlineLiteral",
|
|
724
|
+
isTypeOnly: [
|
|
725
|
+
"asConst",
|
|
726
|
+
"literal",
|
|
727
|
+
void 0
|
|
728
|
+
].includes(enumOptions.type),
|
|
919
729
|
children: parserTs().print(typeNode)
|
|
920
730
|
})] });
|
|
921
731
|
}
|
|
922
732
|
//#endregion
|
|
923
|
-
//#region ../../internals/shared/src/params.ts
|
|
924
|
-
/**
|
|
925
|
-
* Drops parameters that share the same name, keeping the first.
|
|
926
|
-
*
|
|
927
|
-
* A malformed spec can declare the same parameter name twice within one `in` location. Both would
|
|
928
|
-
* resolve to the same output property, so emitting both would yield an object type with a duplicate
|
|
929
|
-
* member, which TypeScript rejects. This is a defensive guard against that case, not a casing guard:
|
|
930
|
-
* parameter names flow through unchanged, so no two distinct names ever collide here anymore.
|
|
931
|
-
*/
|
|
932
|
-
function dedupeParams(params) {
|
|
933
|
-
const seen = /* @__PURE__ */ new Set();
|
|
934
|
-
return params.filter((param) => {
|
|
935
|
-
if (seen.has(param.name)) return false;
|
|
936
|
-
seen.add(param.name);
|
|
937
|
-
return true;
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
//#endregion
|
|
941
733
|
//#region ../../internals/shared/src/operation.ts
|
|
942
734
|
/**
|
|
943
735
|
* Maps a content type to the PascalCase suffix used to name per-content-type variants
|
|
@@ -997,11 +789,19 @@ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
|
|
|
997
789
|
function getOperationParameters(node) {
|
|
998
790
|
const cached = operationParameterGroupsByNode.get(node);
|
|
999
791
|
if (cached) return cached;
|
|
792
|
+
const group = (location) => {
|
|
793
|
+
const seen = /* @__PURE__ */ new Set();
|
|
794
|
+
return node.parameters.filter((param) => {
|
|
795
|
+
if (param.in !== location || seen.has(param.name)) return false;
|
|
796
|
+
seen.add(param.name);
|
|
797
|
+
return true;
|
|
798
|
+
});
|
|
799
|
+
};
|
|
1000
800
|
const groups = {
|
|
1001
|
-
path:
|
|
1002
|
-
query:
|
|
1003
|
-
header:
|
|
1004
|
-
cookie:
|
|
801
|
+
path: group("path"),
|
|
802
|
+
query: group("query"),
|
|
803
|
+
header: group("header"),
|
|
804
|
+
cookie: group("cookie")
|
|
1005
805
|
};
|
|
1006
806
|
operationParameterGroupsByNode.set(node, groups);
|
|
1007
807
|
return groups;
|
|
@@ -1203,20 +1003,6 @@ function createCasedFile(caseLast) {
|
|
|
1203
1003
|
} };
|
|
1204
1004
|
}
|
|
1205
1005
|
//#endregion
|
|
1206
|
-
//#region ../../internals/shared/src/refs.ts
|
|
1207
|
-
/**
|
|
1208
|
-
* Collects the resolved target name of every pointer-carrying ref in a schema tree, in
|
|
1209
|
-
* first-occurrence order. Use this for name-only checks (e.g. redeclaration detection) where
|
|
1210
|
-
* `resolver.imports` would resolve file paths that are then discarded.
|
|
1211
|
-
*/
|
|
1212
|
-
function collectRefNames(schema) {
|
|
1213
|
-
return ast.collectSync(schema, { schema: (node) => {
|
|
1214
|
-
const refNode = ast.narrowSchema(node, "ref");
|
|
1215
|
-
if (!refNode?.ref) return null;
|
|
1216
|
-
return ast.resolveRefName(refNode);
|
|
1217
|
-
} });
|
|
1218
|
-
}
|
|
1219
|
-
//#endregion
|
|
1220
1006
|
//#region ../../internals/shared/src/group.ts
|
|
1221
1007
|
/**
|
|
1222
1008
|
* Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
|
|
@@ -1278,6 +1064,9 @@ function mapSchemaItems(node, transform) {
|
|
|
1278
1064
|
}
|
|
1279
1065
|
//#endregion
|
|
1280
1066
|
//#region src/utils.ts
|
|
1067
|
+
function enumTypeName({ resolver, name, enumOptions, isEnum }) {
|
|
1068
|
+
return isEnum && enumOptions?.type === "asConst" && enumOptions.typeSuffix ? resolver.enum.keyName({ name }, enumOptions.typeSuffix) : resolver.name(name);
|
|
1069
|
+
}
|
|
1281
1070
|
/**
|
|
1282
1071
|
* Tells whether a `const` (single-value enum) should render as a bare literal type (`'active'`)
|
|
1283
1072
|
* rather than a named enum reference or a runtime enum declaration.
|
|
@@ -1414,7 +1203,7 @@ const { isNonNullable } = factory_exports;
|
|
|
1414
1203
|
* ```
|
|
1415
1204
|
*/
|
|
1416
1205
|
const printerTs = ast.createPrinter((options) => {
|
|
1417
|
-
const addsUndefined =
|
|
1206
|
+
const addsUndefined = options.optionalType === "undefined" || options.optionalType === "questionTokenAndUndefined";
|
|
1418
1207
|
return {
|
|
1419
1208
|
name: "typescript",
|
|
1420
1209
|
options,
|
|
@@ -1445,7 +1234,12 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1445
1234
|
if (!node.name) return null;
|
|
1446
1235
|
const refName = ast.resolveRefName(node);
|
|
1447
1236
|
if (!refName) return null;
|
|
1448
|
-
const name = node.ref
|
|
1237
|
+
const name = node.ref ? enumTypeName({
|
|
1238
|
+
resolver: this.options.resolver,
|
|
1239
|
+
name: refName,
|
|
1240
|
+
enumOptions: this.options.enum,
|
|
1241
|
+
isEnum: !!this.options.enumSchemaNames?.has(refName)
|
|
1242
|
+
}) : refName;
|
|
1449
1243
|
return createTypeReferenceNode(name, void 0);
|
|
1450
1244
|
},
|
|
1451
1245
|
enum(node) {
|
|
@@ -1453,8 +1247,13 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1453
1247
|
if (this.options.enum.type === "inlineLiteral" || !node.name || isInlineConstEnum(node, this.options.enumSchemaNames)) return createUnionDeclaration({
|
|
1454
1248
|
withParentheses: true,
|
|
1455
1249
|
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(isNonNullable)
|
|
1456
|
-
})
|
|
1457
|
-
const resolvedName =
|
|
1250
|
+
});
|
|
1251
|
+
const resolvedName = enumTypeName({
|
|
1252
|
+
resolver: this.options.resolver,
|
|
1253
|
+
name: node.name,
|
|
1254
|
+
enumOptions: this.options.enum,
|
|
1255
|
+
isEnum: true
|
|
1256
|
+
});
|
|
1458
1257
|
return createTypeReferenceNode(resolvedName, void 0);
|
|
1459
1258
|
},
|
|
1460
1259
|
union(node) {
|
|
@@ -1472,30 +1271,30 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1472
1271
|
});
|
|
1473
1272
|
return this.transform(m);
|
|
1474
1273
|
}).filter(isNonNullable)
|
|
1475
|
-
})
|
|
1274
|
+
});
|
|
1476
1275
|
return createUnionDeclaration({
|
|
1477
1276
|
withParentheses: true,
|
|
1478
1277
|
nodes: buildMemberNodes(members, this.transform)
|
|
1479
|
-
})
|
|
1278
|
+
});
|
|
1480
1279
|
},
|
|
1481
1280
|
intersection(node) {
|
|
1482
1281
|
return createIntersectionDeclaration({
|
|
1483
1282
|
withParentheses: true,
|
|
1484
1283
|
nodes: buildMemberNodes(node.members, this.transform)
|
|
1485
|
-
})
|
|
1284
|
+
});
|
|
1486
1285
|
},
|
|
1487
1286
|
array(node) {
|
|
1488
1287
|
return createArrayDeclaration({
|
|
1489
1288
|
nodes: mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(isNonNullable),
|
|
1490
1289
|
arrayType: this.options.arrayType
|
|
1491
|
-
})
|
|
1290
|
+
});
|
|
1492
1291
|
},
|
|
1493
1292
|
tuple(node) {
|
|
1494
|
-
return buildTupleNode(node, this.transform)
|
|
1293
|
+
return buildTupleNode(node, this.transform);
|
|
1495
1294
|
},
|
|
1496
1295
|
object(node) {
|
|
1497
1296
|
const { transform, options } = this;
|
|
1498
|
-
const addsQuestionToken =
|
|
1297
|
+
const addsQuestionToken = options.optionalType === "questionToken" || options.optionalType === "questionTokenAndUndefined";
|
|
1499
1298
|
const propertyNodes = mapSchemaProperties(node, (schema) => transform(schema)).map(({ name, property, output }) => {
|
|
1500
1299
|
const baseType = output ?? keywordTypeNodes.unknown;
|
|
1501
1300
|
const optional = !property.required || !!property.schema.optional || !!property.schema.nullish;
|
|
@@ -1523,24 +1322,21 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1523
1322
|
if (!transformed) return null;
|
|
1524
1323
|
const meta = syncSchemaRef(node);
|
|
1525
1324
|
if (!name) {
|
|
1526
|
-
const
|
|
1527
|
-
const result = (meta.nullish || meta.optional) && addsUndefined ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
1325
|
+
const result = wrapNullableOptional(transformed, !!meta.nullable, !!(meta.nullish || meta.optional) && addsUndefined);
|
|
1528
1326
|
return parserTs().print(result);
|
|
1529
1327
|
}
|
|
1530
1328
|
const inner = (() => {
|
|
1531
|
-
|
|
1329
|
+
return wrapNullableOptional(keysToOmit?.length ? createOmitDeclaration({
|
|
1532
1330
|
keys: keysToOmit,
|
|
1533
1331
|
type: transformed,
|
|
1534
1332
|
nonNullable: true
|
|
1535
|
-
}) : transformed;
|
|
1536
|
-
const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [omitted, keywordTypeNodes.null] }) : omitted;
|
|
1537
|
-
return meta.nullish || meta.optional ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
1333
|
+
}) : transformed, !!meta.nullable, !!(meta.nullish || meta.optional));
|
|
1538
1334
|
})();
|
|
1539
1335
|
const typeNode = createTypeDeclaration({
|
|
1540
1336
|
name,
|
|
1541
1337
|
isExportable: true,
|
|
1542
1338
|
type: inner,
|
|
1543
|
-
syntax: syntaxType === "type" || inner
|
|
1339
|
+
syntax: syntaxType === "type" || isUnionTypeNode(inner) || !!keysToOmit?.length ? "type" : "interface",
|
|
1544
1340
|
comments: buildPropertyJSDocComments({
|
|
1545
1341
|
...meta,
|
|
1546
1342
|
description
|
|
@@ -1553,15 +1349,6 @@ const printerTs = ast.createPrinter((options) => {
|
|
|
1553
1349
|
//#endregion
|
|
1554
1350
|
//#region src/generators/typeGenerator.tsx
|
|
1555
1351
|
/**
|
|
1556
|
-
* Resolves the imported type name for a referenced schema. An enum schema emitted
|
|
1557
|
-
* as a `const` object imports its suffixed key alias (e.g. `StatusKey`); every other
|
|
1558
|
-
* schema imports its plain resolved name.
|
|
1559
|
-
*/
|
|
1560
|
-
function resolveImportName({ schemaName, enumOptions, enumSchemaNames, resolver }) {
|
|
1561
|
-
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
|
|
1562
|
-
return resolver.name(schemaName);
|
|
1563
|
-
}
|
|
1564
|
-
/**
|
|
1565
1352
|
* Built-in generator for `@kubb/plugin-ts`. Emits one TypeScript file per
|
|
1566
1353
|
* schema in the spec plus per-operation request, response, and parameter
|
|
1567
1354
|
* types. Drop-replace with a custom `Generator<PluginTs>` to change how
|
|
@@ -1575,11 +1362,11 @@ const typeGenerator = defineGenerator({
|
|
|
1575
1362
|
const { config, resolver, root } = ctx;
|
|
1576
1363
|
if (!node.name) return;
|
|
1577
1364
|
const enumSchemaNames = new Set(ctx.meta.enumNames);
|
|
1578
|
-
const importName = (schemaName) =>
|
|
1579
|
-
|
|
1365
|
+
const importName = (schemaName) => enumTypeName({
|
|
1366
|
+
resolver,
|
|
1367
|
+
name: schemaName,
|
|
1580
1368
|
enumOptions,
|
|
1581
|
-
enumSchemaNames
|
|
1582
|
-
resolver
|
|
1369
|
+
isEnum: enumSchemaNames.has(schemaName)
|
|
1583
1370
|
});
|
|
1584
1371
|
const imports = resolver.imports({
|
|
1585
1372
|
node,
|
|
@@ -1591,7 +1378,7 @@ const typeGenerator = defineGenerator({
|
|
|
1591
1378
|
const enumNode = ast.narrowSchema(node, ast.schemaTypes.enum);
|
|
1592
1379
|
const isEnumSchema = !!enumNode && !isInlineConstEnum(enumNode, enumSchemaNames);
|
|
1593
1380
|
const meta = {
|
|
1594
|
-
name:
|
|
1381
|
+
name: enumOptions.type === "asConst" && isEnumSchema ? resolver.enum.keyName(node, enumOptions.typeSuffix) : resolver.name(node.name),
|
|
1595
1382
|
file: resolver.file({
|
|
1596
1383
|
name: node.name,
|
|
1597
1384
|
extname: ".ts",
|
|
@@ -1662,11 +1449,11 @@ const typeGenerator = defineGenerator({
|
|
|
1662
1449
|
group: group ?? void 0
|
|
1663
1450
|
}) };
|
|
1664
1451
|
const enumSchemaNames = new Set(ctx.meta.enumNames);
|
|
1665
|
-
const importName = (schemaName) =>
|
|
1666
|
-
|
|
1452
|
+
const importName = (schemaName) => enumTypeName({
|
|
1453
|
+
resolver,
|
|
1454
|
+
name: schemaName,
|
|
1667
1455
|
enumOptions,
|
|
1668
|
-
enumSchemaNames
|
|
1669
|
-
resolver
|
|
1456
|
+
isEnum: enumSchemaNames.has(schemaName)
|
|
1670
1457
|
});
|
|
1671
1458
|
function renderSchemaType({ schema, name, keysToOmit }) {
|
|
1672
1459
|
if (!schema) return null;
|
|
@@ -1789,7 +1576,7 @@ const typeGenerator = defineGenerator({
|
|
|
1789
1576
|
if (!node.responses.some(hasSchema)) return null;
|
|
1790
1577
|
const responseName = resolver.response.response(node);
|
|
1791
1578
|
const responsesWithSchema = node.responses.filter(hasSchema);
|
|
1792
|
-
if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ?
|
|
1579
|
+
if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? ast.collectImportedRefNames(entry.schema).map(importName) : []))).has(responseName)) return null;
|
|
1793
1580
|
return renderSchemaType({
|
|
1794
1581
|
schema: {
|
|
1795
1582
|
...buildResponseUnion(node, { resolver }),
|
|
@@ -1838,7 +1625,7 @@ var compatibility = {
|
|
|
1838
1625
|
};
|
|
1839
1626
|
//#endregion
|
|
1840
1627
|
//#region package.json
|
|
1841
|
-
var version = "5.0.
|
|
1628
|
+
var version = "5.0.12";
|
|
1842
1629
|
//#endregion
|
|
1843
1630
|
//#region src/resolvers/resolverTs.ts
|
|
1844
1631
|
/**
|
|
@@ -2116,6 +1903,15 @@ function createFunctionParameters(props = {}) {
|
|
|
2116
1903
|
//#endregion
|
|
2117
1904
|
//#region src/printers/functionPrinter.ts
|
|
2118
1905
|
/**
|
|
1906
|
+
* Ordering priority for function parameters: lower = sorted earlier.
|
|
1907
|
+
*/
|
|
1908
|
+
const PARAM_RANK = {
|
|
1909
|
+
required: 0,
|
|
1910
|
+
optional: 1,
|
|
1911
|
+
withDefault: 2,
|
|
1912
|
+
rest: 3
|
|
1913
|
+
};
|
|
1914
|
+
/**
|
|
2119
1915
|
* Renders a {@link TypeExpression} to its TypeScript source.
|
|
2120
1916
|
*
|
|
2121
1917
|
* - a `string` is a type reference, returned as-is
|
|
@@ -2136,13 +1932,17 @@ function renderType(type, transformType) {
|
|
|
2136
1932
|
function renderKey(name) {
|
|
2137
1933
|
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
2138
1934
|
}
|
|
1935
|
+
function renderMembers(members) {
|
|
1936
|
+
return `{ ${members.map((member) => `${renderKey(member.key)}${member.optional ? "?" : ""}: ${member.type}`).join("; ")} }`;
|
|
1937
|
+
}
|
|
2139
1938
|
function renderTypeExpression(type) {
|
|
2140
1939
|
if (typeof type === "string") return type;
|
|
2141
1940
|
if (isIndexedAccessType(type)) return `${type.target}['${type.key}']`;
|
|
2142
|
-
return
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
1941
|
+
return renderMembers(type.members.map((member) => ({
|
|
1942
|
+
key: member.name,
|
|
1943
|
+
type: renderTypeExpression(member.type),
|
|
1944
|
+
optional: member.optional
|
|
1945
|
+
})));
|
|
2146
1946
|
}
|
|
2147
1947
|
function groupMembers(param) {
|
|
2148
1948
|
if (typeof param.name === "string") return null;
|
|
@@ -2155,9 +1955,6 @@ function rank(param) {
|
|
|
2155
1955
|
if (members) return members.every((m) => m.optional) ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
2156
1956
|
return param.optional ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
2157
1957
|
}
|
|
2158
|
-
function sortParams(params) {
|
|
2159
|
-
return params.toSorted((a, b) => rank(a) - rank(b));
|
|
2160
|
-
}
|
|
2161
1958
|
function sortedGroupMembers(name, type) {
|
|
2162
1959
|
const members = type && isTypeLiteral(type) ? type.members : [];
|
|
2163
1960
|
const memberRank = (optional) => optional ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
@@ -2186,11 +1983,11 @@ function renderGroupType(type, sorted, transformType) {
|
|
|
2186
1983
|
if (!isTypeLiteral(type)) return renderType(type);
|
|
2187
1984
|
const typed = sorted.filter((member) => member.type !== void 0);
|
|
2188
1985
|
if (!typed.length) return void 0;
|
|
2189
|
-
return
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
})
|
|
1986
|
+
return renderMembers(typed.map((member) => ({
|
|
1987
|
+
key: member.propertyName ?? member.name,
|
|
1988
|
+
type: renderType(member.type, transformType),
|
|
1989
|
+
optional: member.optional
|
|
1990
|
+
})));
|
|
2194
1991
|
}
|
|
2195
1992
|
function printParameter(node, options) {
|
|
2196
1993
|
const { mode, transformName, transformType } = options;
|
|
@@ -2243,190 +2040,11 @@ function functionPrinter(options) {
|
|
|
2243
2040
|
name: "functionParameters",
|
|
2244
2041
|
options,
|
|
2245
2042
|
print(node) {
|
|
2246
|
-
return
|
|
2043
|
+
return node.params.toSorted((a, b) => rank(a) - rank(b)).map((p) => printParameter(p, options)).filter(Boolean).join(", ");
|
|
2247
2044
|
}
|
|
2248
2045
|
};
|
|
2249
2046
|
}
|
|
2250
2047
|
//#endregion
|
|
2251
|
-
|
|
2252
|
-
/**
|
|
2253
|
-
* Resolves the {@link TypeExpression} for an individual parameter.
|
|
2254
|
-
*
|
|
2255
|
-
* Without a resolver, it falls back to the schema primitive (a plain type-name string). When the
|
|
2256
|
-
* parameter belongs to a named group, it emits an `IndexedAccessType` like `GroupParams['petId']`,
|
|
2257
|
-
* otherwise the resolved individual name.
|
|
2258
|
-
*/
|
|
2259
|
-
function resolveParamType({ node, param, resolver }) {
|
|
2260
|
-
if (!resolver) return param.schema.primitive ?? "unknown";
|
|
2261
|
-
const individualName = resolver.param.name(node, param);
|
|
2262
|
-
const groupLocation = param.in === "path" || param.in === "query" || param.in === "header" ? param.in : void 0;
|
|
2263
|
-
const groupResolvers = {
|
|
2264
|
-
path: resolver.param.path,
|
|
2265
|
-
query: resolver.param.query,
|
|
2266
|
-
header: resolver.param.headers
|
|
2267
|
-
};
|
|
2268
|
-
const groupName = groupLocation ? groupResolvers[groupLocation].call(resolver, node, param) : void 0;
|
|
2269
|
-
if (groupName && groupName !== individualName) return createIndexedAccessType({
|
|
2270
|
-
target: groupName,
|
|
2271
|
-
key: param.name
|
|
2272
|
-
});
|
|
2273
|
-
return individualName;
|
|
2274
|
-
}
|
|
2275
|
-
/**
|
|
2276
|
-
* Derives a {@link ParamGroupType} for a query or header group from the resolver.
|
|
2277
|
-
*
|
|
2278
|
-
* Returns `null` when there is no resolver, no params, or the group name equals the
|
|
2279
|
-
* individual param name (so there is no real group to emit).
|
|
2280
|
-
*/
|
|
2281
|
-
function resolveGroupType({ node, params, group, resolver }) {
|
|
2282
|
-
if (!resolver || !params.length) return null;
|
|
2283
|
-
const firstParam = params[0];
|
|
2284
|
-
const groupName = (group === "query" ? resolver.param.query : resolver.param.headers).call(resolver, node, firstParam);
|
|
2285
|
-
if (groupName === resolver.param.name(node, firstParam)) return null;
|
|
2286
|
-
return {
|
|
2287
|
-
type: groupName,
|
|
2288
|
-
optional: params.every((p) => !p.required)
|
|
2289
|
-
};
|
|
2290
|
-
}
|
|
2291
|
-
/**
|
|
2292
|
-
* Converts an `OperationNode` into function parameters for code generation.
|
|
2293
|
-
*
|
|
2294
|
-
* Centralizes parameter grouping logic for all plugins. `paramsType` chooses between one
|
|
2295
|
-
* destructured object parameter (`object`) and separate top-level parameters (`inline`), while
|
|
2296
|
-
* `pathParamsType` controls how path params render in inline mode. Provide a `resolver` for type
|
|
2297
|
-
* name resolution and `extraParams` for plugin-specific trailing parameters such as an `options` object.
|
|
2298
|
-
*/
|
|
2299
|
-
function createOperationParams(node, options) {
|
|
2300
|
-
const { paramsType, pathParamsType, resolver, pathParamsDefault, extraParams = [], paramNames, typeWrapper } = options;
|
|
2301
|
-
const dataName = paramNames?.data ?? "data";
|
|
2302
|
-
const paramsName = paramNames?.params ?? "params";
|
|
2303
|
-
const headersName = paramNames?.headers ?? "headers";
|
|
2304
|
-
const pathName = paramNames?.path ?? "pathParams";
|
|
2305
|
-
const wrapType = (type) => typeWrapper ? typeWrapper(type) : type;
|
|
2306
|
-
const wrapTypeExpression = (type) => typeof type === "string" ? wrapType(type) : type;
|
|
2307
|
-
const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node);
|
|
2308
|
-
const toProperty = (param) => ({
|
|
2309
|
-
name: param.name,
|
|
2310
|
-
type: wrapTypeExpression(resolveParamType({
|
|
2311
|
-
node,
|
|
2312
|
-
param,
|
|
2313
|
-
resolver
|
|
2314
|
-
})),
|
|
2315
|
-
optional: !param.required
|
|
2316
|
-
});
|
|
2317
|
-
const emptyObjectDefault = (props) => props.every((p) => p.optional) ? "{}" : void 0;
|
|
2318
|
-
const bodyType = node.requestBody?.content?.[0]?.schema ? wrapType(resolver?.response.body(node) ?? "unknown") : void 0;
|
|
2319
|
-
const bodyProperty = bodyType ? [{
|
|
2320
|
-
name: dataName,
|
|
2321
|
-
type: bodyType,
|
|
2322
|
-
optional: !(node.requestBody?.required ?? false)
|
|
2323
|
-
}] : [];
|
|
2324
|
-
const trailingGroups = [{
|
|
2325
|
-
name: paramsName,
|
|
2326
|
-
node,
|
|
2327
|
-
params: queryParams,
|
|
2328
|
-
groupType: resolveGroupType({
|
|
2329
|
-
node,
|
|
2330
|
-
params: queryParams,
|
|
2331
|
-
group: "query",
|
|
2332
|
-
resolver
|
|
2333
|
-
}),
|
|
2334
|
-
resolver,
|
|
2335
|
-
wrapType
|
|
2336
|
-
}, {
|
|
2337
|
-
name: headersName,
|
|
2338
|
-
node,
|
|
2339
|
-
params: headerParams,
|
|
2340
|
-
groupType: resolveGroupType({
|
|
2341
|
-
node,
|
|
2342
|
-
params: headerParams,
|
|
2343
|
-
group: "header",
|
|
2344
|
-
resolver
|
|
2345
|
-
}),
|
|
2346
|
-
resolver,
|
|
2347
|
-
wrapType
|
|
2348
|
-
}];
|
|
2349
|
-
const params = [];
|
|
2350
|
-
if (paramsType === "object") {
|
|
2351
|
-
const children = [
|
|
2352
|
-
...pathParams.map(toProperty),
|
|
2353
|
-
...bodyProperty,
|
|
2354
|
-
...trailingGroups.flatMap(buildGroupProperty)
|
|
2355
|
-
];
|
|
2356
|
-
if (children.length) params.push(createFunctionParameter({
|
|
2357
|
-
properties: children,
|
|
2358
|
-
default: emptyObjectDefault(children)
|
|
2359
|
-
}));
|
|
2360
|
-
} else {
|
|
2361
|
-
if (pathParamsType === "inlineSpread" && pathParams.length) {
|
|
2362
|
-
const spreadType = resolver?.param.path(node, pathParams[0]);
|
|
2363
|
-
params.push(createFunctionParameter({
|
|
2364
|
-
name: pathName,
|
|
2365
|
-
type: spreadType ? wrapType(spreadType) : void 0,
|
|
2366
|
-
rest: true
|
|
2367
|
-
}));
|
|
2368
|
-
} else if (pathParamsType === "inline") params.push(...pathParams.map((p) => createFunctionParameter(toProperty(p))));
|
|
2369
|
-
else if (pathParams.length) {
|
|
2370
|
-
const pathChildren = pathParams.map(toProperty);
|
|
2371
|
-
params.push(createFunctionParameter({
|
|
2372
|
-
properties: pathChildren,
|
|
2373
|
-
default: pathParamsDefault ?? emptyObjectDefault(pathChildren)
|
|
2374
|
-
}));
|
|
2375
|
-
}
|
|
2376
|
-
params.push(...bodyProperty.map((p) => createFunctionParameter(p)));
|
|
2377
|
-
params.push(...trailingGroups.flatMap(buildGroupParam));
|
|
2378
|
-
}
|
|
2379
|
-
params.push(...extraParams);
|
|
2380
|
-
return createFunctionParameters({ params });
|
|
2381
|
-
}
|
|
2382
|
-
/**
|
|
2383
|
-
* Builds the property descriptor for a query or header group.
|
|
2384
|
-
* Returns an empty array when there are no params to emit.
|
|
2385
|
-
*
|
|
2386
|
-
* A pre-resolved `groupType` emits `name: GroupType`. Otherwise it builds an inline
|
|
2387
|
-
* {@link TypeLiteralNode} from the individual params.
|
|
2388
|
-
*/
|
|
2389
|
-
function buildGroupProperty({ name, node, params, groupType, resolver, wrapType }) {
|
|
2390
|
-
if (groupType) return [{
|
|
2391
|
-
name,
|
|
2392
|
-
type: typeof groupType.type === "string" ? wrapType(groupType.type) : groupType.type,
|
|
2393
|
-
optional: groupType.optional
|
|
2394
|
-
}];
|
|
2395
|
-
if (params.length) return [{
|
|
2396
|
-
name,
|
|
2397
|
-
type: buildTypeLiteral({
|
|
2398
|
-
node,
|
|
2399
|
-
params,
|
|
2400
|
-
resolver
|
|
2401
|
-
}),
|
|
2402
|
-
optional: params.every((p) => !p.required)
|
|
2403
|
-
}];
|
|
2404
|
-
return [];
|
|
2405
|
-
}
|
|
2406
|
-
/**
|
|
2407
|
-
* Builds a single {@link FunctionParameterNode} for a query or header group.
|
|
2408
|
-
* Returns an empty array when there are no params to emit.
|
|
2409
|
-
*/
|
|
2410
|
-
function buildGroupParam(args) {
|
|
2411
|
-
return buildGroupProperty(args).map((p) => createFunctionParameter(p));
|
|
2412
|
-
}
|
|
2413
|
-
/**
|
|
2414
|
-
* Builds a {@link TypeLiteralNode} for an inline anonymous type grouping named fields.
|
|
2415
|
-
*
|
|
2416
|
-
* Used when query or header parameters have no dedicated group type name.
|
|
2417
|
-
*/
|
|
2418
|
-
function buildTypeLiteral({ node, params, resolver }) {
|
|
2419
|
-
return createTypeLiteral({ members: params.map((p) => ({
|
|
2420
|
-
name: p.name,
|
|
2421
|
-
type: resolveParamType({
|
|
2422
|
-
node,
|
|
2423
|
-
param: p,
|
|
2424
|
-
resolver
|
|
2425
|
-
}),
|
|
2426
|
-
optional: !p.required
|
|
2427
|
-
})) });
|
|
2428
|
-
}
|
|
2429
|
-
//#endregion
|
|
2430
|
-
export { Enum, Type, buildParams, createFunctionParameter, createFunctionParameters, createIndexedAccessType, createObjectBindingPattern, createOperationParams, createTypeLiteral, pluginTs as default, pluginTs, functionPrinter, pluginTsName, printerTs, renderType, resolverTs, typeGenerator };
|
|
2048
|
+
export { Enum, Type, buildParams, createFunctionParameter, createFunctionParameters, createIndexedAccessType, createObjectBindingPattern, createTypeLiteral, pluginTs as default, pluginTs, enumTypeName, functionPrinter, pluginTsName, printerTs, renderType, resolverTs, typeGenerator };
|
|
2431
2049
|
|
|
2432
2050
|
//# sourceMappingURL=index.js.map
|