@kubb/plugin-ts 5.0.0-alpha.11 → 5.0.0-alpha.12

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/dist/{components-CRu8IKY3.js → Type-CX1HRooG.js} +377 -365
  2. package/dist/Type-CX1HRooG.js.map +1 -0
  3. package/dist/Type-Cat0_htq.cjs +808 -0
  4. package/dist/Type-Cat0_htq.cjs.map +1 -0
  5. package/dist/components.cjs +3 -2
  6. package/dist/components.d.ts +40 -9
  7. package/dist/components.js +2 -2
  8. package/dist/generators-CLuCmfUz.js +532 -0
  9. package/dist/generators-CLuCmfUz.js.map +1 -0
  10. package/dist/generators-DWBU-MuW.cjs +536 -0
  11. package/dist/generators-DWBU-MuW.cjs.map +1 -0
  12. package/dist/generators.cjs +2 -3
  13. package/dist/generators.d.ts +3 -503
  14. package/dist/generators.js +2 -2
  15. package/dist/index.cjs +308 -4
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.ts +26 -21
  18. package/dist/index.js +305 -2
  19. package/dist/index.js.map +1 -0
  20. package/dist/{types-mSXmB8WU.d.ts → types-BA1ZCQ5p.d.ts} +73 -57
  21. package/package.json +5 -5
  22. package/src/components/{v2/Enum.tsx → Enum.tsx} +27 -11
  23. package/src/components/Type.tsx +23 -141
  24. package/src/components/index.ts +1 -0
  25. package/src/generators/index.ts +0 -1
  26. package/src/generators/typeGenerator.tsx +189 -413
  27. package/src/generators/utils.ts +298 -0
  28. package/src/index.ts +1 -1
  29. package/src/plugin.ts +80 -126
  30. package/src/printer.ts +15 -4
  31. package/src/resolverTs.ts +109 -1
  32. package/src/types.ts +68 -52
  33. package/dist/components-CRu8IKY3.js.map +0 -1
  34. package/dist/components-DeNDKlzf.cjs +0 -982
  35. package/dist/components-DeNDKlzf.cjs.map +0 -1
  36. package/dist/plugin-CJ29AwE2.cjs +0 -1320
  37. package/dist/plugin-CJ29AwE2.cjs.map +0 -1
  38. package/dist/plugin-D60XNJSD.js +0 -1267
  39. package/dist/plugin-D60XNJSD.js.map +0 -1
  40. package/src/components/v2/Type.tsx +0 -59
  41. package/src/generators/v2/typeGenerator.tsx +0 -167
  42. package/src/generators/v2/utils.ts +0 -140
  43. package/src/parser.ts +0 -389
