@kubb/plugin-ts 5.0.0-alpha.1 → 5.0.0-alpha.3

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.
@@ -0,0 +1,944 @@
1
+ import "./chunk--u3MIqq1.js";
2
+ import { A as keywordTypeNodes, C as createTypeDeclaration, D as createUnionDeclaration, E as createTypeReferenceNode, F as camelCase, I as pascalCase, M as syntaxKind, N as jsStringEscape, O as createUrlTemplateType, P as trimQuotes, S as createTypeAliasDeclaration, T as createTypeOperatorNode, _ as createPropertySignature, a as createArrayTypeNode, b as createTrue, c as createIdentifier, d as createIntersectionDeclaration, f as createLiteralTypeNode, g as createPrefixUnaryExpression, h as createOptionalTypeNode, i as createArrayDeclaration, j as modifiers, k as getUnknownType, l as createIndexSignature, m as createOmitDeclaration, n as SyntaxKind, o as createEnumDeclaration, p as createNumericLiteral, r as appendJSDocToNode, s as createFalse, t as Type$1, u as createIndexedAccessTypeNode, v as createRestTypeNode, w as createTypeLiteralNode, x as createTupleTypeNode, y as createStringLiteral } from "./components-CRjwjdyE.js";
3
+ import path from "node:path";
4
+ import { collect, isPlainStringType, walk } from "@kubb/ast";
5
+ import { definePlugin, definePrinter, getBarrelFiles, getMode } from "@kubb/core";
6
+ import { OperationGenerator, SchemaGenerator, buildOperation, buildSchema, isKeyword, pluginOasName, schemaKeywords } from "@kubb/plugin-oas";
7
+ import { useKubb, useMode, usePluginManager } from "@kubb/core/hooks";
8
+ import { safePrint } from "@kubb/fabric-core/parsers/typescript";
9
+ import { createReactGenerator } from "@kubb/plugin-oas/generators";
10
+ import { useOas, useOperationManager, useSchemaManager } from "@kubb/plugin-oas/hooks";
11
+ import { applyParamsCasing, getBanner, getFooter, getImports, isParameterSchema } from "@kubb/plugin-oas/utils";
12
+ import { File } from "@kubb/react-fabric";
13
+ import ts from "typescript";
14
+ import { Fragment, jsx, jsxs } from "@kubb/react-fabric/jsx-runtime";
15
+ //#region ../../internals/utils/src/object.ts
16
+ /**
17
+ * Serializes a primitive value to a JSON string literal, stripping any surrounding quote characters first.
18
+ *
19
+ * @example
20
+ * stringify('hello') // '"hello"'
21
+ * stringify('"hello"') // '"hello"'
22
+ */
23
+ function stringify(value) {
24
+ if (value === void 0 || value === null) return "\"\"";
25
+ return JSON.stringify(trimQuotes(value.toString()));
26
+ }
27
+ //#endregion
28
+ //#region src/generators/typeGenerator.tsx
29
+ function printCombinedSchema({ name, schemas, pluginManager }) {
30
+ const properties = {};
31
+ if (schemas.response) properties["response"] = createUnionDeclaration({ nodes: schemas.responses.map((res) => {
32
+ return createTypeReferenceNode(createIdentifier(pluginManager.resolveName({
33
+ name: res.name,
34
+ pluginName: pluginTsName,
35
+ type: "function"
36
+ })), void 0);
37
+ }) });
38
+ if (schemas.request) properties["request"] = createTypeReferenceNode(createIdentifier(pluginManager.resolveName({
39
+ name: schemas.request.name,
40
+ pluginName: pluginTsName,
41
+ type: "function"
42
+ })), void 0);
43
+ if (schemas.pathParams) properties["pathParams"] = createTypeReferenceNode(createIdentifier(pluginManager.resolveName({
44
+ name: schemas.pathParams.name,
45
+ pluginName: pluginTsName,
46
+ type: "function"
47
+ })), void 0);
48
+ if (schemas.queryParams) properties["queryParams"] = createTypeReferenceNode(createIdentifier(pluginManager.resolveName({
49
+ name: schemas.queryParams.name,
50
+ pluginName: pluginTsName,
51
+ type: "function"
52
+ })), void 0);
53
+ if (schemas.headerParams) properties["headerParams"] = createTypeReferenceNode(createIdentifier(pluginManager.resolveName({
54
+ name: schemas.headerParams.name,
55
+ pluginName: pluginTsName,
56
+ type: "function"
57
+ })), void 0);
58
+ if (schemas.errors) properties["errors"] = createUnionDeclaration({ nodes: schemas.errors.map((error) => {
59
+ return createTypeReferenceNode(createIdentifier(pluginManager.resolveName({
60
+ name: error.name,
61
+ pluginName: pluginTsName,
62
+ type: "function"
63
+ })), void 0);
64
+ }) });
65
+ return safePrint(createTypeAliasDeclaration({
66
+ name,
67
+ type: createTypeLiteralNode(Object.keys(properties).map((key) => {
68
+ const type = properties[key];
69
+ if (!type) return;
70
+ return createPropertySignature({
71
+ name: pascalCase(key),
72
+ type
73
+ });
74
+ }).filter(Boolean)),
75
+ modifiers: [modifiers.export]
76
+ }));
77
+ }
78
+ function printRequestSchema({ baseName, operation, schemas, pluginManager }) {
79
+ const name = pluginManager.resolveName({
80
+ name: `${baseName} Request`,
81
+ pluginName: pluginTsName,
82
+ type: "type"
83
+ });
84
+ const results = [];
85
+ const dataRequestProperties = [];
86
+ if (schemas.request) {
87
+ const identifier = pluginManager.resolveName({
88
+ name: schemas.request.name,
89
+ pluginName: pluginTsName,
90
+ type: "type"
91
+ });
92
+ dataRequestProperties.push(createPropertySignature({
93
+ name: "data",
94
+ questionToken: true,
95
+ type: createTypeReferenceNode(createIdentifier(identifier), void 0)
96
+ }));
97
+ } else dataRequestProperties.push(createPropertySignature({
98
+ name: "data",
99
+ questionToken: true,
100
+ type: keywordTypeNodes.never
101
+ }));
102
+ if (schemas.pathParams) {
103
+ const identifier = pluginManager.resolveName({
104
+ name: schemas.pathParams.name,
105
+ pluginName: pluginTsName,
106
+ type: "type"
107
+ });
108
+ dataRequestProperties.push(createPropertySignature({
109
+ name: "pathParams",
110
+ type: createTypeReferenceNode(createIdentifier(identifier), void 0)
111
+ }));
112
+ } else dataRequestProperties.push(createPropertySignature({
113
+ name: "pathParams",
114
+ questionToken: true,
115
+ type: keywordTypeNodes.never
116
+ }));
117
+ if (schemas.queryParams) {
118
+ const identifier = pluginManager.resolveName({
119
+ name: schemas.queryParams.name,
120
+ pluginName: pluginTsName,
121
+ type: "type"
122
+ });
123
+ dataRequestProperties.push(createPropertySignature({
124
+ name: "queryParams",
125
+ questionToken: true,
126
+ type: createTypeReferenceNode(createIdentifier(identifier), void 0)
127
+ }));
128
+ } else dataRequestProperties.push(createPropertySignature({
129
+ name: "queryParams",
130
+ questionToken: true,
131
+ type: keywordTypeNodes.never
132
+ }));
133
+ if (schemas.headerParams) {
134
+ const identifier = pluginManager.resolveName({
135
+ name: schemas.headerParams.name,
136
+ pluginName: pluginTsName,
137
+ type: "type"
138
+ });
139
+ dataRequestProperties.push(createPropertySignature({
140
+ name: "headerParams",
141
+ questionToken: true,
142
+ type: createTypeReferenceNode(createIdentifier(identifier), void 0)
143
+ }));
144
+ } else dataRequestProperties.push(createPropertySignature({
145
+ name: "headerParams",
146
+ questionToken: true,
147
+ type: keywordTypeNodes.never
148
+ }));
149
+ dataRequestProperties.push(createPropertySignature({
150
+ name: "url",
151
+ type: createUrlTemplateType(operation.path)
152
+ }));
153
+ const dataRequestNode = createTypeAliasDeclaration({
154
+ name,
155
+ type: createTypeLiteralNode(dataRequestProperties),
156
+ modifiers: [modifiers.export]
157
+ });
158
+ results.push(safePrint(dataRequestNode));
159
+ return results.join("\n\n");
160
+ }
161
+ function printResponseSchema({ baseName, schemas, pluginManager, unknownType }) {
162
+ const results = [];
163
+ const name = pluginManager.resolveName({
164
+ name: `${baseName} ResponseData`,
165
+ pluginName: pluginTsName,
166
+ type: "type"
167
+ });
168
+ if (schemas.responses && schemas.responses.length > 0) {
169
+ const responsesProperties = schemas.responses.map((res) => {
170
+ const identifier = pluginManager.resolveName({
171
+ name: res.name,
172
+ pluginName: pluginTsName,
173
+ type: "type"
174
+ });
175
+ return createPropertySignature({
176
+ name: res.statusCode?.toString() ?? "default",
177
+ type: createTypeReferenceNode(createIdentifier(identifier), void 0)
178
+ });
179
+ });
180
+ const responsesNode = createTypeAliasDeclaration({
181
+ name: `${baseName}Responses`,
182
+ type: createTypeLiteralNode(responsesProperties),
183
+ modifiers: [modifiers.export]
184
+ });
185
+ results.push(safePrint(responsesNode));
186
+ const responseNode = createTypeAliasDeclaration({
187
+ name,
188
+ type: createIndexedAccessTypeNode(createTypeReferenceNode(createIdentifier(`${baseName}Responses`), void 0), createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, createTypeReferenceNode(createIdentifier(`${baseName}Responses`), void 0))),
189
+ modifiers: [modifiers.export]
190
+ });
191
+ results.push(safePrint(responseNode));
192
+ } else {
193
+ const responseNode = createTypeAliasDeclaration({
194
+ name,
195
+ modifiers: [modifiers.export],
196
+ type: getUnknownType(unknownType)
197
+ });
198
+ results.push(safePrint(responseNode));
199
+ }
200
+ return results.join("\n\n");
201
+ }
202
+ const typeGenerator$1 = createReactGenerator({
203
+ name: "typescript",
204
+ version: "1",
205
+ Operation({ operation, generator, plugin }) {
206
+ const { options, options: { mapper, enumType, enumKeyCasing, syntaxType, optionalType, arrayType, unknownType, paramsCasing } } = plugin;
207
+ const mode = useMode();
208
+ const pluginManager = usePluginManager();
209
+ const oas = useOas();
210
+ const { getSchemas, getFile, getName, getGroup } = useOperationManager(generator);
211
+ const schemaManager = useSchemaManager();
212
+ const name = getName(operation, {
213
+ type: "type",
214
+ pluginName: pluginTsName
215
+ });
216
+ const file = getFile(operation);
217
+ const schemas = getSchemas(operation);
218
+ const schemaGenerator = new SchemaGenerator(options, {
219
+ fabric: generator.context.fabric,
220
+ oas,
221
+ events: generator.context.events,
222
+ plugin,
223
+ pluginManager,
224
+ mode,
225
+ override: options.override
226
+ });
227
+ const operationSchemas = [
228
+ schemas.pathParams,
229
+ schemas.queryParams,
230
+ schemas.headerParams,
231
+ schemas.statusCodes,
232
+ schemas.request,
233
+ schemas.response
234
+ ].flat().filter(Boolean);
235
+ const mapOperationSchema = ({ name, schema, description, keysToOmit, ...options }) => {
236
+ const transformedSchema = paramsCasing && isParameterSchema(name) ? applyParamsCasing(schema, paramsCasing) : schema;
237
+ const tree = schemaGenerator.parse({
238
+ schema: transformedSchema,
239
+ name,
240
+ parentName: null
241
+ });
242
+ const imports = getImports(tree);
243
+ const group = options.operation ? getGroup(options.operation) : void 0;
244
+ const type = {
245
+ name: schemaManager.getName(name, { type: "type" }),
246
+ typedName: schemaManager.getName(name, { type: "type" }),
247
+ file: schemaManager.getFile(options.operationName || name, { group })
248
+ };
249
+ return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
250
+ root: file.path,
251
+ path: imp.path,
252
+ name: imp.name,
253
+ isTypeOnly: true
254
+ }, [
255
+ name,
256
+ imp.name,
257
+ imp.path,
258
+ imp.isTypeOnly
259
+ ].join("-"))), /* @__PURE__ */ jsx(Type$1, {
260
+ name: type.name,
261
+ typedName: type.typedName,
262
+ description,
263
+ tree,
264
+ schema: transformedSchema,
265
+ mapper,
266
+ enumType,
267
+ enumKeyCasing,
268
+ optionalType,
269
+ arrayType,
270
+ keysToOmit,
271
+ syntaxType
272
+ })] });
273
+ };
274
+ const responseName = schemaManager.getName(schemas.response.name, { type: "type" });
275
+ const combinedSchemaName = operation.method === "get" ? `${name}Query` : `${name}Mutation`;
276
+ return /* @__PURE__ */ jsxs(File, {
277
+ baseName: file.baseName,
278
+ path: file.path,
279
+ meta: file.meta,
280
+ banner: getBanner({
281
+ oas,
282
+ output: plugin.options.output,
283
+ config: pluginManager.config
284
+ }),
285
+ footer: getFooter({
286
+ oas,
287
+ output: plugin.options.output
288
+ }),
289
+ children: [operationSchemas.map(mapOperationSchema), generator.context.UNSTABLE_NAMING ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File.Source, {
290
+ name: `${name}Request`,
291
+ isExportable: true,
292
+ isIndexable: true,
293
+ isTypeOnly: true,
294
+ children: printRequestSchema({
295
+ baseName: name,
296
+ operation,
297
+ schemas,
298
+ pluginManager
299
+ })
300
+ }), /* @__PURE__ */ jsx(File.Source, {
301
+ name: responseName,
302
+ isExportable: true,
303
+ isIndexable: true,
304
+ isTypeOnly: true,
305
+ children: printResponseSchema({
306
+ baseName: name,
307
+ schemas,
308
+ pluginManager,
309
+ unknownType
310
+ })
311
+ })] }) : /* @__PURE__ */ jsx(File.Source, {
312
+ name: combinedSchemaName,
313
+ isExportable: true,
314
+ isIndexable: true,
315
+ isTypeOnly: true,
316
+ children: printCombinedSchema({
317
+ name: combinedSchemaName,
318
+ schemas,
319
+ pluginManager
320
+ })
321
+ })]
322
+ });
323
+ },
324
+ Schema({ schema, plugin }) {
325
+ const { options: { mapper, enumType, enumKeyCasing, syntaxType, optionalType, arrayType, output } } = plugin;
326
+ const mode = useMode();
327
+ const oas = useOas();
328
+ const pluginManager = usePluginManager();
329
+ const { getName, getFile } = useSchemaManager();
330
+ const imports = getImports(schema.tree);
331
+ const schemaFromTree = schema.tree.find((item) => item.keyword === schemaKeywords.schema);
332
+ let typedName = getName(schema.name, { type: "type" });
333
+ if (["asConst", "asPascalConst"].includes(enumType) && schemaFromTree && isKeyword(schemaFromTree, schemaKeywords.enum)) typedName = typedName += "Key";
334
+ const type = {
335
+ name: getName(schema.name, { type: "function" }),
336
+ typedName,
337
+ file: getFile(schema.name)
338
+ };
339
+ return /* @__PURE__ */ jsxs(File, {
340
+ baseName: type.file.baseName,
341
+ path: type.file.path,
342
+ meta: type.file.meta,
343
+ banner: getBanner({
344
+ oas,
345
+ output,
346
+ config: pluginManager.config
347
+ }),
348
+ footer: getFooter({
349
+ oas,
350
+ output
351
+ }),
352
+ children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
353
+ root: type.file.path,
354
+ path: imp.path,
355
+ name: imp.name,
356
+ isTypeOnly: true
357
+ }, [
358
+ schema.name,
359
+ imp.path,
360
+ imp.isTypeOnly
361
+ ].join("-"))), /* @__PURE__ */ jsx(Type$1, {
362
+ name: type.name,
363
+ typedName: type.typedName,
364
+ description: schema.value.description,
365
+ tree: schema.tree,
366
+ schema: schema.value,
367
+ mapper,
368
+ enumType,
369
+ enumKeyCasing,
370
+ optionalType,
371
+ arrayType,
372
+ syntaxType
373
+ })]
374
+ });
375
+ }
376
+ });
377
+ //#endregion
378
+ //#region src/printer.ts
379
+ function constToTypeNode(value, format) {
380
+ if (format === "boolean") return createLiteralTypeNode(value === true ? createTrue() : createFalse());
381
+ if (format === "number" && typeof value === "number") {
382
+ if (value < 0) return createLiteralTypeNode(createPrefixUnaryExpression(SyntaxKind.MinusToken, createNumericLiteral(Math.abs(value))));
383
+ return createLiteralTypeNode(createNumericLiteral(value));
384
+ }
385
+ return createLiteralTypeNode(createStringLiteral(String(value)));
386
+ }
387
+ function dateOrStringNode(node) {
388
+ return node.representation === "date" ? createTypeReferenceNode(createIdentifier("Date")) : keywordTypeNodes.string;
389
+ }
390
+ function buildMemberNodes(members, print) {
391
+ return (members ?? []).map(print).filter(Boolean);
392
+ }
393
+ function buildTupleNode(node, print) {
394
+ let items = (node.items ?? []).map(print).filter(Boolean);
395
+ const restNode = node.rest ? print(node.rest) ?? void 0 : void 0;
396
+ const { min, max } = node;
397
+ if (max !== void 0) {
398
+ items = items.slice(0, max);
399
+ if (items.length < max && restNode) items = [...items, ...Array(max - items.length).fill(restNode)];
400
+ }
401
+ if (min !== void 0) items = items.map((item, i) => i >= min ? createOptionalTypeNode(item) : item);
402
+ if (max === void 0 && restNode) items.push(createRestTypeNode(createArrayTypeNode(restNode)));
403
+ return createTupleTypeNode(items);
404
+ }
405
+ function buildPropertyType(schema, baseType, optionalType) {
406
+ const addsUndefined = ["undefined", "questionTokenAndUndefined"].includes(optionalType);
407
+ let type = baseType;
408
+ if (schema.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
409
+ if ((schema.nullish || schema.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
410
+ return type;
411
+ }
412
+ function buildPropertyJSDocComments(schema) {
413
+ return [
414
+ "description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
415
+ "deprecated" in schema && schema.deprecated ? "@deprecated" : void 0,
416
+ "min" in schema && schema.min !== void 0 ? `@minLength ${schema.min}` : void 0,
417
+ "max" in schema && schema.max !== void 0 ? `@maxLength ${schema.max}` : void 0,
418
+ "pattern" in schema && schema.pattern ? `@pattern ${schema.pattern}` : void 0,
419
+ "default" in schema && schema.default !== void 0 ? `@default ${"primitive" in schema && schema.primitive === "string" ? stringify(schema.default) : schema.default}` : void 0,
420
+ "example" in schema && schema.example !== void 0 ? `@example ${schema.example}` : void 0,
421
+ "primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
422
+ ];
423
+ }
424
+ function buildIndexSignatures(node, propertyCount, print) {
425
+ const elements = [];
426
+ if (node.additionalProperties && node.additionalProperties !== true) {
427
+ const additionalType = print(node.additionalProperties) ?? keywordTypeNodes.unknown;
428
+ elements.push(createIndexSignature(propertyCount > 0 ? keywordTypeNodes.unknown : additionalType));
429
+ } else if (node.additionalProperties === true) elements.push(createIndexSignature(keywordTypeNodes.unknown));
430
+ if (node.patternProperties) {
431
+ const first = Object.values(node.patternProperties)[0];
432
+ if (first) {
433
+ let patternType = print(first) ?? keywordTypeNodes.unknown;
434
+ if (first.nullable) patternType = createUnionDeclaration({ nodes: [patternType, keywordTypeNodes.null] });
435
+ elements.push(createIndexSignature(patternType));
436
+ }
437
+ }
438
+ return elements;
439
+ }
440
+ /**
441
+ * Converts a `SchemaNode` AST node into a TypeScript `ts.TypeNode`.
442
+ *
443
+ * Built on `definePrinter` — dispatches on `node.type`, with options closed over
444
+ * per printer instance. Produces the same `ts.TypeNode` output as the keyword-based
445
+ * `parse` in `parser.ts`.
446
+ */
447
+ const printerTs = definePrinter((options) => ({
448
+ name: "typescript",
449
+ options,
450
+ nodes: {
451
+ any: () => keywordTypeNodes.any,
452
+ unknown: () => keywordTypeNodes.unknown,
453
+ void: () => keywordTypeNodes.void,
454
+ boolean: () => keywordTypeNodes.boolean,
455
+ null: () => keywordTypeNodes.null,
456
+ blob: () => createTypeReferenceNode("Blob", []),
457
+ string: () => keywordTypeNodes.string,
458
+ uuid: () => keywordTypeNodes.string,
459
+ email: () => keywordTypeNodes.string,
460
+ url: () => keywordTypeNodes.string,
461
+ datetime: () => keywordTypeNodes.string,
462
+ number: () => keywordTypeNodes.number,
463
+ integer: () => keywordTypeNodes.number,
464
+ bigint: () => keywordTypeNodes.bigint,
465
+ date: (node) => dateOrStringNode(node),
466
+ time: (node) => dateOrStringNode(node),
467
+ ref(node) {
468
+ if (!node.name) return;
469
+ return createTypeReferenceNode(node.name, void 0);
470
+ },
471
+ enum(node) {
472
+ const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
473
+ if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
474
+ withParentheses: true,
475
+ nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string")).filter(Boolean)
476
+ }) ?? void 0;
477
+ return createTypeReferenceNode(["asConst", "asPascalConst"].includes(this.options.enumType) ? `${node.name}Key` : node.name, void 0);
478
+ },
479
+ union(node) {
480
+ const members = node.members ?? [];
481
+ const hasStringLiteral = members.some((m) => m.type === "enum" && m.enumType === "string");
482
+ const hasPlainString = members.some((m) => isPlainStringType(m));
483
+ if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
484
+ withParentheses: true,
485
+ nodes: members.map((m) => {
486
+ if (isPlainStringType(m)) return createIntersectionDeclaration({
487
+ nodes: [keywordTypeNodes.string, createTypeLiteralNode([])],
488
+ withParentheses: true
489
+ });
490
+ return this.print(m);
491
+ }).filter(Boolean)
492
+ }) ?? void 0;
493
+ return createUnionDeclaration({
494
+ withParentheses: true,
495
+ nodes: buildMemberNodes(members, this.print)
496
+ }) ?? void 0;
497
+ },
498
+ intersection(node) {
499
+ return createIntersectionDeclaration({
500
+ withParentheses: true,
501
+ nodes: buildMemberNodes(node.members, this.print)
502
+ }) ?? void 0;
503
+ },
504
+ array(node) {
505
+ return createArrayDeclaration({
506
+ nodes: (node.items ?? []).map((item) => this.print(item)).filter(Boolean),
507
+ arrayType: this.options.arrayType
508
+ }) ?? void 0;
509
+ },
510
+ tuple(node) {
511
+ return buildTupleNode(node, this.print);
512
+ },
513
+ object(node) {
514
+ const addsQuestionToken = ["questionToken", "questionTokenAndUndefined"].includes(this.options.optionalType);
515
+ const { print } = this;
516
+ const propertyNodes = node.properties.map((prop) => {
517
+ const baseType = print(prop.schema) ?? keywordTypeNodes.unknown;
518
+ const type = buildPropertyType(prop.schema, baseType, this.options.optionalType);
519
+ return appendJSDocToNode({
520
+ node: createPropertySignature({
521
+ questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
522
+ name: prop.name,
523
+ type,
524
+ readOnly: prop.schema.readOnly
525
+ }),
526
+ comments: buildPropertyJSDocComments(prop.schema)
527
+ });
528
+ });
529
+ const allElements = [...propertyNodes, ...buildIndexSignatures(node, propertyNodes.length, print)];
530
+ if (!allElements.length) return keywordTypeNodes.object;
531
+ return createTypeLiteralNode(allElements);
532
+ }
533
+ }
534
+ }));
535
+ //#endregion
536
+ //#region src/components/v2/Type.tsx
537
+ function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumKeyCasing, ...rest }) {
538
+ const typeNodes = [];
539
+ const description = rest.description || node?.description;
540
+ const enumSchemaNodes = collect(node, { schema(n) {
541
+ if (n.type === "enum" && n.name) return n;
542
+ } });
543
+ let type = printerTs({
544
+ optionalType,
545
+ arrayType,
546
+ enumType
547
+ }).print(node);
548
+ if (!type) return;
549
+ if (["asConst", "asPascalConst"].includes(enumType) && enumSchemaNodes.length > 0) {
550
+ const isDirectEnum = node.type === "array" && node.items !== void 0;
551
+ const isEnumOnly = "enum" in node && node.enum;
552
+ if (isDirectEnum || isEnumOnly) {
553
+ type = createTypeReferenceNode(`${enumSchemaNodes[0].name}Key`);
554
+ if (isDirectEnum) if (arrayType === "generic") type = createTypeReferenceNode(createIdentifier("Array"), [type]);
555
+ else type = createArrayTypeNode(type);
556
+ }
557
+ }
558
+ if (node) {
559
+ if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
560
+ if (node.nullish && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
561
+ if (node.optional && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
562
+ }
563
+ const useTypeGeneration = syntaxType === "type" || [syntaxKind.union].includes(type.kind) || !!keysToOmit?.length;
564
+ typeNodes.push(createTypeDeclaration({
565
+ name,
566
+ isExportable: true,
567
+ type: keysToOmit?.length ? createOmitDeclaration({
568
+ keys: keysToOmit,
569
+ type,
570
+ nonNullable: true
571
+ }) : type,
572
+ syntax: useTypeGeneration ? "type" : "interface",
573
+ comments: [
574
+ node?.title ? `${jsStringEscape(node.title)}` : void 0,
575
+ description ? `@description ${jsStringEscape(description)}` : void 0,
576
+ node?.deprecated ? "@deprecated" : void 0,
577
+ node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
578
+ node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
579
+ node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
580
+ node?.default ? `@default ${node.default}` : void 0,
581
+ node?.example ? `@example ${node.example}` : void 0
582
+ ]
583
+ }));
584
+ const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((enumSchemaNode) => {
585
+ const enumName = enumType === "asPascalConst" ? pascalCase(enumSchemaNode.name) : camelCase(enumSchemaNode.name);
586
+ const typeName = ["asConst", "asPascalConst"].includes(enumType) ? `${enumSchemaNode.name}Key` : enumSchemaNode.name;
587
+ const [nameNode, typeNode] = createEnumDeclaration({
588
+ name: enumName,
589
+ typeName,
590
+ enums: enumSchemaNode.namedEnumValues?.map((v) => [trimQuotes(v.name.toString()), v.value]) ?? enumSchemaNode.enumValues?.filter((v) => v !== null && v !== void 0).map((v) => [trimQuotes(v.toString()), v]) ?? [],
591
+ type: enumType,
592
+ enumKeyCasing
593
+ });
594
+ return {
595
+ nameNode,
596
+ typeNode,
597
+ name: enumName,
598
+ typeName
599
+ };
600
+ });
601
+ const shouldExportEnums = enumType !== "inlineLiteral";
602
+ const shouldExportType = enumType === "inlineLiteral" || enums.every((item) => item.typeName !== name);
603
+ return /* @__PURE__ */ jsxs(Fragment, { children: [shouldExportEnums && enums.map(({ name: enumName, nameNode, typeName, typeNode }) => /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
604
+ name: enumName,
605
+ isExportable: true,
606
+ isIndexable: true,
607
+ isTypeOnly: false,
608
+ children: safePrint(nameNode)
609
+ }), /* @__PURE__ */ jsx(File.Source, {
610
+ name: typeName,
611
+ isIndexable: true,
612
+ isExportable: [
613
+ "enum",
614
+ "asConst",
615
+ "asPascalConst",
616
+ "constEnum",
617
+ "literal",
618
+ void 0
619
+ ].includes(enumType),
620
+ isTypeOnly: [
621
+ "asConst",
622
+ "asPascalConst",
623
+ "literal",
624
+ void 0
625
+ ].includes(enumType),
626
+ children: safePrint(typeNode)
627
+ })] })), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
628
+ name: typedName,
629
+ isTypeOnly: true,
630
+ isExportable: true,
631
+ isIndexable: true,
632
+ children: safePrint(...typeNodes)
633
+ })] });
634
+ }
635
+ //#endregion
636
+ //#region src/generators/v2/typeGenerator.tsx
637
+ const typeGenerator = createReactGenerator({
638
+ name: "typescript",
639
+ version: "2",
640
+ Operation({ node, adapter, options }) {
641
+ const { enumType, enumKeyCasing, optionalType, arrayType, syntaxType } = options;
642
+ const { plugin, mode, getFile, resolveName } = useKubb();
643
+ const file = getFile({
644
+ name: node.operationId,
645
+ pluginName: plugin.name,
646
+ extname: ".ts",
647
+ mode
648
+ });
649
+ function renderSchemaType({ node: schemaNode, name, typedName, description }) {
650
+ const imports = adapter.getImports(schemaNode, (schemaName) => ({
651
+ name: resolveName({
652
+ name: schemaName,
653
+ pluginName: plugin.name,
654
+ type: "type"
655
+ }),
656
+ path: getFile({
657
+ name: schemaName,
658
+ pluginName: plugin.name,
659
+ extname: ".ts",
660
+ mode
661
+ }).path
662
+ }));
663
+ return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
664
+ root: file.path,
665
+ path: imp.path,
666
+ name: imp.name,
667
+ isTypeOnly: true
668
+ }, [
669
+ name,
670
+ imp.path,
671
+ imp.isTypeOnly
672
+ ].join("-"))), /* @__PURE__ */ jsx(Type, {
673
+ name,
674
+ typedName,
675
+ node: schemaNode,
676
+ description,
677
+ enumType,
678
+ enumKeyCasing,
679
+ optionalType,
680
+ arrayType,
681
+ syntaxType
682
+ })] });
683
+ }
684
+ const paramTypes = node.parameters.map((param) => {
685
+ const name = resolveName({
686
+ name: `${node.operationId} ${param.name}`,
687
+ pluginName: plugin.name,
688
+ type: "function"
689
+ });
690
+ const typedName = resolveName({
691
+ name: `${node.operationId} ${param.name}`,
692
+ pluginName: plugin.name,
693
+ type: "type"
694
+ });
695
+ return renderSchemaType({
696
+ node: param.schema,
697
+ name,
698
+ typedName
699
+ });
700
+ });
701
+ const responseTypes = node.responses.filter((res) => res.schema).map((res) => {
702
+ const schemaNode = res.schema;
703
+ const responseName = `${node.operationId} ${res.statusCode}`;
704
+ return renderSchemaType({
705
+ node: schemaNode,
706
+ name: resolveName({
707
+ name: responseName,
708
+ pluginName: plugin.name,
709
+ type: "function"
710
+ }),
711
+ typedName: resolveName({
712
+ name: responseName,
713
+ pluginName: plugin.name,
714
+ type: "type"
715
+ }),
716
+ description: res.description
717
+ });
718
+ });
719
+ const requestType = node.requestBody ? (() => {
720
+ const requestName = `${node.operationId} MutationRequest`;
721
+ const resolvedName = resolveName({
722
+ name: requestName,
723
+ pluginName: plugin.name,
724
+ type: "function"
725
+ });
726
+ const typedName = resolveName({
727
+ name: requestName,
728
+ pluginName: plugin.name,
729
+ type: "type"
730
+ });
731
+ return renderSchemaType({
732
+ node: node.requestBody,
733
+ name: resolvedName,
734
+ typedName,
735
+ description: node.requestBody.description
736
+ });
737
+ })() : null;
738
+ return /* @__PURE__ */ jsxs(File, {
739
+ baseName: file.baseName,
740
+ path: file.path,
741
+ meta: file.meta,
742
+ children: [
743
+ paramTypes,
744
+ responseTypes,
745
+ requestType
746
+ ]
747
+ });
748
+ },
749
+ Schema({ node, adapter, options }) {
750
+ const { enumType, enumKeyCasing, syntaxType, optionalType, arrayType } = options;
751
+ const { plugin, mode, resolveName, getFile } = useKubb();
752
+ if (!node.name) return;
753
+ const imports = adapter.getImports(node, (schemaName) => ({
754
+ name: resolveName({
755
+ name: schemaName,
756
+ pluginName: plugin.name,
757
+ type: "type"
758
+ }),
759
+ path: getFile({
760
+ name: schemaName,
761
+ pluginName: plugin.name,
762
+ extname: ".ts",
763
+ mode
764
+ }).path
765
+ }));
766
+ const isEnumSchema = node.type === "enum";
767
+ let typedName = resolveName({
768
+ name: node.name,
769
+ pluginName: plugin.name,
770
+ type: "type"
771
+ });
772
+ if (["asConst", "asPascalConst"].includes(enumType) && isEnumSchema) typedName = typedName += "Key";
773
+ const type = {
774
+ name: resolveName({
775
+ name: node.name,
776
+ pluginName: plugin.name,
777
+ type: "function"
778
+ }),
779
+ typedName,
780
+ file: getFile({
781
+ name: node.name,
782
+ pluginName: plugin.name,
783
+ extname: ".ts",
784
+ mode
785
+ })
786
+ };
787
+ return /* @__PURE__ */ jsxs(File, {
788
+ baseName: type.file.baseName,
789
+ path: type.file.path,
790
+ meta: type.file.meta,
791
+ children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
792
+ root: type.file.path,
793
+ path: imp.path,
794
+ name: imp.name,
795
+ isTypeOnly: true
796
+ }, [
797
+ node.name,
798
+ imp.path,
799
+ imp.isTypeOnly
800
+ ].join("-"))), /* @__PURE__ */ jsx(Type, {
801
+ name: type.name,
802
+ typedName: type.typedName,
803
+ node,
804
+ enumType,
805
+ enumKeyCasing,
806
+ optionalType,
807
+ arrayType,
808
+ syntaxType
809
+ })]
810
+ });
811
+ }
812
+ });
813
+ //#endregion
814
+ //#region src/plugin.ts
815
+ const pluginTsName = "plugin-ts";
816
+ const pluginTs = definePlugin((options) => {
817
+ const { output = {
818
+ path: "types",
819
+ barrelType: "named"
820
+ }, group, exclude = [], include, override = [], enumType = "asConst", enumKeyCasing = "none", enumSuffix = "enum", dateType = "string", integerType = "number", unknownType = "any", optionalType = "questionToken", arrayType = "array", emptySchemaType = unknownType, syntaxType = "type", transformers = {}, mapper = {}, paramsCasing, generators = [typeGenerator$1, typeGenerator].filter(Boolean), contentType, UNSTABLE_NAMING } = options;
821
+ return {
822
+ name: pluginTsName,
823
+ options: {
824
+ output,
825
+ transformers,
826
+ dateType,
827
+ integerType,
828
+ optionalType,
829
+ arrayType,
830
+ enumType,
831
+ enumKeyCasing,
832
+ enumSuffix,
833
+ unknownType,
834
+ emptySchemaType,
835
+ syntaxType,
836
+ group,
837
+ override,
838
+ mapper,
839
+ paramsCasing,
840
+ usedEnumNames: {}
841
+ },
842
+ pre: [pluginOasName],
843
+ resolvePath(baseName, pathMode, options) {
844
+ const root = path.resolve(this.config.root, this.config.output.path);
845
+ if ((pathMode ?? getMode(path.resolve(root, output.path))) === "single")
846
+ /**
847
+ * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
848
+ * Other plugins then need to call addOrAppend instead of just add from the fileManager class
849
+ */
850
+ return path.resolve(root, output.path);
851
+ if (group && (options?.group?.path || options?.group?.tag)) {
852
+ const groupName = group?.name ? group.name : (ctx) => {
853
+ if (group?.type === "path") return `${ctx.group.split("/")[1]}`;
854
+ return `${camelCase(ctx.group)}Controller`;
855
+ };
856
+ return path.resolve(root, output.path, groupName({ group: group.type === "path" ? options.group.path : options.group.tag }), baseName);
857
+ }
858
+ return path.resolve(root, output.path, baseName);
859
+ },
860
+ resolveName(name, type) {
861
+ const resolvedName = pascalCase(name, { isFile: type === "file" });
862
+ if (type) return transformers?.name?.(resolvedName, type) || resolvedName;
863
+ return resolvedName;
864
+ },
865
+ async install() {
866
+ const { config, fabric, plugin, adapter, rootNode, pluginManager, openInStudio } = this;
867
+ const root = path.resolve(config.root, config.output.path);
868
+ const mode = getMode(path.resolve(root, output.path));
869
+ if (adapter) {
870
+ await openInStudio({ ast: true });
871
+ await walk(rootNode, {
872
+ async schema(schemaNode) {
873
+ await generators.map(async (generator) => {
874
+ if (generator.type === "react" && generator.version === "2") await buildSchema(schemaNode, {
875
+ adapter,
876
+ config,
877
+ fabric,
878
+ Component: generator.Schema,
879
+ plugin,
880
+ pluginManager,
881
+ mode,
882
+ version: generator.version
883
+ });
884
+ });
885
+ },
886
+ async operation(operationNode) {
887
+ await generators.map(async (generator) => {
888
+ if (generator.type === "react" && generator.version === "2") await buildOperation(operationNode, {
889
+ adapter,
890
+ config,
891
+ fabric,
892
+ Component: generator.Operation,
893
+ plugin,
894
+ pluginManager,
895
+ mode,
896
+ version: generator.version
897
+ });
898
+ });
899
+ }
900
+ }, { depth: "shallow" });
901
+ return;
902
+ }
903
+ const oas = await this.getOas();
904
+ const schemaFiles = await new SchemaGenerator(this.plugin.options, {
905
+ fabric: this.fabric,
906
+ oas,
907
+ pluginManager: this.pluginManager,
908
+ events: this.events,
909
+ plugin: this.plugin,
910
+ contentType,
911
+ include: void 0,
912
+ override,
913
+ mode,
914
+ output: output.path
915
+ }).build(...generators);
916
+ await this.upsertFile(...schemaFiles);
917
+ const operationFiles = await new OperationGenerator(this.plugin.options, {
918
+ fabric: this.fabric,
919
+ oas,
920
+ pluginManager: this.pluginManager,
921
+ events: this.events,
922
+ plugin: this.plugin,
923
+ contentType,
924
+ exclude,
925
+ include,
926
+ override,
927
+ mode,
928
+ UNSTABLE_NAMING
929
+ }).build(...generators);
930
+ await this.upsertFile(...operationFiles);
931
+ const barrelFiles = await getBarrelFiles(this.fabric.files, {
932
+ type: output.barrelType ?? "named",
933
+ root,
934
+ output,
935
+ meta: { pluginName: this.plugin.name }
936
+ });
937
+ await this.upsertFile(...barrelFiles);
938
+ }
939
+ };
940
+ });
941
+ //#endregion
942
+ export { typeGenerator$1 as i, pluginTsName as n, typeGenerator as r, pluginTs as t };
943
+
944
+ //# sourceMappingURL=plugin-DmwgRHK8.js.map