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