@kubb/plugin-ts 5.0.0-alpha.24 → 5.0.0-alpha.25
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 +468 -473
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +9 -4
- package/dist/index.js +472 -477
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/components/Enum.tsx +1 -1
- package/src/constants.ts +10 -0
- package/src/factory.ts +122 -1
- package/src/generators/typeGenerator.tsx +107 -108
- package/src/generators/typeGeneratorLegacy.tsx +85 -80
- package/src/index.ts +0 -5
- package/src/plugin.ts +19 -49
- package/src/printers/functionPrinter.ts +6 -5
- package/src/printers/printerTs.ts +49 -181
- package/src/resolvers/resolverTs.ts +2 -2
- package/src/types.ts +6 -4
- package/src/utils.ts +41 -13
package/dist/index.js
CHANGED
|
@@ -2,11 +2,11 @@ import "./chunk--u3MIqq1.js";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { safePrint } from "@kubb/fabric-core/parsers/typescript";
|
|
4
4
|
import { File } from "@kubb/react-fabric";
|
|
5
|
+
import { caseParams, collect, composeTransformers, createPrinterFactory, createProperty, createSchema, extractRefName, isStringType, narrowSchema, schemaTypes, syncSchemaRef, transform, walk } from "@kubb/ast";
|
|
5
6
|
import { isNumber } from "remeda";
|
|
6
7
|
import ts from "typescript";
|
|
7
8
|
import { Fragment, jsx, jsxs } from "@kubb/react-fabric/jsx-runtime";
|
|
8
|
-
import {
|
|
9
|
-
import { createPlugin, defineGenerator, definePresets, definePrinter, defineResolver, getBarrelFiles, getMode, getPreset, renderOperation, renderSchema } from "@kubb/core";
|
|
9
|
+
import { createPlugin, defineGenerator, definePresets, definePrinter, defineResolver, getBarrelFiles, getMode, getPreset, runGeneratorOperation, runGeneratorOperations, runGeneratorSchema } from "@kubb/core";
|
|
10
10
|
//#region ../../internals/utils/src/casing.ts
|
|
11
11
|
/**
|
|
12
12
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -176,6 +176,15 @@ const ENUM_TYPES_WITH_TYPE_ONLY = new Set([
|
|
|
176
176
|
"literal",
|
|
177
177
|
void 0
|
|
178
178
|
]);
|
|
179
|
+
/**
|
|
180
|
+
* Ordering priority for function parameters: lower = sorted earlier.
|
|
181
|
+
*/
|
|
182
|
+
const PARAM_RANK = {
|
|
183
|
+
required: 0,
|
|
184
|
+
optional: 1,
|
|
185
|
+
withDefault: 2,
|
|
186
|
+
rest: 3
|
|
187
|
+
};
|
|
179
188
|
//#endregion
|
|
180
189
|
//#region src/factory.ts
|
|
181
190
|
const { SyntaxKind, factory } = ts;
|
|
@@ -264,7 +273,7 @@ function createInterfaceDeclaration({ modifiers, name, typeParameters, members }
|
|
|
264
273
|
function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
|
|
265
274
|
if (syntax === "interface" && "members" in type) return appendJSDocToNode({
|
|
266
275
|
node: createInterfaceDeclaration({
|
|
267
|
-
members: type.members,
|
|
276
|
+
members: [...type.members],
|
|
268
277
|
modifiers: isExportable ? [modifiers.export] : [],
|
|
269
278
|
name,
|
|
270
279
|
typeParameters: void 0
|
|
@@ -397,63 +406,6 @@ const createFalse = factory.createFalse;
|
|
|
397
406
|
factory.createIndexedAccessTypeNode;
|
|
398
407
|
factory.createTypeOperatorNode;
|
|
399
408
|
const createPrefixUnaryExpression = factory.createPrefixUnaryExpression;
|
|
400
|
-
//#endregion
|
|
401
|
-
//#region src/components/Enum.tsx
|
|
402
|
-
/**
|
|
403
|
-
* Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
|
|
404
|
-
*
|
|
405
|
-
* The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
|
|
406
|
-
* valid TypeScript identifier. The resolver normalizes it; for inline enum
|
|
407
|
-
* properties the adapter already emits a PascalCase+suffix name so resolution is typically a no-op.
|
|
408
|
-
*/
|
|
409
|
-
function getEnumNames({ node, enumType, enumTypeSuffix, resolver }) {
|
|
410
|
-
const resolved = resolver.default(node.name, "type");
|
|
411
|
-
return {
|
|
412
|
-
enumName: enumType === "asPascalConst" ? resolved : camelCase(node.name),
|
|
413
|
-
typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolved
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* Renders the enum declaration(s) for a single named `EnumSchemaNode`.
|
|
418
|
-
*
|
|
419
|
-
* Depending on `enumType` this may emit:
|
|
420
|
-
* - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
|
|
421
|
-
* - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
|
|
422
|
-
* - A union literal type alias (`literal`)
|
|
423
|
-
*
|
|
424
|
-
* The emitted `File.Source` nodes carry the resolved names so that the barrel
|
|
425
|
-
* index picks up the correct export identifiers.
|
|
426
|
-
*/
|
|
427
|
-
function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
|
|
428
|
-
const { enumName, typeName } = getEnumNames({
|
|
429
|
-
node,
|
|
430
|
-
enumType,
|
|
431
|
-
enumTypeSuffix,
|
|
432
|
-
resolver
|
|
433
|
-
});
|
|
434
|
-
const [nameNode, typeNode] = createEnumDeclaration({
|
|
435
|
-
name: enumName,
|
|
436
|
-
typeName,
|
|
437
|
-
enums: node.namedEnumValues?.map((v) => [trimQuotes(v.name.toString()), v.value]) ?? node.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [trimQuotes(v.toString()), v]) ?? [],
|
|
438
|
-
type: enumType,
|
|
439
|
-
enumKeyCasing
|
|
440
|
-
});
|
|
441
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
|
|
442
|
-
name: enumName,
|
|
443
|
-
isExportable: true,
|
|
444
|
-
isIndexable: true,
|
|
445
|
-
isTypeOnly: false,
|
|
446
|
-
children: safePrint(nameNode)
|
|
447
|
-
}), /* @__PURE__ */ jsx(File.Source, {
|
|
448
|
-
name: typeName,
|
|
449
|
-
isIndexable: true,
|
|
450
|
-
isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
|
|
451
|
-
isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
|
|
452
|
-
children: safePrint(typeNode)
|
|
453
|
-
})] });
|
|
454
|
-
}
|
|
455
|
-
//#endregion
|
|
456
|
-
//#region src/printers/printerTs.ts
|
|
457
409
|
/**
|
|
458
410
|
* Converts a primitive const value to a TypeScript literal type node.
|
|
459
411
|
* Handles negative numbers via a prefix unary expression.
|
|
@@ -499,28 +451,13 @@ function buildTupleNode(node, print) {
|
|
|
499
451
|
*/
|
|
500
452
|
function buildPropertyType(schema, baseType, optionalType) {
|
|
501
453
|
const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType);
|
|
454
|
+
const meta = syncSchemaRef(schema);
|
|
502
455
|
let type = baseType;
|
|
503
|
-
if (
|
|
504
|
-
if ((
|
|
456
|
+
if (meta.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
|
|
457
|
+
if ((meta.nullish || meta.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
505
458
|
return type;
|
|
506
459
|
}
|
|
507
460
|
/**
|
|
508
|
-
* Collects JSDoc annotation strings (description, deprecated, min/max, pattern, default, example, type) for a schema node.
|
|
509
|
-
*/
|
|
510
|
-
function buildPropertyJSDocComments(schema) {
|
|
511
|
-
const isArray = schema.type === "array";
|
|
512
|
-
return [
|
|
513
|
-
"description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
|
|
514
|
-
"deprecated" in schema && schema.deprecated ? "@deprecated" : void 0,
|
|
515
|
-
!isArray && "min" in schema && schema.min !== void 0 ? `@minLength ${schema.min}` : void 0,
|
|
516
|
-
!isArray && "max" in schema && schema.max !== void 0 ? `@maxLength ${schema.max}` : void 0,
|
|
517
|
-
"pattern" in schema && schema.pattern ? `@pattern ${schema.pattern}` : void 0,
|
|
518
|
-
"default" in schema && schema.default !== void 0 ? `@default ${"primitive" in schema && schema.primitive === "string" ? stringify(schema.default) : schema.default}` : void 0,
|
|
519
|
-
"example" in schema && schema.example !== void 0 ? `@example ${schema.example}` : void 0,
|
|
520
|
-
"primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
|
|
521
|
-
];
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
461
|
* Creates TypeScript index signatures for `additionalProperties` and `patternProperties` on an object schema node.
|
|
525
462
|
*/
|
|
526
463
|
function buildIndexSignatures(node, propertyCount, print) {
|
|
@@ -539,6 +476,194 @@ function buildIndexSignatures(node, propertyCount, print) {
|
|
|
539
476
|
}
|
|
540
477
|
return elements;
|
|
541
478
|
}
|
|
479
|
+
//#endregion
|
|
480
|
+
//#region src/components/Enum.tsx
|
|
481
|
+
/**
|
|
482
|
+
* Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
|
|
483
|
+
*
|
|
484
|
+
* The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
|
|
485
|
+
* valid TypeScript identifier. The resolver normalizes it; for inline enum
|
|
486
|
+
* properties the adapter already emits a PascalCase+suffix name so resolution is typically a no-op.
|
|
487
|
+
*/
|
|
488
|
+
function getEnumNames({ node, enumType, enumTypeSuffix, resolver }) {
|
|
489
|
+
const resolved = resolver.default(node.name, "type");
|
|
490
|
+
return {
|
|
491
|
+
enumName: enumType === "asPascalConst" ? resolved : camelCase(node.name),
|
|
492
|
+
typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolved
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Renders the enum declaration(s) for a single named `EnumSchemaNode`.
|
|
497
|
+
*
|
|
498
|
+
* Depending on `enumType` this may emit:
|
|
499
|
+
* - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
|
|
500
|
+
* - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
|
|
501
|
+
* - A union literal type alias (`literal`)
|
|
502
|
+
*
|
|
503
|
+
* The emitted `File.Source` nodes carry the resolved names so that the barrel
|
|
504
|
+
* index picks up the correct export identifiers.
|
|
505
|
+
*/
|
|
506
|
+
function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
|
|
507
|
+
const { enumName, typeName } = getEnumNames({
|
|
508
|
+
node,
|
|
509
|
+
enumType,
|
|
510
|
+
enumTypeSuffix,
|
|
511
|
+
resolver
|
|
512
|
+
});
|
|
513
|
+
const [nameNode, typeNode] = createEnumDeclaration({
|
|
514
|
+
name: enumName,
|
|
515
|
+
typeName,
|
|
516
|
+
enums: node.namedEnumValues?.map((v) => [trimQuotes(v.name.toString()), v.value]) ?? node.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [trimQuotes(v.toString()), v]) ?? [],
|
|
517
|
+
type: enumType,
|
|
518
|
+
enumKeyCasing
|
|
519
|
+
});
|
|
520
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
|
|
521
|
+
name: enumName,
|
|
522
|
+
isExportable: true,
|
|
523
|
+
isIndexable: true,
|
|
524
|
+
isTypeOnly: false,
|
|
525
|
+
children: safePrint(nameNode)
|
|
526
|
+
}), /* @__PURE__ */ jsx(File.Source, {
|
|
527
|
+
name: typeName,
|
|
528
|
+
isIndexable: true,
|
|
529
|
+
isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
|
|
530
|
+
isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
|
|
531
|
+
children: safePrint(typeNode)
|
|
532
|
+
})] });
|
|
533
|
+
}
|
|
534
|
+
//#endregion
|
|
535
|
+
//#region src/utils.ts
|
|
536
|
+
/**
|
|
537
|
+
* Collects JSDoc annotation strings for a schema node.
|
|
538
|
+
*
|
|
539
|
+
* Only uses official JSDoc tags from https://jsdoc.app/: `@description`, `@deprecated`, `@default`, `@example`, `@type`.
|
|
540
|
+
* Constraint metadata (min/max length, pattern, multipleOf, min/maxProperties) is emitted as plain-text lines.
|
|
541
|
+
|
|
542
|
+
*/
|
|
543
|
+
function buildPropertyJSDocComments(schema) {
|
|
544
|
+
const meta = syncSchemaRef(schema);
|
|
545
|
+
const isArray = meta?.primitive === "array";
|
|
546
|
+
return [
|
|
547
|
+
meta && "description" in meta && meta.description ? `@description ${jsStringEscape(meta.description)}` : void 0,
|
|
548
|
+
meta && "deprecated" in meta && meta.deprecated ? "@deprecated" : void 0,
|
|
549
|
+
!isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` : void 0,
|
|
550
|
+
!isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : void 0,
|
|
551
|
+
meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : void 0,
|
|
552
|
+
meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` : void 0,
|
|
553
|
+
meta && "example" in meta && meta.example !== void 0 ? `@example ${meta.example}` : void 0,
|
|
554
|
+
meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
|
|
555
|
+
].filter(Boolean);
|
|
556
|
+
}
|
|
557
|
+
function buildParams(node, { params, resolver }) {
|
|
558
|
+
return createSchema({
|
|
559
|
+
type: "object",
|
|
560
|
+
properties: params.map((param) => createProperty({
|
|
561
|
+
name: param.name,
|
|
562
|
+
required: param.required,
|
|
563
|
+
schema: createSchema({
|
|
564
|
+
type: "ref",
|
|
565
|
+
name: resolver.resolveParamName(node, param)
|
|
566
|
+
})
|
|
567
|
+
}))
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
function buildData(node, { resolver }) {
|
|
571
|
+
const pathParams = node.parameters.filter((p) => p.in === "path");
|
|
572
|
+
const queryParams = node.parameters.filter((p) => p.in === "query");
|
|
573
|
+
const headerParams = node.parameters.filter((p) => p.in === "header");
|
|
574
|
+
return createSchema({
|
|
575
|
+
type: "object",
|
|
576
|
+
deprecated: node.deprecated,
|
|
577
|
+
properties: [
|
|
578
|
+
createProperty({
|
|
579
|
+
name: "data",
|
|
580
|
+
schema: node.requestBody?.schema ? createSchema({
|
|
581
|
+
type: "ref",
|
|
582
|
+
name: resolver.resolveDataName(node),
|
|
583
|
+
optional: true
|
|
584
|
+
}) : createSchema({
|
|
585
|
+
type: "never",
|
|
586
|
+
primitive: void 0,
|
|
587
|
+
optional: true
|
|
588
|
+
})
|
|
589
|
+
}),
|
|
590
|
+
createProperty({
|
|
591
|
+
name: "pathParams",
|
|
592
|
+
required: pathParams.length > 0,
|
|
593
|
+
schema: pathParams.length > 0 ? buildParams(node, {
|
|
594
|
+
params: pathParams,
|
|
595
|
+
resolver
|
|
596
|
+
}) : createSchema({
|
|
597
|
+
type: "never",
|
|
598
|
+
primitive: void 0
|
|
599
|
+
})
|
|
600
|
+
}),
|
|
601
|
+
createProperty({
|
|
602
|
+
name: "queryParams",
|
|
603
|
+
schema: queryParams.length > 0 ? createSchema({
|
|
604
|
+
...buildParams(node, {
|
|
605
|
+
params: queryParams,
|
|
606
|
+
resolver
|
|
607
|
+
}),
|
|
608
|
+
optional: true
|
|
609
|
+
}) : createSchema({
|
|
610
|
+
type: "never",
|
|
611
|
+
primitive: void 0,
|
|
612
|
+
optional: true
|
|
613
|
+
})
|
|
614
|
+
}),
|
|
615
|
+
createProperty({
|
|
616
|
+
name: "headerParams",
|
|
617
|
+
schema: headerParams.length > 0 ? createSchema({
|
|
618
|
+
...buildParams(node, {
|
|
619
|
+
params: headerParams,
|
|
620
|
+
resolver
|
|
621
|
+
}),
|
|
622
|
+
optional: true
|
|
623
|
+
}) : createSchema({
|
|
624
|
+
type: "never",
|
|
625
|
+
primitive: void 0,
|
|
626
|
+
optional: true
|
|
627
|
+
})
|
|
628
|
+
}),
|
|
629
|
+
createProperty({
|
|
630
|
+
name: "url",
|
|
631
|
+
required: true,
|
|
632
|
+
schema: createSchema({
|
|
633
|
+
type: "url",
|
|
634
|
+
path: node.path
|
|
635
|
+
})
|
|
636
|
+
})
|
|
637
|
+
]
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
function buildResponses(node, { resolver }) {
|
|
641
|
+
if (node.responses.length === 0) return null;
|
|
642
|
+
return createSchema({
|
|
643
|
+
type: "object",
|
|
644
|
+
properties: node.responses.map((res) => createProperty({
|
|
645
|
+
name: String(res.statusCode),
|
|
646
|
+
required: true,
|
|
647
|
+
schema: createSchema({
|
|
648
|
+
type: "ref",
|
|
649
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
650
|
+
})
|
|
651
|
+
}))
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
function buildResponseUnion(node, { resolver }) {
|
|
655
|
+
const responsesWithSchema = node.responses.filter((res) => res.schema);
|
|
656
|
+
if (responsesWithSchema.length === 0) return null;
|
|
657
|
+
return createSchema({
|
|
658
|
+
type: "union",
|
|
659
|
+
members: responsesWithSchema.map((res) => createSchema({
|
|
660
|
+
type: "ref",
|
|
661
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
662
|
+
}))
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
//#endregion
|
|
666
|
+
//#region src/printers/printerTs.ts
|
|
542
667
|
/**
|
|
543
668
|
* TypeScript type printer built with `definePrinter`.
|
|
544
669
|
*
|
|
@@ -582,6 +707,8 @@ const printerTs = definePrinter((options) => {
|
|
|
582
707
|
if (node.path) return createUrlTemplateType(node.path);
|
|
583
708
|
return keywordTypeNodes.string;
|
|
584
709
|
},
|
|
710
|
+
ipv4: () => keywordTypeNodes.string,
|
|
711
|
+
ipv6: () => keywordTypeNodes.string,
|
|
585
712
|
datetime: () => keywordTypeNodes.string,
|
|
586
713
|
number: () => keywordTypeNodes.number,
|
|
587
714
|
integer: () => keywordTypeNodes.number,
|
|
@@ -590,14 +717,14 @@ const printerTs = definePrinter((options) => {
|
|
|
590
717
|
time: dateOrStringNode,
|
|
591
718
|
ref(node) {
|
|
592
719
|
if (!node.name) return;
|
|
593
|
-
const refName = node.ref ? node.ref
|
|
720
|
+
const refName = node.ref ? extractRefName(node.ref) ?? node.name : node.name;
|
|
594
721
|
return createTypeReferenceNode(node.ref && ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) && this.options.enumTypeSuffix && this.options.enumSchemaNames?.has(refName) ? this.options.resolver.resolveEnumKeyName({ name: refName }, this.options.enumTypeSuffix) : node.ref ? this.options.resolver.default(refName, "type") : refName, void 0);
|
|
595
722
|
},
|
|
596
723
|
enum(node) {
|
|
597
724
|
const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
|
|
598
725
|
if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
|
|
599
726
|
withParentheses: true,
|
|
600
|
-
nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value)).filter(Boolean)
|
|
727
|
+
nodes: values.filter((v) => v !== null && v !== void 0).map((value) => constToTypeNode(value, typeof value)).filter(Boolean)
|
|
601
728
|
}) ?? void 0;
|
|
602
729
|
return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) && this.options.enumTypeSuffix ? this.options.resolver.resolveEnumKeyName(node, this.options.enumTypeSuffix) : this.options.resolver.default(node.name, "type"), void 0);
|
|
603
730
|
},
|
|
@@ -643,12 +770,13 @@ const printerTs = definePrinter((options) => {
|
|
|
643
770
|
const propertyNodes = node.properties.map((prop) => {
|
|
644
771
|
const baseType = transform(prop.schema) ?? keywordTypeNodes.unknown;
|
|
645
772
|
const type = buildPropertyType(prop.schema, baseType, options.optionalType);
|
|
773
|
+
const propMeta = syncSchemaRef(prop.schema);
|
|
646
774
|
return appendJSDocToNode({
|
|
647
775
|
node: createPropertySignature({
|
|
648
776
|
questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
|
|
649
777
|
name: prop.name,
|
|
650
778
|
type,
|
|
651
|
-
readOnly:
|
|
779
|
+
readOnly: propMeta?.readOnly
|
|
652
780
|
}),
|
|
653
781
|
comments: buildPropertyJSDocComments(prop.schema)
|
|
654
782
|
});
|
|
@@ -659,32 +787,32 @@ const printerTs = definePrinter((options) => {
|
|
|
659
787
|
}
|
|
660
788
|
},
|
|
661
789
|
print(node) {
|
|
662
|
-
let type = this.transform(node);
|
|
663
|
-
if (!type) return null;
|
|
664
|
-
if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
|
|
665
|
-
if ((node.nullish || node.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
666
790
|
const { name, syntaxType = "type", description, keysToOmit } = this.options;
|
|
667
|
-
|
|
668
|
-
|
|
791
|
+
let base = this.transform(node);
|
|
792
|
+
if (!base) return null;
|
|
793
|
+
const meta = syncSchemaRef(node);
|
|
794
|
+
if (!name) {
|
|
795
|
+
if (meta.nullable) base = createUnionDeclaration({ nodes: [base, keywordTypeNodes.null] });
|
|
796
|
+
if ((meta.nullish || meta.optional) && addsUndefined) base = createUnionDeclaration({ nodes: [base, keywordTypeNodes.undefined] });
|
|
797
|
+
return safePrint(base);
|
|
798
|
+
}
|
|
799
|
+
let inner = keysToOmit?.length ? createOmitDeclaration({
|
|
800
|
+
keys: keysToOmit,
|
|
801
|
+
type: base,
|
|
802
|
+
nonNullable: true
|
|
803
|
+
}) : base;
|
|
804
|
+
if (meta.nullable) inner = createUnionDeclaration({ nodes: [inner, keywordTypeNodes.null] });
|
|
805
|
+
if (meta.nullish || meta.optional) inner = createUnionDeclaration({ nodes: [inner, keywordTypeNodes.undefined] });
|
|
806
|
+
const useTypeGeneration = syntaxType === "type" || inner.kind === syntaxKind.union || !!keysToOmit?.length;
|
|
669
807
|
return safePrint(createTypeDeclaration({
|
|
670
808
|
name,
|
|
671
809
|
isExportable: true,
|
|
672
|
-
type:
|
|
673
|
-
keys: keysToOmit,
|
|
674
|
-
type,
|
|
675
|
-
nonNullable: true
|
|
676
|
-
}) : type,
|
|
810
|
+
type: inner,
|
|
677
811
|
syntax: useTypeGeneration ? "type" : "interface",
|
|
678
|
-
comments:
|
|
679
|
-
|
|
680
|
-
description
|
|
681
|
-
|
|
682
|
-
node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
|
|
683
|
-
node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
|
|
684
|
-
node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
|
|
685
|
-
node?.default ? `@default ${node.default}` : void 0,
|
|
686
|
-
node?.example ? `@example ${node.example}` : void 0
|
|
687
|
-
]
|
|
812
|
+
comments: buildPropertyJSDocComments({
|
|
813
|
+
...meta,
|
|
814
|
+
description
|
|
815
|
+
})
|
|
688
816
|
}));
|
|
689
817
|
}
|
|
690
818
|
};
|
|
@@ -738,141 +866,103 @@ function Type({ name, node, keysToOmit, optionalType, arrayType, syntaxType, enu
|
|
|
738
866
|
})] });
|
|
739
867
|
}
|
|
740
868
|
//#endregion
|
|
741
|
-
//#region src/
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
schema: pathParams.length > 0 ? buildParams({
|
|
778
|
-
params: pathParams,
|
|
779
|
-
node,
|
|
780
|
-
resolver
|
|
781
|
-
}) : createSchema({ type: "never" })
|
|
782
|
-
}),
|
|
783
|
-
createProperty({
|
|
784
|
-
name: "queryParams",
|
|
785
|
-
schema: queryParams.length > 0 ? createSchema({
|
|
786
|
-
...buildParams({
|
|
787
|
-
params: queryParams,
|
|
788
|
-
node,
|
|
789
|
-
resolver
|
|
790
|
-
}),
|
|
791
|
-
optional: true
|
|
792
|
-
}) : createSchema({
|
|
793
|
-
type: "never",
|
|
794
|
-
optional: true
|
|
795
|
-
})
|
|
796
|
-
}),
|
|
797
|
-
createProperty({
|
|
798
|
-
name: "headerParams",
|
|
799
|
-
schema: headerParams.length > 0 ? createSchema({
|
|
800
|
-
...buildParams({
|
|
801
|
-
params: headerParams,
|
|
802
|
-
node,
|
|
803
|
-
resolver
|
|
804
|
-
}),
|
|
805
|
-
optional: true
|
|
806
|
-
}) : createSchema({
|
|
807
|
-
type: "never",
|
|
808
|
-
optional: true
|
|
809
|
-
})
|
|
810
|
-
}),
|
|
811
|
-
createProperty({
|
|
812
|
-
name: "url",
|
|
813
|
-
required: true,
|
|
814
|
-
schema: createSchema({
|
|
815
|
-
type: "url",
|
|
816
|
-
path: node.path
|
|
817
|
-
})
|
|
818
|
-
})
|
|
819
|
-
]
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
function buildResponses({ node, resolver }) {
|
|
823
|
-
if (node.responses.length === 0) return null;
|
|
824
|
-
return createSchema({
|
|
825
|
-
type: "object",
|
|
826
|
-
properties: node.responses.map((res) => createProperty({
|
|
827
|
-
name: String(res.statusCode),
|
|
828
|
-
required: true,
|
|
829
|
-
schema: createSchema({
|
|
830
|
-
type: "ref",
|
|
831
|
-
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
869
|
+
//#region src/generators/typeGenerator.tsx
|
|
870
|
+
const typeGenerator = defineGenerator({
|
|
871
|
+
name: "typescript",
|
|
872
|
+
type: "react",
|
|
873
|
+
Schema({ node, adapter, options, config, resolver }) {
|
|
874
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
|
|
875
|
+
const transformedNode = transform(node, composeTransformers(...transformers));
|
|
876
|
+
if (!transformedNode.name) return;
|
|
877
|
+
const root = path.resolve(config.root, config.output.path);
|
|
878
|
+
const mode = getMode(path.resolve(root, output.path));
|
|
879
|
+
const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name));
|
|
880
|
+
function resolveImportName(schemaName) {
|
|
881
|
+
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
|
|
882
|
+
return resolver.default(schemaName, "type");
|
|
883
|
+
}
|
|
884
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
885
|
+
name: resolveImportName(schemaName),
|
|
886
|
+
path: resolver.resolveFile({
|
|
887
|
+
name: schemaName,
|
|
888
|
+
extname: ".ts"
|
|
889
|
+
}, {
|
|
890
|
+
root,
|
|
891
|
+
output,
|
|
892
|
+
group
|
|
893
|
+
}).path
|
|
894
|
+
}));
|
|
895
|
+
const isEnumSchema = !!narrowSchema(transformedNode, schemaTypes.enum);
|
|
896
|
+
const meta = {
|
|
897
|
+
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(transformedNode, enumTypeSuffix) : resolver.resolveName(transformedNode.name),
|
|
898
|
+
file: resolver.resolveFile({
|
|
899
|
+
name: transformedNode.name,
|
|
900
|
+
extname: ".ts"
|
|
901
|
+
}, {
|
|
902
|
+
root,
|
|
903
|
+
output,
|
|
904
|
+
group
|
|
832
905
|
})
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
906
|
+
};
|
|
907
|
+
return /* @__PURE__ */ jsxs(File, {
|
|
908
|
+
baseName: meta.file.baseName,
|
|
909
|
+
path: meta.file.path,
|
|
910
|
+
meta: meta.file.meta,
|
|
911
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
912
|
+
output,
|
|
913
|
+
config
|
|
914
|
+
}),
|
|
915
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
916
|
+
output,
|
|
917
|
+
config
|
|
918
|
+
}),
|
|
919
|
+
children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
920
|
+
root: meta.file.path,
|
|
921
|
+
path: imp.path,
|
|
922
|
+
name: imp.name,
|
|
923
|
+
isTypeOnly: true
|
|
924
|
+
}, [
|
|
925
|
+
transformedNode.name,
|
|
926
|
+
imp.path,
|
|
927
|
+
imp.isTypeOnly
|
|
928
|
+
].join("-"))), /* @__PURE__ */ jsx(Type, {
|
|
929
|
+
name: meta.name,
|
|
930
|
+
node: transformedNode,
|
|
931
|
+
enumType,
|
|
932
|
+
enumTypeSuffix,
|
|
933
|
+
enumKeyCasing,
|
|
934
|
+
optionalType,
|
|
935
|
+
arrayType,
|
|
936
|
+
syntaxType,
|
|
937
|
+
resolver,
|
|
938
|
+
enumSchemaNames
|
|
939
|
+
})]
|
|
940
|
+
});
|
|
941
|
+
},
|
|
852
942
|
Operation({ node, adapter, options, config, resolver }) {
|
|
853
943
|
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options;
|
|
944
|
+
const transformedNode = transform(node, composeTransformers(...transformers));
|
|
854
945
|
const root = path.resolve(config.root, config.output.path);
|
|
855
946
|
const mode = getMode(path.resolve(root, output.path));
|
|
856
|
-
const
|
|
857
|
-
|
|
947
|
+
const params = caseParams(transformedNode.parameters, paramsCasing);
|
|
948
|
+
const meta = { file: resolver.resolveFile({
|
|
949
|
+
name: transformedNode.operationId,
|
|
858
950
|
extname: ".ts",
|
|
859
|
-
tag:
|
|
860
|
-
path:
|
|
951
|
+
tag: transformedNode.tags[0] ?? "default",
|
|
952
|
+
path: transformedNode.path
|
|
861
953
|
}, {
|
|
862
954
|
root,
|
|
863
955
|
output,
|
|
864
956
|
group
|
|
865
|
-
});
|
|
866
|
-
const params = caseParams(node.parameters, paramsCasing);
|
|
957
|
+
}) };
|
|
867
958
|
const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name));
|
|
868
959
|
function resolveImportName(schemaName) {
|
|
869
960
|
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
|
|
870
961
|
return resolver.default(schemaName, "type");
|
|
871
962
|
}
|
|
872
|
-
function renderSchemaType({
|
|
873
|
-
if (!
|
|
874
|
-
const
|
|
875
|
-
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
963
|
+
function renderSchemaType({ schema, name, keysToOmit }) {
|
|
964
|
+
if (!schema) return null;
|
|
965
|
+
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
876
966
|
name: resolveImportName(schemaName),
|
|
877
967
|
path: resolver.resolveFile({
|
|
878
968
|
name: schemaName,
|
|
@@ -884,7 +974,7 @@ const typeGenerator = defineGenerator({
|
|
|
884
974
|
}).path
|
|
885
975
|
}));
|
|
886
976
|
return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
887
|
-
root: file.path,
|
|
977
|
+
root: meta.file.path,
|
|
888
978
|
path: imp.path,
|
|
889
979
|
name: imp.name,
|
|
890
980
|
isTypeOnly: true
|
|
@@ -894,8 +984,7 @@ const typeGenerator = defineGenerator({
|
|
|
894
984
|
imp.isTypeOnly
|
|
895
985
|
].join("-"))), /* @__PURE__ */ jsx(Type, {
|
|
896
986
|
name,
|
|
897
|
-
node:
|
|
898
|
-
description,
|
|
987
|
+
node: schema,
|
|
899
988
|
enumType,
|
|
900
989
|
enumTypeSuffix,
|
|
901
990
|
enumKeyCasing,
|
|
@@ -908,50 +997,44 @@ const typeGenerator = defineGenerator({
|
|
|
908
997
|
})] });
|
|
909
998
|
}
|
|
910
999
|
const paramTypes = params.map((param) => renderSchemaType({
|
|
911
|
-
|
|
912
|
-
name: resolver.resolveParamName(
|
|
1000
|
+
schema: param.schema,
|
|
1001
|
+
name: resolver.resolveParamName(transformedNode, param)
|
|
913
1002
|
}));
|
|
914
|
-
const requestType =
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1003
|
+
const requestType = transformedNode.requestBody?.schema ? renderSchemaType({
|
|
1004
|
+
schema: {
|
|
1005
|
+
...transformedNode.requestBody.schema,
|
|
1006
|
+
description: transformedNode.requestBody.description ?? transformedNode.requestBody.schema.description
|
|
1007
|
+
},
|
|
1008
|
+
name: resolver.resolveDataName(transformedNode),
|
|
1009
|
+
keysToOmit: transformedNode.requestBody.keysToOmit
|
|
919
1010
|
}) : null;
|
|
920
|
-
const responseTypes =
|
|
921
|
-
|
|
922
|
-
name: resolver.resolveResponseStatusName(
|
|
923
|
-
description: res.description,
|
|
1011
|
+
const responseTypes = transformedNode.responses.map((res) => renderSchemaType({
|
|
1012
|
+
schema: res.schema,
|
|
1013
|
+
name: resolver.resolveResponseStatusName(transformedNode, res.statusCode),
|
|
924
1014
|
keysToOmit: res.keysToOmit
|
|
925
1015
|
}));
|
|
926
1016
|
const dataType = renderSchemaType({
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
resolver
|
|
933
|
-
}),
|
|
934
|
-
name: resolver.resolveRequestConfigName(node)
|
|
1017
|
+
schema: buildData({
|
|
1018
|
+
...transformedNode,
|
|
1019
|
+
parameters: params
|
|
1020
|
+
}, { resolver }),
|
|
1021
|
+
name: resolver.resolveRequestConfigName(transformedNode)
|
|
935
1022
|
});
|
|
936
1023
|
const responsesType = renderSchemaType({
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
resolver
|
|
940
|
-
}),
|
|
941
|
-
name: resolver.resolveResponsesName(node)
|
|
1024
|
+
schema: buildResponses(transformedNode, { resolver }),
|
|
1025
|
+
name: resolver.resolveResponsesName(transformedNode)
|
|
942
1026
|
});
|
|
943
1027
|
const responseType = renderSchemaType({
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
}
|
|
948
|
-
name: resolver.resolveResponseName(
|
|
949
|
-
description: "Union of all possible responses"
|
|
1028
|
+
schema: transformedNode.responses.some((res) => res.schema) ? {
|
|
1029
|
+
...buildResponseUnion(transformedNode, { resolver }),
|
|
1030
|
+
description: "Union of all possible responses"
|
|
1031
|
+
} : null,
|
|
1032
|
+
name: resolver.resolveResponseName(transformedNode)
|
|
950
1033
|
});
|
|
951
1034
|
return /* @__PURE__ */ jsxs(File, {
|
|
952
|
-
baseName: file.baseName,
|
|
953
|
-
path: file.path,
|
|
954
|
-
meta: file.meta,
|
|
1035
|
+
baseName: meta.file.baseName,
|
|
1036
|
+
path: meta.file.path,
|
|
1037
|
+
meta: meta.file.meta,
|
|
955
1038
|
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
956
1039
|
output,
|
|
957
1040
|
config
|
|
@@ -969,80 +1052,11 @@ const typeGenerator = defineGenerator({
|
|
|
969
1052
|
responseType
|
|
970
1053
|
]
|
|
971
1054
|
});
|
|
972
|
-
},
|
|
973
|
-
Schema({ node, adapter, options, config, resolver }) {
|
|
974
|
-
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
|
|
975
|
-
const root = path.resolve(config.root, config.output.path);
|
|
976
|
-
const mode = getMode(path.resolve(root, output.path));
|
|
977
|
-
if (!node.name) return;
|
|
978
|
-
const transformedNode = transform(node, composeTransformers(...transformers));
|
|
979
|
-
const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name));
|
|
980
|
-
function resolveImportName(schemaName) {
|
|
981
|
-
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix);
|
|
982
|
-
return resolver.default(schemaName, "type");
|
|
983
|
-
}
|
|
984
|
-
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
985
|
-
name: resolveImportName(schemaName),
|
|
986
|
-
path: resolver.resolveFile({
|
|
987
|
-
name: schemaName,
|
|
988
|
-
extname: ".ts"
|
|
989
|
-
}, {
|
|
990
|
-
root,
|
|
991
|
-
output,
|
|
992
|
-
group
|
|
993
|
-
}).path
|
|
994
|
-
}));
|
|
995
|
-
const isEnumSchema = !!narrowSchema(node, schemaTypes.enum);
|
|
996
|
-
const type = {
|
|
997
|
-
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
|
|
998
|
-
file: resolver.resolveFile({
|
|
999
|
-
name: node.name,
|
|
1000
|
-
extname: ".ts"
|
|
1001
|
-
}, {
|
|
1002
|
-
root,
|
|
1003
|
-
output,
|
|
1004
|
-
group
|
|
1005
|
-
})
|
|
1006
|
-
};
|
|
1007
|
-
return /* @__PURE__ */ jsxs(File, {
|
|
1008
|
-
baseName: type.file.baseName,
|
|
1009
|
-
path: type.file.path,
|
|
1010
|
-
meta: type.file.meta,
|
|
1011
|
-
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1012
|
-
output,
|
|
1013
|
-
config
|
|
1014
|
-
}),
|
|
1015
|
-
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1016
|
-
output,
|
|
1017
|
-
config
|
|
1018
|
-
}),
|
|
1019
|
-
children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
1020
|
-
root: type.file.path,
|
|
1021
|
-
path: imp.path,
|
|
1022
|
-
name: imp.name,
|
|
1023
|
-
isTypeOnly: true
|
|
1024
|
-
}, [
|
|
1025
|
-
node.name,
|
|
1026
|
-
imp.path,
|
|
1027
|
-
imp.isTypeOnly
|
|
1028
|
-
].join("-"))), /* @__PURE__ */ jsx(Type, {
|
|
1029
|
-
name: type.name,
|
|
1030
|
-
node: transformedNode,
|
|
1031
|
-
enumType,
|
|
1032
|
-
enumTypeSuffix,
|
|
1033
|
-
enumKeyCasing,
|
|
1034
|
-
optionalType,
|
|
1035
|
-
arrayType,
|
|
1036
|
-
syntaxType,
|
|
1037
|
-
resolver,
|
|
1038
|
-
enumSchemaNames
|
|
1039
|
-
})]
|
|
1040
|
-
});
|
|
1041
1055
|
}
|
|
1042
1056
|
});
|
|
1043
1057
|
//#endregion
|
|
1044
1058
|
//#region src/resolvers/resolverTs.ts
|
|
1045
|
-
function
|
|
1059
|
+
function toTypeName(name, type) {
|
|
1046
1060
|
return pascalCase(name, { isFile: type === "file" });
|
|
1047
1061
|
}
|
|
1048
1062
|
/**
|
|
@@ -1067,7 +1081,7 @@ const resolverTs = defineResolver(() => {
|
|
|
1067
1081
|
name: "default",
|
|
1068
1082
|
pluginName: "plugin-ts",
|
|
1069
1083
|
default(name, type) {
|
|
1070
|
-
return
|
|
1084
|
+
return toTypeName(name, type);
|
|
1071
1085
|
},
|
|
1072
1086
|
resolveName(name) {
|
|
1073
1087
|
return this.default(name, "function");
|
|
@@ -1186,7 +1200,7 @@ function buildGroupedParamsSchema({ params, parentName }) {
|
|
|
1186
1200
|
})
|
|
1187
1201
|
});
|
|
1188
1202
|
}
|
|
1189
|
-
function buildLegacyResponsesSchemaNode(
|
|
1203
|
+
function buildLegacyResponsesSchemaNode(node, { resolver }) {
|
|
1190
1204
|
const isGet = node.method.toLowerCase() === "get";
|
|
1191
1205
|
const successResponses = node.responses.filter((res) => {
|
|
1192
1206
|
const code = Number(res.statusCode);
|
|
@@ -1202,7 +1216,10 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
|
|
|
1202
1216
|
type: "ref",
|
|
1203
1217
|
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1204
1218
|
}))
|
|
1205
|
-
}) : createSchema({
|
|
1219
|
+
}) : createSchema({
|
|
1220
|
+
type: "any",
|
|
1221
|
+
primitive: void 0
|
|
1222
|
+
});
|
|
1206
1223
|
const errorsSchema = errorResponses.length > 0 ? errorResponses.length === 1 ? createSchema({
|
|
1207
1224
|
type: "ref",
|
|
1208
1225
|
name: resolver.resolveResponseStatusName(node, errorResponses[0].statusCode)
|
|
@@ -1212,7 +1229,10 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
|
|
|
1212
1229
|
type: "ref",
|
|
1213
1230
|
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1214
1231
|
}))
|
|
1215
|
-
}) : createSchema({
|
|
1232
|
+
}) : createSchema({
|
|
1233
|
+
type: "any",
|
|
1234
|
+
primitive: void 0
|
|
1235
|
+
});
|
|
1216
1236
|
const properties = [createProperty({
|
|
1217
1237
|
name: "Response",
|
|
1218
1238
|
required: true,
|
|
@@ -1263,12 +1283,15 @@ function buildLegacyResponsesSchemaNode({ node, resolver }) {
|
|
|
1263
1283
|
properties
|
|
1264
1284
|
});
|
|
1265
1285
|
}
|
|
1266
|
-
function buildLegacyResponseUnionSchemaNode(
|
|
1286
|
+
function buildLegacyResponseUnionSchemaNode(node, { resolver }) {
|
|
1267
1287
|
const successResponses = node.responses.filter((res) => {
|
|
1268
1288
|
const code = Number(res.statusCode);
|
|
1269
1289
|
return !Number.isNaN(code) && code >= 200 && code < 300;
|
|
1270
1290
|
});
|
|
1271
|
-
if (successResponses.length === 0) return createSchema({
|
|
1291
|
+
if (successResponses.length === 0) return createSchema({
|
|
1292
|
+
type: "any",
|
|
1293
|
+
primitive: void 0
|
|
1294
|
+
});
|
|
1272
1295
|
if (successResponses.length === 1) return createSchema({
|
|
1273
1296
|
type: "ref",
|
|
1274
1297
|
name: resolver.resolveResponseStatusName(node, successResponses[0].statusCode)
|
|
@@ -1309,25 +1332,88 @@ function nameUnnamedEnums(node, parentName) {
|
|
|
1309
1332
|
const typeGeneratorLegacy = defineGenerator({
|
|
1310
1333
|
name: "typescript-legacy",
|
|
1311
1334
|
type: "react",
|
|
1335
|
+
Schema({ node, adapter, options, config, resolver }) {
|
|
1336
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
|
|
1337
|
+
const transformedNode = transform(node, composeTransformers(...transformers));
|
|
1338
|
+
if (!transformedNode.name) return;
|
|
1339
|
+
const root = path.resolve(config.root, config.output.path);
|
|
1340
|
+
const mode = getMode(path.resolve(root, output.path));
|
|
1341
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
1342
|
+
name: resolver.default(schemaName, "type"),
|
|
1343
|
+
path: resolver.resolveFile({
|
|
1344
|
+
name: schemaName,
|
|
1345
|
+
extname: ".ts"
|
|
1346
|
+
}, {
|
|
1347
|
+
root,
|
|
1348
|
+
output,
|
|
1349
|
+
group
|
|
1350
|
+
}).path
|
|
1351
|
+
}));
|
|
1352
|
+
const isEnumSchema = !!narrowSchema(transformedNode, schemaTypes.enum);
|
|
1353
|
+
const meta = {
|
|
1354
|
+
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(transformedNode, enumTypeSuffix) : resolver.resolveName(transformedNode.name),
|
|
1355
|
+
file: resolver.resolveFile({
|
|
1356
|
+
name: transformedNode.name,
|
|
1357
|
+
extname: ".ts"
|
|
1358
|
+
}, {
|
|
1359
|
+
root,
|
|
1360
|
+
output,
|
|
1361
|
+
group
|
|
1362
|
+
})
|
|
1363
|
+
};
|
|
1364
|
+
return /* @__PURE__ */ jsxs(File, {
|
|
1365
|
+
baseName: meta.file.baseName,
|
|
1366
|
+
path: meta.file.path,
|
|
1367
|
+
meta: meta.file.meta,
|
|
1368
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1369
|
+
output,
|
|
1370
|
+
config
|
|
1371
|
+
}),
|
|
1372
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1373
|
+
output,
|
|
1374
|
+
config
|
|
1375
|
+
}),
|
|
1376
|
+
children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
1377
|
+
root: meta.file.path,
|
|
1378
|
+
path: imp.path,
|
|
1379
|
+
name: imp.name,
|
|
1380
|
+
isTypeOnly: true
|
|
1381
|
+
}, [
|
|
1382
|
+
transformedNode.name,
|
|
1383
|
+
imp.path,
|
|
1384
|
+
imp.isTypeOnly
|
|
1385
|
+
].join("-"))), /* @__PURE__ */ jsx(Type, {
|
|
1386
|
+
name: meta.name,
|
|
1387
|
+
node: transformedNode,
|
|
1388
|
+
enumType,
|
|
1389
|
+
enumTypeSuffix,
|
|
1390
|
+
enumKeyCasing,
|
|
1391
|
+
optionalType,
|
|
1392
|
+
arrayType,
|
|
1393
|
+
syntaxType,
|
|
1394
|
+
resolver
|
|
1395
|
+
})]
|
|
1396
|
+
});
|
|
1397
|
+
},
|
|
1312
1398
|
Operation({ node, adapter, options, config, resolver }) {
|
|
1313
1399
|
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options;
|
|
1400
|
+
const transformedNode = transform(node, composeTransformers(...transformers));
|
|
1314
1401
|
const root = path.resolve(config.root, config.output.path);
|
|
1315
1402
|
const mode = getMode(path.resolve(root, output.path));
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1403
|
+
const params = caseParams(node.parameters, paramsCasing);
|
|
1404
|
+
const meta = { file: resolver.resolveFile({
|
|
1405
|
+
name: transformedNode.operationId,
|
|
1318
1406
|
extname: ".ts",
|
|
1319
|
-
tag:
|
|
1320
|
-
path:
|
|
1407
|
+
tag: transformedNode.tags[0] ?? "default",
|
|
1408
|
+
path: transformedNode.path
|
|
1321
1409
|
}, {
|
|
1322
1410
|
root,
|
|
1323
1411
|
output,
|
|
1324
1412
|
group
|
|
1325
|
-
});
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
const transformedNode = transform(schemaNode, composeTransformers(...transformers));
|
|
1330
|
-
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
1413
|
+
}) };
|
|
1414
|
+
function renderSchemaType({ schema, name, description, keysToOmit }) {
|
|
1415
|
+
if (!schema) return null;
|
|
1416
|
+
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
1331
1417
|
name: resolver.default(schemaName, "type"),
|
|
1332
1418
|
path: resolver.resolveFile({
|
|
1333
1419
|
name: schemaName,
|
|
@@ -1339,7 +1425,7 @@ const typeGeneratorLegacy = defineGenerator({
|
|
|
1339
1425
|
}).path
|
|
1340
1426
|
}));
|
|
1341
1427
|
return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
1342
|
-
root: file.path,
|
|
1428
|
+
root: meta.file.path,
|
|
1343
1429
|
path: imp.path,
|
|
1344
1430
|
name: imp.name,
|
|
1345
1431
|
isTypeOnly: true
|
|
@@ -1349,7 +1435,7 @@ const typeGeneratorLegacy = defineGenerator({
|
|
|
1349
1435
|
imp.isTypeOnly
|
|
1350
1436
|
].join("-"))), /* @__PURE__ */ jsx(Type, {
|
|
1351
1437
|
name,
|
|
1352
|
-
node:
|
|
1438
|
+
node: schema,
|
|
1353
1439
|
description,
|
|
1354
1440
|
enumType,
|
|
1355
1441
|
enumTypeSuffix,
|
|
@@ -1368,35 +1454,35 @@ const typeGeneratorLegacy = defineGenerator({
|
|
|
1368
1454
|
const responseName = resolver.resolveResponseStatusName(node, res.statusCode);
|
|
1369
1455
|
const baseResponseName = resolverTsLegacy.resolveResponseStatusName(node, res.statusCode);
|
|
1370
1456
|
return renderSchemaType({
|
|
1371
|
-
|
|
1457
|
+
schema: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
|
|
1372
1458
|
name: responseName,
|
|
1373
1459
|
description: res.description,
|
|
1374
1460
|
keysToOmit: res.keysToOmit
|
|
1375
1461
|
});
|
|
1376
1462
|
});
|
|
1377
1463
|
const requestType = node.requestBody?.schema ? renderSchemaType({
|
|
1378
|
-
|
|
1464
|
+
schema: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
|
|
1379
1465
|
name: resolver.resolveDataName(node),
|
|
1380
1466
|
description: node.requestBody.description ?? node.requestBody.schema.description,
|
|
1381
1467
|
keysToOmit: node.requestBody.keysToOmit
|
|
1382
1468
|
}) : null;
|
|
1383
1469
|
const legacyParamTypes = [
|
|
1384
1470
|
pathParams.length > 0 ? renderSchemaType({
|
|
1385
|
-
|
|
1471
|
+
schema: buildGroupedParamsSchema({
|
|
1386
1472
|
params: pathParams,
|
|
1387
1473
|
parentName: resolverTsLegacy.resolvePathParamsName(node, pathParams[0])
|
|
1388
1474
|
}),
|
|
1389
1475
|
name: resolver.resolvePathParamsName(node, pathParams[0])
|
|
1390
1476
|
}) : null,
|
|
1391
1477
|
queryParams.length > 0 ? renderSchemaType({
|
|
1392
|
-
|
|
1478
|
+
schema: buildGroupedParamsSchema({
|
|
1393
1479
|
params: queryParams,
|
|
1394
1480
|
parentName: resolverTsLegacy.resolveQueryParamsName(node, queryParams[0])
|
|
1395
1481
|
}),
|
|
1396
1482
|
name: resolver.resolveQueryParamsName(node, queryParams[0])
|
|
1397
1483
|
}) : null,
|
|
1398
1484
|
headerParams.length > 0 ? renderSchemaType({
|
|
1399
|
-
|
|
1485
|
+
schema: buildGroupedParamsSchema({
|
|
1400
1486
|
params: headerParams,
|
|
1401
1487
|
parentName: resolverTsLegacy.resolveHeaderParamsName(node, headerParams[0])
|
|
1402
1488
|
}),
|
|
@@ -1404,23 +1490,17 @@ const typeGeneratorLegacy = defineGenerator({
|
|
|
1404
1490
|
}) : null
|
|
1405
1491
|
];
|
|
1406
1492
|
const legacyResponsesType = renderSchemaType({
|
|
1407
|
-
|
|
1408
|
-
node,
|
|
1409
|
-
resolver
|
|
1410
|
-
}),
|
|
1493
|
+
schema: buildLegacyResponsesSchemaNode(node, { resolver }),
|
|
1411
1494
|
name: resolver.resolveResponsesName(node)
|
|
1412
1495
|
});
|
|
1413
1496
|
const legacyResponseType = renderSchemaType({
|
|
1414
|
-
|
|
1415
|
-
node,
|
|
1416
|
-
resolver
|
|
1417
|
-
}),
|
|
1497
|
+
schema: buildLegacyResponseUnionSchemaNode(node, { resolver }),
|
|
1418
1498
|
name: resolver.resolveResponseName(node)
|
|
1419
1499
|
});
|
|
1420
1500
|
return /* @__PURE__ */ jsxs(File, {
|
|
1421
|
-
baseName: file.baseName,
|
|
1422
|
-
path: file.path,
|
|
1423
|
-
meta: file.meta,
|
|
1501
|
+
baseName: meta.file.baseName,
|
|
1502
|
+
path: meta.file.path,
|
|
1503
|
+
meta: meta.file.meta,
|
|
1424
1504
|
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1425
1505
|
output,
|
|
1426
1506
|
config
|
|
@@ -1437,69 +1517,6 @@ const typeGeneratorLegacy = defineGenerator({
|
|
|
1437
1517
|
legacyResponsesType
|
|
1438
1518
|
]
|
|
1439
1519
|
});
|
|
1440
|
-
},
|
|
1441
|
-
Schema({ node, adapter, options, config, resolver }) {
|
|
1442
|
-
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
|
|
1443
|
-
const root = path.resolve(config.root, config.output.path);
|
|
1444
|
-
const mode = getMode(path.resolve(root, output.path));
|
|
1445
|
-
if (!node.name) return;
|
|
1446
|
-
const transformedNode = transform(node, composeTransformers(...transformers));
|
|
1447
|
-
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
1448
|
-
name: resolver.default(schemaName, "type"),
|
|
1449
|
-
path: resolver.resolveFile({
|
|
1450
|
-
name: schemaName,
|
|
1451
|
-
extname: ".ts"
|
|
1452
|
-
}, {
|
|
1453
|
-
root,
|
|
1454
|
-
output,
|
|
1455
|
-
group
|
|
1456
|
-
}).path
|
|
1457
|
-
}));
|
|
1458
|
-
const isEnumSchema = !!narrowSchema(node, schemaTypes.enum);
|
|
1459
|
-
const type = {
|
|
1460
|
-
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
|
|
1461
|
-
file: resolver.resolveFile({
|
|
1462
|
-
name: node.name,
|
|
1463
|
-
extname: ".ts"
|
|
1464
|
-
}, {
|
|
1465
|
-
root,
|
|
1466
|
-
output,
|
|
1467
|
-
group
|
|
1468
|
-
})
|
|
1469
|
-
};
|
|
1470
|
-
return /* @__PURE__ */ jsxs(File, {
|
|
1471
|
-
baseName: type.file.baseName,
|
|
1472
|
-
path: type.file.path,
|
|
1473
|
-
meta: type.file.meta,
|
|
1474
|
-
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1475
|
-
output,
|
|
1476
|
-
config
|
|
1477
|
-
}),
|
|
1478
|
-
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1479
|
-
output,
|
|
1480
|
-
config
|
|
1481
|
-
}),
|
|
1482
|
-
children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
1483
|
-
root: type.file.path,
|
|
1484
|
-
path: imp.path,
|
|
1485
|
-
name: imp.name,
|
|
1486
|
-
isTypeOnly: true
|
|
1487
|
-
}, [
|
|
1488
|
-
node.name,
|
|
1489
|
-
imp.path,
|
|
1490
|
-
imp.isTypeOnly
|
|
1491
|
-
].join("-"))), /* @__PURE__ */ jsx(Type, {
|
|
1492
|
-
name: type.name,
|
|
1493
|
-
node: transformedNode,
|
|
1494
|
-
enumType,
|
|
1495
|
-
enumTypeSuffix,
|
|
1496
|
-
enumKeyCasing,
|
|
1497
|
-
optionalType,
|
|
1498
|
-
arrayType,
|
|
1499
|
-
syntaxType,
|
|
1500
|
-
resolver
|
|
1501
|
-
})]
|
|
1502
|
-
});
|
|
1503
1520
|
}
|
|
1504
1521
|
});
|
|
1505
1522
|
//#endregion
|
|
@@ -1568,9 +1585,9 @@ const pluginTs = createPlugin((options) => {
|
|
|
1568
1585
|
output,
|
|
1569
1586
|
optionalType,
|
|
1570
1587
|
group: group ? {
|
|
1571
|
-
...
|
|
1588
|
+
...group,
|
|
1572
1589
|
name: (ctx) => {
|
|
1573
|
-
if (
|
|
1590
|
+
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
1574
1591
|
return `${camelCase(ctx.group)}Controller`;
|
|
1575
1592
|
}
|
|
1576
1593
|
} : void 0,
|
|
@@ -1609,59 +1626,37 @@ const pluginTs = createPlugin((options) => {
|
|
|
1609
1626
|
async install() {
|
|
1610
1627
|
const { config, fabric, plugin, adapter, rootNode, driver, openInStudio, resolver } = this;
|
|
1611
1628
|
const root = path.resolve(config.root, config.output.path);
|
|
1612
|
-
if (!adapter) throw new Error(
|
|
1629
|
+
if (!adapter) throw new Error(`[${pluginTsName}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
|
|
1613
1630
|
await openInStudio({ ast: true });
|
|
1631
|
+
const collectedOperations = [];
|
|
1632
|
+
const generatorContext = {
|
|
1633
|
+
generators: preset.generators,
|
|
1634
|
+
plugin,
|
|
1635
|
+
resolver,
|
|
1636
|
+
exclude,
|
|
1637
|
+
include,
|
|
1638
|
+
override,
|
|
1639
|
+
fabric,
|
|
1640
|
+
adapter,
|
|
1641
|
+
config,
|
|
1642
|
+
driver
|
|
1643
|
+
};
|
|
1614
1644
|
await walk(rootNode, {
|
|
1615
1645
|
depth: "shallow",
|
|
1616
1646
|
async schema(schemaNode) {
|
|
1617
|
-
|
|
1618
|
-
if (generator.type === "react" && generator.version === "2") {
|
|
1619
|
-
const options = resolver.resolveOptions(schemaNode, {
|
|
1620
|
-
options: plugin.options,
|
|
1621
|
-
exclude,
|
|
1622
|
-
include,
|
|
1623
|
-
override
|
|
1624
|
-
});
|
|
1625
|
-
if (options === null) return;
|
|
1626
|
-
await renderSchema(schemaNode, {
|
|
1627
|
-
options,
|
|
1628
|
-
resolver,
|
|
1629
|
-
adapter,
|
|
1630
|
-
config,
|
|
1631
|
-
fabric,
|
|
1632
|
-
Component: generator.Schema,
|
|
1633
|
-
plugin,
|
|
1634
|
-
driver
|
|
1635
|
-
});
|
|
1636
|
-
}
|
|
1637
|
-
});
|
|
1638
|
-
await Promise.all(writeTasks);
|
|
1647
|
+
await runGeneratorSchema(schemaNode, generatorContext);
|
|
1639
1648
|
},
|
|
1640
1649
|
async operation(operationNode) {
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
});
|
|
1649
|
-
if (options === null) return;
|
|
1650
|
-
await renderOperation(operationNode, {
|
|
1651
|
-
options,
|
|
1652
|
-
resolver,
|
|
1653
|
-
adapter,
|
|
1654
|
-
config,
|
|
1655
|
-
fabric,
|
|
1656
|
-
Component: generator.Operation,
|
|
1657
|
-
plugin,
|
|
1658
|
-
driver
|
|
1659
|
-
});
|
|
1660
|
-
}
|
|
1661
|
-
});
|
|
1662
|
-
await Promise.all(writeTasks);
|
|
1650
|
+
if (resolver.resolveOptions(operationNode, {
|
|
1651
|
+
options: plugin.options,
|
|
1652
|
+
exclude,
|
|
1653
|
+
include,
|
|
1654
|
+
override
|
|
1655
|
+
}) !== null) collectedOperations.push(operationNode);
|
|
1656
|
+
await runGeneratorOperation(operationNode, generatorContext);
|
|
1663
1657
|
}
|
|
1664
1658
|
});
|
|
1659
|
+
await runGeneratorOperations(collectedOperations, generatorContext);
|
|
1665
1660
|
const barrelFiles = await getBarrelFiles(this.fabric.files, {
|
|
1666
1661
|
type: output.barrelType ?? "named",
|
|
1667
1662
|
root,
|
|
@@ -1689,12 +1684,12 @@ const kindToHandlerKey = {
|
|
|
1689
1684
|
const defineFunctionPrinter = createPrinterFactory((node) => kindToHandlerKey[node.kind]);
|
|
1690
1685
|
function rank(param) {
|
|
1691
1686
|
if (param.kind === "ParameterGroup") {
|
|
1692
|
-
if (param.default) return
|
|
1693
|
-
return param.optional ?? param.properties.every((p) => p.optional || p.default !== void 0) ?
|
|
1687
|
+
if (param.default) return PARAM_RANK.withDefault;
|
|
1688
|
+
return param.optional ?? param.properties.every((p) => p.optional || p.default !== void 0) ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
1694
1689
|
}
|
|
1695
|
-
if (param.rest) return
|
|
1696
|
-
if (param.default) return
|
|
1697
|
-
return param.optional ?
|
|
1690
|
+
if (param.rest) return PARAM_RANK.rest;
|
|
1691
|
+
if (param.default) return PARAM_RANK.withDefault;
|
|
1692
|
+
return param.optional ? PARAM_RANK.optional : PARAM_RANK.required;
|
|
1698
1693
|
}
|
|
1699
1694
|
function sortParams(params) {
|
|
1700
1695
|
return [...params].sort((a, b) => rank(a) - rank(b));
|