@kubb/plugin-ts 5.0.0-alpha.8 → 5.0.0-beta.10

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