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