@kubb/plugin-ts 5.1.0-canary.20261023T200213 → 5.2.0-canary.20261024T091509
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 +357 -243
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +240 -17
- package/dist/index.d.ts +240 -17
- package/dist/index.js +357 -243
- package/dist/index.js.map +1 -1
- package/docs/guides/customization.md +5 -4
- package/package.json +14 -5
package/dist/index.cjs
CHANGED
|
@@ -18,11 +18,11 @@ var __exportAll = (all, no_symbols) => {
|
|
|
18
18
|
return target;
|
|
19
19
|
};
|
|
20
20
|
//#endregion
|
|
21
|
-
let _kubb_parser_ts = require("@kubb/parser-ts");
|
|
22
21
|
let kubb_jsx = require("kubb/jsx");
|
|
23
|
-
let node_module = require("node:module");
|
|
24
22
|
let kubb_kit = require("kubb/kit");
|
|
23
|
+
let yuku_codegen = require("yuku-codegen");
|
|
25
24
|
let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
|
|
25
|
+
let _kubb_parser_ts = require("@kubb/parser-ts");
|
|
26
26
|
//#region ../../internals/utils/src/casing.ts
|
|
27
27
|
/**
|
|
28
28
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -322,6 +322,7 @@ var factory_exports = /* @__PURE__ */ __exportAll({
|
|
|
322
322
|
createIntersectionDeclaration: () => createIntersectionDeclaration,
|
|
323
323
|
createOmitDeclaration: () => createOmitDeclaration,
|
|
324
324
|
createPropertySignature: () => createPropertySignature,
|
|
325
|
+
createRaw: () => createRaw,
|
|
325
326
|
createTypeDeclaration: () => createTypeDeclaration,
|
|
326
327
|
createTypeLiteralNode: () => createTypeLiteralNode,
|
|
327
328
|
createTypeReferenceNode: () => createTypeReferenceNode,
|
|
@@ -329,84 +330,113 @@ var factory_exports = /* @__PURE__ */ __exportAll({
|
|
|
329
330
|
createUrlTemplateType: () => createUrlTemplateType,
|
|
330
331
|
dateOrStringNode: () => dateOrStringNode,
|
|
331
332
|
isNonNullable: () => isNonNullable$1,
|
|
332
|
-
isUnionTypeNode: () => isUnionTypeNode,
|
|
333
333
|
keywordTypeNodes: () => keywordTypeNodes,
|
|
334
|
-
|
|
334
|
+
print: () => print,
|
|
335
335
|
wrapNullableOptional: () => wrapNullableOptional
|
|
336
336
|
});
|
|
337
|
-
/**
|
|
338
|
-
* Loaded with `require`, not `import`. When ESM imports a CommonJS package, Node keeps a second
|
|
339
|
-
* copy of its source to detect named exports, and for TypeScript that copy is about 9 MB.
|
|
340
|
-
*/
|
|
341
|
-
const typescript = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)("@typescript/typescript6");
|
|
342
|
-
const { SyntaxKind, factory } = typescript;
|
|
343
337
|
function isNumber(value) {
|
|
344
338
|
return typeof value === "number" && !Number.isNaN(value);
|
|
345
339
|
}
|
|
346
|
-
/**
|
|
347
|
-
* TypeScript AST modifiers for the `export` keyword.
|
|
348
|
-
*/
|
|
349
|
-
const modifiers = { export: factory.createModifier(typescript.SyntaxKind.ExportKeyword) };
|
|
350
|
-
const isUnionTypeNode = typescript.isUnionTypeNode;
|
|
351
340
|
function isNonNullable$1(value) {
|
|
352
341
|
return value !== null && value !== void 0;
|
|
353
342
|
}
|
|
354
343
|
__name(isNonNullable$1, "isNonNullable");
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Prints `node` as TypeScript source with single quotes and two-space indentation.
|
|
346
|
+
*/
|
|
347
|
+
function print(node) {
|
|
348
|
+
return (0, yuku_codegen.generate)(node, { quotes: "single" }).code;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Wraps already printed TypeScript, such as a user override result, so it can sit inside a node tree.
|
|
352
|
+
* Parentheses keep a union or function type intact when it lands inside an array or intersection.
|
|
353
|
+
*/
|
|
354
|
+
function createRaw(text) {
|
|
355
|
+
const name = {
|
|
356
|
+
type: "TSTypeReference",
|
|
357
|
+
typeName: identifier(text),
|
|
358
|
+
typeArguments: null
|
|
359
|
+
};
|
|
360
|
+
return /[|&?]|=>/.test(text) ? {
|
|
361
|
+
type: "TSParenthesizedType",
|
|
362
|
+
typeAnnotation: name
|
|
363
|
+
} : name;
|
|
364
|
+
}
|
|
365
|
+
function identifier(name) {
|
|
366
|
+
return {
|
|
367
|
+
type: "Identifier",
|
|
368
|
+
name
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
function literal(value) {
|
|
372
|
+
return {
|
|
373
|
+
type: "Literal",
|
|
374
|
+
value
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function createLiteralType(value) {
|
|
378
|
+
return {
|
|
379
|
+
type: "TSLiteralType",
|
|
380
|
+
literal: literal(value)
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Whether `name` can be written as a bare property name instead of a quoted string.
|
|
385
|
+
*/
|
|
386
|
+
function isValidIdentifier(name) {
|
|
387
|
+
return /^[\p{ID_Start}$_][\p{ID_Continue}$]*$/u.test(name);
|
|
364
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* A property or enum member name, quoted when it is not a valid identifier.
|
|
391
|
+
*/
|
|
365
392
|
function propertyName(name) {
|
|
366
|
-
|
|
367
|
-
return name;
|
|
393
|
+
return isValidIdentifier(name) ? identifier(name) : literal(name);
|
|
368
394
|
}
|
|
369
|
-
const questionToken = factory.createToken(typescript.SyntaxKind.QuestionToken);
|
|
370
395
|
/**
|
|
371
|
-
*
|
|
372
|
-
* Pass `true` to use the cached token, or provide a pre-created token.
|
|
396
|
+
* Indents every non-empty line of `text` by two spaces.
|
|
373
397
|
*/
|
|
374
|
-
function
|
|
375
|
-
|
|
376
|
-
if (token === true) return questionToken;
|
|
377
|
-
return token;
|
|
398
|
+
function indent(text) {
|
|
399
|
+
return text.split("\n").map((line) => line ? ` ${line}` : line).join("\n");
|
|
378
400
|
}
|
|
379
401
|
/**
|
|
380
|
-
* Creates a TypeScript intersection type
|
|
381
|
-
* Returns the single
|
|
402
|
+
* Creates a TypeScript intersection type.
|
|
403
|
+
* Returns the single type if only one is provided. `yuku-codegen` adds the parentheses a union member needs.
|
|
382
404
|
*/
|
|
383
405
|
function createIntersectionDeclaration({ nodes, withParentheses }) {
|
|
384
406
|
if (!nodes.length) return null;
|
|
385
407
|
if (nodes.length === 1) return nodes[0] || null;
|
|
386
|
-
const node =
|
|
387
|
-
|
|
388
|
-
|
|
408
|
+
const node = {
|
|
409
|
+
type: "TSIntersectionType",
|
|
410
|
+
types: nodes
|
|
411
|
+
};
|
|
412
|
+
return withParentheses ? {
|
|
413
|
+
type: "TSParenthesizedType",
|
|
414
|
+
typeAnnotation: node
|
|
415
|
+
} : node;
|
|
389
416
|
}
|
|
390
417
|
/**
|
|
391
|
-
* Creates a TypeScript array type
|
|
418
|
+
* Creates a TypeScript array type.
|
|
392
419
|
* Use `arrayType: 'array'` for bracket syntax (`T[]`), or `'generic'` for `Array<T>`.
|
|
393
420
|
*
|
|
394
421
|
* @example Array bracket syntax
|
|
395
|
-
* `createArrayDeclaration({ nodes: [
|
|
422
|
+
* `createArrayDeclaration({ nodes: [string], arrayType: 'array' }) // → string[]`
|
|
396
423
|
*
|
|
397
424
|
* @example Generic Array syntax
|
|
398
|
-
* `createArrayDeclaration({ nodes: [
|
|
425
|
+
* `createArrayDeclaration({ nodes: [string], arrayType: 'generic' }) // → Array<string>`
|
|
399
426
|
*/
|
|
400
427
|
function createArrayDeclaration({ nodes, arrayType = "array" }) {
|
|
401
|
-
if (!nodes.length) return
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
return
|
|
428
|
+
if (!nodes.length) return {
|
|
429
|
+
type: "TSTupleType",
|
|
430
|
+
elementTypes: []
|
|
431
|
+
};
|
|
432
|
+
const node = nodes.length === 1 ? nodes[0] : {
|
|
433
|
+
type: "TSUnionType",
|
|
434
|
+
types: nodes
|
|
435
|
+
};
|
|
436
|
+
return arrayType === "generic" ? createTypeReferenceNode("Array", [node]) : {
|
|
437
|
+
type: "TSArrayType",
|
|
438
|
+
elementType: node
|
|
439
|
+
};
|
|
410
440
|
}
|
|
411
441
|
/**
|
|
412
442
|
* Minimum nodes length of 2
|
|
@@ -416,60 +446,115 @@ function createArrayDeclaration({ nodes, arrayType = "array" }) {
|
|
|
416
446
|
function createUnionDeclaration({ nodes, withParentheses }) {
|
|
417
447
|
if (!nodes.length) return keywordTypeNodes.any;
|
|
418
448
|
if (nodes.length === 1) return nodes[0];
|
|
419
|
-
const node =
|
|
420
|
-
|
|
421
|
-
|
|
449
|
+
const node = {
|
|
450
|
+
type: "TSUnionType",
|
|
451
|
+
types: nodes
|
|
452
|
+
};
|
|
453
|
+
return withParentheses ? {
|
|
454
|
+
type: "TSParenthesizedType",
|
|
455
|
+
typeAnnotation: node
|
|
456
|
+
} : node;
|
|
422
457
|
}
|
|
423
458
|
/**
|
|
424
459
|
* Creates a TypeScript property signature for object/interface members.
|
|
425
460
|
* Supports optional markers, readonly modifiers, and type annotations.
|
|
426
461
|
*/
|
|
427
|
-
function createPropertySignature({ readOnly,
|
|
428
|
-
return
|
|
462
|
+
function createPropertySignature({ readOnly, name, questionToken, type }) {
|
|
463
|
+
return {
|
|
464
|
+
type: "TSPropertySignature",
|
|
465
|
+
key: propertyName(name),
|
|
466
|
+
computed: false,
|
|
467
|
+
optional: !!questionToken,
|
|
468
|
+
readonly: !!readOnly,
|
|
469
|
+
static: false,
|
|
470
|
+
typeAnnotation: type ? {
|
|
471
|
+
type: "TSTypeAnnotation",
|
|
472
|
+
typeAnnotation: type
|
|
473
|
+
} : null
|
|
474
|
+
};
|
|
429
475
|
}
|
|
430
476
|
/**
|
|
431
|
-
* Attaches JSDoc comments to
|
|
432
|
-
* Filters out undefined comments before attaching.
|
|
433
|
-
*
|
|
434
|
-
* @see https://github.com/microsoft/TypeScript/issues/44151
|
|
477
|
+
* Attaches a JSDoc block built from `comments` to `node`, dropping empty comments.
|
|
435
478
|
*/
|
|
436
479
|
function appendJSDocToNode({ node, comments }) {
|
|
437
|
-
const
|
|
438
|
-
if (!
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
480
|
+
const lines = comments.filter(Boolean).flatMap((comment = "") => comment.split(/\r?\n/));
|
|
481
|
+
if (!lines.length) return node;
|
|
482
|
+
const value = `*\n${lines.map((line) => ` * ${line.replaceAll("*/", "*\\/")}`.trimEnd()).join("\n")}\n `;
|
|
483
|
+
return {
|
|
484
|
+
...node,
|
|
485
|
+
comments: [{
|
|
486
|
+
type: "Block",
|
|
487
|
+
value,
|
|
488
|
+
position: "before",
|
|
489
|
+
sameLine: false
|
|
490
|
+
}]
|
|
491
|
+
};
|
|
443
492
|
}
|
|
444
493
|
/**
|
|
445
|
-
* Creates a TypeScript
|
|
446
|
-
* Defines the key type (default: `string`) and value type on an object.
|
|
494
|
+
* Creates a TypeScript type literal (anonymous object type) with one member per line.
|
|
447
495
|
*/
|
|
448
|
-
function
|
|
449
|
-
return
|
|
496
|
+
function createTypeLiteralNode(members) {
|
|
497
|
+
return {
|
|
498
|
+
type: "TSTypeLiteral",
|
|
499
|
+
members
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Creates a TypeScript type reference (e.g., `Array<string>`, `Record<K, V>`).
|
|
504
|
+
*/
|
|
505
|
+
function createTypeReferenceNode(name, typeArguments) {
|
|
506
|
+
return {
|
|
507
|
+
type: "TSTypeReference",
|
|
508
|
+
typeName: identifier(name),
|
|
509
|
+
typeArguments: typeArguments?.length ? {
|
|
510
|
+
type: "TSTypeParameterInstantiation",
|
|
511
|
+
params: typeArguments
|
|
512
|
+
} : null
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
function exportNamed(declaration, exportKind) {
|
|
516
|
+
return {
|
|
517
|
+
type: "ExportNamedDeclaration",
|
|
518
|
+
declaration,
|
|
519
|
+
specifiers: [],
|
|
520
|
+
source: null,
|
|
521
|
+
attributes: [],
|
|
522
|
+
exportKind
|
|
523
|
+
};
|
|
450
524
|
}
|
|
451
525
|
/**
|
|
452
|
-
*
|
|
453
|
-
*
|
|
526
|
+
* Prints a TypeScript type declaration as either a type alias or interface.
|
|
527
|
+
* Uses interface syntax only when requested and the type is an object literal, and attaches JSDoc comments.
|
|
454
528
|
*/
|
|
455
529
|
function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
530
|
+
const declaration = syntax === "interface" && type.type === "TSTypeLiteral" ? {
|
|
531
|
+
type: "TSInterfaceDeclaration",
|
|
532
|
+
declare: false,
|
|
533
|
+
id: identifier(name),
|
|
534
|
+
typeParameters: null,
|
|
535
|
+
extends: [],
|
|
536
|
+
body: {
|
|
537
|
+
type: "TSInterfaceBody",
|
|
538
|
+
body: type.members
|
|
539
|
+
}
|
|
540
|
+
} : {
|
|
541
|
+
type: "TSTypeAliasDeclaration",
|
|
542
|
+
declare: false,
|
|
543
|
+
id: identifier(name),
|
|
544
|
+
typeParameters: null,
|
|
545
|
+
typeAnnotation: type
|
|
546
|
+
};
|
|
547
|
+
return print(appendJSDocToNode({
|
|
548
|
+
node: isExportable ? exportNamed(declaration, "type") : declaration,
|
|
462
549
|
comments
|
|
463
|
-
});
|
|
550
|
+
}));
|
|
464
551
|
}
|
|
465
552
|
/**
|
|
466
|
-
* Converts an enum member value to a literal
|
|
467
|
-
*
|
|
553
|
+
* Converts an enum member value to a literal. Numbers become numeric literals unless `asNumber` is `false`,
|
|
554
|
+
* which emits the string form.
|
|
468
555
|
*/
|
|
469
556
|
function valueToExpression(value, asNumber = isNumber(value)) {
|
|
470
|
-
|
|
471
|
-
if (asNumber && isNumber(value)) return value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value))) : factory.createNumericLiteral(value);
|
|
472
|
-
return factory.createStringLiteral(value.toString());
|
|
557
|
+
return literal(typeof value === "boolean" || asNumber && isNumber(value) ? value : value.toString());
|
|
473
558
|
}
|
|
474
559
|
/**
|
|
475
560
|
* Apply casing transformation to enum keys
|
|
@@ -484,7 +569,7 @@ function applyEnumKeyCasing(key, casing = "none") {
|
|
|
484
569
|
}
|
|
485
570
|
/**
|
|
486
571
|
* Creates a TypeScript enum declaration or equivalent construct in various formats.
|
|
487
|
-
* Returns a tuple of [name
|
|
572
|
+
* Returns a tuple of [name declaration, type declaration] - the name declaration may be undefined for certain types.
|
|
488
573
|
*
|
|
489
574
|
* @example
|
|
490
575
|
* ```ts
|
|
@@ -497,126 +582,135 @@ function applyEnumKeyCasing(key, casing = "none") {
|
|
|
497
582
|
* ```
|
|
498
583
|
*/
|
|
499
584
|
function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCasing = "none" }) {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
585
|
+
const typeAlias = (annotation) => createTypeDeclaration({
|
|
586
|
+
syntax: "type",
|
|
587
|
+
isExportable: true,
|
|
588
|
+
name: typeName,
|
|
589
|
+
comments: [],
|
|
590
|
+
type: annotation
|
|
591
|
+
});
|
|
592
|
+
if (type === "literal" || type === "inlineLiteral") {
|
|
593
|
+
const members = enums.map(([_key, value]) => isNonNullable$1(value) ? {
|
|
594
|
+
type: "TSLiteralType",
|
|
595
|
+
literal: valueToExpression(value)
|
|
596
|
+
} : void 0).filter(isNonNullable$1);
|
|
597
|
+
return [void 0, typeAlias(members.length ? createUnionDeclaration({ nodes: members }) : keywordTypeNodes.never)];
|
|
598
|
+
}
|
|
599
|
+
if (type === "enum" || type === "constEnum") {
|
|
600
|
+
const members = enums.map(([key, value, description]) => {
|
|
601
|
+
const initializer = valueToExpression(value, Number.parseInt(value.toString(), 10) === value);
|
|
602
|
+
const memberName = isNumber(Number.parseInt(key.toString(), 10)) ? `${typeName}_${key}` : key?.toString();
|
|
603
|
+
if (memberName === void 0) return void 0;
|
|
519
604
|
return appendJSDocToNode({
|
|
520
|
-
node:
|
|
605
|
+
node: {
|
|
606
|
+
type: "TSEnumMember",
|
|
607
|
+
id: propertyName(applyEnumKeyCasing(memberName, enumKeyCasing)),
|
|
608
|
+
initializer
|
|
609
|
+
},
|
|
521
610
|
comments: [description]
|
|
522
611
|
});
|
|
523
|
-
}
|
|
524
|
-
|
|
612
|
+
}).filter(isNonNullable$1);
|
|
613
|
+
return [void 0, print(exportNamed({
|
|
614
|
+
type: "TSEnumDeclaration",
|
|
615
|
+
declare: false,
|
|
616
|
+
const: type === "constEnum",
|
|
617
|
+
id: identifier(typeName),
|
|
618
|
+
body: {
|
|
619
|
+
type: "TSEnumBody",
|
|
620
|
+
members
|
|
621
|
+
}
|
|
622
|
+
}, "value"))];
|
|
623
|
+
}
|
|
525
624
|
const identifierName = name;
|
|
526
|
-
if (enums.length === 0) return [void 0,
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
625
|
+
if (enums.length === 0) return [void 0, typeAlias(keywordTypeNodes.never)];
|
|
626
|
+
const properties = enums.map(([key, value, description]) => {
|
|
627
|
+
if (key === null || key === void 0) return void 0;
|
|
628
|
+
return print(appendJSDocToNode({
|
|
629
|
+
node: {
|
|
630
|
+
type: "Property",
|
|
631
|
+
kind: "init",
|
|
632
|
+
key: propertyName(applyEnumKeyCasing(key.toString(), enumKeyCasing)),
|
|
633
|
+
value: valueToExpression(value),
|
|
634
|
+
computed: false,
|
|
635
|
+
method: false,
|
|
636
|
+
shorthand: false
|
|
637
|
+
},
|
|
638
|
+
comments: [description]
|
|
639
|
+
}));
|
|
640
|
+
}).filter(isNonNullable$1);
|
|
641
|
+
const query = {
|
|
642
|
+
type: "TSTypeQuery",
|
|
643
|
+
exprName: identifier(identifierName),
|
|
644
|
+
typeArguments: null
|
|
645
|
+
};
|
|
646
|
+
return [`export const ${identifierName} = {\n${properties.map(indent).join(",\n")},\n} as const;`, typeAlias({
|
|
647
|
+
type: "TSIndexedAccessType",
|
|
648
|
+
objectType: {
|
|
649
|
+
type: "TSParenthesizedType",
|
|
650
|
+
typeAnnotation: query
|
|
651
|
+
},
|
|
652
|
+
indexType: {
|
|
653
|
+
type: "TSTypeOperator",
|
|
654
|
+
operator: "keyof",
|
|
655
|
+
typeAnnotation: query
|
|
535
656
|
}
|
|
536
|
-
})
|
|
657
|
+
})];
|
|
537
658
|
}
|
|
538
659
|
/**
|
|
539
|
-
* Creates a TypeScript `Omit<T, Keys>` type reference
|
|
660
|
+
* Creates a TypeScript `Omit<T, Keys>` type reference.
|
|
540
661
|
* Optionally wraps the type in `NonNullable<T>` if `nonNullable` is true.
|
|
541
662
|
*/
|
|
542
663
|
function createOmitDeclaration({ keys, type, nonNullable }) {
|
|
543
|
-
|
|
544
|
-
if (Array.isArray(keys)) return factory.createTypeReferenceNode(factory.createIdentifier("Omit"), [node, factory.createUnionTypeNode(keys.map((key) => {
|
|
545
|
-
return factory.createLiteralTypeNode(factory.createStringLiteral(key));
|
|
546
|
-
}))]);
|
|
547
|
-
return factory.createTypeReferenceNode(factory.createIdentifier("Omit"), [node, factory.createLiteralTypeNode(factory.createStringLiteral(keys))]);
|
|
664
|
+
return createTypeReferenceNode("Omit", [nonNullable ? createTypeReferenceNode("NonNullable", [type]) : type, createUnionDeclaration({ nodes: [keys].flat().map(createLiteralType) })]);
|
|
548
665
|
}
|
|
549
666
|
/**
|
|
550
|
-
*
|
|
551
|
-
* Use these to avoid repeatedly creating the same type nodes.
|
|
667
|
+
* TypeScript keyword types for common primitive types.
|
|
552
668
|
*/
|
|
553
669
|
const keywordTypeNodes = {
|
|
554
|
-
any:
|
|
555
|
-
unknown:
|
|
556
|
-
void:
|
|
557
|
-
number:
|
|
558
|
-
integer:
|
|
559
|
-
bigint:
|
|
560
|
-
object:
|
|
561
|
-
string:
|
|
562
|
-
boolean:
|
|
563
|
-
undefined:
|
|
564
|
-
null:
|
|
565
|
-
never:
|
|
670
|
+
any: { type: "TSAnyKeyword" },
|
|
671
|
+
unknown: { type: "TSUnknownKeyword" },
|
|
672
|
+
void: { type: "TSVoidKeyword" },
|
|
673
|
+
number: { type: "TSNumberKeyword" },
|
|
674
|
+
integer: { type: "TSNumberKeyword" },
|
|
675
|
+
bigint: { type: "TSBigIntKeyword" },
|
|
676
|
+
object: { type: "TSObjectKeyword" },
|
|
677
|
+
string: { type: "TSStringKeyword" },
|
|
678
|
+
boolean: { type: "TSBooleanKeyword" },
|
|
679
|
+
undefined: { type: "TSUndefinedKeyword" },
|
|
680
|
+
null: { type: "TSNullKeyword" },
|
|
681
|
+
never: { type: "TSNeverKeyword" }
|
|
566
682
|
};
|
|
567
683
|
/**
|
|
568
|
-
* Converts a path like '/pet/{petId}/uploadImage' to a template literal type
|
|
569
|
-
* like `/pet/${string}/uploadImage`
|
|
570
|
-
*/
|
|
571
|
-
/**
|
|
572
684
|
* Converts an OAS-style path (e.g. `/pets/{petId}`) or an Express-style path
|
|
573
685
|
* (e.g. `/pets/:petId`) to a TypeScript template literal type
|
|
574
686
|
* like `` `/pets/${string}` ``.
|
|
575
687
|
*/
|
|
576
688
|
function createUrlTemplateType(path) {
|
|
577
689
|
const normalized = path.replace(/:([^/]+)/g, "{$1}");
|
|
578
|
-
if (!normalized.includes("{")) return
|
|
579
|
-
const segments = normalized.split(
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const templateSpans = [];
|
|
590
|
-
parameterIndices.forEach((paramIndex, i) => {
|
|
591
|
-
const isLast = i === parameterIndices.length - 1;
|
|
592
|
-
const nextPart = parts[paramIndex + 1] || "";
|
|
593
|
-
const literal = isLast ? typescript.factory.createTemplateTail(nextPart) : typescript.factory.createTemplateMiddle(nextPart);
|
|
594
|
-
templateSpans.push(typescript.factory.createTemplateLiteralTypeSpan(keywordTypeNodes.string, literal));
|
|
595
|
-
});
|
|
596
|
-
return typescript.factory.createTemplateLiteralType(head, templateSpans);
|
|
690
|
+
if (!normalized.includes("{")) return createLiteralType(normalized);
|
|
691
|
+
const segments = normalized.split(/\{[^}]+\}/);
|
|
692
|
+
return {
|
|
693
|
+
type: "TSTemplateLiteralType",
|
|
694
|
+
quasis: segments.map((cooked, i) => ({
|
|
695
|
+
type: "TemplateElement",
|
|
696
|
+
value: { cooked },
|
|
697
|
+
tail: i === segments.length - 1
|
|
698
|
+
})),
|
|
699
|
+
types: segments.slice(1).map(() => keywordTypeNodes.string)
|
|
700
|
+
};
|
|
597
701
|
}
|
|
598
702
|
/**
|
|
599
|
-
*
|
|
600
|
-
*/
|
|
601
|
-
const createTypeLiteralNode = factory.createTypeLiteralNode;
|
|
602
|
-
/**
|
|
603
|
-
* Creates a TypeScript type reference node (e.g., `Array<string>`, `Record<K, V>`).
|
|
604
|
-
*/
|
|
605
|
-
const createTypeReferenceNode = factory.createTypeReferenceNode;
|
|
606
|
-
/**
|
|
607
|
-
* Converts a primitive const value to a TypeScript literal type node.
|
|
608
|
-
* Handles negative numbers via a prefix unary expression.
|
|
703
|
+
* Converts a primitive const value to a TypeScript literal type.
|
|
609
704
|
*/
|
|
610
705
|
function constToTypeNode(value, format) {
|
|
611
|
-
if (format === "boolean") return
|
|
612
|
-
|
|
613
|
-
return factory.createLiteralTypeNode(valueToExpression(literal));
|
|
706
|
+
if (format === "boolean") return createLiteralType(value === true);
|
|
707
|
+
return createLiteralType(format === "number" && typeof value === "number" ? value : String(value));
|
|
614
708
|
}
|
|
615
709
|
/**
|
|
616
|
-
* Returns a `Date` reference type
|
|
710
|
+
* Returns a `Date` reference type when `representation` is `'date'`, otherwise falls back to `string`.
|
|
617
711
|
*/
|
|
618
712
|
function dateOrStringNode(node) {
|
|
619
|
-
return node.representation === "date" ? createTypeReferenceNode(
|
|
713
|
+
return node.representation === "date" ? createTypeReferenceNode("Date") : keywordTypeNodes.string;
|
|
620
714
|
}
|
|
621
715
|
/**
|
|
622
716
|
* Maps an array of `SchemaNode`s through the printer, filtering out `null` and `undefined` results.
|
|
@@ -625,7 +719,7 @@ function buildMemberNodes(members, print) {
|
|
|
625
719
|
return (members ?? []).map(print).filter(isNonNullable$1);
|
|
626
720
|
}
|
|
627
721
|
/**
|
|
628
|
-
* Builds a TypeScript tuple type
|
|
722
|
+
* Builds a TypeScript tuple type from an array schema's `items`,
|
|
629
723
|
* applying min/max slice and optional/rest element rules.
|
|
630
724
|
*/
|
|
631
725
|
function buildTupleNode(node, print) {
|
|
@@ -636,9 +730,21 @@ function buildTupleNode(node, print) {
|
|
|
636
730
|
items = items.slice(0, max);
|
|
637
731
|
if (items.length < max && restNode) items = [...items, ...Array(max - items.length).fill(restNode)];
|
|
638
732
|
}
|
|
639
|
-
if (min !== void 0) items = items.map((item, i) => i >= min ?
|
|
640
|
-
|
|
641
|
-
|
|
733
|
+
if (min !== void 0) items = items.map((item, i) => i >= min ? {
|
|
734
|
+
type: "TSOptionalType",
|
|
735
|
+
typeAnnotation: item
|
|
736
|
+
} : item);
|
|
737
|
+
if (max === void 0 && restNode) items.push({
|
|
738
|
+
type: "TSRestType",
|
|
739
|
+
typeAnnotation: {
|
|
740
|
+
type: "TSArrayType",
|
|
741
|
+
elementType: restNode
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
return {
|
|
745
|
+
type: "TSTupleType",
|
|
746
|
+
elementTypes: items
|
|
747
|
+
};
|
|
642
748
|
}
|
|
643
749
|
/**
|
|
644
750
|
* Appends `| null` and then `| undefined` to a type when requested.
|
|
@@ -655,8 +761,6 @@ function buildPropertyType(schema, baseType, optionalType, optional) {
|
|
|
655
761
|
const meta = (0, kubb_kit.syncSchemaRef)(schema);
|
|
656
762
|
return wrapNullableOptional(baseType, !!meta.nullable, addsUndefined && !!(optional || meta.nullish || meta.optional));
|
|
657
763
|
}
|
|
658
|
-
const indexSignaturePrinter = typescript.createPrinter();
|
|
659
|
-
const indexSignatureSource = typescript.createSourceFile("", "", typescript.ScriptTarget.Latest);
|
|
660
764
|
/**
|
|
661
765
|
* Creates a TypeScript index signature for `additionalProperties` and `patternProperties` on an
|
|
662
766
|
* object schema node. TypeScript allows only one string index signature and its value must be
|
|
@@ -664,21 +768,35 @@ const indexSignatureSource = typescript.createSourceFile("", "", typescript.Scri
|
|
|
664
768
|
* union of all value types (deduplicated), or `unknown` when the object also has fixed properties.
|
|
665
769
|
* The key regex of `patternProperties` cannot be expressed by an index signature and is dropped.
|
|
666
770
|
*/
|
|
667
|
-
function buildIndexSignatures(node, propertyCount,
|
|
771
|
+
function buildIndexSignatures(node, propertyCount, printNode) {
|
|
668
772
|
const valueTypes = [];
|
|
669
|
-
if (node.additionalProperties && node.additionalProperties !== true) valueTypes.push(
|
|
773
|
+
if (node.additionalProperties && node.additionalProperties !== true) valueTypes.push(printNode(node.additionalProperties) ?? keywordTypeNodes.unknown);
|
|
670
774
|
else if (node.additionalProperties === true) valueTypes.push(keywordTypeNodes.unknown);
|
|
671
775
|
for (const schema of Object.values(node.patternProperties ?? {})) {
|
|
672
|
-
const patternType =
|
|
776
|
+
const patternType = printNode(schema) ?? keywordTypeNodes.unknown;
|
|
673
777
|
valueTypes.push(schema.nullable ? createUnionDeclaration({ nodes: [patternType, keywordTypeNodes.null] }) : patternType);
|
|
674
778
|
}
|
|
675
779
|
if (valueTypes.length === 0) return [];
|
|
676
|
-
const
|
|
677
|
-
const
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
780
|
+
const distinct = [...new Map(valueTypes.map((type) => [print(type), type])).values()];
|
|
781
|
+
const valueType = propertyCount > 0 ? keywordTypeNodes.unknown : createUnionDeclaration({ nodes: distinct });
|
|
782
|
+
return [{
|
|
783
|
+
type: "TSIndexSignature",
|
|
784
|
+
parameters: [{
|
|
785
|
+
type: "Identifier",
|
|
786
|
+
name: "key",
|
|
787
|
+
typeAnnotation: {
|
|
788
|
+
type: "TSTypeAnnotation",
|
|
789
|
+
typeAnnotation: keywordTypeNodes.string
|
|
790
|
+
}
|
|
791
|
+
}],
|
|
792
|
+
typeAnnotation: {
|
|
793
|
+
type: "TSTypeAnnotation",
|
|
794
|
+
typeAnnotation: valueType
|
|
795
|
+
},
|
|
796
|
+
readonly: false,
|
|
797
|
+
static: false,
|
|
798
|
+
accessibility: null
|
|
799
|
+
}];
|
|
682
800
|
}
|
|
683
801
|
//#endregion
|
|
684
802
|
//#region src/components/Enum.tsx
|
|
@@ -733,7 +851,7 @@ function Enum({ node, enum: enumOptions, resolver }) {
|
|
|
733
851
|
isExportable: true,
|
|
734
852
|
isIndexable: true,
|
|
735
853
|
isTypeOnly: false,
|
|
736
|
-
children:
|
|
854
|
+
children: nameNode
|
|
737
855
|
}), /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
|
|
738
856
|
name: typeName,
|
|
739
857
|
isIndexable: !namesMerge,
|
|
@@ -743,7 +861,7 @@ function Enum({ node, enum: enumOptions, resolver }) {
|
|
|
743
861
|
"literal",
|
|
744
862
|
void 0
|
|
745
863
|
].includes(enumOptions.type),
|
|
746
|
-
children:
|
|
864
|
+
children: typeNode
|
|
747
865
|
})] });
|
|
748
866
|
}
|
|
749
867
|
//#endregion
|
|
@@ -1197,12 +1315,30 @@ function Type({ name, node, printer, enum: enumOptions, resolver }) {
|
|
|
1197
1315
|
//#region src/printers/printerTs.ts
|
|
1198
1316
|
const { isNonNullable } = factory_exports;
|
|
1199
1317
|
/**
|
|
1318
|
+
* Adapts user overrides, which work in strings, to the node-based printer: `this.transform` hands them printed
|
|
1319
|
+
* strings and their result is wrapped back into a node. A deprecated compiler node prints through `@kubb/parser-ts`.
|
|
1320
|
+
*/
|
|
1321
|
+
function toNodeHandlers(nodes) {
|
|
1322
|
+
return Object.fromEntries(Object.entries(nodes ?? {}).map(([type, handler]) => [type, function(node) {
|
|
1323
|
+
const transform = (child) => {
|
|
1324
|
+
const output = this.transform(child);
|
|
1325
|
+
return output ? print(output) : null;
|
|
1326
|
+
};
|
|
1327
|
+
const result = handler.call({
|
|
1328
|
+
...this,
|
|
1329
|
+
transform
|
|
1330
|
+
}, node);
|
|
1331
|
+
if (result === null || result === void 0) return result;
|
|
1332
|
+
return createRaw(typeof result === "string" ? result : (0, _kubb_parser_ts.parserTs)().print(result).trimEnd());
|
|
1333
|
+
}]));
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1200
1336
|
* TypeScript type printer built with `definePrinter`.
|
|
1201
1337
|
*
|
|
1202
|
-
* Converts a `SchemaNode` AST node into
|
|
1203
|
-
* - **`printer.print(node)`** — when `options.
|
|
1204
|
-
* `type Name = …` or `interface Name { … }` declaration
|
|
1205
|
-
* Without `
|
|
1338
|
+
* Converts a `SchemaNode` AST node into TypeScript source:
|
|
1339
|
+
* - **`printer.print(node)`** — when `options.name` is set, returns a full
|
|
1340
|
+
* `type Name = …` or `interface Name { … }` declaration.
|
|
1341
|
+
* Without `name`, returns the type for the schema, such as `string | null`.
|
|
1206
1342
|
*
|
|
1207
1343
|
* Dispatches on `node.type` to the appropriate handler in `nodes`. Options are closed
|
|
1208
1344
|
* over per printer instance, so each call to `printerTs(options)` produces an independent printer.
|
|
@@ -1210,13 +1346,13 @@ const { isNonNullable } = factory_exports;
|
|
|
1210
1346
|
* @example Raw type node (no `typeName`)
|
|
1211
1347
|
* ```ts
|
|
1212
1348
|
* const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enum: { type: 'inlineLiteral' } })
|
|
1213
|
-
* const
|
|
1349
|
+
* const type = printer.print(schemaNode) // 'string | null'
|
|
1214
1350
|
* ```
|
|
1215
1351
|
*
|
|
1216
1352
|
* @example Full declaration (with `typeName`)
|
|
1217
1353
|
* ```ts
|
|
1218
1354
|
* const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enum: { type: 'inlineLiteral' }, typeName: 'MyType' })
|
|
1219
|
-
* const declaration = printer.print(schemaNode) //
|
|
1355
|
+
* const declaration = printer.print(schemaNode) // 'export type MyType = …'
|
|
1220
1356
|
* ```
|
|
1221
1357
|
*/
|
|
1222
1358
|
const printerTs = kubb_kit.ast.createPrinter((options) => {
|
|
@@ -1231,7 +1367,7 @@ const printerTs = kubb_kit.ast.createPrinter((options) => {
|
|
|
1231
1367
|
never: () => keywordTypeNodes.never,
|
|
1232
1368
|
boolean: () => keywordTypeNodes.boolean,
|
|
1233
1369
|
null: () => keywordTypeNodes.null,
|
|
1234
|
-
blob: () => createTypeReferenceNode("Blob"
|
|
1370
|
+
blob: () => createTypeReferenceNode("Blob"),
|
|
1235
1371
|
string: () => keywordTypeNodes.string,
|
|
1236
1372
|
uuid: () => keywordTypeNodes.string,
|
|
1237
1373
|
email: () => keywordTypeNodes.string,
|
|
@@ -1251,27 +1387,22 @@ const printerTs = kubb_kit.ast.createPrinter((options) => {
|
|
|
1251
1387
|
if (!node.name) return null;
|
|
1252
1388
|
const refName = kubb_kit.ast.resolveRefName(node);
|
|
1253
1389
|
if (!refName) return null;
|
|
1254
|
-
|
|
1390
|
+
return createTypeReferenceNode(node.ref ? enumTypeName({
|
|
1255
1391
|
resolver: this.options.resolver,
|
|
1256
1392
|
name: refName,
|
|
1257
1393
|
enumOptions: this.options.enum,
|
|
1258
1394
|
isEnum: !!this.options.enumSchemaNames?.has(refName)
|
|
1259
|
-
}) : refName;
|
|
1260
|
-
return createTypeReferenceNode(name, void 0);
|
|
1395
|
+
}) : refName);
|
|
1261
1396
|
},
|
|
1262
1397
|
enum(node) {
|
|
1263
1398
|
const values = kubb_kit.ast.getSchemaLiteralValues(node);
|
|
1264
|
-
if (this.options.enum.type === "inlineLiteral" || !node.name || isInlineConstEnum(node, this.options.enumSchemaNames)) return createUnionDeclaration({
|
|
1265
|
-
|
|
1266
|
-
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(isNonNullable)
|
|
1267
|
-
});
|
|
1268
|
-
const resolvedName = enumTypeName({
|
|
1399
|
+
if (this.options.enum.type === "inlineLiteral" || !node.name || isInlineConstEnum(node, this.options.enumSchemaNames)) return createUnionDeclaration({ nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(isNonNullable) });
|
|
1400
|
+
return createTypeReferenceNode(enumTypeName({
|
|
1269
1401
|
resolver: this.options.resolver,
|
|
1270
1402
|
name: node.name,
|
|
1271
1403
|
enumOptions: this.options.enum,
|
|
1272
1404
|
isEnum: true
|
|
1273
|
-
});
|
|
1274
|
-
return createTypeReferenceNode(resolvedName, void 0);
|
|
1405
|
+
}));
|
|
1275
1406
|
},
|
|
1276
1407
|
union(node) {
|
|
1277
1408
|
const members = node.members ?? [];
|
|
@@ -1279,26 +1410,14 @@ const printerTs = kubb_kit.ast.createPrinter((options) => {
|
|
|
1279
1410
|
return kubb_kit.ast.narrowSchema(m, kubb_kit.ast.schemaTypes.enum)?.primitive === "string";
|
|
1280
1411
|
});
|
|
1281
1412
|
const hasPlainString = members.some((m) => (0, kubb_kit.isStringType)(m));
|
|
1282
|
-
if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
withParentheses: true
|
|
1288
|
-
});
|
|
1289
|
-
return this.transform(m);
|
|
1290
|
-
}).filter(isNonNullable)
|
|
1291
|
-
});
|
|
1292
|
-
return createUnionDeclaration({
|
|
1293
|
-
withParentheses: true,
|
|
1294
|
-
nodes: buildMemberNodes(members, this.transform)
|
|
1295
|
-
});
|
|
1413
|
+
if (hasStringLiteral && hasPlainString) return createUnionDeclaration({ nodes: members.map((m) => {
|
|
1414
|
+
if ((0, kubb_kit.isStringType)(m)) return createIntersectionDeclaration({ nodes: [keywordTypeNodes.string, createTypeLiteralNode([])] });
|
|
1415
|
+
return this.transform(m);
|
|
1416
|
+
}).filter(isNonNullable) });
|
|
1417
|
+
return createUnionDeclaration({ nodes: buildMemberNodes(members, this.transform) });
|
|
1296
1418
|
},
|
|
1297
1419
|
intersection(node) {
|
|
1298
|
-
return createIntersectionDeclaration({
|
|
1299
|
-
withParentheses: true,
|
|
1300
|
-
nodes: buildMemberNodes(node.members, this.transform)
|
|
1301
|
-
});
|
|
1420
|
+
return createIntersectionDeclaration({ nodes: buildMemberNodes(node.members, this.transform) });
|
|
1302
1421
|
},
|
|
1303
1422
|
array(node) {
|
|
1304
1423
|
return createArrayDeclaration({
|
|
@@ -1331,35 +1450,30 @@ const printerTs = kubb_kit.ast.createPrinter((options) => {
|
|
|
1331
1450
|
if (!allElements.length) return keywordTypeNodes.object;
|
|
1332
1451
|
return createTypeLiteralNode(allElements);
|
|
1333
1452
|
},
|
|
1334
|
-
...options.nodes
|
|
1453
|
+
...toNodeHandlers(options.nodes)
|
|
1335
1454
|
},
|
|
1336
1455
|
print(node) {
|
|
1337
1456
|
const { name, syntaxType = "type", description, keysToOmit } = this.options;
|
|
1338
1457
|
const transformed = this.transform(node);
|
|
1339
1458
|
if (!transformed) return null;
|
|
1340
1459
|
const meta = (0, kubb_kit.syncSchemaRef)(node);
|
|
1341
|
-
if (!name)
|
|
1342
|
-
|
|
1343
|
-
return (0, _kubb_parser_ts.parserTs)().print(result);
|
|
1344
|
-
}
|
|
1345
|
-
const inner = (() => {
|
|
1346
|
-
return wrapNullableOptional(keysToOmit?.length ? createOmitDeclaration({
|
|
1347
|
-
keys: keysToOmit,
|
|
1348
|
-
type: transformed,
|
|
1349
|
-
nonNullable: true
|
|
1350
|
-
}) : transformed, !!meta.nullable, !!(meta.nullish || meta.optional));
|
|
1351
|
-
})();
|
|
1352
|
-
const typeNode = createTypeDeclaration({
|
|
1460
|
+
if (!name) return print(wrapNullableOptional(transformed, !!meta.nullable, !!(meta.nullish || meta.optional) && addsUndefined));
|
|
1461
|
+
return createTypeDeclaration({
|
|
1353
1462
|
name,
|
|
1354
1463
|
isExportable: true,
|
|
1355
|
-
type:
|
|
1356
|
-
|
|
1464
|
+
type: (() => {
|
|
1465
|
+
return wrapNullableOptional(keysToOmit?.length ? createOmitDeclaration({
|
|
1466
|
+
keys: keysToOmit,
|
|
1467
|
+
type: transformed,
|
|
1468
|
+
nonNullable: true
|
|
1469
|
+
}) : transformed, !!meta.nullable, !!(meta.nullish || meta.optional));
|
|
1470
|
+
})(),
|
|
1471
|
+
syntax: syntaxType === "type" || !!keysToOmit?.length ? "type" : "interface",
|
|
1357
1472
|
comments: buildPropertyJSDocComments({
|
|
1358
1473
|
...meta,
|
|
1359
1474
|
description
|
|
1360
1475
|
})
|
|
1361
1476
|
});
|
|
1362
|
-
return (0, _kubb_parser_ts.parserTs)().print(typeNode);
|
|
1363
1477
|
}
|
|
1364
1478
|
};
|
|
1365
1479
|
});
|
|
@@ -1642,7 +1756,7 @@ var compatibility = {
|
|
|
1642
1756
|
};
|
|
1643
1757
|
//#endregion
|
|
1644
1758
|
//#region package.json
|
|
1645
|
-
var version = "5.
|
|
1759
|
+
var version = "5.2.0-canary.20261024T091509";
|
|
1646
1760
|
//#endregion
|
|
1647
1761
|
//#region src/resolvers/resolverTs.ts
|
|
1648
1762
|
/**
|