@@ -1,1267 +0,0 @@
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-CRu8IKY3.js";
3
- import path from "node:path";
4
- import { applyParamsCasing, collect, createProperty, createSchema, isPlainStringType, walk } from "@kubb/ast";
5
- import { createPlugin, defineGenerator, definePrinter, defineResolver, getBarrelFiles, getMode, renderOperation, renderSchema } from "@kubb/core";
6
- import { OperationGenerator, SchemaGenerator, isKeyword, pluginOasName, schemaKeywords } from "@kubb/plugin-oas";
7
- import { useKubb, useMode, usePluginDriver } 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 as applyParamsCasing$1, 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, driver }) {
30
- const properties = {};
31
- if (schemas.response) properties["response"] = createUnionDeclaration({ nodes: schemas.responses.map((res) => {
32
- return createTypeReferenceNode(createIdentifier(driver.resolveName({
33
- name: res.name,
34
- pluginName: pluginTsName,
35
- type: "function"
36
- })), void 0);
37
- }) });
38
- if (schemas.request) properties["request"] = createTypeReferenceNode(createIdentifier(driver.resolveName({
39
- name: schemas.request.name,
40
- pluginName: pluginTsName,
41
- type: "function"
42
- })), void 0);
43
- if (schemas.pathParams) properties["pathParams"] = createTypeReferenceNode(createIdentifier(driver.resolveName({
44
- name: schemas.pathParams.name,
45
- pluginName: pluginTsName,
46
- type: "function"
47
- })), void 0);
48
- if (schemas.queryParams) properties["queryParams"] = createTypeReferenceNode(createIdentifier(driver.resolveName({
49
- name: schemas.queryParams.name,
50
- pluginName: pluginTsName,
51
- type: "function"
52
- })), void 0);
53
- if (schemas.headerParams) properties["headerParams"] = createTypeReferenceNode(createIdentifier(driver.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(driver.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, driver }) {
79
- const name = driver.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 = driver.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 = driver.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 = driver.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 = driver.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, driver, unknownType }) {
162
- const results = [];
163
- const name = driver.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 = driver.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: { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, unknownType, paramsCasing } } = plugin;
206
- const mode = useMode();
207
- const driver = usePluginDriver();
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
- driver,
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$1(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
- enumType,
265
- enumKeyCasing,
266
- optionalType,
267
- arrayType,
268
- keysToOmit,
269
- syntaxType
270
- })] });
271
- };
272
- const responseName = schemaManager.getName(schemas.response.name, { type: "type" });
273
- const combinedSchemaName = operation.method === "get" ? `${name}Query` : `${name}Mutation`;
274
- return /* @__PURE__ */ jsxs(File, {
275
- baseName: file.baseName,
276
- path: file.path,
277
- meta: file.meta,
278
- banner: getBanner({
279
- oas,
280
- output: plugin.options.output,
281
- config: driver.config
282
- }),
283
- footer: getFooter({
284
- oas,
285
- output: plugin.options.output
286
- }),
287
- children: [operationSchemas.map(mapOperationSchema), generator.context.UNSTABLE_NAMING ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File.Source, {
288
- name: `${name}Request`,
289
- isExportable: true,
290
- isIndexable: true,
291
- isTypeOnly: true,
292
- children: printRequestSchema({
293
- baseName: name,
294
- operation,
295
- schemas,
296
- driver
297
- })
298
- }), /* @__PURE__ */ jsx(File.Source, {
299
- name: responseName,
300
- isExportable: true,
301
- isIndexable: true,
302
- isTypeOnly: true,
303
- children: printResponseSchema({
304
- baseName: name,
305
- schemas,
306
- driver,
307
- unknownType
308
- })
309
- })] }) : /* @__PURE__ */ jsx(File.Source, {
310
- name: combinedSchemaName,
311
- isExportable: true,
312
- isIndexable: true,
313
- isTypeOnly: true,
314
- children: printCombinedSchema({
315
- name: combinedSchemaName,
316
- schemas,
317
- driver
318
- })
319
- })]
320
- });
321
- },
322
- Schema({ schema, plugin }) {
323
- const { options: { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, output } } = plugin;
324
- const mode = useMode();
325
- const oas = useOas();
326
- const driver = usePluginDriver();
327
- const { getName, getFile } = useSchemaManager();
328
- const imports = getImports(schema.tree);
329
- const schemaFromTree = schema.tree.find((item) => item.keyword === schemaKeywords.schema);
330
- let typedName = getName(schema.name, { type: "type" });
331
- if (["asConst", "asPascalConst"].includes(enumType) && schemaFromTree && isKeyword(schemaFromTree, schemaKeywords.enum)) typedName = typedName += "Key";
332
- const type = {
333
- name: getName(schema.name, { type: "function" }),
334
- typedName,
335
- file: getFile(schema.name)
336
- };
337
- return /* @__PURE__ */ jsxs(File, {
338
- baseName: type.file.baseName,
339
- path: type.file.path,
340
- meta: type.file.meta,
341
- banner: getBanner({
342
- oas,
343
- output,
344
- config: driver.config
345
- }),
346
- footer: getFooter({
347
- oas,
348
- output
349
- }),
350
- children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
351
- root: type.file.path,
352
- path: imp.path,
353
- name: imp.name,
354
- isTypeOnly: true
355
- }, [
356
- schema.name,
357
- imp.path,
358
- imp.isTypeOnly
359
- ].join("-"))), /* @__PURE__ */ jsx(Type$1, {
360
- name: type.name,
361
- typedName: type.typedName,
362
- description: schema.value.description,
363
- tree: schema.tree,
364
- schema: schema.value,
365
- enumType,
366
- enumKeyCasing,
367
- optionalType,
368
- arrayType,
369
- syntaxType
370
- })]
371
- });
372
- }
373
- });
374
- //#endregion
375
- //#region src/constants.ts
376
- /**
377
- * `optionalType` values that cause a property's type to include `| undefined`.
378
- */
379
- const OPTIONAL_ADDS_UNDEFINED = new Set(["undefined", "questionTokenAndUndefined"]);
380
- /**
381
- * `optionalType` values that render the property key with a `?` token.
382
- */
383
- const OPTIONAL_ADDS_QUESTION_TOKEN = new Set(["questionToken", "questionTokenAndUndefined"]);
384
- /**
385
- * `enumType` values that append a `Key` suffix to the generated enum type alias.
386
- */
387
- const ENUM_TYPES_WITH_KEY_SUFFIX = new Set(["asConst", "asPascalConst"]);
388
- /**
389
- * `enumType` values that require a runtime value declaration (object, enum, or literal).
390
- */
391
- const ENUM_TYPES_WITH_RUNTIME_VALUE = new Set([
392
- "enum",
393
- "asConst",
394
- "asPascalConst",
395
- "constEnum",
396
- "literal",
397
- void 0
398
- ]);
399
- /**
400
- * `enumType` values whose type declaration is type-only (no runtime value emitted for the type alias).
401
- */
402
- const ENUM_TYPES_WITH_TYPE_ONLY = new Set([
403
- "asConst",
404
- "asPascalConst",
405
- "literal",
406
- void 0
407
- ]);
408
- //#endregion
409
- //#region src/printer.ts
410
- /**
411
- * Converts a primitive const value to a TypeScript literal type node.
412
- * Handles negative numbers via a prefix unary expression.
413
- */
414
- function constToTypeNode(value, format) {
415
- if (format === "boolean") return createLiteralTypeNode(value === true ? createTrue() : createFalse());
416
- if (format === "number" && typeof value === "number") {
417
- if (value < 0) return createLiteralTypeNode(createPrefixUnaryExpression(SyntaxKind.MinusToken, createNumericLiteral(Math.abs(value))));
418
- return createLiteralTypeNode(createNumericLiteral(value));
419
- }
420
- return createLiteralTypeNode(createStringLiteral(String(value)));
421
- }
422
- /**
423
- * Returns a `Date` reference type node when `representation` is `'date'`, otherwise falls back to `string`.
424
- */
425
- function dateOrStringNode(node) {
426
- return node.representation === "date" ? createTypeReferenceNode(createIdentifier("Date")) : keywordTypeNodes.string;
427
- }
428
- /**
429
- * Maps an array of `SchemaNode`s through the printer, filtering out `null` and `undefined` results.
430
- */
431
- function buildMemberNodes(members, print) {
432
- return (members ?? []).map(print).filter(Boolean);
433
- }
434
- /**
435
- * Builds a TypeScript tuple type node from an array schema's `items`,
436
- * applying min/max slice and optional/rest element rules.
437
- */
438
- function buildTupleNode(node, print) {
439
- let items = (node.items ?? []).map(print).filter(Boolean);
440
- const restNode = node.rest ? print(node.rest) ?? void 0 : void 0;
441
- const { min, max } = node;
442
- if (max !== void 0) {
443
- items = items.slice(0, max);
444
- if (items.length < max && restNode) items = [...items, ...Array(max - items.length).fill(restNode)];
445
- }
446
- if (min !== void 0) items = items.map((item, i) => i >= min ? createOptionalTypeNode(item) : item);
447
- if (max === void 0 && restNode) items.push(createRestTypeNode(createArrayTypeNode(restNode)));
448
- return createTupleTypeNode(items);
449
- }
450
- /**
451
- * Applies `nullable` and optional/nullish `| undefined` union modifiers to a property's resolved base type.
452
- */
453
- function buildPropertyType(schema, baseType, optionalType) {
454
- const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType);
455
- let type = baseType;
456
- if (schema.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
457
- if ((schema.nullish || schema.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
458
- return type;
459
- }
460
- /**
461
- * Collects JSDoc annotation strings (description, deprecated, min/max, pattern, default, example, type) for a schema node.
462
- */
463
- function buildPropertyJSDocComments(schema) {
464
- return [
465
- "description" in schema && schema.description ? `@description ${jsStringEscape(schema.description)}` : void 0,
466
- "deprecated" in schema && schema.deprecated ? "@deprecated" : void 0,
467
- "min" in schema && schema.min !== void 0 ? `@minLength ${schema.min}` : void 0,
468
- "max" in schema && schema.max !== void 0 ? `@maxLength ${schema.max}` : void 0,
469
- "pattern" in schema && schema.pattern ? `@pattern ${schema.pattern}` : void 0,
470
- "default" in schema && schema.default !== void 0 ? `@default ${"primitive" in schema && schema.primitive === "string" ? stringify(schema.default) : schema.default}` : void 0,
471
- "example" in schema && schema.example !== void 0 ? `@example ${schema.example}` : void 0,
472
- "primitive" in schema && schema.primitive ? [`@type ${schema.primitive || "unknown"}`, "optional" in schema && schema.optional ? " | undefined" : void 0].filter(Boolean).join("") : void 0
473
- ];
474
- }
475
- /**
476
- * Creates TypeScript index signatures for `additionalProperties` and `patternProperties` on an object schema node.
477
- */
478
- function buildIndexSignatures(node, propertyCount, print) {
479
- const elements = [];
480
- if (node.additionalProperties && node.additionalProperties !== true) {
481
- const additionalType = print(node.additionalProperties) ?? keywordTypeNodes.unknown;
482
- elements.push(createIndexSignature(propertyCount > 0 ? keywordTypeNodes.unknown : additionalType));
483
- } else if (node.additionalProperties === true) elements.push(createIndexSignature(keywordTypeNodes.unknown));
484
- if (node.patternProperties) {
485
- const first = Object.values(node.patternProperties)[0];
486
- if (first) {
487
- let patternType = print(first) ?? keywordTypeNodes.unknown;
488
- if (first.nullable) patternType = createUnionDeclaration({ nodes: [patternType, keywordTypeNodes.null] });
489
- elements.push(createIndexSignature(patternType));
490
- }
491
- }
492
- return elements;
493
- }
494
- /**
495
- * TypeScript type printer built with `definePrinter`.
496
- *
497
- * Converts a `SchemaNode` AST node into a TypeScript AST node:
498
- * - **`printer.print(node)`** — when `options.typeName` is set, returns a full
499
- * `type Name = …` or `interface Name { … }` declaration (`ts.Node`).
500
- * Without `typeName`, returns the raw `ts.TypeNode` for the schema.
501
- *
502
- * Dispatches on `node.type` to the appropriate handler in `nodes`. Options are closed
503
- * over per printer instance, so each call to `printerTs(options)` produces an independent printer.
504
- *
505
- * @example Raw type node (no `typeName`)
506
- * ```ts
507
- * const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enumType: 'inlineLiteral' })
508
- * const typeNode = printer.print(schemaNode) // ts.TypeNode
509
- * ```
510
- *
511
- * @example Full declaration (with `typeName`)
512
- * ```ts
513
- * const printer = printerTs({ optionalType: 'questionToken', arrayType: 'array', enumType: 'inlineLiteral', typeName: 'MyType' })
514
- * const declaration = printer.print(schemaNode) // ts.TypeAliasDeclaration | ts.InterfaceDeclaration
515
- * ```
516
- */
517
- const printerTs = definePrinter((options) => {
518
- const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(options.optionalType);
519
- return {
520
- name: "typescript",
521
- options,
522
- nodes: {
523
- any: () => keywordTypeNodes.any,
524
- unknown: () => keywordTypeNodes.unknown,
525
- void: () => keywordTypeNodes.void,
526
- never: () => keywordTypeNodes.never,
527
- boolean: () => keywordTypeNodes.boolean,
528
- null: () => keywordTypeNodes.null,
529
- blob: () => createTypeReferenceNode("Blob", []),
530
- string: () => keywordTypeNodes.string,
531
- uuid: () => keywordTypeNodes.string,
532
- email: () => keywordTypeNodes.string,
533
- url: (node) => {
534
- if (node.path) return createUrlTemplateType(node.path);
535
- return keywordTypeNodes.string;
536
- },
537
- datetime: () => keywordTypeNodes.string,
538
- number: () => keywordTypeNodes.number,
539
- integer: () => keywordTypeNodes.number,
540
- bigint: () => keywordTypeNodes.bigint,
541
- date: dateOrStringNode,
542
- time: dateOrStringNode,
543
- ref(node) {
544
- if (!node.name) return;
545
- return createTypeReferenceNode(node.name, void 0);
546
- },
547
- enum(node) {
548
- const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? [];
549
- if (this.options.enumType === "inlineLiteral" || !node.name) return createUnionDeclaration({
550
- withParentheses: true,
551
- nodes: values.filter((v) => v !== null).map((value) => constToTypeNode(value, typeof value)).filter(Boolean)
552
- }) ?? void 0;
553
- const resolvedName = pascalCase(node.name);
554
- return createTypeReferenceNode(ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) ? `${resolvedName}Key` : resolvedName, void 0);
555
- },
556
- union(node) {
557
- const members = node.members ?? [];
558
- const hasStringLiteral = members.some((m) => m.type === "enum" && (m.enumType === "string" || m.primitive === "string"));
559
- const hasPlainString = members.some((m) => isPlainStringType(m));
560
- if (hasStringLiteral && hasPlainString) return createUnionDeclaration({
561
- withParentheses: true,
562
- nodes: members.map((m) => {
563
- if (isPlainStringType(m)) return createIntersectionDeclaration({
564
- nodes: [keywordTypeNodes.string, createTypeLiteralNode([])],
565
- withParentheses: true
566
- });
567
- return this.print(m);
568
- }).filter(Boolean)
569
- }) ?? void 0;
570
- return createUnionDeclaration({
571
- withParentheses: true,
572
- nodes: buildMemberNodes(members, this.print)
573
- }) ?? void 0;
574
- },
575
- intersection(node) {
576
- return createIntersectionDeclaration({
577
- withParentheses: true,
578
- nodes: buildMemberNodes(node.members, this.print)
579
- }) ?? void 0;
580
- },
581
- array(node) {
582
- return createArrayDeclaration({
583
- nodes: (node.items ?? []).map((item) => this.print(item)).filter(Boolean),
584
- arrayType: this.options.arrayType
585
- }) ?? void 0;
586
- },
587
- tuple(node) {
588
- return buildTupleNode(node, this.print);
589
- },
590
- object(node) {
591
- const { print, options } = this;
592
- const addsQuestionToken = OPTIONAL_ADDS_QUESTION_TOKEN.has(options.optionalType);
593
- const propertyNodes = node.properties.map((prop) => {
594
- const baseType = print(prop.schema) ?? keywordTypeNodes.unknown;
595
- const type = buildPropertyType(prop.schema, baseType, options.optionalType);
596
- return appendJSDocToNode({
597
- node: createPropertySignature({
598
- questionToken: prop.schema.optional || prop.schema.nullish ? addsQuestionToken : false,
599
- name: prop.name,
600
- type,
601
- readOnly: prop.schema.readOnly
602
- }),
603
- comments: buildPropertyJSDocComments(prop.schema)
604
- });
605
- });
606
- const allElements = [...propertyNodes, ...buildIndexSignatures(node, propertyNodes.length, print)];
607
- if (!allElements.length) return keywordTypeNodes.object;
608
- return createTypeLiteralNode(allElements);
609
- }
610
- },
611
- print(node) {
612
- let type = this.print(node);
613
- if (!type) return;
614
- if (node.nullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] });
615
- if ((node.nullish || node.optional) && addsUndefined) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] });
616
- const { typeName, syntaxType = "type", description, keysToOmit } = this.options;
617
- if (!typeName) return type;
618
- const useTypeGeneration = syntaxType === "type" || type.kind === syntaxKind.union || !!keysToOmit?.length;
619
- return createTypeDeclaration({
620
- name: typeName,
621
- isExportable: true,
622
- type: keysToOmit?.length ? createOmitDeclaration({
623
- keys: keysToOmit,
624
- type,
625
- nonNullable: true
626
- }) : type,
627
- syntax: useTypeGeneration ? "type" : "interface",
628
- comments: [
629
- node?.title ? jsStringEscape(node.title) : void 0,
630
- description ? `@description ${jsStringEscape(description)}` : void 0,
631
- node?.deprecated ? "@deprecated" : void 0,
632
- node && "min" in node && node.min !== void 0 ? `@minLength ${node.min}` : void 0,
633
- node && "max" in node && node.max !== void 0 ? `@maxLength ${node.max}` : void 0,
634
- node && "pattern" in node && node.pattern ? `@pattern ${node.pattern}` : void 0,
635
- node?.default ? `@default ${node.default}` : void 0,
636
- node?.example ? `@example ${node.example}` : void 0
637
- ]
638
- });
639
- }
640
- };
641
- });
642
- //#endregion
643
- //#region src/components/v2/Enum.tsx
644
- /**
645
- * Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
646
- *
647
- * The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
648
- * valid TypeScript identifier. `pascalCase` normalizes it unconditionally; for inline enum
649
- * properties the adapter already emits a PascalCase+suffix name so `pascalCase` is a no-op.
650
- */
651
- function getEnumNames(node, enumType) {
652
- const resolved = pascalCase(node.name);
653
- return {
654
- enumName: enumType === "asPascalConst" ? resolved : camelCase(node.name),
655
- typeName: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? `${resolved}Key` : resolved
656
- };
657
- }
658
- /**
659
- * Renders the enum declaration(s) for a single named `EnumSchemaNode`.
660
- *
661
- * Depending on `enumType` this may emit:
662
- * - A runtime object (`asConst` / `asPascalConst`) plus a `typeof` type alias
663
- * - A `const enum` or plain `enum` declaration (`constEnum` / `enum`)
664
- * - A union literal type alias (`literal`)
665
- *
666
- * The emitted `File.Source` nodes carry the resolved names so that the barrel
667
- * index picks up the correct export identifiers.
668
- */
669
- function Enum({ node, enumType, enumKeyCasing }) {
670
- const { enumName, typeName } = getEnumNames(node, enumType);
671
- const [nameNode, typeNode] = createEnumDeclaration({
672
- name: enumName,
673
- typeName,
674
- 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]) ?? [],
675
- type: enumType,
676
- enumKeyCasing
677
- });
678
- return /* @__PURE__ */ jsxs(Fragment, { children: [nameNode && /* @__PURE__ */ jsx(File.Source, {
679
- name: enumName,
680
- isExportable: true,
681
- isIndexable: true,
682
- isTypeOnly: false,
683
- children: safePrint(nameNode)
684
- }), /* @__PURE__ */ jsx(File.Source, {
685
- name: typeName,
686
- isIndexable: true,
687
- isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
688
- isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
689
- children: safePrint(typeNode)
690
- })] });
691
- }
692
- //#endregion
693
- //#region src/components/v2/Type.tsx
694
- function Type({ name, typedName, node, keysToOmit, optionalType, arrayType, syntaxType, enumType, enumKeyCasing, description }) {
695
- const resolvedDescription = description || node?.description;
696
- const enumSchemaNodes = collect(node, { schema(n) {
697
- if (n.type === "enum" && n.name) return n;
698
- } });
699
- const typeNode = printerTs({
700
- optionalType,
701
- arrayType,
702
- enumType,
703
- typeName: name,
704
- syntaxType,
705
- description: resolvedDescription,
706
- keysToOmit
707
- }).print(node);
708
- if (!typeNode) return;
709
- const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((node) => {
710
- return {
711
- node,
712
- ...getEnumNames(node, enumType)
713
- };
714
- });
715
- const shouldExportEnums = enumType !== "inlineLiteral";
716
- const shouldExportType = enumType === "inlineLiteral" || enums.every((item) => item.typeName !== name);
717
- return /* @__PURE__ */ jsxs(Fragment, { children: [shouldExportEnums && enums.map(({ node }) => /* @__PURE__ */ jsx(Enum, {
718
- node,
719
- enumType,
720
- enumKeyCasing
721
- })), shouldExportType && /* @__PURE__ */ jsx(File.Source, {
722
- name: typedName,
723
- isTypeOnly: true,
724
- isExportable: true,
725
- isIndexable: true,
726
- children: safePrint(typeNode)
727
- })] });
728
- }
729
- //#endregion
730
- //#region src/resolverTs.ts
731
- /**
732
- * Resolver for `@kubb/plugin-ts` that provides the default naming and path-resolution
733
- * helpers used by the plugin. Import this in other plugins to resolve the exact names and
734
- * paths that `plugin-ts` generates without hardcoding the conventions.
735
- *
736
- * The `default` method is automatically injected by `defineResolver` — it uses `camelCase`
737
- * for identifiers/files and `pascalCase` for type names.
738
- *
739
- * @example
740
- * ```ts
741
- * import { resolver } from '@kubb/plugin-ts'
742
- *
743
- * resolver.default('list pets', 'type') // → 'ListPets'
744
- * resolver.resolveName('list pets status 200') // → 'listPetsStatus200'
745
- * resolver.resolveTypedName('list pets status 200') // → 'ListPetsStatus200'
746
- * resolver.resolvePathName('list pets', 'file') // → 'listPets'
747
- * ```
748
- */
749
- const resolverTs = defineResolver(() => {
750
- return {
751
- default(name, type) {
752
- return pascalCase(name, { isFile: type === "file" });
753
- },
754
- resolveName(name) {
755
- return this.default(name, "function");
756
- },
757
- resolveTypedName(name) {
758
- return this.default(name, "type");
759
- },
760
- resolvePathName(name, type) {
761
- return this.default(name, type);
762
- },
763
- resolveParamName(node, param) {
764
- return this.resolveName(`${node.operationId} ${this.default(param.in)} ${param.name}`);
765
- },
766
- resolveParamTypedName(node, param) {
767
- return this.resolveTypedName(`${node.operationId} ${this.default(param.in)} ${param.name}`);
768
- },
769
- resolveResponseStatusName(node, statusCode) {
770
- return this.resolveName(`${node.operationId} Status ${statusCode}`);
771
- },
772
- resolveResponseStatusTypedName(node, statusCode) {
773
- return this.resolveTypedName(`${node.operationId} Status ${statusCode}`);
774
- },
775
- resolveDataName(node) {
776
- return this.resolveName(`${node.operationId} Data`);
777
- },
778
- resolveDataTypedName(node) {
779
- return this.resolveTypedName(`${node.operationId} Data`);
780
- },
781
- resolveRequestConfigName(node) {
782
- return this.resolveName(`${node.operationId} RequestConfig`);
783
- },
784
- resolveRequestConfigTypedName(node) {
785
- return this.resolveTypedName(`${node.operationId} RequestConfig`);
786
- },
787
- resolveResponsesName(node) {
788
- return this.resolveName(`${node.operationId} Responses`);
789
- },
790
- resolveResponsesTypedName(node) {
791
- return this.resolveTypedName(`${node.operationId} Responses`);
792
- },
793
- resolveResponseName(node) {
794
- return this.resolveName(`${node.operationId} Response`);
795
- },
796
- resolveResponseTypedName(node) {
797
- return this.resolveTypedName(`${node.operationId} Response`);
798
- },
799
- resolveEnumKeyTypedName(node) {
800
- return `${this.resolveTypedName(node.name ?? "")}Key`;
801
- }
802
- };
803
- });
804
- //#endregion
805
- //#region src/generators/v2/utils.ts
806
- /**
807
- * Builds an `ObjectSchemaNode` for a group of parameters (path/query/header).
808
- * Each property is a `ref` schema pointing to the individually-resolved parameter type.
809
- * The ref name includes the parameter location so generated type names follow
810
- * the `<OperationId><Location><ParamName>` convention.
811
- */
812
- function buildParamsSchema({ params, operationId, resolveName }) {
813
- return createSchema({
814
- type: "object",
815
- properties: params.map((param) => createProperty({
816
- name: param.name,
817
- schema: createSchema({
818
- type: "ref",
819
- name: resolveName({
820
- name: `${operationId} ${pascalCase(param.in)} ${param.name}`,
821
- type: "function"
822
- }),
823
- optional: !param.required
824
- })
825
- }))
826
- });
827
- }
828
- /**
829
- * Builds an `ObjectSchemaNode` representing the `<OperationId>RequestConfig` type:
830
- * - `data` → request body ref (optional) or `never`
831
- * - `pathParams` → inline object of path param refs, or `never`
832
- * - `queryParams` → inline object of query param refs (optional), or `never`
833
- * - `headerParams` → inline object of header param refs (optional), or `never`
834
- * - `url` → Express-style template literal (plugin-ts extension, handled by printer)
835
- */
836
- function buildDataSchemaNode({ node, resolveName }) {
837
- const pathParams = node.parameters.filter((p) => p.in === "path");
838
- const queryParams = node.parameters.filter((p) => p.in === "query");
839
- const headerParams = node.parameters.filter((p) => p.in === "header");
840
- return createSchema({
841
- type: "object",
842
- deprecated: node.deprecated,
843
- properties: [
844
- createProperty({
845
- name: "data",
846
- schema: node.requestBody ? createSchema({
847
- type: "ref",
848
- name: resolveName({
849
- name: `${node.operationId} Data`,
850
- type: "function"
851
- }),
852
- optional: true
853
- }) : createSchema({
854
- type: "never",
855
- optional: true
856
- })
857
- }),
858
- createProperty({
859
- name: "pathParams",
860
- schema: pathParams.length > 0 ? buildParamsSchema({
861
- params: pathParams,
862
- operationId: node.operationId,
863
- resolveName
864
- }) : createSchema({
865
- type: "never",
866
- optional: true
867
- })
868
- }),
869
- createProperty({
870
- name: "queryParams",
871
- schema: queryParams.length > 0 ? createSchema({
872
- ...buildParamsSchema({
873
- params: queryParams,
874
- operationId: node.operationId,
875
- resolveName
876
- }),
877
- optional: true
878
- }) : createSchema({
879
- type: "never",
880
- optional: true
881
- })
882
- }),
883
- createProperty({
884
- name: "headerParams",
885
- schema: headerParams.length > 0 ? createSchema({
886
- ...buildParamsSchema({
887
- params: headerParams,
888
- operationId: node.operationId,
889
- resolveName
890
- }),
891
- optional: true
892
- }) : createSchema({
893
- type: "never",
894
- optional: true
895
- })
896
- }),
897
- createProperty({
898
- name: "url",
899
- schema: createSchema({
900
- type: "url",
901
- path: node.path
902
- })
903
- })
904
- ]
905
- });
906
- }
907
- /**
908
- * Builds an `ObjectSchemaNode` representing `<OperationId>Responses` — keyed by HTTP status code.
909
- * Numeric status codes produce unquoted numeric keys (e.g. `200:`).
910
- * All responses are included; those without a schema are represented as a ref to a `never` type.
911
- */
912
- function buildResponsesSchemaNode({ node, resolveName }) {
913
- if (node.responses.length === 0) return null;
914
- return createSchema({
915
- type: "object",
916
- properties: node.responses.map((res) => createProperty({
917
- name: String(res.statusCode),
918
- schema: createSchema({
919
- type: "ref",
920
- name: resolveName({
921
- name: `${node.operationId} Status ${res.statusCode}`,
922
- type: "function"
923
- })
924
- })
925
- }))
926
- });
927
- }
928
- /**
929
- * Builds a `UnionSchemaNode` representing `<OperationId>Response` — all response types in union format.
930
- * Returns `null` when the operation has no responses with schemas.
931
- */
932
- function buildResponseUnionSchemaNode({ node, resolveName }) {
933
- const responsesWithSchema = node.responses.filter((res) => res.schema);
934
- if (responsesWithSchema.length === 0) return null;
935
- return createSchema({
936
- type: "union",
937
- members: responsesWithSchema.map((res) => createSchema({
938
- type: "ref",
939
- name: resolveName({
940
- name: `${node.operationId} Status ${res.statusCode}`,
941
- type: "function"
942
- })
943
- }))
944
- });
945
- }
946
- //#endregion
947
- //#region src/generators/v2/typeGenerator.tsx
948
- const typeGenerator = defineGenerator({
949
- name: "typescript",
950
- type: "react",
951
- Operation({ node, adapter, options }) {
952
- const { enumType, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group } = options;
953
- const { mode, getFile, resolveName, resolveBanner, resolveFooter } = useKubb();
954
- const file = getFile({
955
- name: node.operationId,
956
- extname: ".ts",
957
- mode,
958
- options: { group: group ? group.type === "tag" ? { tag: node.tags[0] } : { path: node.path } : void 0 }
959
- });
960
- const params = applyParamsCasing(node.parameters, paramsCasing);
961
- function renderSchemaType({ node: schemaNode, name, typedName, description }) {
962
- if (!schemaNode) return null;
963
- const imports = adapter.getImports(schemaNode, (schemaName) => ({
964
- name: resolveName({
965
- name: schemaName,
966
- type: "type"
967
- }),
968
- path: getFile({
969
- name: schemaName,
970
- extname: ".ts",
971
- mode
972
- }).path
973
- }));
974
- return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
975
- root: file.path,
976
- path: imp.path,
977
- name: imp.name,
978
- isTypeOnly: true
979
- }, [
980
- name,
981
- imp.path,
982
- imp.isTypeOnly
983
- ].join("-"))), /* @__PURE__ */ jsx(Type, {
984
- name,
985
- typedName,
986
- node: schemaNode,
987
- description,
988
- enumType,
989
- enumKeyCasing,
990
- optionalType,
991
- arrayType,
992
- syntaxType
993
- })] });
994
- }
995
- const paramTypes = params.map((param) => renderSchemaType({
996
- node: param.schema,
997
- name: resolverTs.resolveParamName(node, param),
998
- typedName: resolverTs.resolveParamTypedName(node, param)
999
- }));
1000
- const responseTypes = node.responses.map((res) => renderSchemaType({
1001
- node: res.schema,
1002
- name: resolverTs.resolveResponseStatusName(node, res.statusCode),
1003
- typedName: resolverTs.resolveResponseStatusTypedName(node, res.statusCode),
1004
- description: res.description
1005
- }));
1006
- const requestType = node.requestBody ? renderSchemaType({
1007
- node: node.requestBody,
1008
- name: resolverTs.resolveDataName(node),
1009
- typedName: resolverTs.resolveDataTypedName(node),
1010
- description: node.requestBody.description
1011
- }) : null;
1012
- const dataType = renderSchemaType({
1013
- node: buildDataSchemaNode({
1014
- node: {
1015
- ...node,
1016
- parameters: params
1017
- },
1018
- resolveName
1019
- }),
1020
- name: resolverTs.resolveRequestConfigName(node),
1021
- typedName: resolverTs.resolveRequestConfigTypedName(node)
1022
- });
1023
- const responsesType = renderSchemaType({
1024
- node: buildResponsesSchemaNode({
1025
- node,
1026
- resolveName
1027
- }),
1028
- name: resolverTs.resolveResponsesName(node),
1029
- typedName: resolverTs.resolveResponsesTypedName(node)
1030
- });
1031
- const responseType = renderSchemaType({
1032
- node: buildResponseUnionSchemaNode({
1033
- node,
1034
- resolveName
1035
- }),
1036
- name: resolverTs.resolveResponseName(node),
1037
- typedName: resolverTs.resolveResponseTypedName(node),
1038
- description: "Union of all possible responses"
1039
- });
1040
- return /* @__PURE__ */ jsxs(File, {
1041
- baseName: file.baseName,
1042
- path: file.path,
1043
- meta: file.meta,
1044
- banner: resolveBanner(),
1045
- footer: resolveFooter(),
1046
- children: [
1047
- paramTypes,
1048
- responseTypes,
1049
- requestType,
1050
- dataType,
1051
- responsesType,
1052
- responseType
1053
- ]
1054
- });
1055
- },
1056
- Schema({ node, adapter, options }) {
1057
- const { enumType, enumKeyCasing, syntaxType, optionalType, arrayType } = options;
1058
- const { mode, resolveName, getFile, resolveBanner, resolveFooter } = useKubb();
1059
- if (!node.name) return;
1060
- const imports = adapter.getImports(node, (schemaName) => ({
1061
- name: resolveName({
1062
- name: schemaName,
1063
- type: "type"
1064
- }),
1065
- path: getFile({
1066
- name: schemaName,
1067
- extname: ".ts",
1068
- mode
1069
- }).path
1070
- }));
1071
- const isEnumSchema = node.type === "enum";
1072
- const typedName = ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolverTs.resolveEnumKeyTypedName(node) : resolverTs.resolveTypedName(node.name);
1073
- const type = {
1074
- name: resolverTs.resolveName(node.name),
1075
- typedName,
1076
- file: getFile({
1077
- name: node.name,
1078
- extname: ".ts",
1079
- mode
1080
- })
1081
- };
1082
- return /* @__PURE__ */ jsxs(File, {
1083
- baseName: type.file.baseName,
1084
- path: type.file.path,
1085
- meta: type.file.meta,
1086
- banner: resolveBanner(),
1087
- footer: resolveFooter(),
1088
- children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1089
- root: type.file.path,
1090
- path: imp.path,
1091
- name: imp.name,
1092
- isTypeOnly: true
1093
- }, [
1094
- node.name,
1095
- imp.path,
1096
- imp.isTypeOnly
1097
- ].join("-"))), /* @__PURE__ */ jsx(Type, {
1098
- name: type.name,
1099
- typedName: type.typedName,
1100
- node,
1101
- enumType,
1102
- enumKeyCasing,
1103
- optionalType,
1104
- arrayType,
1105
- syntaxType
1106
- })]
1107
- });
1108
- }
1109
- });
1110
- //#endregion
1111
- //#region src/plugin.ts
1112
- const pluginTsName = "plugin-ts";
1113
- const pluginTs = createPlugin((options) => {
1114
- const { output = {
1115
- path: "types",
1116
- barrelType: "named"
1117
- }, 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 = {}, paramsCasing, generators = [typeGenerator$1, typeGenerator].filter(Boolean), contentType, UNSTABLE_NAMING } = options;
1118
- return {
1119
- name: pluginTsName,
1120
- options: {
1121
- output,
1122
- transformers,
1123
- dateType,
1124
- integerType,
1125
- optionalType,
1126
- arrayType,
1127
- enumType,
1128
- enumKeyCasing,
1129
- enumSuffix,
1130
- unknownType,
1131
- emptySchemaType,
1132
- syntaxType,
1133
- group,
1134
- override,
1135
- paramsCasing,
1136
- usedEnumNames: {}
1137
- },
1138
- pre: [pluginOasName],
1139
- resolvePath(baseName, pathMode, options) {
1140
- const root = path.resolve(this.config.root, this.config.output.path);
1141
- if ((pathMode ?? getMode(path.resolve(root, output.path))) === "single")
1142
- /**
1143
- * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
1144
- * Other plugins then need to call addOrAppend instead of just add from the fileManager class
1145
- */
1146
- return path.resolve(root, output.path);
1147
- if (group && (options?.group?.path || options?.group?.tag)) {
1148
- const groupName = group?.name ? group.name : (ctx) => {
1149
- if (group?.type === "path") return `${ctx.group.split("/")[1]}`;
1150
- return `${camelCase(ctx.group)}Controller`;
1151
- };
1152
- return path.resolve(root, output.path, groupName({ group: group.type === "path" ? options.group.path : options.group.tag }), baseName);
1153
- }
1154
- return path.resolve(root, output.path, baseName);
1155
- },
1156
- resolveName(name, type) {
1157
- const resolvedName = resolverTs.default(name, type);
1158
- if (type) return transformers?.name?.(resolvedName, type) || resolvedName;
1159
- return resolvedName;
1160
- },
1161
- async install() {
1162
- const { config, fabric, plugin, adapter, rootNode, driver, openInStudio } = this;
1163
- const root = path.resolve(config.root, config.output.path);
1164
- const mode = getMode(path.resolve(root, output.path));
1165
- if (adapter) {
1166
- await openInStudio({ ast: true });
1167
- await walk(rootNode, {
1168
- async schema(schemaNode) {
1169
- const writeTasks = generators.map(async (generator) => {
1170
- if (generator.type === "react" && generator.version === "2") {
1171
- const options = resolverTs.resolveOptions(schemaNode, {
1172
- options: plugin.options,
1173
- exclude,
1174
- include,
1175
- override
1176
- });
1177
- if (options === null) return;
1178
- await renderSchema(schemaNode, {
1179
- options,
1180
- adapter,
1181
- config,
1182
- fabric,
1183
- Component: generator.Schema,
1184
- plugin,
1185
- driver,
1186
- mode
1187
- });
1188
- }
1189
- });
1190
- await Promise.all(writeTasks);
1191
- },
1192
- async operation(operationNode) {
1193
- const writeTasks = generators.map(async (generator) => {
1194
- if (generator.type === "react" && generator.version === "2") {
1195
- const options = resolverTs.resolveOptions(operationNode, {
1196
- options: plugin.options,
1197
- exclude,
1198
- include,
1199
- override
1200
- });
1201
- if (options === null) return;
1202
- await renderOperation(operationNode, {
1203
- options,
1204
- adapter,
1205
- config,
1206
- fabric,
1207
- Component: generator.Operation,
1208
- plugin,
1209
- driver,
1210
- mode
1211
- });
1212
- }
1213
- });
1214
- await Promise.all(writeTasks);
1215
- }
1216
- }, { depth: "shallow" });
1217
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
1218
- type: output.barrelType ?? "named",
1219
- root,
1220
- output,
1221
- meta: { pluginName: this.plugin.name }
1222
- });
1223
- await this.upsertFile(...barrelFiles);
1224
- return;
1225
- }
1226
- const oas = await this.getOas();
1227
- const schemaFiles = await new SchemaGenerator(this.plugin.options, {
1228
- fabric: this.fabric,
1229
- oas,
1230
- driver: this.driver,
1231
- events: this.events,
1232
- plugin: this.plugin,
1233
- contentType,
1234
- include: void 0,
1235
- override,
1236
- mode,
1237
- output: output.path
1238
- }).build(...generators);
1239
- await this.upsertFile(...schemaFiles);
1240
- const operationFiles = await new OperationGenerator(this.plugin.options, {
1241
- fabric: this.fabric,
1242
- oas,
1243
- driver: this.driver,
1244
- events: this.events,
1245
- plugin: this.plugin,
1246
- contentType,
1247
- exclude,
1248
- include,
1249
- override,
1250
- mode,
1251
- UNSTABLE_NAMING
1252
- }).build(...generators);
1253
- await this.upsertFile(...operationFiles);
1254
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
1255
- type: output.barrelType ?? "named",
1256
- root,
1257
- output,
1258
- meta: { pluginName: this.plugin.name }
1259
- });
1260
- await this.upsertFile(...barrelFiles);
1261
- }
1262
- };
1263
- });
1264
- //#endregion
1265
- export { typeGenerator$1 as a, resolverTs as i, pluginTsName as n, typeGenerator as r, pluginTs as t };
1266
-
1267
- //# sourceMappingURL=plugin-D60XNJSD.js.map