@kubb/plugin-ts 5.0.0-alpha.2 → 5.0.0-alpha.4

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,965 @@
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 { defineGenerator, definePlugin, definePrinter, getBarrelFiles, getMode, resolveOptions } 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
+ Operation({ operation, generator, plugin }) {
205
+ const { options, options: { mapper, enumType, enumKeyCasing, syntaxType, optionalType, arrayType, unknownType, paramsCasing } } = plugin;
206
+ const mode = useMode();
207
+ const pluginManager = usePluginManager();
208
+ const oas = useOas();
209
+ const { getSchemas, getFile, getName, getGroup } = useOperationManager(generator);
210
+ const schemaManager = useSchemaManager();
211
+ const name = getName(operation, {
212
+ type: "type",
213
+ pluginName: pluginTsName
214
+ });
215
+ const file = getFile(operation);
216
+ const schemas = getSchemas(operation);
217
+ const schemaGenerator = new SchemaGenerator(options, {
218
+ fabric: generator.context.fabric,
219
+ oas,
220
+ events: generator.context.events,
221
+ plugin,
222
+ pluginManager,
223
+ mode,
224
+ override: options.override
225
+ });
226
+ const operationSchemas = [
227
+ schemas.pathParams,
228
+ schemas.queryParams,
229
+ schemas.headerParams,
230
+ schemas.statusCodes,
231
+ schemas.request,
232
+ schemas.response
233
+ ].flat().filter(Boolean);
234
+ const mapOperationSchema = ({ name, schema, description, keysToOmit, ...options }) => {
235
+ const transformedSchema = paramsCasing && isParameterSchema(name) ? applyParamsCasing(schema, paramsCasing) : schema;
236
+ const tree = schemaGenerator.parse({
237
+ schema: transformedSchema,
238
+ name,
239
+ parentName: null
240
+ });
241
+ const imports = getImports(tree);
242
+ const group = options.operation ? getGroup(options.operation) : void 0;
243
+ const type = {
244
+ name: schemaManager.getName(name, { type: "type" }),
245
+ typedName: schemaManager.getName(name, { type: "type" }),
246
+ file: schemaManager.getFile(options.operationName || name, { group })
247
+ };
248
+ return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
249
+ root: file.path,
250
+ path: imp.path,
251
+ name: imp.name,
252
+ isTypeOnly: true
253
+ }, [
254
+ name,
255
+ imp.name,
256
+ imp.path,
257
+ imp.isTypeOnly
258
+ ].join("-"))), /* @__PURE__ */ jsx(Type$1, {
259
+ name: type.name,
260
+ typedName: type.typedName,
261
+ description,
262
+ tree,
263
+ schema: transformedSchema,
264
+ mapper,
265
+ enumType,
266
+ enumKeyCasing,
267
+ optionalType,
268
+ arrayType,
269
+ keysToOmit,
270
+ syntaxType
271
+ })] });
272
+ };
273
+ const responseName = schemaManager.getName(schemas.response.name, { type: "type" });
274
+ const combinedSchemaName = operation.method === "get" ? `${name}Query` : `${name}Mutation`;
275
+ return /* @__PURE__ */ jsxs(File, {
276
+ baseName: file.baseName,
277
+ path: file.path,
278
+ meta: file.meta,
279
+ banner: getBanner({
280
+ oas,
281
+ output: plugin.options.output,
282
+ config: pluginManager.config
283
+ }),
284
+ footer: getFooter({
285
+ oas,
286
+ output: plugin.options.output
287
+ }),
288
+ children: [operationSchemas.map(mapOperationSchema), generator.context.UNSTABLE_NAMING ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File.Source, {
289
+ name: `${name}Request`,
290
+ isExportable: true,
291
+ isIndexable: true,
292
+ isTypeOnly: true,
293
+ children: printRequestSchema({
294
+ baseName: name,
295
+ operation,
296
+ schemas,
297
+ pluginManager
298
+ })
299
+ }), /* @__PURE__ */ jsx(File.Source, {
300
+ name: responseName,
301
+ isExportable: true,
302
+ isIndexable: true,
303
+ isTypeOnly: true,
304
+ children: printResponseSchema({
305
+ baseName: name,
306
+ schemas,
307
+ pluginManager,
308
+ unknownType
309
+ })
310
+ })] }) : /* @__PURE__ */ jsx(File.Source, {
311
+ name: combinedSchemaName,
312
+ isExportable: true,
313
+ isIndexable: true,
314
+ isTypeOnly: true,
315
+ children: printCombinedSchema({
316
+ name: combinedSchemaName,
317
+ schemas,
318
+ pluginManager
319
+ })
320
+ })]
321
+ });
322
+ },
323
+ Schema({ schema, plugin }) {
324
+ const { options: { mapper, enumType, enumKeyCasing, syntaxType, optionalType, arrayType, output } } = plugin;
325
+ const mode = useMode();
326
+ const oas = useOas();
327
+ const pluginManager = usePluginManager();
328
+ const { getName, getFile } = useSchemaManager();
329
+ const imports = getImports(schema.tree);
330
+ const schemaFromTree = schema.tree.find((item) => item.keyword === schemaKeywords.schema);
331
+ let typedName = getName(schema.name, { type: "type" });
332
+ if (["asConst", "asPascalConst"].includes(enumType) && schemaFromTree && isKeyword(schemaFromTree, schemaKeywords.enum)) typedName = typedName += "Key";
333
+ const type = {
334
+ name: getName(schema.name, { type: "function" }),
335
+ typedName,
336
+ file: getFile(schema.name)
337
+ };
338
+ return /* @__PURE__ */ jsxs(File, {
339
+ baseName: type.file.baseName,
340
+ path: type.file.path,
341
+ meta: type.file.meta,
342
+ banner: getBanner({
343
+ oas,
344
+ output,
345
+ config: pluginManager.config
346
+ }),
347
+ footer: getFooter({
348
+ oas,
349
+ output
350
+ }),
351
+ children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
352
+ root: type.file.path,
353
+ path: imp.path,
354
+ name: imp.name,
355
+ isTypeOnly: true
356
+ }, [
357
+ schema.name,
358
+ imp.path,
359
+ imp.isTypeOnly
360
+ ].join("-"))), /* @__PURE__ */ jsx(Type$1, {
361
+ name: type.name,
362
+ typedName: type.typedName,
363
+ description: schema.value.description,
364
+ tree: schema.tree,
365
+ schema: schema.value,
366
+ mapper,
367
+ enumType,
368
+ enumKeyCasing,
369
+ optionalType,
370
+ arrayType,
371
+ syntaxType
372
+ })]
373
+ });
374
+ }
375
+ });
376
+ //#endregion
377
+ //#region src/printer.ts
378
+ function constToTypeNode(value, format) {
379
+ if (format === "boolean") return createLiteralTypeNode(value === true ? createTrue() : createFalse());
380
+ if (format === "number" && typeof value === "number") {
381
+ if (value < 0) return createLiteralTypeNode(createPrefixUnaryExpression(SyntaxKind.MinusToken, createNumericLiteral(Math.abs(value))));
382
+ return createLiteralTypeNode(createNumericLiteral(value));
383
+ }
384
+ return createLiteralTypeNode(createStringLiteral(String(value)));
385
+ }
386
+ function dateOrStringNode(node) {
387
+ return node.representation === "date" ? createTypeReferenceNode(createIdentifier("Date")) : keywordTypeNodes.string;
388
+ }
389
+ function buildMemberNodes(members, print) {
390
+ return (members ?? []).map(print).filter(Boolean);
391
+ }
392
+ function buildTupleNode(node, print) {
393
+ let items = (node.items ?? []).map(print).filter(Boolean);
394
+ const restNode = node.rest ? print(node.rest) ?? void 0 : void 0;
395
+ const { min, max } = node;
396
+ if (max !== void 0) {
397
+ items = items.slice(0, max);
398
+ if (items.length < max && restNode) items = [...items, ...Array(max - items.length).fill(restNode)];
399
+ }
400
+ if (min !== void 0) items = items.map((item, i) => i >= min ? createOptionalTypeNode(item) : item);
401
+ if (max === void 0 && restNode) items.push(createRestTypeNode(createArrayTypeNode(restNode)));
402
+ return createTupleTypeNode(items);
403
+ }
404
+ function buildPropertyType(schema, baseType, optionalType) {
405
+ const addsUndefined = ["undefined", "questionTokenAndUndefined"].includes(optionalType);
406
+ let type = baseType;
407
+ if (schema.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
408
+ if ((schema.nullish || schema.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
409
+ return type;
410
+ }
411
+ function buildPropertyJSDocComments(schema) {
412
+ return [
413
+ "description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
414
+ "deprecated" in schema && schema.deprecated ? "@deprecated" : void 0,
415
+ "min" in schema && schema.min !== void 0 ? `@minLength ${schema.min}` : void 0,
416
+ "max" in schema && schema.max !== void 0 ? `@maxLength ${schema.max}` : void 0,
417
+ "pattern" in schema && schema.pattern ? `@pattern ${schema.pattern}` : void 0,
418
+ "default" in schema && schema.default !== void 0 ? `@default ${"primitive" in schema && schema.primitive === "string" ? stringify(schema.default) : schema.default}` : void 0,
419
+ "example" in schema && schema.example !== void 0 ? `@example ${schema.example}` : void 0,
420
+ "primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
421
+ ];
422
+ }
423
+ function buildIndexSignatures(node, propertyCount, print) {
424
+ const elements = [];
425
+ if (node.additionalProperties && node.additionalProperties !== true) {
426
+ const additionalType = print(node.additionalProperties) ?? keywordTypeNodes.unknown;
427
+ elements.push(createIndexSignature(propertyCount > 0 ? keywordTypeNodes.unknown : additionalType));
428
+ } else if (node.additionalProperties === true) elements.push(createIndexSignature(keywordTypeNodes.unknown));
429
+ if (node.patternProperties) {
430
+ const first = Object.values(node.patternProperties)[0];
431
+ if (first) {
432
+ let patternType = print(first) ?? keywordTypeNodes.unknown;
433
+ if (first.nullable) patternType = createUnionDeclaration({ nodes: [patternType, keywordTypeNodes.null] });
434
+ elements.push(createIndexSignature(patternType));
435
+ }
436
+ }
437
+ return elements;
438
+ }
439
+ /**
440
+ * Converts a `SchemaNode` AST node into a TypeScript `ts.TypeNode`.
441
+ *
442
+ * Built on `definePrinter` — dispatches on `node.type`, with options closed over
443
+ * per printer instance. Produces the same `ts.TypeNode` output as the keyword-based
444
+ * `parse` in `parser.ts`.
445
+ */
446
+ const printerTs = definePrinter((options) => ({
447
+ name: "typescript",
448
+ options,
449
+ nodes: {
450
+ any: () => keywordTypeNodes.any,
451
+ unknown: () => keywordTypeNodes.unknown,
452
+ void: () => keywordTypeNodes.void,
453
+ boolean: () => keywordTypeNodes.boolean,
454
+ null: () => keywordTypeNodes.null,
455
+ blob: () => createTypeReferenceNode("Blob", []),
456
+ string: () => keywordTypeNodes.string,
457
+ uuid: () => keywordTypeNodes.string,
458
+ email: () => keywordTypeNodes.string,
459
+ url: () => keywordTypeNodes.string,
460
+ datetime: () => keywordTypeNodes.string,
461
+ number: () => keywordTypeNodes.number,
462
+ integer: () => keywordTypeNodes.number,
463
+ bigint: () => keywordTypeNodes.bigint,
464
+ date: (node) => dateOrStringNode(node),
465
+ time: (node) => dateOrStringNode(node),
466
+ ref(node) {
467
+ if (!node.name) return;
468
+ return createTypeReferenceNode(node.name, void 0);
469
+ },
470
+ enum(node) {
471
+ const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
472
+ if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
473
+ withParentheses: true,
474
+ nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string")).filter(Boolean)
475
+ }) ?? void 0;
476
+ return createTypeReferenceNode(["asConst", "asPascalConst"].includes(this.options.enumType) ? `${node.name}Key` : node.name, void 0);
477
+ },
478
+ union(node) {
479
+ const members = node.members ?? [];
480
+ const hasStringLiteral = members.some((m) => m.type === "enum" && m.enumType === "string");
481
+ const hasPlainString = members.some((m) => isPlainStringType(m));
482
+ if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
483
+ withParentheses: true,
484
+ nodes: members.map((m) => {
485
+ if (isPlainStringType(m)) return createIntersectionDeclaration({
486
+ nodes: [keywordTypeNodes.string, createTypeLiteralNode([])],
487
+ withParentheses: true
488
+ });
489
+ return this.print(m);
490
+ }).filter(Boolean)
491
+ }) ?? void 0;
492
+ return createUnionDeclaration({
493
+ withParentheses: true,
494
+ nodes: buildMemberNodes(members, this.print)
495
+ }) ?? void 0;
496
+ },
497
+ intersection(node) {
498
+ return createIntersectionDeclaration({
499
+ withParentheses: true,
500
+ nodes: buildMemberNodes(node.members, this.print)
501
+ }) ?? void 0;
502
+ },
503
+ array(node) {
504
+ return createArrayDeclaration({
505
+ nodes: (node.items ?? []).map((item) => this.print(item)).filter(Boolean),
506
+ arrayType: this.options.arrayType
507
+ }) ?? void 0;
508
+ },
509
+ tuple(node) {
510
+ return buildTupleNode(node, this.print);
511
+ },
512
+ object(node) {
513
+ const addsQuestionToken = ["questionToken", "questionTokenAndUndefined"].includes(this.options.optionalType);
514
+ const { print } = this;
515
+ const propertyNodes = node.properties.map((prop) => {
516
+ const baseType = print(prop.schema) ?? keywordTypeNodes.unknown;
517
+ const type = buildPropertyType(prop.schema, baseType, this.options.optionalType);
518
+ return appendJSDocToNode({
519
+ node: createPropertySignature({
520
+ questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
521
+ name: prop.name,
522
+ type,
523
+ readOnly: prop.schema.readOnly
524
+ }),
525
+ comments: buildPropertyJSDocComments(prop.schema)
526
+ });
527
+ });
528
+ const allElements = [...propertyNodes, ...buildIndexSignatures(node, propertyNodes.length, print)];
529
+ if (!allElements.length) return keywordTypeNodes.object;
530
+ return createTypeLiteralNode(allElements);
531
+ }
532
+ }
533
+ }));
534
+ //#endregion
535
+ //#region src/components/v2/Type.tsx
536
+ function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumKeyCasing, ...rest }) {
537
+ const typeNodes = [];
538
+ const description = rest.description || node?.description;
539
+ const enumSchemaNodes = collect(node, { schema(n) {
540
+ if (n.type === "enum" && n.name) return n;
541
+ } });
542
+ let type = printerTs({
543
+ optionalType,
544
+ arrayType,
545
+ enumType
546
+ }).print(node);
547
+ if (!type) return;
548
+ if (["asConst", "asPascalConst"].includes(enumType) && enumSchemaNodes.length > 0) {
549
+ const isDirectEnum = node.type === "array" && node.items !== void 0;
550
+ const isEnumOnly = "enum" in node && node.enum;
551
+ if (isDirectEnum || isEnumOnly) {
552
+ type = createTypeReferenceNode(`${enumSchemaNodes[0].name}Key`);
553
+ if (isDirectEnum) if (arrayType === "generic") type = createTypeReferenceNode(createIdentifier("Array"), [type]);
554
+ else type = createArrayTypeNode(type);
555
+ }
556
+ }
557
+ if (node) {
558
+ if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
559
+ if (node.nullish && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
560
+ if (node.optional && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
561
+ }
562
+ const useTypeGeneration = syntaxType === "type" || [syntaxKind.union].includes(type.kind) || !!keysToOmit?.length;
563
+ typeNodes.push(createTypeDeclaration({
564
+ name,
565
+ isExportable: true,
566
+ type: keysToOmit?.length ? createOmitDeclaration({
567
+ keys: keysToOmit,
568
+ type,
569
+ nonNullable: true
570
+ }) : type,
571
+ syntax: useTypeGeneration ? "type" : "interface",
572
+ comments: [
573
+ node?.title ? `${jsStringEscape(node.title)}` : void 0,
574
+ description ? `@description ${jsStringEscape(description)}` : void 0,
575
+ node?.deprecated ? "@deprecated" : void 0,
576
+ node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
577
+ node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
578
+ node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
579
+ node?.default ? `@default ${node.default}` : void 0,
580
+ node?.example ? `@example ${node.example}` : void 0
581
+ ]
582
+ }));
583
+ const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((enumSchemaNode) => {
584
+ const enumName = enumType === "asPascalConst" ? pascalCase(enumSchemaNode.name) : camelCase(enumSchemaNode.name);
585
+ const typeName = ["asConst", "asPascalConst"].includes(enumType) ? `${enumSchemaNode.name}Key` : enumSchemaNode.name;
586
+ const [nameNode, typeNode] = createEnumDeclaration({
587
+ name: enumName,
588
+ typeName,
589
+ 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]) ?? [],
590
+ type: enumType,
591
+ enumKeyCasing
592
+ });
593
+ return {
594
+ nameNode,
595
+ typeNode,
596
+ name: enumName,
597
+ typeName
598
+ };
599
+ });
600
+ const shouldExportEnums = enumType !== "inlineLiteral";
601
+ const shouldExportType = enumType === "inlineLiteral" || enums.every((item) => item.typeName !== name);
602
+ return /* @__PURE__ */ jsxs(Fragment, { children: [shouldExportEnums && enums.map(({ name: enumName, nameNode, typeName, typeNode }) => /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
603
+ name: enumName,
604
+ isExportable: true,
605
+ isIndexable: true,
606
+ isTypeOnly: false,
607
+ children: safePrint(nameNode)
608
+ }), /* @__PURE__ */ jsx(File.Source, {
609
+ name: typeName,
610
+ isIndexable: true,
611
+ isExportable: [
612
+ "enum",
613
+ "asConst",
614
+ "asPascalConst",
615
+ "constEnum",
616
+ "literal",
617
+ void 0
618
+ ].includes(enumType),
619
+ isTypeOnly: [
620
+ "asConst",
621
+ "asPascalConst",
622
+ "literal",
623
+ void 0
624
+ ].includes(enumType),
625
+ children: safePrint(typeNode)
626
+ })] })), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
627
+ name: typedName,
628
+ isTypeOnly: true,
629
+ isExportable: true,
630
+ isIndexable: true,
631
+ children: safePrint(...typeNodes)
632
+ })] });
633
+ }
634
+ //#endregion
635
+ //#region src/generators/v2/typeGenerator.tsx
636
+ const typeGenerator = defineGenerator({
637
+ name: "typescript",
638
+ type: "react",
639
+ Operation({ node, adapter, options }) {
640
+ const { enumType, enumKeyCasing, optionalType, arrayType, syntaxType } = options;
641
+ const { plugin, mode, getFile, resolveName } = useKubb();
642
+ const file = getFile({
643
+ name: node.operationId,
644
+ pluginName: plugin.name,
645
+ extname: ".ts",
646
+ mode
647
+ });
648
+ function renderSchemaType({ node: schemaNode, name, typedName, description }) {
649
+ const imports = adapter.getImports(schemaNode, (schemaName) => ({
650
+ name: resolveName({
651
+ name: schemaName,
652
+ pluginName: plugin.name,
653
+ type: "type"
654
+ }),
655
+ path: getFile({
656
+ name: schemaName,
657
+ pluginName: plugin.name,
658
+ extname: ".ts",
659
+ mode
660
+ }).path
661
+ }));
662
+ return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
663
+ root: file.path,
664
+ path: imp.path,
665
+ name: imp.name,
666
+ isTypeOnly: true
667
+ }, [
668
+ name,
669
+ imp.path,
670
+ imp.isTypeOnly
671
+ ].join("-"))), /* @__PURE__ */ jsx(Type, {
672
+ name,
673
+ typedName,
674
+ node: schemaNode,
675
+ description,
676
+ enumType,
677
+ enumKeyCasing,
678
+ optionalType,
679
+ arrayType,
680
+ syntaxType
681
+ })] });
682
+ }
683
+ const paramTypes = node.parameters.map((param) => {
684
+ const name = resolveName({
685
+ name: `${node.operationId} ${param.name}`,
686
+ pluginName: plugin.name,
687
+ type: "function"
688
+ });
689
+ const typedName = resolveName({
690
+ name: `${node.operationId} ${param.name}`,
691
+ pluginName: plugin.name,
692
+ type: "type"
693
+ });
694
+ return renderSchemaType({
695
+ node: param.schema,
696
+ name,
697
+ typedName
698
+ });
699
+ });
700
+ const responseTypes = node.responses.filter((res) => res.schema).map((res) => {
701
+ const schemaNode = res.schema;
702
+ const responseName = `${node.operationId} ${res.statusCode}`;
703
+ return renderSchemaType({
704
+ node: schemaNode,
705
+ name: resolveName({
706
+ name: responseName,
707
+ pluginName: plugin.name,
708
+ type: "function"
709
+ }),
710
+ typedName: resolveName({
711
+ name: responseName,
712
+ pluginName: plugin.name,
713
+ type: "type"
714
+ }),
715
+ description: res.description
716
+ });
717
+ });
718
+ const requestType = node.requestBody ? (() => {
719
+ const requestName = `${node.operationId} MutationRequest`;
720
+ const resolvedName = resolveName({
721
+ name: requestName,
722
+ pluginName: plugin.name,
723
+ type: "function"
724
+ });
725
+ const typedName = resolveName({
726
+ name: requestName,
727
+ pluginName: plugin.name,
728
+ type: "type"
729
+ });
730
+ return renderSchemaType({
731
+ node: node.requestBody,
732
+ name: resolvedName,
733
+ typedName,
734
+ description: node.requestBody.description
735
+ });
736
+ })() : null;
737
+ return /* @__PURE__ */ jsxs(File, {
738
+ baseName: file.baseName,
739
+ path: file.path,
740
+ meta: file.meta,
741
+ children: [
742
+ paramTypes,
743
+ responseTypes,
744
+ requestType
745
+ ]
746
+ });
747
+ },
748
+ Schema({ node, adapter, options }) {
749
+ const { enumType, enumKeyCasing, syntaxType, optionalType, arrayType } = options;
750
+ const { plugin, mode, resolveName, getFile } = useKubb();
751
+ if (!node.name) return;
752
+ const imports = adapter.getImports(node, (schemaName) => ({
753
+ name: resolveName({
754
+ name: schemaName,
755
+ pluginName: plugin.name,
756
+ type: "type"
757
+ }),
758
+ path: getFile({
759
+ name: schemaName,
760
+ pluginName: plugin.name,
761
+ extname: ".ts",
762
+ mode
763
+ }).path
764
+ }));
765
+ const isEnumSchema = node.type === "enum";
766
+ let typedName = resolveName({
767
+ name: node.name,
768
+ pluginName: plugin.name,
769
+ type: "type"
770
+ });
771
+ if (["asConst", "asPascalConst"].includes(enumType) && isEnumSchema) typedName = typedName += "Key";
772
+ const type = {
773
+ name: resolveName({
774
+ name: node.name,
775
+ pluginName: plugin.name,
776
+ type: "function"
777
+ }),
778
+ typedName,
779
+ file: getFile({
780
+ name: node.name,
781
+ pluginName: plugin.name,
782
+ extname: ".ts",
783
+ mode
784
+ })
785
+ };
786
+ return /* @__PURE__ */ jsxs(File, {
787
+ baseName: type.file.baseName,
788
+ path: type.file.path,
789
+ meta: type.file.meta,
790
+ children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
791
+ root: type.file.path,
792
+ path: imp.path,
793
+ name: imp.name,
794
+ isTypeOnly: true
795
+ }, [
796
+ node.name,
797
+ imp.path,
798
+ imp.isTypeOnly
799
+ ].join("-"))), /* @__PURE__ */ jsx(Type, {
800
+ name: type.name,
801
+ typedName: type.typedName,
802
+ node,
803
+ enumType,
804
+ enumKeyCasing,
805
+ optionalType,
806
+ arrayType,
807
+ syntaxType
808
+ })]
809
+ });
810
+ }
811
+ });
812
+ //#endregion
813
+ //#region src/plugin.ts
814
+ const pluginTsName = "plugin-ts";
815
+ const pluginTs = definePlugin((options) => {
816
+ const { output = {
817
+ path: "types",
818
+ barrelType: "named"
819
+ }, 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;
820
+ return {
821
+ name: pluginTsName,
822
+ options: {
823
+ output,
824
+ transformers,
825
+ dateType,
826
+ integerType,
827
+ optionalType,
828
+ arrayType,
829
+ enumType,
830
+ enumKeyCasing,
831
+ enumSuffix,
832
+ unknownType,
833
+ emptySchemaType,
834
+ syntaxType,
835
+ group,
836
+ override,
837
+ mapper,
838
+ paramsCasing,
839
+ usedEnumNames: {}
840
+ },
841
+ pre: [pluginOasName],
842
+ resolvePath(baseName, pathMode, options) {
843
+ const root = path.resolve(this.config.root, this.config.output.path);
844
+ if ((pathMode ?? getMode(path.resolve(root, output.path))) === "single")
845
+ /**
846
+ * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
847
+ * Other plugins then need to call addOrAppend instead of just add from the fileManager class
848
+ */
849
+ return path.resolve(root, output.path);
850
+ if (group && (options?.group?.path || options?.group?.tag)) {
851
+ const groupName = group?.name ? group.name : (ctx) => {
852
+ if (group?.type === "path") return `${ctx.group.split("/")[1]}`;
853
+ return `${camelCase(ctx.group)}Controller`;
854
+ };
855
+ return path.resolve(root, output.path, groupName({ group: group.type === "path" ? options.group.path : options.group.tag }), baseName);
856
+ }
857
+ return path.resolve(root, output.path, baseName);
858
+ },
859
+ resolveName(name, type) {
860
+ const resolvedName = pascalCase(name, { isFile: type === "file" });
861
+ if (type) return transformers?.name?.(resolvedName, type) || resolvedName;
862
+ return resolvedName;
863
+ },
864
+ async install() {
865
+ const { config, fabric, plugin, adapter, rootNode, pluginManager, openInStudio } = this;
866
+ const root = path.resolve(config.root, config.output.path);
867
+ const mode = getMode(path.resolve(root, output.path));
868
+ if (adapter) {
869
+ await openInStudio({ ast: true });
870
+ await walk(rootNode, {
871
+ async schema(schemaNode) {
872
+ const writeTasks = generators.map(async (generator) => {
873
+ if (generator.type === "react" && generator.version === "2") {
874
+ const options = resolveOptions(schemaNode, {
875
+ options: plugin.options,
876
+ exclude,
877
+ include,
878
+ override
879
+ });
880
+ if (options === null) return;
881
+ await buildSchema(schemaNode, {
882
+ options,
883
+ adapter,
884
+ config,
885
+ fabric,
886
+ Component: generator.Schema,
887
+ plugin,
888
+ pluginManager,
889
+ mode,
890
+ version: generator.version
891
+ });
892
+ }
893
+ });
894
+ await Promise.all(writeTasks);
895
+ },
896
+ async operation(operationNode) {
897
+ const writeTasks = generators.map(async (generator) => {
898
+ if (generator.type === "react" && generator.version === "2") {
899
+ const options = resolveOptions(operationNode, {
900
+ options: plugin.options,
901
+ exclude,
902
+ include,
903
+ override
904
+ });
905
+ if (options === null) return;
906
+ await buildOperation(operationNode, {
907
+ options,
908
+ adapter,
909
+ config,
910
+ fabric,
911
+ Component: generator.Operation,
912
+ plugin,
913
+ pluginManager,
914
+ mode,
915
+ version: generator.version
916
+ });
917
+ }
918
+ });
919
+ await Promise.all(writeTasks);
920
+ }
921
+ }, { depth: "shallow" });
922
+ return;
923
+ }
924
+ const oas = await this.getOas();
925
+ const schemaFiles = await new SchemaGenerator(this.plugin.options, {
926
+ fabric: this.fabric,
927
+ oas,
928
+ pluginManager: this.pluginManager,
929
+ events: this.events,
930
+ plugin: this.plugin,
931
+ contentType,
932
+ include: void 0,
933
+ override,
934
+ mode,
935
+ output: output.path
936
+ }).build(...generators);
937
+ await this.upsertFile(...schemaFiles);
938
+ const operationFiles = await new OperationGenerator(this.plugin.options, {
939
+ fabric: this.fabric,
940
+ oas,
941
+ pluginManager: this.pluginManager,
942
+ events: this.events,
943
+ plugin: this.plugin,
944
+ contentType,
945
+ exclude,
946
+ include,
947
+ override,
948
+ mode,
949
+ UNSTABLE_NAMING
950
+ }).build(...generators);
951
+ await this.upsertFile(...operationFiles);
952
+ const barrelFiles = await getBarrelFiles(this.fabric.files, {
953
+ type: output.barrelType ?? "named",
954
+ root,
955
+ output,
956
+ meta: { pluginName: this.plugin.name }
957
+ });
958
+ await this.upsertFile(...barrelFiles);
959
+ }
960
+ };
961
+ });
962
+ //#endregion
963
+ export { typeGenerator$1 as i, pluginTsName as n, typeGenerator as r, pluginTs as t };
964
+
965
+ //# sourceMappingURL=plugin-Bgm8TNUt.js.map