@kubb/plugin-ts 5.0.0-alpha.22 → 5.0.0-alpha.23
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 +1668 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +466 -4
- package/dist/index.js +1641 -52
- package/dist/index.js.map +1 -1
- package/package.json +3 -42
- package/src/components/Enum.tsx +1 -1
- package/src/components/Type.tsx +3 -5
- package/src/generators/typeGenerator.tsx +10 -22
- package/src/generators/typeGeneratorLegacy.tsx +28 -38
- package/src/index.ts +13 -1
- package/src/plugin.ts +42 -23
- package/src/presets.ts +16 -34
- package/src/printers/functionPrinter.ts +194 -0
- package/src/printers/printerTs.ts +6 -6
- package/src/resolvers/resolverTs.ts +10 -47
- package/src/resolvers/resolverTsLegacy.ts +4 -31
- package/src/types.ts +85 -225
- package/src/utils.ts +103 -0
- package/dist/Type-Bf8raoQX.cjs +0 -124
- package/dist/Type-Bf8raoQX.cjs.map +0 -1
- package/dist/Type-BpXxT4l_.js +0 -113
- package/dist/Type-BpXxT4l_.js.map +0 -1
- package/dist/builderTs-COUg3xtQ.cjs +0 -135
- package/dist/builderTs-COUg3xtQ.cjs.map +0 -1
- package/dist/builderTs-DPpkJKd1.js +0 -131
- package/dist/builderTs-DPpkJKd1.js.map +0 -1
- package/dist/builders.cjs +0 -3
- package/dist/builders.d.ts +0 -23
- package/dist/builders.js +0 -2
- package/dist/casing-BJHFg-zZ.js +0 -84
- package/dist/casing-BJHFg-zZ.js.map +0 -1
- package/dist/casing-DHfdqpLi.cjs +0 -107
- package/dist/casing-DHfdqpLi.cjs.map +0 -1
- package/dist/chunk-ByKO4r7w.cjs +0 -38
- package/dist/components.cjs +0 -4
- package/dist/components.d.ts +0 -71
- package/dist/components.js +0 -2
- package/dist/generators-DFDut8o-.js +0 -555
- package/dist/generators-DFDut8o-.js.map +0 -1
- package/dist/generators-DKd7MYbx.cjs +0 -567
- package/dist/generators-DKd7MYbx.cjs.map +0 -1
- package/dist/generators.cjs +0 -4
- package/dist/generators.d.ts +0 -12
- package/dist/generators.js +0 -2
- package/dist/printerTs-BcHudagv.cjs +0 -594
- package/dist/printerTs-BcHudagv.cjs.map +0 -1
- package/dist/printerTs-CMBCOuqd.js +0 -558
- package/dist/printerTs-CMBCOuqd.js.map +0 -1
- package/dist/printers.cjs +0 -3
- package/dist/printers.d.ts +0 -81
- package/dist/printers.js +0 -2
- package/dist/resolverTsLegacy-CPiqqsO6.js +0 -185
- package/dist/resolverTsLegacy-CPiqqsO6.js.map +0 -1
- package/dist/resolverTsLegacy-CuR9XbKk.cjs +0 -196
- package/dist/resolverTsLegacy-CuR9XbKk.cjs.map +0 -1
- package/dist/resolvers.cjs +0 -4
- package/dist/resolvers.d.ts +0 -52
- package/dist/resolvers.js +0 -2
- package/dist/types-CRtcZOCz.d.ts +0 -374
- package/src/builders/builderTs.ts +0 -107
- package/src/builders/index.ts +0 -1
- package/src/components/index.ts +0 -2
- package/src/generators/index.ts +0 -2
- package/src/printers/index.ts +0 -1
- package/src/resolvers/index.ts +0 -2
package/dist/index.cjs
CHANGED
|
@@ -1,48 +1,1539 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
5
24
|
let node_path = require("node:path");
|
|
6
|
-
node_path =
|
|
25
|
+
node_path = __toESM(node_path);
|
|
26
|
+
let _kubb_fabric_core_parsers_typescript = require("@kubb/fabric-core/parsers/typescript");
|
|
27
|
+
let _kubb_react_fabric = require("@kubb/react-fabric");
|
|
28
|
+
let remeda = require("remeda");
|
|
29
|
+
let typescript = require("typescript");
|
|
30
|
+
typescript = __toESM(typescript);
|
|
31
|
+
let _kubb_react_fabric_jsx_runtime = require("@kubb/react-fabric/jsx-runtime");
|
|
7
32
|
let _kubb_ast = require("@kubb/ast");
|
|
8
33
|
let _kubb_core = require("@kubb/core");
|
|
9
|
-
//#region src/
|
|
34
|
+
//#region ../../internals/utils/src/casing.ts
|
|
10
35
|
/**
|
|
11
|
-
*
|
|
36
|
+
* Shared implementation for camelCase and PascalCase conversion.
|
|
37
|
+
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
38
|
+
* and capitalizes each word according to `pascal`.
|
|
12
39
|
*
|
|
13
|
-
*
|
|
14
|
-
* - `kubbV4` — uses `resolverTsLegacy` and `typeGeneratorLegacy` (Kubb v4 naming conventions).
|
|
40
|
+
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
15
41
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
42
|
+
function toCamelOrPascal(text, pascal) {
|
|
43
|
+
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
44
|
+
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
45
|
+
if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
|
|
46
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
47
|
+
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
51
|
+
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
52
|
+
* Segments are joined with `/` to form a file path.
|
|
53
|
+
*
|
|
54
|
+
* Only splits on dots followed by a letter so that version numbers
|
|
55
|
+
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
56
|
+
*/
|
|
57
|
+
function applyToFileParts(text, transformPart) {
|
|
58
|
+
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
59
|
+
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Converts `text` to camelCase.
|
|
63
|
+
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* camelCase('hello-world') // 'helloWorld'
|
|
67
|
+
* camelCase('pet.petId', { isFile: true }) // 'pet/petId'
|
|
68
|
+
*/
|
|
69
|
+
function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
70
|
+
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
71
|
+
prefix,
|
|
72
|
+
suffix
|
|
73
|
+
} : {}));
|
|
74
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Converts `text` to PascalCase.
|
|
78
|
+
* When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* pascalCase('hello-world') // 'HelloWorld'
|
|
82
|
+
* pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
|
|
83
|
+
*/
|
|
84
|
+
function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
85
|
+
if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
|
|
86
|
+
prefix,
|
|
87
|
+
suffix
|
|
88
|
+
}) : camelCase(part));
|
|
89
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Converts `text` to snake_case.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* snakeCase('helloWorld') // 'hello_world'
|
|
96
|
+
* snakeCase('Hello-World') // 'hello_world'
|
|
97
|
+
*/
|
|
98
|
+
function snakeCase(text, { prefix = "", suffix = "" } = {}) {
|
|
99
|
+
return `${prefix} ${text} ${suffix}`.trim().replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s\-.]+/g, "_").replace(/[^a-zA-Z0-9_]/g, "").toLowerCase().split("_").filter(Boolean).join("_");
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Converts `text` to SCREAMING_SNAKE_CASE.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* screamingSnakeCase('helloWorld') // 'HELLO_WORLD'
|
|
106
|
+
*/
|
|
107
|
+
function screamingSnakeCase(text, { prefix = "", suffix = "" } = {}) {
|
|
108
|
+
return snakeCase(text, {
|
|
109
|
+
prefix,
|
|
110
|
+
suffix
|
|
111
|
+
}).toUpperCase();
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region ../../internals/utils/src/string.ts
|
|
115
|
+
/**
|
|
116
|
+
* Strips a single matching pair of `"..."`, `'...'`, or `` `...` `` from both ends of `text`.
|
|
117
|
+
* Returns the string unchanged when no balanced quote pair is found.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* trimQuotes('"hello"') // 'hello'
|
|
121
|
+
* trimQuotes('hello') // 'hello'
|
|
122
|
+
*/
|
|
123
|
+
function trimQuotes(text) {
|
|
124
|
+
if (text.length >= 2) {
|
|
125
|
+
const first = text[0];
|
|
126
|
+
const last = text[text.length - 1];
|
|
127
|
+
if (first === "\"" && last === "\"" || first === "'" && last === "'" || first === "`" && last === "`") return text.slice(1, -1);
|
|
128
|
+
}
|
|
129
|
+
return text;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Escapes characters that are not allowed inside JS string literals.
|
|
133
|
+
* Handles quotes, backslashes, and Unicode line terminators (U+2028 / U+2029).
|
|
134
|
+
*
|
|
135
|
+
* @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* jsStringEscape('say "hi"\nbye') // 'say \\"hi\\"\\nbye'
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
function jsStringEscape(input) {
|
|
143
|
+
return `${input}`.replace(/["'\\\n\r\u2028\u2029]/g, (character) => {
|
|
144
|
+
switch (character) {
|
|
145
|
+
case "\"":
|
|
146
|
+
case "'":
|
|
147
|
+
case "\\": return `\\${character}`;
|
|
148
|
+
case "\n": return "\\n";
|
|
149
|
+
case "\r": return "\\r";
|
|
150
|
+
case "\u2028": return "\\u2028";
|
|
151
|
+
case "\u2029": return "\\u2029";
|
|
152
|
+
default: return "";
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region ../../internals/utils/src/object.ts
|
|
158
|
+
/**
|
|
159
|
+
* Serializes a primitive value to a JSON string literal, stripping any surrounding quote characters first.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* stringify('hello') // '"hello"'
|
|
163
|
+
* stringify('"hello"') // '"hello"'
|
|
164
|
+
*/
|
|
165
|
+
function stringify(value) {
|
|
166
|
+
if (value === void 0 || value === null) return "\"\"";
|
|
167
|
+
return JSON.stringify(trimQuotes(value.toString()));
|
|
168
|
+
}
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/constants.ts
|
|
171
|
+
/**
|
|
172
|
+
* `optionalType` values that cause a property's type to include `| undefined`.
|
|
173
|
+
*/
|
|
174
|
+
const OPTIONAL_ADDS_UNDEFINED = new Set(["undefined", "questionTokenAndUndefined"]);
|
|
175
|
+
/**
|
|
176
|
+
* `optionalType` values that render the property key with a `?` token.
|
|
177
|
+
*/
|
|
178
|
+
const OPTIONAL_ADDS_QUESTION_TOKEN = new Set(["questionToken", "questionTokenAndUndefined"]);
|
|
179
|
+
/**
|
|
180
|
+
* `enumType` values that append a `Key` suffix to the generated enum type alias.
|
|
181
|
+
*/
|
|
182
|
+
const ENUM_TYPES_WITH_KEY_SUFFIX = new Set(["asConst", "asPascalConst"]);
|
|
183
|
+
/**
|
|
184
|
+
* `enumType` values that require a runtime value declaration (object, enum, or literal).
|
|
185
|
+
*/
|
|
186
|
+
const ENUM_TYPES_WITH_RUNTIME_VALUE = new Set([
|
|
187
|
+
"enum",
|
|
188
|
+
"asConst",
|
|
189
|
+
"asPascalConst",
|
|
190
|
+
"constEnum",
|
|
191
|
+
"literal",
|
|
192
|
+
void 0
|
|
193
|
+
]);
|
|
194
|
+
/**
|
|
195
|
+
* `enumType` values whose type declaration is type-only (no runtime value emitted for the type alias).
|
|
196
|
+
*/
|
|
197
|
+
const ENUM_TYPES_WITH_TYPE_ONLY = new Set([
|
|
198
|
+
"asConst",
|
|
199
|
+
"asPascalConst",
|
|
200
|
+
"literal",
|
|
201
|
+
void 0
|
|
202
|
+
]);
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/factory.ts
|
|
205
|
+
const { SyntaxKind, factory } = typescript.default;
|
|
206
|
+
const modifiers = {
|
|
207
|
+
async: factory.createModifier(typescript.default.SyntaxKind.AsyncKeyword),
|
|
208
|
+
export: factory.createModifier(typescript.default.SyntaxKind.ExportKeyword),
|
|
209
|
+
const: factory.createModifier(typescript.default.SyntaxKind.ConstKeyword),
|
|
210
|
+
static: factory.createModifier(typescript.default.SyntaxKind.StaticKeyword)
|
|
211
|
+
};
|
|
212
|
+
const syntaxKind = {
|
|
213
|
+
union: SyntaxKind.UnionType,
|
|
214
|
+
literalType: SyntaxKind.LiteralType,
|
|
215
|
+
stringLiteral: SyntaxKind.StringLiteral
|
|
216
|
+
};
|
|
217
|
+
function isValidIdentifier(str) {
|
|
218
|
+
if (!str.length || str.trim() !== str) return false;
|
|
219
|
+
const node = typescript.default.parseIsolatedEntityName(str, typescript.default.ScriptTarget.Latest);
|
|
220
|
+
return !!node && node.kind === typescript.default.SyntaxKind.Identifier && typescript.default.identifierToKeywordKind(node.kind) === void 0;
|
|
221
|
+
}
|
|
222
|
+
function propertyName(name) {
|
|
223
|
+
if (typeof name === "string") return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name);
|
|
224
|
+
return name;
|
|
225
|
+
}
|
|
226
|
+
const questionToken = factory.createToken(typescript.default.SyntaxKind.QuestionToken);
|
|
227
|
+
function createQuestionToken(token) {
|
|
228
|
+
if (!token) return;
|
|
229
|
+
if (token === true) return questionToken;
|
|
230
|
+
return token;
|
|
231
|
+
}
|
|
232
|
+
function createIntersectionDeclaration({ nodes, withParentheses }) {
|
|
233
|
+
if (!nodes.length) return null;
|
|
234
|
+
if (nodes.length === 1) return nodes[0] || null;
|
|
235
|
+
const node = factory.createIntersectionTypeNode(nodes);
|
|
236
|
+
if (withParentheses) return factory.createParenthesizedType(node);
|
|
237
|
+
return node;
|
|
238
|
+
}
|
|
239
|
+
function createArrayDeclaration({ nodes, arrayType = "array" }) {
|
|
240
|
+
if (!nodes.length) return factory.createTupleTypeNode([]);
|
|
241
|
+
if (nodes.length === 1) {
|
|
242
|
+
const node = nodes[0];
|
|
243
|
+
if (!node) return null;
|
|
244
|
+
if (arrayType === "generic") return factory.createTypeReferenceNode(factory.createIdentifier("Array"), [node]);
|
|
245
|
+
return factory.createArrayTypeNode(node);
|
|
246
|
+
}
|
|
247
|
+
const unionType = factory.createUnionTypeNode(nodes);
|
|
248
|
+
if (arrayType === "generic") return factory.createTypeReferenceNode(factory.createIdentifier("Array"), [unionType]);
|
|
249
|
+
return factory.createArrayTypeNode(factory.createParenthesizedType(unionType));
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Minimum nodes length of 2
|
|
253
|
+
* @example `string | number`
|
|
254
|
+
*/
|
|
255
|
+
function createUnionDeclaration({ nodes, withParentheses }) {
|
|
256
|
+
if (!nodes.length) return keywordTypeNodes.any;
|
|
257
|
+
if (nodes.length === 1) return nodes[0];
|
|
258
|
+
const node = factory.createUnionTypeNode(nodes);
|
|
259
|
+
if (withParentheses) return factory.createParenthesizedType(node);
|
|
260
|
+
return node;
|
|
261
|
+
}
|
|
262
|
+
function createPropertySignature({ readOnly, modifiers = [], name, questionToken, type }) {
|
|
263
|
+
return factory.createPropertySignature([...modifiers, readOnly ? factory.createToken(typescript.default.SyntaxKind.ReadonlyKeyword) : void 0].filter(Boolean), propertyName(name), createQuestionToken(questionToken), type);
|
|
264
|
+
}
|
|
265
|
+
function createParameterSignature(name, { modifiers, dotDotDotToken, questionToken, type, initializer }) {
|
|
266
|
+
return factory.createParameterDeclaration(modifiers, dotDotDotToken, name, createQuestionToken(questionToken), type, initializer);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* @link https://github.com/microsoft/TypeScript/issues/44151
|
|
270
|
+
*/
|
|
271
|
+
function appendJSDocToNode({ node, comments }) {
|
|
272
|
+
const filteredComments = comments.filter(Boolean);
|
|
273
|
+
if (!filteredComments.length) return node;
|
|
274
|
+
const text = filteredComments.reduce((acc = "", comment = "") => {
|
|
275
|
+
return `${acc}\n * ${comment.replaceAll("*/", "*\\/")}`;
|
|
276
|
+
}, "*");
|
|
277
|
+
return typescript.default.addSyntheticLeadingComment(node, typescript.default.SyntaxKind.MultiLineCommentTrivia, `${text || "*"}\n`, true);
|
|
278
|
+
}
|
|
279
|
+
function createIndexSignature(type, { modifiers, indexName = "key", indexType = factory.createKeywordTypeNode(typescript.default.SyntaxKind.StringKeyword) } = {}) {
|
|
280
|
+
return factory.createIndexSignature(modifiers, [createParameterSignature(indexName, { type: indexType })], type);
|
|
281
|
+
}
|
|
282
|
+
function createTypeAliasDeclaration({ modifiers, name, typeParameters, type }) {
|
|
283
|
+
return factory.createTypeAliasDeclaration(modifiers, name, typeParameters, type);
|
|
284
|
+
}
|
|
285
|
+
function createInterfaceDeclaration({ modifiers, name, typeParameters, members }) {
|
|
286
|
+
return factory.createInterfaceDeclaration(modifiers, name, typeParameters, void 0, members);
|
|
287
|
+
}
|
|
288
|
+
function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
|
|
289
|
+
if (syntax === "interface" && "members" in type) return appendJSDocToNode({
|
|
290
|
+
node: createInterfaceDeclaration({
|
|
291
|
+
members: type.members,
|
|
292
|
+
modifiers: isExportable ? [modifiers.export] : [],
|
|
293
|
+
name,
|
|
294
|
+
typeParameters: void 0
|
|
295
|
+
}),
|
|
296
|
+
comments
|
|
297
|
+
});
|
|
298
|
+
return appendJSDocToNode({
|
|
299
|
+
node: createTypeAliasDeclaration({
|
|
300
|
+
type,
|
|
301
|
+
modifiers: isExportable ? [modifiers.export] : [],
|
|
302
|
+
name,
|
|
303
|
+
typeParameters: void 0
|
|
304
|
+
}),
|
|
305
|
+
comments
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Apply casing transformation to enum keys
|
|
310
|
+
*/
|
|
311
|
+
function applyEnumKeyCasing(key, casing = "none") {
|
|
312
|
+
if (casing === "none") return key;
|
|
313
|
+
if (casing === "screamingSnakeCase") return screamingSnakeCase(key);
|
|
314
|
+
if (casing === "snakeCase") return snakeCase(key);
|
|
315
|
+
if (casing === "pascalCase") return pascalCase(key);
|
|
316
|
+
if (casing === "camelCase") return camelCase(key);
|
|
317
|
+
return key;
|
|
318
|
+
}
|
|
319
|
+
function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCasing = "none" }) {
|
|
320
|
+
if (type === "literal" || type === "inlineLiteral") return [void 0, factory.createTypeAliasDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createUnionTypeNode(enums.map(([_key, value]) => {
|
|
321
|
+
if ((0, remeda.isNumber)(value)) {
|
|
322
|
+
if (value < 0) return factory.createLiteralTypeNode(factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value))));
|
|
323
|
+
return factory.createLiteralTypeNode(factory.createNumericLiteral(value?.toString()));
|
|
324
|
+
}
|
|
325
|
+
if (typeof value === "boolean") return factory.createLiteralTypeNode(value ? factory.createTrue() : factory.createFalse());
|
|
326
|
+
if (value) return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString()));
|
|
327
|
+
}).filter(Boolean)))];
|
|
328
|
+
if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(typescript.default.SyntaxKind.ConstKeyword) : void 0].filter(Boolean), factory.createIdentifier(typeName), enums.map(([key, value]) => {
|
|
329
|
+
let initializer = factory.createStringLiteral(value?.toString());
|
|
330
|
+
if (Number.parseInt(value.toString(), 10) === value && (0, remeda.isNumber)(Number.parseInt(value.toString(), 10))) if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
331
|
+
else initializer = factory.createNumericLiteral(value);
|
|
332
|
+
if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
|
|
333
|
+
if ((0, remeda.isNumber)(Number.parseInt(key.toString(), 10))) {
|
|
334
|
+
const casingKey = applyEnumKeyCasing(`${typeName}_${key}`, enumKeyCasing);
|
|
335
|
+
return factory.createEnumMember(propertyName(casingKey), initializer);
|
|
336
|
+
}
|
|
337
|
+
if (key) {
|
|
338
|
+
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
339
|
+
return factory.createEnumMember(propertyName(casingKey), initializer);
|
|
340
|
+
}
|
|
341
|
+
}).filter(Boolean))];
|
|
342
|
+
const identifierName = name;
|
|
343
|
+
if (enums.length === 0) return [void 0, factory.createTypeAliasDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createKeywordTypeNode(typescript.default.SyntaxKind.NeverKeyword))];
|
|
344
|
+
return [factory.createVariableStatement([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(identifierName), void 0, void 0, factory.createAsExpression(factory.createObjectLiteralExpression(enums.map(([key, value]) => {
|
|
345
|
+
let initializer = factory.createStringLiteral(value?.toString());
|
|
346
|
+
if ((0, remeda.isNumber)(value)) if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
|
|
347
|
+
else initializer = factory.createNumericLiteral(value);
|
|
348
|
+
if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
|
|
349
|
+
if (key) {
|
|
350
|
+
const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing);
|
|
351
|
+
return factory.createPropertyAssignment(propertyName(casingKey), initializer);
|
|
352
|
+
}
|
|
353
|
+
}).filter(Boolean), true), factory.createTypeReferenceNode(factory.createIdentifier("const"), void 0)))], typescript.default.NodeFlags.Const)), factory.createTypeAliasDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createIndexedAccessTypeNode(factory.createParenthesizedType(factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0)), factory.createTypeOperatorNode(typescript.default.SyntaxKind.KeyOfKeyword, factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0))))];
|
|
354
|
+
}
|
|
355
|
+
function createOmitDeclaration({ keys, type, nonNullable }) {
|
|
356
|
+
const node = nonNullable ? factory.createTypeReferenceNode(factory.createIdentifier("NonNullable"), [type]) : type;
|
|
357
|
+
if (Array.isArray(keys)) return factory.createTypeReferenceNode(factory.createIdentifier("Omit"), [node, factory.createUnionTypeNode(keys.map((key) => {
|
|
358
|
+
return factory.createLiteralTypeNode(factory.createStringLiteral(key));
|
|
359
|
+
}))]);
|
|
360
|
+
return factory.createTypeReferenceNode(factory.createIdentifier("Omit"), [node, factory.createLiteralTypeNode(factory.createStringLiteral(keys))]);
|
|
361
|
+
}
|
|
362
|
+
const keywordTypeNodes = {
|
|
363
|
+
any: factory.createKeywordTypeNode(typescript.default.SyntaxKind.AnyKeyword),
|
|
364
|
+
unknown: factory.createKeywordTypeNode(typescript.default.SyntaxKind.UnknownKeyword),
|
|
365
|
+
void: factory.createKeywordTypeNode(typescript.default.SyntaxKind.VoidKeyword),
|
|
366
|
+
number: factory.createKeywordTypeNode(typescript.default.SyntaxKind.NumberKeyword),
|
|
367
|
+
integer: factory.createKeywordTypeNode(typescript.default.SyntaxKind.NumberKeyword),
|
|
368
|
+
bigint: factory.createKeywordTypeNode(typescript.default.SyntaxKind.BigIntKeyword),
|
|
369
|
+
object: factory.createKeywordTypeNode(typescript.default.SyntaxKind.ObjectKeyword),
|
|
370
|
+
string: factory.createKeywordTypeNode(typescript.default.SyntaxKind.StringKeyword),
|
|
371
|
+
boolean: factory.createKeywordTypeNode(typescript.default.SyntaxKind.BooleanKeyword),
|
|
372
|
+
undefined: factory.createKeywordTypeNode(typescript.default.SyntaxKind.UndefinedKeyword),
|
|
373
|
+
null: factory.createLiteralTypeNode(factory.createToken(typescript.default.SyntaxKind.NullKeyword)),
|
|
374
|
+
never: factory.createKeywordTypeNode(typescript.default.SyntaxKind.NeverKeyword)
|
|
375
|
+
};
|
|
376
|
+
/**
|
|
377
|
+
* Converts a path like '/pet/{petId}/uploadImage' to a template literal type
|
|
378
|
+
* like `/pet/${string}/uploadImage`
|
|
379
|
+
*/
|
|
380
|
+
/**
|
|
381
|
+
* Converts an OAS-style path (e.g. `/pets/{petId}`) or an Express-style path
|
|
382
|
+
* (e.g. `/pets/:petId`) to a TypeScript template literal type
|
|
383
|
+
* like `` `/pets/${string}` ``.
|
|
384
|
+
*/
|
|
385
|
+
function createUrlTemplateType(path) {
|
|
386
|
+
const normalized = path.replace(/:([^/]+)/g, "{$1}");
|
|
387
|
+
if (!normalized.includes("{")) return factory.createLiteralTypeNode(factory.createStringLiteral(normalized));
|
|
388
|
+
const segments = normalized.split(/(\{[^}]+\})/);
|
|
389
|
+
const parts = [];
|
|
390
|
+
const parameterIndices = [];
|
|
391
|
+
segments.forEach((segment) => {
|
|
392
|
+
if (segment.startsWith("{") && segment.endsWith("}")) {
|
|
393
|
+
parameterIndices.push(parts.length);
|
|
394
|
+
parts.push(segment);
|
|
395
|
+
} else if (segment) parts.push(segment);
|
|
396
|
+
});
|
|
397
|
+
const head = typescript.default.factory.createTemplateHead(parts[0] || "");
|
|
398
|
+
const templateSpans = [];
|
|
399
|
+
parameterIndices.forEach((paramIndex, i) => {
|
|
400
|
+
const isLast = i === parameterIndices.length - 1;
|
|
401
|
+
const nextPart = parts[paramIndex + 1] || "";
|
|
402
|
+
const literal = isLast ? typescript.default.factory.createTemplateTail(nextPart) : typescript.default.factory.createTemplateMiddle(nextPart);
|
|
403
|
+
templateSpans.push(typescript.default.factory.createTemplateLiteralTypeSpan(keywordTypeNodes.string, literal));
|
|
404
|
+
});
|
|
405
|
+
return typescript.default.factory.createTemplateLiteralType(head, templateSpans);
|
|
406
|
+
}
|
|
407
|
+
const createTypeLiteralNode = factory.createTypeLiteralNode;
|
|
408
|
+
const createTypeReferenceNode = factory.createTypeReferenceNode;
|
|
409
|
+
const createNumericLiteral = factory.createNumericLiteral;
|
|
410
|
+
const createStringLiteral = factory.createStringLiteral;
|
|
411
|
+
const createArrayTypeNode = factory.createArrayTypeNode;
|
|
412
|
+
factory.createParenthesizedType;
|
|
413
|
+
const createLiteralTypeNode = factory.createLiteralTypeNode;
|
|
414
|
+
factory.createNull;
|
|
415
|
+
const createIdentifier = factory.createIdentifier;
|
|
416
|
+
const createOptionalTypeNode = factory.createOptionalTypeNode;
|
|
417
|
+
const createTupleTypeNode = factory.createTupleTypeNode;
|
|
418
|
+
const createRestTypeNode = factory.createRestTypeNode;
|
|
419
|
+
const createTrue = factory.createTrue;
|
|
420
|
+
const createFalse = factory.createFalse;
|
|
421
|
+
factory.createIndexedAccessTypeNode;
|
|
422
|
+
factory.createTypeOperatorNode;
|
|
423
|
+
const createPrefixUnaryExpression = factory.createPrefixUnaryExpression;
|
|
424
|
+
//#endregion
|
|
425
|
+
//#region src/components/Enum.tsx
|
|
426
|
+
/**
|
|
427
|
+
* Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
|
|
428
|
+
*
|
|
429
|
+
* The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
|
|
430
|
+
* valid TypeScript identifier. The resolver normalizes it; for inline enum
|
|
431
|
+
* properties the adapter already emits a PascalCase+suffix name so resolution is typically a no-op.
|
|
432
|
+
*/
|
|
433
|
+
function getEnumNames({ node, enumType, enumTypeSuffix, resolver }) {
|
|
434
|
+
const resolved = resolver.default(node.name, "type");
|
|
435
|
+
return {
|
|
436
|
+
enumName: enumType === "asPascalConst" ? resolved : camelCase(node.name),
|
|
437
|
+
typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolved,
|
|
438
|
+
refName: resolved
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Renders the enum declaration(s) for a single named `EnumSchemaNode`.
|
|
443
|
+
*
|
|
444
|
+
* Depending on `enumType` this may emit:
|
|
445
|
+
* - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
|
|
446
|
+
* - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
|
|
447
|
+
* - A union literal type alias (`literal`)
|
|
448
|
+
*
|
|
449
|
+
* The emitted `File.Source` nodes carry the resolved names so that the barrel
|
|
450
|
+
* index picks up the correct export identifiers.
|
|
451
|
+
*/
|
|
452
|
+
function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
|
|
453
|
+
const { enumName, typeName } = getEnumNames({
|
|
454
|
+
node,
|
|
455
|
+
enumType,
|
|
456
|
+
enumTypeSuffix,
|
|
457
|
+
resolver
|
|
458
|
+
});
|
|
459
|
+
const [nameNode, typeNode] = createEnumDeclaration({
|
|
460
|
+
name: enumName,
|
|
461
|
+
typeName,
|
|
462
|
+
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]) ?? [],
|
|
463
|
+
type: enumType,
|
|
464
|
+
enumKeyCasing
|
|
465
|
+
});
|
|
466
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [nameNode && /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
467
|
+
name: enumName,
|
|
468
|
+
isExportable: true,
|
|
469
|
+
isIndexable: true,
|
|
470
|
+
isTypeOnly: false,
|
|
471
|
+
children: (0, _kubb_fabric_core_parsers_typescript.safePrint)(nameNode)
|
|
472
|
+
}), /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
473
|
+
name: typeName,
|
|
474
|
+
isIndexable: true,
|
|
475
|
+
isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
|
|
476
|
+
isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
|
|
477
|
+
children: (0, _kubb_fabric_core_parsers_typescript.safePrint)(typeNode)
|
|
478
|
+
})] });
|
|
479
|
+
}
|
|
480
|
+
//#endregion
|
|
481
|
+
//#region src/printers/printerTs.ts
|
|
482
|
+
/**
|
|
483
|
+
* Converts a primitive const value to a TypeScript literal type node.
|
|
484
|
+
* Handles negative numbers via a prefix unary expression.
|
|
485
|
+
*/
|
|
486
|
+
function constToTypeNode(value, format) {
|
|
487
|
+
if (format === "boolean") return createLiteralTypeNode(value === true ? createTrue() : createFalse());
|
|
488
|
+
if (format === "number" && typeof value === "number") {
|
|
489
|
+
if (value < 0) return createLiteralTypeNode(createPrefixUnaryExpression(SyntaxKind.MinusToken, createNumericLiteral(Math.abs(value))));
|
|
490
|
+
return createLiteralTypeNode(createNumericLiteral(value));
|
|
491
|
+
}
|
|
492
|
+
return createLiteralTypeNode(createStringLiteral(String(value)));
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Returns a `Date` reference type node when `representation` is `'date'`, otherwise falls back to `string`.
|
|
496
|
+
*/
|
|
497
|
+
function dateOrStringNode(node) {
|
|
498
|
+
return node.representation === "date" ? createTypeReferenceNode(createIdentifier("Date")) : keywordTypeNodes.string;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Maps an array of `SchemaNode`s through the printer, filtering out `null` and `undefined` results.
|
|
502
|
+
*/
|
|
503
|
+
function buildMemberNodes(members, print) {
|
|
504
|
+
return (members ?? []).map(print).filter(Boolean);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Builds a TypeScript tuple type node from an array schema's `items`,
|
|
508
|
+
* applying min/max slice and optional/rest element rules.
|
|
509
|
+
*/
|
|
510
|
+
function buildTupleNode(node, print) {
|
|
511
|
+
let items = (node.items ?? []).map(print).filter(Boolean);
|
|
512
|
+
const restNode = node.rest ? print(node.rest) ?? void 0 : void 0;
|
|
513
|
+
const { min, max } = node;
|
|
514
|
+
if (max !== void 0) {
|
|
515
|
+
items = items.slice(0, max);
|
|
516
|
+
if (items.length < max && restNode) items = [...items, ...Array(max - items.length).fill(restNode)];
|
|
517
|
+
}
|
|
518
|
+
if (min !== void 0) items = items.map((item, i) => i >= min ? createOptionalTypeNode(item) : item);
|
|
519
|
+
if (max === void 0 && restNode) items.push(createRestTypeNode(createArrayTypeNode(restNode)));
|
|
520
|
+
return createTupleTypeNode(items);
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Applies `nullable` and optional/nullish `| undefined` union modifiers to a property's resolved base type.
|
|
524
|
+
*/
|
|
525
|
+
function buildPropertyType(schema, baseType, optionalType) {
|
|
526
|
+
const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType);
|
|
527
|
+
let type = baseType;
|
|
528
|
+
if (schema.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
|
|
529
|
+
if ((schema.nullish || schema.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
530
|
+
return type;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Collects JSDoc annotation strings (description, deprecated, min/max, pattern, default, example, type) for a schema node.
|
|
534
|
+
*/
|
|
535
|
+
function buildPropertyJSDocComments(schema) {
|
|
536
|
+
const isArray = schema.type === "array";
|
|
537
|
+
return [
|
|
538
|
+
"description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
|
|
539
|
+
"deprecated" in schema && schema.deprecated ? "@deprecated" : void 0,
|
|
540
|
+
!isArray && "min" in schema && schema.min !== void 0 ? `@minLength ${schema.min}` : void 0,
|
|
541
|
+
!isArray && "max" in schema && schema.max !== void 0 ? `@maxLength ${schema.max}` : void 0,
|
|
542
|
+
"pattern" in schema && schema.pattern ? `@pattern ${schema.pattern}` : void 0,
|
|
543
|
+
"default" in schema && schema.default !== void 0 ? `@default ${"primitive" in schema && schema.primitive === "string" ? stringify(schema.default) : schema.default}` : void 0,
|
|
544
|
+
"example" in schema && schema.example !== void 0 ? `@example ${schema.example}` : void 0,
|
|
545
|
+
"primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
|
|
546
|
+
];
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Creates TypeScript index signatures for `additionalProperties` and `patternProperties` on an object schema node.
|
|
550
|
+
*/
|
|
551
|
+
function buildIndexSignatures(node, propertyCount, print) {
|
|
552
|
+
const elements = [];
|
|
553
|
+
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
554
|
+
const additionalType = print(node.additionalProperties) ?? keywordTypeNodes.unknown;
|
|
555
|
+
elements.push(createIndexSignature(propertyCount > 0 ? keywordTypeNodes.unknown : additionalType));
|
|
556
|
+
} else if (node.additionalProperties === true) elements.push(createIndexSignature(keywordTypeNodes.unknown));
|
|
557
|
+
if (node.patternProperties) {
|
|
558
|
+
const first = Object.values(node.patternProperties)[0];
|
|
559
|
+
if (first) {
|
|
560
|
+
let patternType = print(first) ?? keywordTypeNodes.unknown;
|
|
561
|
+
if (first.nullable) patternType = createUnionDeclaration({ nodes: [patternType, keywordTypeNodes.null] });
|
|
562
|
+
elements.push(createIndexSignature(patternType));
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return elements;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* TypeScript type printer built with `definePrinter`.
|
|
569
|
+
*
|
|
570
|
+
* Converts a `SchemaNode` AST node into a TypeScript AST node:
|
|
571
|
+
* - **`printer.print(node)`** — when `options.typeName` is set, returns a full
|
|
572
|
+
* `type Name = …` or `interface Name { … }` declaration (`ts.Node`).
|
|
573
|
+
* Without `typeName`, returns the raw `ts.TypeNode` for the schema.
|
|
574
|
+
*
|
|
575
|
+
* Dispatches on `node.type` to the appropriate handler in `nodes`. Options are closed
|
|
576
|
+
* over per printer instance, so each call to `printerTs(options)` produces an independent printer.
|
|
577
|
+
*
|
|
578
|
+
* @example Raw type node (no `typeName`)
|
|
579
|
+
* ```ts
|
|
580
|
+
* const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enumType: 'inlineLiteral' })
|
|
581
|
+
* const typeNode = printer.print(schemaNode) // ts.TypeNode
|
|
582
|
+
* ```
|
|
583
|
+
*
|
|
584
|
+
* @example Full declaration (with `typeName`)
|
|
585
|
+
* ```ts
|
|
586
|
+
* const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enumType: 'inlineLiteral', typeName: 'MyType' })
|
|
587
|
+
* const declaration = printer.print(schemaNode) // ts.TypeAliasDeclaration | ts.InterfaceDeclaration
|
|
588
|
+
* ```
|
|
589
|
+
*/
|
|
590
|
+
const printerTs = (0, _kubb_core.definePrinter)((options) => {
|
|
591
|
+
const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(options.optionalType);
|
|
592
|
+
return {
|
|
593
|
+
name: "typescript",
|
|
594
|
+
options,
|
|
595
|
+
nodes: {
|
|
596
|
+
any: () => keywordTypeNodes.any,
|
|
597
|
+
unknown: () => keywordTypeNodes.unknown,
|
|
598
|
+
void: () => keywordTypeNodes.void,
|
|
599
|
+
never: () => keywordTypeNodes.never,
|
|
600
|
+
boolean: () => keywordTypeNodes.boolean,
|
|
601
|
+
null: () => keywordTypeNodes.null,
|
|
602
|
+
blob: () => createTypeReferenceNode("Blob", []),
|
|
603
|
+
string: () => keywordTypeNodes.string,
|
|
604
|
+
uuid: () => keywordTypeNodes.string,
|
|
605
|
+
email: () => keywordTypeNodes.string,
|
|
606
|
+
url: (node) => {
|
|
607
|
+
if (node.path) return createUrlTemplateType(node.path);
|
|
608
|
+
return keywordTypeNodes.string;
|
|
609
|
+
},
|
|
610
|
+
datetime: () => keywordTypeNodes.string,
|
|
611
|
+
number: () => keywordTypeNodes.number,
|
|
612
|
+
integer: () => keywordTypeNodes.number,
|
|
613
|
+
bigint: () => keywordTypeNodes.bigint,
|
|
614
|
+
date: dateOrStringNode,
|
|
615
|
+
time: dateOrStringNode,
|
|
616
|
+
ref(node) {
|
|
617
|
+
if (!node.name) return;
|
|
618
|
+
const refName = node.ref ? node.ref.split("/").at(-1) ?? node.name : node.name;
|
|
619
|
+
return createTypeReferenceNode(node.ref ? this.options.resolver.default(refName, "type") : refName, void 0);
|
|
620
|
+
},
|
|
621
|
+
enum(node) {
|
|
622
|
+
const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
|
|
623
|
+
if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
|
|
624
|
+
withParentheses: true,
|
|
625
|
+
nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value)).filter(Boolean)
|
|
626
|
+
}) ?? void 0;
|
|
627
|
+
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);
|
|
628
|
+
},
|
|
629
|
+
union(node) {
|
|
630
|
+
const members = node.members ?? [];
|
|
631
|
+
const hasStringLiteral = members.some((m) => {
|
|
632
|
+
return (0, _kubb_ast.narrowSchema)(m, _kubb_ast.schemaTypes.enum)?.primitive === "string";
|
|
633
|
+
});
|
|
634
|
+
const hasPlainString = members.some((m) => (0, _kubb_ast.isStringType)(m));
|
|
635
|
+
if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
|
|
636
|
+
withParentheses: true,
|
|
637
|
+
nodes: members.map((m) => {
|
|
638
|
+
if ((0, _kubb_ast.isStringType)(m)) return createIntersectionDeclaration({
|
|
639
|
+
nodes: [keywordTypeNodes.string, createTypeLiteralNode([])],
|
|
640
|
+
withParentheses: true
|
|
641
|
+
});
|
|
642
|
+
return this.transform(m);
|
|
643
|
+
}).filter(Boolean)
|
|
644
|
+
}) ?? void 0;
|
|
645
|
+
return createUnionDeclaration({
|
|
646
|
+
withParentheses: true,
|
|
647
|
+
nodes: buildMemberNodes(members, this.transform)
|
|
648
|
+
}) ?? void 0;
|
|
649
|
+
},
|
|
650
|
+
intersection(node) {
|
|
651
|
+
return createIntersectionDeclaration({
|
|
652
|
+
withParentheses: true,
|
|
653
|
+
nodes: buildMemberNodes(node.members, this.transform)
|
|
654
|
+
}) ?? void 0;
|
|
655
|
+
},
|
|
656
|
+
array(node) {
|
|
657
|
+
return createArrayDeclaration({
|
|
658
|
+
nodes: (node.items ?? []).map((item) => this.transform(item)).filter(Boolean),
|
|
659
|
+
arrayType: this.options.arrayType
|
|
660
|
+
}) ?? void 0;
|
|
661
|
+
},
|
|
662
|
+
tuple(node) {
|
|
663
|
+
return buildTupleNode(node, this.transform);
|
|
664
|
+
},
|
|
665
|
+
object(node) {
|
|
666
|
+
const { transform, options } = this;
|
|
667
|
+
const addsQuestionToken = OPTIONAL_ADDS_QUESTION_TOKEN.has(options.optionalType);
|
|
668
|
+
const propertyNodes = node.properties.map((prop) => {
|
|
669
|
+
const baseType = transform(prop.schema) ?? keywordTypeNodes.unknown;
|
|
670
|
+
const type = buildPropertyType(prop.schema, baseType, options.optionalType);
|
|
671
|
+
return appendJSDocToNode({
|
|
672
|
+
node: createPropertySignature({
|
|
673
|
+
questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
|
|
674
|
+
name: prop.name,
|
|
675
|
+
type,
|
|
676
|
+
readOnly: prop.schema.readOnly
|
|
677
|
+
}),
|
|
678
|
+
comments: buildPropertyJSDocComments(prop.schema)
|
|
679
|
+
});
|
|
680
|
+
});
|
|
681
|
+
const allElements = [...propertyNodes, ...buildIndexSignatures(node, propertyNodes.length, transform)];
|
|
682
|
+
if (!allElements.length) return keywordTypeNodes.object;
|
|
683
|
+
return createTypeLiteralNode(allElements);
|
|
684
|
+
}
|
|
685
|
+
},
|
|
686
|
+
print(node) {
|
|
687
|
+
let type = this.transform(node);
|
|
688
|
+
if (!type) return null;
|
|
689
|
+
if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
|
|
690
|
+
if ((node.nullish || node.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
|
|
691
|
+
const { name, syntaxType = "type", description, keysToOmit } = this.options;
|
|
692
|
+
if (!name) return (0, _kubb_fabric_core_parsers_typescript.safePrint)(type);
|
|
693
|
+
const useTypeGeneration = syntaxType === "type" || type.kind === syntaxKind.union || !!keysToOmit?.length;
|
|
694
|
+
return (0, _kubb_fabric_core_parsers_typescript.safePrint)(createTypeDeclaration({
|
|
695
|
+
name,
|
|
696
|
+
isExportable: true,
|
|
697
|
+
type: keysToOmit?.length ? createOmitDeclaration({
|
|
698
|
+
keys: keysToOmit,
|
|
699
|
+
type,
|
|
700
|
+
nonNullable: true
|
|
701
|
+
}) : type,
|
|
702
|
+
syntax: useTypeGeneration ? "type" : "interface",
|
|
703
|
+
comments: [
|
|
704
|
+
node?.title ? jsStringEscape(node.title) : void 0,
|
|
705
|
+
description ? `@description ${jsStringEscape(description)}` : void 0,
|
|
706
|
+
node?.deprecated ? "@deprecated" : void 0,
|
|
707
|
+
node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
|
|
708
|
+
node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
|
|
709
|
+
node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
|
|
710
|
+
node?.default ? `@default ${node.default}` : void 0,
|
|
711
|
+
node?.example ? `@example ${node.example}` : void 0
|
|
712
|
+
]
|
|
713
|
+
}));
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
});
|
|
717
|
+
//#endregion
|
|
718
|
+
//#region src/components/Type.tsx
|
|
719
|
+
function Type({ name, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumTypeSuffix, enumKeyCasing, description, resolver }) {
|
|
720
|
+
const resolvedDescription = description || node?.description;
|
|
721
|
+
const enumSchemaNodes = (0, _kubb_ast.collect)(node, { schema(n) {
|
|
722
|
+
const enumNode = (0, _kubb_ast.narrowSchema)(n, _kubb_ast.schemaTypes.enum);
|
|
723
|
+
if (enumNode?.name) return enumNode;
|
|
724
|
+
} });
|
|
725
|
+
const output = printerTs({
|
|
726
|
+
optionalType,
|
|
727
|
+
arrayType,
|
|
728
|
+
enumType,
|
|
729
|
+
enumTypeSuffix,
|
|
730
|
+
name,
|
|
731
|
+
syntaxType,
|
|
732
|
+
description: resolvedDescription,
|
|
733
|
+
keysToOmit,
|
|
734
|
+
resolver
|
|
735
|
+
}).print(node);
|
|
736
|
+
if (!output) return;
|
|
737
|
+
const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((node) => {
|
|
738
|
+
return {
|
|
739
|
+
node,
|
|
740
|
+
...getEnumNames({
|
|
741
|
+
node,
|
|
742
|
+
enumType,
|
|
743
|
+
enumTypeSuffix,
|
|
744
|
+
resolver
|
|
745
|
+
})
|
|
746
|
+
};
|
|
747
|
+
});
|
|
748
|
+
const shouldExportEnums = enumType !== "inlineLiteral";
|
|
749
|
+
const shouldExportType = enumType === "inlineLiteral" || enums.every((item) => item.typeName !== name);
|
|
750
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [shouldExportEnums && enums.map(({ node }) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Enum, {
|
|
751
|
+
node,
|
|
752
|
+
enumType,
|
|
753
|
+
enumTypeSuffix,
|
|
754
|
+
enumKeyCasing,
|
|
755
|
+
resolver
|
|
756
|
+
})), shouldExportType && /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
757
|
+
name,
|
|
758
|
+
isTypeOnly: true,
|
|
759
|
+
isExportable: true,
|
|
760
|
+
isIndexable: true,
|
|
761
|
+
children: output
|
|
762
|
+
})] });
|
|
763
|
+
}
|
|
764
|
+
//#endregion
|
|
765
|
+
//#region src/utils.ts
|
|
766
|
+
function buildParams({ params, node, resolver }) {
|
|
767
|
+
return (0, _kubb_ast.createSchema)({
|
|
768
|
+
type: "object",
|
|
769
|
+
properties: params.map((param) => (0, _kubb_ast.createProperty)({
|
|
770
|
+
name: param.name,
|
|
771
|
+
required: param.required,
|
|
772
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
773
|
+
type: "ref",
|
|
774
|
+
name: resolver.resolveParamName(node, param)
|
|
775
|
+
})
|
|
776
|
+
}))
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
function buildData({ node, resolver }) {
|
|
780
|
+
const pathParams = node.parameters.filter((p) => p.in === "path");
|
|
781
|
+
const queryParams = node.parameters.filter((p) => p.in === "query");
|
|
782
|
+
const headerParams = node.parameters.filter((p) => p.in === "header");
|
|
783
|
+
return (0, _kubb_ast.createSchema)({
|
|
784
|
+
type: "object",
|
|
785
|
+
deprecated: node.deprecated,
|
|
786
|
+
properties: [
|
|
787
|
+
(0, _kubb_ast.createProperty)({
|
|
788
|
+
name: "data",
|
|
789
|
+
schema: node.requestBody?.schema ? (0, _kubb_ast.createSchema)({
|
|
790
|
+
type: "ref",
|
|
791
|
+
name: resolver.resolveDataName(node),
|
|
792
|
+
optional: true
|
|
793
|
+
}) : (0, _kubb_ast.createSchema)({
|
|
794
|
+
type: "never",
|
|
795
|
+
optional: true
|
|
796
|
+
})
|
|
797
|
+
}),
|
|
798
|
+
(0, _kubb_ast.createProperty)({
|
|
799
|
+
name: "pathParams",
|
|
800
|
+
required: pathParams.length > 0,
|
|
801
|
+
schema: pathParams.length > 0 ? buildParams({
|
|
802
|
+
params: pathParams,
|
|
803
|
+
node,
|
|
804
|
+
resolver
|
|
805
|
+
}) : (0, _kubb_ast.createSchema)({ type: "never" })
|
|
806
|
+
}),
|
|
807
|
+
(0, _kubb_ast.createProperty)({
|
|
808
|
+
name: "queryParams",
|
|
809
|
+
schema: queryParams.length > 0 ? (0, _kubb_ast.createSchema)({
|
|
810
|
+
...buildParams({
|
|
811
|
+
params: queryParams,
|
|
812
|
+
node,
|
|
813
|
+
resolver
|
|
814
|
+
}),
|
|
815
|
+
optional: true
|
|
816
|
+
}) : (0, _kubb_ast.createSchema)({
|
|
817
|
+
type: "never",
|
|
818
|
+
optional: true
|
|
819
|
+
})
|
|
820
|
+
}),
|
|
821
|
+
(0, _kubb_ast.createProperty)({
|
|
822
|
+
name: "headerParams",
|
|
823
|
+
schema: headerParams.length > 0 ? (0, _kubb_ast.createSchema)({
|
|
824
|
+
...buildParams({
|
|
825
|
+
params: headerParams,
|
|
826
|
+
node,
|
|
827
|
+
resolver
|
|
828
|
+
}),
|
|
829
|
+
optional: true
|
|
830
|
+
}) : (0, _kubb_ast.createSchema)({
|
|
831
|
+
type: "never",
|
|
832
|
+
optional: true
|
|
833
|
+
})
|
|
834
|
+
}),
|
|
835
|
+
(0, _kubb_ast.createProperty)({
|
|
836
|
+
name: "url",
|
|
837
|
+
required: true,
|
|
838
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
839
|
+
type: "url",
|
|
840
|
+
path: node.path
|
|
841
|
+
})
|
|
842
|
+
})
|
|
843
|
+
]
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
function buildResponses({ node, resolver }) {
|
|
847
|
+
if (node.responses.length === 0) return null;
|
|
848
|
+
return (0, _kubb_ast.createSchema)({
|
|
849
|
+
type: "object",
|
|
850
|
+
properties: node.responses.map((res) => (0, _kubb_ast.createProperty)({
|
|
851
|
+
name: String(res.statusCode),
|
|
852
|
+
required: true,
|
|
853
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
854
|
+
type: "ref",
|
|
855
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
856
|
+
})
|
|
857
|
+
}))
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
function buildResponseUnion({ node, resolver }) {
|
|
861
|
+
const responsesWithSchema = node.responses.filter((res) => res.schema);
|
|
862
|
+
if (responsesWithSchema.length === 0) return null;
|
|
863
|
+
return (0, _kubb_ast.createSchema)({
|
|
864
|
+
type: "union",
|
|
865
|
+
members: responsesWithSchema.map((res) => (0, _kubb_ast.createSchema)({
|
|
866
|
+
type: "ref",
|
|
867
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
868
|
+
}))
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
//#endregion
|
|
872
|
+
//#region src/generators/typeGenerator.tsx
|
|
873
|
+
const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
874
|
+
name: "typescript",
|
|
875
|
+
type: "react",
|
|
876
|
+
Operation({ node, adapter, options, config, resolver }) {
|
|
877
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options;
|
|
878
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
879
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
880
|
+
const file = resolver.resolveFile({
|
|
881
|
+
name: node.operationId,
|
|
882
|
+
extname: ".ts",
|
|
883
|
+
tag: node.tags[0] ?? "default",
|
|
884
|
+
path: node.path
|
|
885
|
+
}, {
|
|
886
|
+
root,
|
|
887
|
+
output,
|
|
888
|
+
group
|
|
889
|
+
});
|
|
890
|
+
const params = (0, _kubb_ast.caseParams)(node.parameters, paramsCasing);
|
|
891
|
+
function renderSchemaType({ node: schemaNode, name, description, keysToOmit }) {
|
|
892
|
+
if (!schemaNode) return null;
|
|
893
|
+
const transformedNode = (0, _kubb_ast.transform)(schemaNode, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
894
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
895
|
+
name: resolver.default(schemaName, "type"),
|
|
896
|
+
path: resolver.resolveFile({
|
|
897
|
+
name: schemaName,
|
|
898
|
+
extname: ".ts"
|
|
899
|
+
}, {
|
|
900
|
+
root,
|
|
901
|
+
output,
|
|
902
|
+
group
|
|
903
|
+
}).path
|
|
904
|
+
}));
|
|
905
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
906
|
+
root: file.path,
|
|
907
|
+
path: imp.path,
|
|
908
|
+
name: imp.name,
|
|
909
|
+
isTypeOnly: true
|
|
910
|
+
}, [
|
|
911
|
+
name,
|
|
912
|
+
imp.path,
|
|
913
|
+
imp.isTypeOnly
|
|
914
|
+
].join("-"))), /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Type, {
|
|
915
|
+
name,
|
|
916
|
+
node: transformedNode,
|
|
917
|
+
description,
|
|
918
|
+
enumType,
|
|
919
|
+
enumTypeSuffix,
|
|
920
|
+
enumKeyCasing,
|
|
921
|
+
optionalType,
|
|
922
|
+
arrayType,
|
|
923
|
+
syntaxType,
|
|
924
|
+
resolver,
|
|
925
|
+
keysToOmit
|
|
926
|
+
})] });
|
|
927
|
+
}
|
|
928
|
+
const paramTypes = params.map((param) => renderSchemaType({
|
|
929
|
+
node: param.schema,
|
|
930
|
+
name: resolver.resolveParamName(node, param)
|
|
931
|
+
}));
|
|
932
|
+
const requestType = node.requestBody?.schema ? renderSchemaType({
|
|
933
|
+
node: node.requestBody.schema,
|
|
934
|
+
name: resolver.resolveDataName(node),
|
|
935
|
+
description: node.requestBody.description ?? node.requestBody.schema.description,
|
|
936
|
+
keysToOmit: node.requestBody.keysToOmit
|
|
937
|
+
}) : null;
|
|
938
|
+
const responseTypes = node.responses.map((res) => renderSchemaType({
|
|
939
|
+
node: res.schema,
|
|
940
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode),
|
|
941
|
+
description: res.description,
|
|
942
|
+
keysToOmit: res.keysToOmit
|
|
943
|
+
}));
|
|
944
|
+
const dataType = renderSchemaType({
|
|
945
|
+
node: buildData({
|
|
946
|
+
node: {
|
|
947
|
+
...node,
|
|
948
|
+
parameters: params
|
|
949
|
+
},
|
|
950
|
+
resolver
|
|
951
|
+
}),
|
|
952
|
+
name: resolver.resolveRequestConfigName(node)
|
|
953
|
+
});
|
|
954
|
+
const responsesType = renderSchemaType({
|
|
955
|
+
node: buildResponses({
|
|
956
|
+
node,
|
|
957
|
+
resolver
|
|
958
|
+
}),
|
|
959
|
+
name: resolver.resolveResponsesName(node)
|
|
960
|
+
});
|
|
961
|
+
const responseType = renderSchemaType({
|
|
962
|
+
node: buildResponseUnion({
|
|
963
|
+
node,
|
|
964
|
+
resolver
|
|
965
|
+
}),
|
|
966
|
+
name: resolver.resolveResponseName(node),
|
|
967
|
+
description: "Union of all possible responses"
|
|
968
|
+
});
|
|
969
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
970
|
+
baseName: file.baseName,
|
|
971
|
+
path: file.path,
|
|
972
|
+
meta: file.meta,
|
|
973
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
974
|
+
output,
|
|
975
|
+
config
|
|
976
|
+
}),
|
|
977
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
978
|
+
output,
|
|
979
|
+
config
|
|
980
|
+
}),
|
|
981
|
+
children: [
|
|
982
|
+
paramTypes,
|
|
983
|
+
responseTypes,
|
|
984
|
+
requestType,
|
|
985
|
+
dataType,
|
|
986
|
+
responsesType,
|
|
987
|
+
responseType
|
|
988
|
+
]
|
|
989
|
+
});
|
|
990
|
+
},
|
|
991
|
+
Schema({ node, adapter, options, config, resolver }) {
|
|
992
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
|
|
993
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
994
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
995
|
+
if (!node.name) return;
|
|
996
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
997
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
998
|
+
name: resolver.default(schemaName, "type"),
|
|
999
|
+
path: resolver.resolveFile({
|
|
1000
|
+
name: schemaName,
|
|
1001
|
+
extname: ".ts"
|
|
1002
|
+
}, {
|
|
1003
|
+
root,
|
|
1004
|
+
output,
|
|
1005
|
+
group
|
|
1006
|
+
}).path
|
|
1007
|
+
}));
|
|
1008
|
+
const isEnumSchema = !!(0, _kubb_ast.narrowSchema)(node, _kubb_ast.schemaTypes.enum);
|
|
1009
|
+
const type = {
|
|
1010
|
+
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
|
|
1011
|
+
file: resolver.resolveFile({
|
|
1012
|
+
name: node.name,
|
|
1013
|
+
extname: ".ts"
|
|
1014
|
+
}, {
|
|
1015
|
+
root,
|
|
1016
|
+
output,
|
|
1017
|
+
group
|
|
1018
|
+
})
|
|
1019
|
+
};
|
|
1020
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
1021
|
+
baseName: type.file.baseName,
|
|
1022
|
+
path: type.file.path,
|
|
1023
|
+
meta: type.file.meta,
|
|
1024
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1025
|
+
output,
|
|
1026
|
+
config
|
|
1027
|
+
}),
|
|
1028
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1029
|
+
output,
|
|
1030
|
+
config
|
|
1031
|
+
}),
|
|
1032
|
+
children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1033
|
+
root: type.file.path,
|
|
1034
|
+
path: imp.path,
|
|
1035
|
+
name: imp.name,
|
|
1036
|
+
isTypeOnly: true
|
|
1037
|
+
}, [
|
|
1038
|
+
node.name,
|
|
1039
|
+
imp.path,
|
|
1040
|
+
imp.isTypeOnly
|
|
1041
|
+
].join("-"))), /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Type, {
|
|
1042
|
+
name: type.name,
|
|
1043
|
+
node: transformedNode,
|
|
1044
|
+
enumType,
|
|
1045
|
+
enumTypeSuffix,
|
|
1046
|
+
enumKeyCasing,
|
|
1047
|
+
optionalType,
|
|
1048
|
+
arrayType,
|
|
1049
|
+
syntaxType,
|
|
1050
|
+
resolver
|
|
1051
|
+
})]
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
25
1054
|
});
|
|
1055
|
+
//#endregion
|
|
1056
|
+
//#region src/resolvers/resolverTs.ts
|
|
1057
|
+
function resolveName(name, type) {
|
|
1058
|
+
return pascalCase(name, { isFile: type === "file" });
|
|
1059
|
+
}
|
|
26
1060
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
1061
|
+
* Resolver for `@kubb/plugin-ts` that provides the default naming and path-resolution
|
|
1062
|
+
* helpers used by the plugin. Import this in other plugins to resolve the exact names and
|
|
1063
|
+
* paths that `plugin-ts` generates without hardcoding the conventions.
|
|
29
1064
|
*
|
|
30
|
-
* `
|
|
1065
|
+
* The `default` method is automatically injected by `defineResolver` — it uses `camelCase`
|
|
1066
|
+
* for identifiers/files and `pascalCase` for type names.
|
|
31
1067
|
*
|
|
32
1068
|
* @example
|
|
33
1069
|
* ```ts
|
|
34
|
-
*
|
|
1070
|
+
* import { resolver } from '@kubb/plugin-ts'
|
|
1071
|
+
*
|
|
1072
|
+
* resolver.default('list pets', 'type') // → 'ListPets'
|
|
1073
|
+
* resolver.resolveName('list pets status 200') // → 'ListPetsStatus200'
|
|
1074
|
+
* resolver.resolvePathName('list pets', 'file') // → 'listPets'
|
|
35
1075
|
* ```
|
|
36
1076
|
*/
|
|
37
|
-
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
1077
|
+
const resolverTs = (0, _kubb_core.defineResolver)(() => {
|
|
1078
|
+
return {
|
|
1079
|
+
name: "default",
|
|
1080
|
+
pluginName: "plugin-ts",
|
|
1081
|
+
default(name, type) {
|
|
1082
|
+
return resolveName(name, type);
|
|
1083
|
+
},
|
|
1084
|
+
resolveName(name) {
|
|
1085
|
+
return this.default(name, "function");
|
|
1086
|
+
},
|
|
1087
|
+
resolvePathName(name, type) {
|
|
1088
|
+
return this.default(name, type);
|
|
1089
|
+
},
|
|
1090
|
+
resolveParamName(node, param) {
|
|
1091
|
+
return this.resolveName(`${node.operationId} ${param.in} ${param.name}`);
|
|
1092
|
+
},
|
|
1093
|
+
resolveResponseStatusName(node, statusCode) {
|
|
1094
|
+
return this.resolveName(`${node.operationId} Status ${statusCode}`);
|
|
1095
|
+
},
|
|
1096
|
+
resolveDataName(node) {
|
|
1097
|
+
return this.resolveName(`${node.operationId} Data`);
|
|
1098
|
+
},
|
|
1099
|
+
resolveRequestConfigName(node) {
|
|
1100
|
+
return this.resolveName(`${node.operationId} RequestConfig`);
|
|
1101
|
+
},
|
|
1102
|
+
resolveResponsesName(node) {
|
|
1103
|
+
return this.resolveName(`${node.operationId} Responses`);
|
|
1104
|
+
},
|
|
1105
|
+
resolveResponseName(node) {
|
|
1106
|
+
return this.resolveName(`${node.operationId} Response`);
|
|
1107
|
+
},
|
|
1108
|
+
resolveEnumKeyName(node, enumTypeSuffix = "key") {
|
|
1109
|
+
return `${this.resolveName(node.name ?? "")}${enumTypeSuffix}`;
|
|
1110
|
+
},
|
|
1111
|
+
resolvePathParamsName(node, param) {
|
|
1112
|
+
return this.resolveParamName(node, param);
|
|
1113
|
+
},
|
|
1114
|
+
resolveQueryParamsName(node, param) {
|
|
1115
|
+
return this.resolveParamName(node, param);
|
|
1116
|
+
},
|
|
1117
|
+
resolveHeaderParamsName(node, param) {
|
|
1118
|
+
return this.resolveParamName(node, param);
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
});
|
|
1122
|
+
//#endregion
|
|
1123
|
+
//#region src/resolvers/resolverTsLegacy.ts
|
|
1124
|
+
/**
|
|
1125
|
+
* Legacy resolver for `@kubb/plugin-ts` that reproduces the naming conventions
|
|
1126
|
+
* used before the v2 resolver refactor. Enable via `compatibilityPreset: 'kubbV4'`
|
|
1127
|
+
* (or by composing this resolver manually).
|
|
1128
|
+
*
|
|
1129
|
+
* Key differences from the default resolver:
|
|
1130
|
+
* - Response status types: `<OperationId><StatusCode>` (e.g. `CreatePets201`) instead of `<OperationId>Status201`
|
|
1131
|
+
* - Default/error responses: `<OperationId>Error` instead of `<OperationId>StatusDefault`
|
|
1132
|
+
* - Request body: `<OperationId>MutationRequest` (non-GET) / `<OperationId>QueryRequest` (GET)
|
|
1133
|
+
* - Combined responses type: `<OperationId>Mutation` / `<OperationId>Query`
|
|
1134
|
+
* - Response union: `<OperationId>MutationResponse` / `<OperationId>QueryResponse`
|
|
1135
|
+
*
|
|
1136
|
+
* @example
|
|
1137
|
+
* ```ts
|
|
1138
|
+
* import { resolverTsLegacy } from '@kubb/plugin-ts'
|
|
1139
|
+
*
|
|
1140
|
+
* resolverTsLegacy.resolveResponseStatusTypedName(node, 201) // → 'CreatePets201'
|
|
1141
|
+
* resolverTsLegacy.resolveResponseStatusTypedName(node, 'default') // → 'CreatePetsError'
|
|
1142
|
+
* resolverTsLegacy.resolveDataTypedName(node) // → 'CreatePetsMutationRequest' (POST)
|
|
1143
|
+
* resolverTsLegacy.resolveResponsesTypedName(node) // → 'CreatePetsMutation' (POST)
|
|
1144
|
+
* resolverTsLegacy.resolveResponseTypedName(node) // → 'CreatePetsMutationResponse' (POST)
|
|
1145
|
+
* ```
|
|
1146
|
+
*/
|
|
1147
|
+
const resolverTsLegacy = (0, _kubb_core.defineResolver)(() => {
|
|
1148
|
+
return {
|
|
1149
|
+
...resolverTs,
|
|
1150
|
+
pluginName: "plugin-ts",
|
|
1151
|
+
resolveResponseStatusName(node, statusCode) {
|
|
1152
|
+
if (statusCode === "default") return this.resolveName(`${node.operationId} Error`);
|
|
1153
|
+
return this.resolveName(`${node.operationId} ${statusCode}`);
|
|
1154
|
+
},
|
|
1155
|
+
resolveDataName(node) {
|
|
1156
|
+
const suffix = node.method === "GET" ? "QueryRequest" : "MutationRequest";
|
|
1157
|
+
return this.resolveName(`${node.operationId} ${suffix}`);
|
|
1158
|
+
},
|
|
1159
|
+
resolveResponsesName(node) {
|
|
1160
|
+
const suffix = node.method === "GET" ? "Query" : "Mutation";
|
|
1161
|
+
return this.resolveName(`${node.operationId} ${suffix}`);
|
|
1162
|
+
},
|
|
1163
|
+
resolveResponseName(node) {
|
|
1164
|
+
const suffix = node.method === "GET" ? "QueryResponse" : "MutationResponse";
|
|
1165
|
+
return this.resolveName(`${node.operationId} ${suffix}`);
|
|
1166
|
+
},
|
|
1167
|
+
resolvePathParamsName(node, _param) {
|
|
1168
|
+
return this.resolveName(`${node.operationId} PathParams`);
|
|
1169
|
+
},
|
|
1170
|
+
resolveQueryParamsName(node, _param) {
|
|
1171
|
+
return this.resolveName(`${node.operationId} QueryParams`);
|
|
1172
|
+
},
|
|
1173
|
+
resolveHeaderParamsName(node, _param) {
|
|
1174
|
+
return this.resolveName(`${node.operationId} HeaderParams`);
|
|
1175
|
+
}
|
|
1176
|
+
};
|
|
1177
|
+
});
|
|
1178
|
+
//#endregion
|
|
1179
|
+
//#region src/generators/typeGeneratorLegacy.tsx
|
|
1180
|
+
function buildGroupedParamsSchema({ params, parentName }) {
|
|
1181
|
+
return (0, _kubb_ast.createSchema)({
|
|
1182
|
+
type: "object",
|
|
1183
|
+
properties: params.map((param) => {
|
|
1184
|
+
let schema = param.schema;
|
|
1185
|
+
if ((0, _kubb_ast.narrowSchema)(schema, "enum") && !schema.name && parentName) schema = {
|
|
1186
|
+
...schema,
|
|
1187
|
+
name: pascalCase([
|
|
1188
|
+
parentName,
|
|
1189
|
+
param.name,
|
|
1190
|
+
"enum"
|
|
1191
|
+
].join(" "))
|
|
1192
|
+
};
|
|
1193
|
+
return (0, _kubb_ast.createProperty)({
|
|
1194
|
+
name: param.name,
|
|
1195
|
+
required: param.required,
|
|
1196
|
+
schema
|
|
1197
|
+
});
|
|
1198
|
+
})
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
function buildLegacyResponsesSchemaNode({ node, resolver }) {
|
|
1202
|
+
const isGet = node.method.toLowerCase() === "get";
|
|
1203
|
+
const successResponses = node.responses.filter((res) => {
|
|
1204
|
+
const code = Number(res.statusCode);
|
|
1205
|
+
return !Number.isNaN(code) && code >= 200 && code < 300;
|
|
1206
|
+
});
|
|
1207
|
+
const errorResponses = node.responses.filter((res) => res.statusCode === "default" || Number(res.statusCode) >= 400);
|
|
1208
|
+
const responseSchema = successResponses.length > 0 ? successResponses.length === 1 ? (0, _kubb_ast.createSchema)({
|
|
1209
|
+
type: "ref",
|
|
1210
|
+
name: resolver.resolveResponseStatusName(node, successResponses[0].statusCode)
|
|
1211
|
+
}) : (0, _kubb_ast.createSchema)({
|
|
1212
|
+
type: "union",
|
|
1213
|
+
members: successResponses.map((res) => (0, _kubb_ast.createSchema)({
|
|
1214
|
+
type: "ref",
|
|
1215
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1216
|
+
}))
|
|
1217
|
+
}) : (0, _kubb_ast.createSchema)({ type: "any" });
|
|
1218
|
+
const errorsSchema = errorResponses.length > 0 ? errorResponses.length === 1 ? (0, _kubb_ast.createSchema)({
|
|
1219
|
+
type: "ref",
|
|
1220
|
+
name: resolver.resolveResponseStatusName(node, errorResponses[0].statusCode)
|
|
1221
|
+
}) : (0, _kubb_ast.createSchema)({
|
|
1222
|
+
type: "union",
|
|
1223
|
+
members: errorResponses.map((res) => (0, _kubb_ast.createSchema)({
|
|
1224
|
+
type: "ref",
|
|
1225
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1226
|
+
}))
|
|
1227
|
+
}) : (0, _kubb_ast.createSchema)({ type: "any" });
|
|
1228
|
+
const properties = [(0, _kubb_ast.createProperty)({
|
|
1229
|
+
name: "Response",
|
|
1230
|
+
required: true,
|
|
1231
|
+
schema: responseSchema
|
|
1232
|
+
})];
|
|
1233
|
+
if (!isGet && node.requestBody?.schema) properties.push((0, _kubb_ast.createProperty)({
|
|
1234
|
+
name: "Request",
|
|
1235
|
+
required: true,
|
|
1236
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1237
|
+
type: "ref",
|
|
1238
|
+
name: resolver.resolveDataName(node)
|
|
1239
|
+
})
|
|
1240
|
+
}));
|
|
1241
|
+
const queryParam = node.parameters.find((p) => p.in === "query");
|
|
1242
|
+
if (queryParam) properties.push((0, _kubb_ast.createProperty)({
|
|
1243
|
+
name: "QueryParams",
|
|
1244
|
+
required: true,
|
|
1245
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1246
|
+
type: "ref",
|
|
1247
|
+
name: resolver.resolveQueryParamsName(node, queryParam)
|
|
1248
|
+
})
|
|
1249
|
+
}));
|
|
1250
|
+
const pathParam = node.parameters.find((p) => p.in === "path");
|
|
1251
|
+
if (pathParam) properties.push((0, _kubb_ast.createProperty)({
|
|
1252
|
+
name: "PathParams",
|
|
1253
|
+
required: true,
|
|
1254
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1255
|
+
type: "ref",
|
|
1256
|
+
name: resolver.resolvePathParamsName(node, pathParam)
|
|
1257
|
+
})
|
|
1258
|
+
}));
|
|
1259
|
+
const headerParam = node.parameters.find((p) => p.in === "header");
|
|
1260
|
+
if (headerParam) properties.push((0, _kubb_ast.createProperty)({
|
|
1261
|
+
name: "HeaderParams",
|
|
1262
|
+
required: true,
|
|
1263
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1264
|
+
type: "ref",
|
|
1265
|
+
name: resolver.resolveHeaderParamsName(node, headerParam)
|
|
1266
|
+
})
|
|
1267
|
+
}));
|
|
1268
|
+
properties.push((0, _kubb_ast.createProperty)({
|
|
1269
|
+
name: "Errors",
|
|
1270
|
+
required: true,
|
|
1271
|
+
schema: errorsSchema
|
|
1272
|
+
}));
|
|
1273
|
+
return (0, _kubb_ast.createSchema)({
|
|
1274
|
+
type: "object",
|
|
1275
|
+
properties
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
function buildLegacyResponseUnionSchemaNode({ node, resolver }) {
|
|
1279
|
+
const successResponses = node.responses.filter((res) => {
|
|
1280
|
+
const code = Number(res.statusCode);
|
|
1281
|
+
return !Number.isNaN(code) && code >= 200 && code < 300;
|
|
1282
|
+
});
|
|
1283
|
+
if (successResponses.length === 0) return (0, _kubb_ast.createSchema)({ type: "any" });
|
|
1284
|
+
if (successResponses.length === 1) return (0, _kubb_ast.createSchema)({
|
|
1285
|
+
type: "ref",
|
|
1286
|
+
name: resolver.resolveResponseStatusName(node, successResponses[0].statusCode)
|
|
1287
|
+
});
|
|
1288
|
+
return (0, _kubb_ast.createSchema)({
|
|
1289
|
+
type: "union",
|
|
1290
|
+
members: successResponses.map((res) => (0, _kubb_ast.createSchema)({
|
|
1291
|
+
type: "ref",
|
|
1292
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1293
|
+
}))
|
|
44
1294
|
});
|
|
45
1295
|
}
|
|
1296
|
+
function nameUnnamedEnums(node, parentName) {
|
|
1297
|
+
return (0, _kubb_ast.transform)(node, {
|
|
1298
|
+
schema(n) {
|
|
1299
|
+
const enumNode = (0, _kubb_ast.narrowSchema)(n, "enum");
|
|
1300
|
+
if (enumNode && !enumNode.name) return {
|
|
1301
|
+
...enumNode,
|
|
1302
|
+
name: pascalCase([parentName, "enum"].join(" "))
|
|
1303
|
+
};
|
|
1304
|
+
},
|
|
1305
|
+
property(p) {
|
|
1306
|
+
const enumNode = (0, _kubb_ast.narrowSchema)(p.schema, "enum");
|
|
1307
|
+
if (enumNode && !enumNode.name) return {
|
|
1308
|
+
...p,
|
|
1309
|
+
schema: {
|
|
1310
|
+
...enumNode,
|
|
1311
|
+
name: pascalCase([
|
|
1312
|
+
parentName,
|
|
1313
|
+
p.name,
|
|
1314
|
+
"enum"
|
|
1315
|
+
].join(" "))
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
const typeGeneratorLegacy = (0, _kubb_core.defineGenerator)({
|
|
1322
|
+
name: "typescript-legacy",
|
|
1323
|
+
type: "react",
|
|
1324
|
+
Operation({ node, adapter, options, config, resolver }) {
|
|
1325
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options;
|
|
1326
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
1327
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
1328
|
+
const file = resolver.resolveFile({
|
|
1329
|
+
name: node.operationId,
|
|
1330
|
+
extname: ".ts",
|
|
1331
|
+
tag: node.tags[0] ?? "default",
|
|
1332
|
+
path: node.path
|
|
1333
|
+
}, {
|
|
1334
|
+
root,
|
|
1335
|
+
output,
|
|
1336
|
+
group
|
|
1337
|
+
});
|
|
1338
|
+
const params = (0, _kubb_ast.caseParams)(node.parameters, paramsCasing);
|
|
1339
|
+
function renderSchemaType({ node: schemaNode, name, description, keysToOmit }) {
|
|
1340
|
+
if (!schemaNode) return null;
|
|
1341
|
+
const transformedNode = (0, _kubb_ast.transform)(schemaNode, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
1342
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
1343
|
+
name: resolver.default(schemaName, "type"),
|
|
1344
|
+
path: resolver.resolveFile({
|
|
1345
|
+
name: schemaName,
|
|
1346
|
+
extname: ".ts"
|
|
1347
|
+
}, {
|
|
1348
|
+
root,
|
|
1349
|
+
output,
|
|
1350
|
+
group
|
|
1351
|
+
}).path
|
|
1352
|
+
}));
|
|
1353
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1354
|
+
root: file.path,
|
|
1355
|
+
path: imp.path,
|
|
1356
|
+
name: imp.name,
|
|
1357
|
+
isTypeOnly: true
|
|
1358
|
+
}, [
|
|
1359
|
+
name,
|
|
1360
|
+
imp.path,
|
|
1361
|
+
imp.isTypeOnly
|
|
1362
|
+
].join("-"))), /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Type, {
|
|
1363
|
+
name,
|
|
1364
|
+
node: transformedNode,
|
|
1365
|
+
description,
|
|
1366
|
+
enumType,
|
|
1367
|
+
enumTypeSuffix,
|
|
1368
|
+
enumKeyCasing,
|
|
1369
|
+
optionalType,
|
|
1370
|
+
arrayType,
|
|
1371
|
+
syntaxType,
|
|
1372
|
+
resolver,
|
|
1373
|
+
keysToOmit
|
|
1374
|
+
})] });
|
|
1375
|
+
}
|
|
1376
|
+
const pathParams = params.filter((p) => p.in === "path");
|
|
1377
|
+
const queryParams = params.filter((p) => p.in === "query");
|
|
1378
|
+
const headerParams = params.filter((p) => p.in === "header");
|
|
1379
|
+
const responseTypes = node.responses.map((res) => {
|
|
1380
|
+
const responseName = resolver.resolveResponseStatusName(node, res.statusCode);
|
|
1381
|
+
const baseResponseName = resolverTsLegacy.resolveResponseStatusName(node, res.statusCode);
|
|
1382
|
+
return renderSchemaType({
|
|
1383
|
+
node: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
|
|
1384
|
+
name: responseName,
|
|
1385
|
+
description: res.description,
|
|
1386
|
+
keysToOmit: res.keysToOmit
|
|
1387
|
+
});
|
|
1388
|
+
});
|
|
1389
|
+
const requestType = node.requestBody?.schema ? renderSchemaType({
|
|
1390
|
+
node: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
|
|
1391
|
+
name: resolver.resolveDataName(node),
|
|
1392
|
+
description: node.requestBody.description ?? node.requestBody.schema.description,
|
|
1393
|
+
keysToOmit: node.requestBody.keysToOmit
|
|
1394
|
+
}) : null;
|
|
1395
|
+
const legacyParamTypes = [
|
|
1396
|
+
pathParams.length > 0 ? renderSchemaType({
|
|
1397
|
+
node: buildGroupedParamsSchema({
|
|
1398
|
+
params: pathParams,
|
|
1399
|
+
parentName: resolverTsLegacy.resolvePathParamsName(node, pathParams[0])
|
|
1400
|
+
}),
|
|
1401
|
+
name: resolver.resolvePathParamsName(node, pathParams[0])
|
|
1402
|
+
}) : null,
|
|
1403
|
+
queryParams.length > 0 ? renderSchemaType({
|
|
1404
|
+
node: buildGroupedParamsSchema({
|
|
1405
|
+
params: queryParams,
|
|
1406
|
+
parentName: resolverTsLegacy.resolveQueryParamsName(node, queryParams[0])
|
|
1407
|
+
}),
|
|
1408
|
+
name: resolver.resolveQueryParamsName(node, queryParams[0])
|
|
1409
|
+
}) : null,
|
|
1410
|
+
headerParams.length > 0 ? renderSchemaType({
|
|
1411
|
+
node: buildGroupedParamsSchema({
|
|
1412
|
+
params: headerParams,
|
|
1413
|
+
parentName: resolverTsLegacy.resolveHeaderParamsName(node, headerParams[0])
|
|
1414
|
+
}),
|
|
1415
|
+
name: resolver.resolveHeaderParamsName(node, headerParams[0])
|
|
1416
|
+
}) : null
|
|
1417
|
+
];
|
|
1418
|
+
const legacyResponsesType = renderSchemaType({
|
|
1419
|
+
node: buildLegacyResponsesSchemaNode({
|
|
1420
|
+
node,
|
|
1421
|
+
resolver
|
|
1422
|
+
}),
|
|
1423
|
+
name: resolver.resolveResponsesName(node)
|
|
1424
|
+
});
|
|
1425
|
+
const legacyResponseType = renderSchemaType({
|
|
1426
|
+
node: buildLegacyResponseUnionSchemaNode({
|
|
1427
|
+
node,
|
|
1428
|
+
resolver
|
|
1429
|
+
}),
|
|
1430
|
+
name: resolver.resolveResponseName(node)
|
|
1431
|
+
});
|
|
1432
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
1433
|
+
baseName: file.baseName,
|
|
1434
|
+
path: file.path,
|
|
1435
|
+
meta: file.meta,
|
|
1436
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1437
|
+
output,
|
|
1438
|
+
config
|
|
1439
|
+
}),
|
|
1440
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1441
|
+
output,
|
|
1442
|
+
config
|
|
1443
|
+
}),
|
|
1444
|
+
children: [
|
|
1445
|
+
legacyParamTypes,
|
|
1446
|
+
responseTypes,
|
|
1447
|
+
requestType,
|
|
1448
|
+
legacyResponseType,
|
|
1449
|
+
legacyResponsesType
|
|
1450
|
+
]
|
|
1451
|
+
});
|
|
1452
|
+
},
|
|
1453
|
+
Schema({ node, adapter, options, config, resolver }) {
|
|
1454
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options;
|
|
1455
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
1456
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
1457
|
+
if (!node.name) return;
|
|
1458
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
1459
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
1460
|
+
name: resolver.default(schemaName, "type"),
|
|
1461
|
+
path: resolver.resolveFile({
|
|
1462
|
+
name: schemaName,
|
|
1463
|
+
extname: ".ts"
|
|
1464
|
+
}, {
|
|
1465
|
+
root,
|
|
1466
|
+
output,
|
|
1467
|
+
group
|
|
1468
|
+
}).path
|
|
1469
|
+
}));
|
|
1470
|
+
const isEnumSchema = !!(0, _kubb_ast.narrowSchema)(node, _kubb_ast.schemaTypes.enum);
|
|
1471
|
+
const type = {
|
|
1472
|
+
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name),
|
|
1473
|
+
file: resolver.resolveFile({
|
|
1474
|
+
name: node.name,
|
|
1475
|
+
extname: ".ts"
|
|
1476
|
+
}, {
|
|
1477
|
+
root,
|
|
1478
|
+
output,
|
|
1479
|
+
group
|
|
1480
|
+
})
|
|
1481
|
+
};
|
|
1482
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
1483
|
+
baseName: type.file.baseName,
|
|
1484
|
+
path: type.file.path,
|
|
1485
|
+
meta: type.file.meta,
|
|
1486
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1487
|
+
output,
|
|
1488
|
+
config
|
|
1489
|
+
}),
|
|
1490
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1491
|
+
output,
|
|
1492
|
+
config
|
|
1493
|
+
}),
|
|
1494
|
+
children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1495
|
+
root: type.file.path,
|
|
1496
|
+
path: imp.path,
|
|
1497
|
+
name: imp.name,
|
|
1498
|
+
isTypeOnly: true
|
|
1499
|
+
}, [
|
|
1500
|
+
node.name,
|
|
1501
|
+
imp.path,
|
|
1502
|
+
imp.isTypeOnly
|
|
1503
|
+
].join("-"))), /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Type, {
|
|
1504
|
+
name: type.name,
|
|
1505
|
+
node: transformedNode,
|
|
1506
|
+
enumType,
|
|
1507
|
+
enumTypeSuffix,
|
|
1508
|
+
enumKeyCasing,
|
|
1509
|
+
optionalType,
|
|
1510
|
+
arrayType,
|
|
1511
|
+
syntaxType,
|
|
1512
|
+
resolver
|
|
1513
|
+
})]
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
});
|
|
1517
|
+
//#endregion
|
|
1518
|
+
//#region src/presets.ts
|
|
1519
|
+
/**
|
|
1520
|
+
* Built-in preset registry for `@kubb/plugin-ts`.
|
|
1521
|
+
*
|
|
1522
|
+
* - `default` — uses `resolverTs` and `typeGenerator` (current naming conventions).
|
|
1523
|
+
* - `kubbV4` — uses `resolverTsLegacy` and `typeGeneratorLegacy` (Kubb v4 naming conventions).
|
|
1524
|
+
*/
|
|
1525
|
+
const presets = (0, _kubb_core.definePresets)({
|
|
1526
|
+
default: {
|
|
1527
|
+
name: "default",
|
|
1528
|
+
resolvers: [resolverTs],
|
|
1529
|
+
generators: [typeGenerator]
|
|
1530
|
+
},
|
|
1531
|
+
kubbV4: {
|
|
1532
|
+
name: "kubbV4",
|
|
1533
|
+
resolvers: [resolverTsLegacy],
|
|
1534
|
+
generators: [typeGeneratorLegacy]
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
46
1537
|
//#endregion
|
|
47
1538
|
//#region src/plugin.ts
|
|
48
1539
|
/**
|
|
@@ -70,7 +1561,9 @@ const pluginTs = (0, _kubb_core.createPlugin)((options) => {
|
|
|
70
1561
|
path: "types",
|
|
71
1562
|
barrelType: "named"
|
|
72
1563
|
}, group, exclude = [], include, override = [], enumType = "asConst", enumTypeSuffix = "Key", enumKeyCasing = "none", optionalType = "questionToken", arrayType = "array", syntaxType = "type", paramsCasing, compatibilityPreset = "default", resolvers: userResolvers = [], transformers: userTransformers = [], generators: userGenerators = [] } = options;
|
|
73
|
-
const
|
|
1564
|
+
const preset = (0, _kubb_core.getPreset)({
|
|
1565
|
+
preset: compatibilityPreset,
|
|
1566
|
+
presets,
|
|
74
1567
|
resolvers: userResolvers,
|
|
75
1568
|
transformers: userTransformers,
|
|
76
1569
|
generators: userGenerators
|
|
@@ -79,25 +1572,35 @@ const pluginTs = (0, _kubb_core.createPlugin)((options) => {
|
|
|
79
1572
|
let resolvePathWarning = false;
|
|
80
1573
|
return {
|
|
81
1574
|
name: pluginTsName,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
1575
|
+
get resolver() {
|
|
1576
|
+
return preset.resolver;
|
|
1577
|
+
},
|
|
1578
|
+
get options() {
|
|
1579
|
+
return {
|
|
1580
|
+
output,
|
|
1581
|
+
optionalType,
|
|
1582
|
+
group: group ? {
|
|
1583
|
+
...options.group,
|
|
1584
|
+
name: (ctx) => {
|
|
1585
|
+
if (options.group?.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
1586
|
+
return `${camelCase(ctx.group)}Controller`;
|
|
1587
|
+
}
|
|
1588
|
+
} : void 0,
|
|
1589
|
+
arrayType,
|
|
1590
|
+
enumType,
|
|
1591
|
+
enumTypeSuffix,
|
|
1592
|
+
enumKeyCasing,
|
|
1593
|
+
syntaxType,
|
|
1594
|
+
paramsCasing,
|
|
1595
|
+
transformers: preset.transformers
|
|
1596
|
+
};
|
|
94
1597
|
},
|
|
95
1598
|
resolvePath(baseName, pathMode, options) {
|
|
96
1599
|
if (!resolvePathWarning) {
|
|
97
|
-
this.
|
|
1600
|
+
this.events.emit("warn", "Do not use resolvePath for pluginTs, use resolverTs.resolvePath instead");
|
|
98
1601
|
resolvePathWarning = true;
|
|
99
1602
|
}
|
|
100
|
-
return resolver.resolvePath({
|
|
1603
|
+
return this.plugin.resolver.resolvePath({
|
|
101
1604
|
baseName,
|
|
102
1605
|
pathMode,
|
|
103
1606
|
tag: options?.group?.tag,
|
|
@@ -105,25 +1608,25 @@ const pluginTs = (0, _kubb_core.createPlugin)((options) => {
|
|
|
105
1608
|
}, {
|
|
106
1609
|
root: node_path.default.resolve(this.config.root, this.config.output.path),
|
|
107
1610
|
output,
|
|
108
|
-
group
|
|
1611
|
+
group: this.plugin.options.group
|
|
109
1612
|
});
|
|
110
1613
|
},
|
|
111
1614
|
resolveName(name, type) {
|
|
112
1615
|
if (!resolveNameWarning) {
|
|
113
|
-
this.
|
|
1616
|
+
this.events.emit("warn", "Do not use resolveName for pluginTs, use resolverTs.default instead");
|
|
114
1617
|
resolveNameWarning = true;
|
|
115
1618
|
}
|
|
116
|
-
return resolver.default(name, type);
|
|
1619
|
+
return this.plugin.resolver.default(name, type);
|
|
117
1620
|
},
|
|
118
1621
|
async install() {
|
|
119
|
-
const { config, fabric, plugin, adapter, rootNode, driver, openInStudio } = this;
|
|
1622
|
+
const { config, fabric, plugin, adapter, rootNode, driver, openInStudio, resolver } = this;
|
|
120
1623
|
const root = node_path.default.resolve(config.root, config.output.path);
|
|
121
1624
|
if (!adapter) throw new Error("Plugin cannot work without adapter being set");
|
|
122
1625
|
await openInStudio({ ast: true });
|
|
123
1626
|
await (0, _kubb_ast.walk)(rootNode, {
|
|
124
1627
|
depth: "shallow",
|
|
125
1628
|
async schema(schemaNode) {
|
|
126
|
-
const writeTasks = generators.map(async (generator) => {
|
|
1629
|
+
const writeTasks = preset.generators.map(async (generator) => {
|
|
127
1630
|
if (generator.type === "react" && generator.version === "2") {
|
|
128
1631
|
const options = resolver.resolveOptions(schemaNode, {
|
|
129
1632
|
options: plugin.options,
|
|
@@ -134,6 +1637,7 @@ const pluginTs = (0, _kubb_core.createPlugin)((options) => {
|
|
|
134
1637
|
if (options === null) return;
|
|
135
1638
|
await (0, _kubb_core.renderSchema)(schemaNode, {
|
|
136
1639
|
options,
|
|
1640
|
+
resolver,
|
|
137
1641
|
adapter,
|
|
138
1642
|
config,
|
|
139
1643
|
fabric,
|
|
@@ -146,7 +1650,7 @@ const pluginTs = (0, _kubb_core.createPlugin)((options) => {
|
|
|
146
1650
|
await Promise.all(writeTasks);
|
|
147
1651
|
},
|
|
148
1652
|
async operation(operationNode) {
|
|
149
|
-
const writeTasks = generators.map(async (generator) => {
|
|
1653
|
+
const writeTasks = preset.generators.map(async (generator) => {
|
|
150
1654
|
if (generator.type === "react" && generator.version === "2") {
|
|
151
1655
|
const options = resolver.resolveOptions(operationNode, {
|
|
152
1656
|
options: plugin.options,
|
|
@@ -157,6 +1661,7 @@ const pluginTs = (0, _kubb_core.createPlugin)((options) => {
|
|
|
157
1661
|
if (options === null) return;
|
|
158
1662
|
await (0, _kubb_core.renderOperation)(operationNode, {
|
|
159
1663
|
options,
|
|
1664
|
+
resolver,
|
|
160
1665
|
adapter,
|
|
161
1666
|
config,
|
|
162
1667
|
fabric,
|
|
@@ -180,7 +1685,121 @@ const pluginTs = (0, _kubb_core.createPlugin)((options) => {
|
|
|
180
1685
|
};
|
|
181
1686
|
});
|
|
182
1687
|
//#endregion
|
|
1688
|
+
//#region src/printers/functionPrinter.ts
|
|
1689
|
+
const kindToHandlerKey = {
|
|
1690
|
+
FunctionParameter: "functionParameter",
|
|
1691
|
+
ParameterGroup: "parameterGroup",
|
|
1692
|
+
FunctionParameters: "functionParameters",
|
|
1693
|
+
Type: "type"
|
|
1694
|
+
};
|
|
1695
|
+
/**
|
|
1696
|
+
* Creates a function-parameter printer factory.
|
|
1697
|
+
*
|
|
1698
|
+
* Uses `createPrinterFactory` and dispatches handlers by `node.kind`
|
|
1699
|
+
* (for function nodes) rather than by `node.type` (for schema nodes).
|
|
1700
|
+
*/
|
|
1701
|
+
const defineFunctionPrinter = (0, _kubb_ast.createPrinterFactory)((node) => kindToHandlerKey[node.kind]);
|
|
1702
|
+
function rank(param) {
|
|
1703
|
+
if (param.kind === "ParameterGroup") {
|
|
1704
|
+
if (param.default) return 2;
|
|
1705
|
+
return param.optional ?? param.properties.every((p) => p.optional || p.default !== void 0) ? 1 : 0;
|
|
1706
|
+
}
|
|
1707
|
+
if (param.rest) return 3;
|
|
1708
|
+
if (param.default) return 2;
|
|
1709
|
+
return param.optional ? 1 : 0;
|
|
1710
|
+
}
|
|
1711
|
+
function sortParams(params) {
|
|
1712
|
+
return [...params].sort((a, b) => rank(a) - rank(b));
|
|
1713
|
+
}
|
|
1714
|
+
function sortChildParams(params) {
|
|
1715
|
+
return [...params].sort((a, b) => rank(a) - rank(b));
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Default function-signature printer.
|
|
1719
|
+
* Covers the four standard output modes used across Kubb plugins.
|
|
1720
|
+
*
|
|
1721
|
+
* @example
|
|
1722
|
+
* ```ts
|
|
1723
|
+
* const printer = functionPrinter({ mode: 'declaration' })
|
|
1724
|
+
*
|
|
1725
|
+
* const sig = createFunctionParameters({
|
|
1726
|
+
* params: [
|
|
1727
|
+
* createFunctionParameter({ name: 'petId', type: 'string', optional: false }),
|
|
1728
|
+
* createFunctionParameter({ name: 'config', type: 'Config', optional: false, default: '{}' }),
|
|
1729
|
+
* ],
|
|
1730
|
+
* })
|
|
1731
|
+
*
|
|
1732
|
+
* printer.print(sig) // → "petId: string, config: Config = {}"
|
|
1733
|
+
* ```
|
|
1734
|
+
*/
|
|
1735
|
+
const functionPrinter = defineFunctionPrinter((options) => ({
|
|
1736
|
+
name: "functionParameters",
|
|
1737
|
+
options,
|
|
1738
|
+
nodes: {
|
|
1739
|
+
type(node) {
|
|
1740
|
+
if (node.variant === "member") return `${node.base}['${node.key}']`;
|
|
1741
|
+
if (node.variant === "struct") return `{ ${node.properties.map((p) => {
|
|
1742
|
+
const typeStr = this.transform(p.type);
|
|
1743
|
+
return p.optional ? `${p.name}?: ${typeStr}` : `${p.name}: ${typeStr}`;
|
|
1744
|
+
}).join("; ")} }`;
|
|
1745
|
+
if (node.variant === "reference") return node.name;
|
|
1746
|
+
return null;
|
|
1747
|
+
},
|
|
1748
|
+
functionParameter(node) {
|
|
1749
|
+
const { mode, transformName, transformType } = this.options;
|
|
1750
|
+
const name = transformName ? transformName(node.name) : node.name;
|
|
1751
|
+
const rawType = node.type ? this.transform(node.type) : void 0;
|
|
1752
|
+
const type = rawType != null && transformType ? transformType(rawType) : rawType;
|
|
1753
|
+
if (mode === "keys" || mode === "values") return node.rest ? `...${name}` : name;
|
|
1754
|
+
if (mode === "call") return node.rest ? `...${name}` : name;
|
|
1755
|
+
if (node.rest) return type ? `...${name}: ${type}` : `...${name}`;
|
|
1756
|
+
if (type) {
|
|
1757
|
+
if (node.optional) return `${name}?: ${type}`;
|
|
1758
|
+
return node.default ? `${name}: ${type} = ${node.default}` : `${name}: ${type}`;
|
|
1759
|
+
}
|
|
1760
|
+
return node.default ? `${name} = ${node.default}` : name;
|
|
1761
|
+
},
|
|
1762
|
+
parameterGroup(node) {
|
|
1763
|
+
const { mode, transformName, transformType } = this.options;
|
|
1764
|
+
const sorted = sortChildParams(node.properties);
|
|
1765
|
+
const isOptional = node.optional ?? sorted.every((p) => p.optional || p.default !== void 0);
|
|
1766
|
+
if (node.inline) return sorted.map((p) => this.transform(p)).filter(Boolean).join(", ");
|
|
1767
|
+
if (mode === "keys" || mode === "values") return `{ ${sorted.map((p) => p.name).join(", ")} }`;
|
|
1768
|
+
if (mode === "call") return `{ ${sorted.map((p) => p.name).join(", ")} }`;
|
|
1769
|
+
const names = sorted.map((p) => {
|
|
1770
|
+
return transformName ? transformName(p.name) : p.name;
|
|
1771
|
+
});
|
|
1772
|
+
const nameStr = names.length ? `{ ${names.join(", ")} }` : void 0;
|
|
1773
|
+
if (!nameStr) return null;
|
|
1774
|
+
let typeAnnotation = node.type ? this.transform(node.type) ?? void 0 : void 0;
|
|
1775
|
+
if (!typeAnnotation) {
|
|
1776
|
+
const typeParts = sorted.filter((p) => p.type).map((p) => {
|
|
1777
|
+
const rawT = p.type ? this.transform(p.type) : void 0;
|
|
1778
|
+
const t = rawT != null && transformType ? transformType(rawT) : rawT;
|
|
1779
|
+
return p.optional || p.default !== void 0 ? `${p.name}?: ${t}` : `${p.name}: ${t}`;
|
|
1780
|
+
});
|
|
1781
|
+
typeAnnotation = typeParts.length ? `{ ${typeParts.join("; ")} }` : void 0;
|
|
1782
|
+
}
|
|
1783
|
+
if (typeAnnotation) {
|
|
1784
|
+
if (isOptional) return `${nameStr}: ${typeAnnotation} = ${node.default ?? "{}"}`;
|
|
1785
|
+
return node.default ? `${nameStr}: ${typeAnnotation} = ${node.default}` : `${nameStr}: ${typeAnnotation}`;
|
|
1786
|
+
}
|
|
1787
|
+
return node.default ? `${nameStr} = ${node.default}` : nameStr;
|
|
1788
|
+
},
|
|
1789
|
+
functionParameters(node) {
|
|
1790
|
+
return sortParams(node.params).map((p) => this.transform(p)).filter(Boolean).join(", ");
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
}));
|
|
1794
|
+
//#endregion
|
|
1795
|
+
exports.Enum = Enum;
|
|
1796
|
+
exports.Type = Type;
|
|
1797
|
+
exports.functionPrinter = functionPrinter;
|
|
183
1798
|
exports.pluginTs = pluginTs;
|
|
184
1799
|
exports.pluginTsName = pluginTsName;
|
|
1800
|
+
exports.printerTs = printerTs;
|
|
1801
|
+
exports.resolverTs = resolverTs;
|
|
1802
|
+
exports.resolverTsLegacy = resolverTsLegacy;
|
|
1803
|
+
exports.typeGenerator = typeGenerator;
|
|
185
1804
|
|
|
186
1805
|
//# sourceMappingURL=index.cjs.map
|