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

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 (42) hide show
  1. package/dist/index.cjs +1806 -3
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.ts +590 -4
  4. package/dist/index.js +1776 -2
  5. package/dist/index.js.map +1 -0
  6. package/package.json +7 -27
  7. package/src/components/Enum.tsx +82 -0
  8. package/src/components/Type.tsx +29 -162
  9. package/src/constants.ts +39 -0
  10. package/src/factory.ts +134 -49
  11. package/src/generators/typeGenerator.tsx +165 -428
  12. package/src/generators/typeGeneratorLegacy.tsx +349 -0
  13. package/src/index.ts +9 -1
  14. package/src/plugin.ts +98 -176
  15. package/src/presets.ts +28 -0
  16. package/src/printers/functionPrinter.ts +196 -0
  17. package/src/printers/printerTs.ts +310 -0
  18. package/src/resolvers/resolverTs.ts +66 -0
  19. package/src/resolvers/resolverTsLegacy.ts +60 -0
  20. package/src/types.ts +258 -98
  21. package/src/utils.ts +131 -0
  22. package/dist/components-CRjwjdyE.js +0 -725
  23. package/dist/components-CRjwjdyE.js.map +0 -1
  24. package/dist/components-DI0aTIBg.cjs +0 -978
  25. package/dist/components-DI0aTIBg.cjs.map +0 -1
  26. package/dist/components.cjs +0 -3
  27. package/dist/components.d.ts +0 -38
  28. package/dist/components.js +0 -2
  29. package/dist/generators.cjs +0 -4
  30. package/dist/generators.d.ts +0 -503
  31. package/dist/generators.js +0 -2
  32. package/dist/plugin-D5rCK1zO.cjs +0 -992
  33. package/dist/plugin-D5rCK1zO.cjs.map +0 -1
  34. package/dist/plugin-DmwgRHK8.js +0 -944
  35. package/dist/plugin-DmwgRHK8.js.map +0 -1
  36. package/dist/types-BpeKGgCn.d.ts +0 -170
  37. package/src/components/index.ts +0 -1
  38. package/src/components/v2/Type.tsx +0 -165
  39. package/src/generators/index.ts +0 -2
  40. package/src/generators/v2/typeGenerator.tsx +0 -196
  41. package/src/parser.ts +0 -396
  42. package/src/printer.ts +0 -244
@@ -0,0 +1,349 @@
1
+ import { pascalCase } from '@internals/utils'
2
+ import { caseParams, createProperty, createSchema, narrowSchema, schemaTypes, transform } from '@kubb/ast'
3
+ import type { OperationNode, ParameterNode, SchemaNode } from '@kubb/ast/types'
4
+ import { defineGenerator } from '@kubb/core'
5
+ import { File } from '@kubb/react-fabric'
6
+ import { Type } from '../components/Type.tsx'
7
+ import { ENUM_TYPES_WITH_KEY_SUFFIX } from '../constants.ts'
8
+ import { printerTs } from '../printers/printerTs.ts'
9
+ import { resolverTsLegacy } from '../resolvers/resolverTsLegacy.ts'
10
+ import type { PluginTs, ResolverTs } from '../types'
11
+
12
+ type BuildGroupedParamsSchemaOptions = {
13
+ params: Array<ParameterNode>
14
+ parentName?: string
15
+ }
16
+
17
+ function buildGroupedParamsSchema({ params, parentName }: BuildGroupedParamsSchemaOptions): SchemaNode {
18
+ return createSchema({
19
+ type: 'object',
20
+ properties: params.map((param) => {
21
+ let schema = param.schema
22
+ if (narrowSchema(schema, 'enum') && !schema.name && parentName) {
23
+ schema = { ...schema, name: pascalCase([parentName, param.name, 'enum'].join(' ')) }
24
+ }
25
+ return createProperty({
26
+ name: param.name,
27
+ required: param.required,
28
+ schema,
29
+ })
30
+ }),
31
+ })
32
+ }
33
+
34
+ type BuildOperationSchemaOptions = {
35
+ resolver: ResolverTs
36
+ }
37
+
38
+ function buildLegacyResponsesSchemaNode(node: OperationNode, { resolver }: BuildOperationSchemaOptions): SchemaNode | null {
39
+ const isGet = node.method.toLowerCase() === 'get'
40
+ const successResponses = node.responses.filter((res) => {
41
+ const code = Number(res.statusCode)
42
+ return !Number.isNaN(code) && code >= 200 && code < 300
43
+ })
44
+ const errorResponses = node.responses.filter((res) => res.statusCode === 'default' || Number(res.statusCode) >= 400)
45
+
46
+ const responseSchema =
47
+ successResponses.length > 0
48
+ ? successResponses.length === 1
49
+ ? createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
50
+ : createSchema({
51
+ type: 'union',
52
+ members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
53
+ })
54
+ : createSchema({ type: 'any', primitive: undefined })
55
+
56
+ const errorsSchema =
57
+ errorResponses.length > 0
58
+ ? errorResponses.length === 1
59
+ ? createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, errorResponses[0]!.statusCode) })
60
+ : createSchema({
61
+ type: 'union',
62
+ members: errorResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
63
+ })
64
+ : createSchema({ type: 'any', primitive: undefined })
65
+
66
+ const properties = [createProperty({ name: 'Response', required: true, schema: responseSchema })]
67
+
68
+ if (!isGet && node.requestBody?.schema) {
69
+ properties.push(
70
+ createProperty({
71
+ name: 'Request',
72
+ required: true,
73
+ schema: createSchema({ type: 'ref', name: resolver.resolveDataName(node) }),
74
+ }),
75
+ )
76
+ }
77
+
78
+ const queryParam = node.parameters.find((p) => p.in === 'query')
79
+ if (queryParam) {
80
+ properties.push(
81
+ createProperty({
82
+ name: 'QueryParams',
83
+ required: true,
84
+ schema: createSchema({ type: 'ref', name: resolver.resolveQueryParamsName(node, queryParam) }),
85
+ }),
86
+ )
87
+ }
88
+
89
+ const pathParam = node.parameters.find((p) => p.in === 'path')
90
+ if (pathParam) {
91
+ properties.push(
92
+ createProperty({
93
+ name: 'PathParams',
94
+ required: true,
95
+ schema: createSchema({ type: 'ref', name: resolver.resolvePathParamsName(node, pathParam) }),
96
+ }),
97
+ )
98
+ }
99
+
100
+ const headerParam = node.parameters.find((p) => p.in === 'header')
101
+ if (headerParam) {
102
+ properties.push(
103
+ createProperty({
104
+ name: 'HeaderParams',
105
+ required: true,
106
+ schema: createSchema({ type: 'ref', name: resolver.resolveHeaderParamsName(node, headerParam) }),
107
+ }),
108
+ )
109
+ }
110
+
111
+ properties.push(createProperty({ name: 'Errors', required: true, schema: errorsSchema }))
112
+
113
+ return createSchema({ type: 'object', properties })
114
+ }
115
+
116
+ function buildLegacyResponseUnionSchemaNode(node: OperationNode, { resolver }: BuildOperationSchemaOptions): SchemaNode {
117
+ const successResponses = node.responses.filter((res) => {
118
+ const code = Number(res.statusCode)
119
+ return !Number.isNaN(code) && code >= 200 && code < 300
120
+ })
121
+
122
+ if (successResponses.length === 0) {
123
+ return createSchema({ type: 'any', primitive: undefined })
124
+ }
125
+
126
+ if (successResponses.length === 1) {
127
+ return createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
128
+ }
129
+
130
+ return createSchema({
131
+ type: 'union',
132
+ members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
133
+ })
134
+ }
135
+
136
+ function nameUnnamedEnums(node: SchemaNode, parentName: string): SchemaNode {
137
+ return transform(node, {
138
+ schema(n) {
139
+ const enumNode = narrowSchema(n, 'enum')
140
+ if (enumNode && !enumNode.name) {
141
+ return { ...enumNode, name: pascalCase([parentName, 'enum'].join(' ')) }
142
+ }
143
+ return undefined
144
+ },
145
+ property(p) {
146
+ const enumNode = narrowSchema(p.schema, 'enum')
147
+ if (enumNode && !enumNode.name) {
148
+ return {
149
+ ...p,
150
+ schema: { ...enumNode, name: pascalCase([parentName, p.name, 'enum'].join(' ')) },
151
+ }
152
+ }
153
+ return undefined
154
+ },
155
+ })
156
+ }
157
+
158
+ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
159
+ name: 'typescript-legacy',
160
+ schema(node, options) {
161
+ const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group } = options
162
+ const { adapter, config, resolver, root } = this
163
+
164
+ if (!node.name) {
165
+ return
166
+ }
167
+
168
+ const mode = this.getMode(output)
169
+
170
+ const imports = adapter.getImports(node, (schemaName) => ({
171
+ name: resolver.resolveTypeName(schemaName),
172
+ path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
173
+ }))
174
+
175
+ const isEnumSchema = !!narrowSchema(node, schemaTypes.enum)
176
+
177
+ const meta = {
178
+ name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveTypeName(node.name),
179
+ file: resolver.resolveFile({ name: node.name, extname: '.ts' }, { root, output, group }),
180
+ } as const
181
+
182
+ const schemaPrinter = printerTs({
183
+ optionalType,
184
+ arrayType,
185
+ enumType,
186
+ enumTypeSuffix,
187
+ name: meta.name,
188
+ syntaxType,
189
+ description: node.description,
190
+ resolver,
191
+ })
192
+
193
+ return (
194
+ <File
195
+ baseName={meta.file.baseName}
196
+ path={meta.file.path}
197
+ meta={meta.file.meta}
198
+ banner={resolver.resolveBanner(adapter.rootNode, { output, config })}
199
+ footer={resolver.resolveFooter(adapter.rootNode, { output, config })}
200
+ >
201
+ {mode === 'split' &&
202
+ imports.map((imp) => (
203
+ <File.Import key={[node.name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
204
+ ))}
205
+ <Type
206
+ name={meta.name}
207
+ node={node}
208
+ enumType={enumType}
209
+ enumTypeSuffix={enumTypeSuffix}
210
+ enumKeyCasing={enumKeyCasing}
211
+ resolver={resolver}
212
+ printer={schemaPrinter}
213
+ />
214
+ </File>
215
+ )
216
+ },
217
+ operation(node, options) {
218
+ const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output } = options
219
+ const { adapter, config, resolver, root } = this
220
+
221
+ const mode = this.getMode(output)
222
+ const params = caseParams(node.parameters, paramsCasing)
223
+
224
+ const meta = {
225
+ file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
226
+ } as const
227
+
228
+ function renderSchemaType({
229
+ schema,
230
+ name,
231
+ description,
232
+ keysToOmit,
233
+ }: {
234
+ schema: SchemaNode | null
235
+ name: string
236
+ description?: string
237
+ keysToOmit?: Array<string>
238
+ }) {
239
+ if (!schema) return null
240
+
241
+ const imports = adapter.getImports(schema, (schemaName) => ({
242
+ name: resolver.resolveTypeName(schemaName),
243
+ path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
244
+ }))
245
+
246
+ const opPrinter = printerTs({
247
+ optionalType,
248
+ arrayType,
249
+ enumType,
250
+ enumTypeSuffix,
251
+ name,
252
+ syntaxType,
253
+ description,
254
+ keysToOmit,
255
+ resolver,
256
+ })
257
+
258
+ return (
259
+ <>
260
+ {mode === 'split' &&
261
+ imports.map((imp) => (
262
+ <File.Import key={[name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
263
+ ))}
264
+ <Type
265
+ name={name}
266
+ node={schema}
267
+ enumType={enumType}
268
+ enumTypeSuffix={enumTypeSuffix}
269
+ enumKeyCasing={enumKeyCasing}
270
+ resolver={resolver}
271
+ printer={opPrinter}
272
+ />
273
+ </>
274
+ )
275
+ }
276
+
277
+ const pathParams = params.filter((p) => p.in === 'path')
278
+ const queryParams = params.filter((p) => p.in === 'query')
279
+ const headerParams = params.filter((p) => p.in === 'header')
280
+
281
+ const responseTypes = node.responses.map((res) => {
282
+ const responseName = resolver.resolveResponseStatusName(node, res.statusCode)
283
+ const baseResponseName = resolverTsLegacy.resolveResponseStatusName(node, res.statusCode)
284
+
285
+ return renderSchemaType({
286
+ schema: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
287
+ name: responseName,
288
+ description: res.description,
289
+ keysToOmit: res.keysToOmit,
290
+ })
291
+ })
292
+
293
+ const requestType = node.requestBody?.schema
294
+ ? renderSchemaType({
295
+ schema: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
296
+ name: resolver.resolveDataName(node),
297
+ description: node.requestBody.description ?? node.requestBody.schema.description,
298
+ keysToOmit: node.requestBody.keysToOmit,
299
+ })
300
+ : null
301
+
302
+ const legacyParamTypes = [
303
+ pathParams.length > 0
304
+ ? renderSchemaType({
305
+ schema: buildGroupedParamsSchema({ params: pathParams, parentName: resolverTsLegacy.resolvePathParamsName(node, pathParams[0]!) }),
306
+ name: resolver.resolvePathParamsName(node, pathParams[0]!),
307
+ })
308
+ : null,
309
+ queryParams.length > 0
310
+ ? renderSchemaType({
311
+ schema: buildGroupedParamsSchema({ params: queryParams, parentName: resolverTsLegacy.resolveQueryParamsName(node, queryParams[0]!) }),
312
+ name: resolver.resolveQueryParamsName(node, queryParams[0]!),
313
+ })
314
+ : null,
315
+ headerParams.length > 0
316
+ ? renderSchemaType({
317
+ schema: buildGroupedParamsSchema({ params: headerParams, parentName: resolverTsLegacy.resolveHeaderParamsName(node, headerParams[0]!) }),
318
+ name: resolver.resolveHeaderParamsName(node, headerParams[0]!),
319
+ })
320
+ : null,
321
+ ]
322
+
323
+ const legacyResponsesType = renderSchemaType({
324
+ schema: buildLegacyResponsesSchemaNode(node, { resolver }),
325
+ name: resolver.resolveResponsesName(node),
326
+ })
327
+
328
+ const legacyResponseType = renderSchemaType({
329
+ schema: buildLegacyResponseUnionSchemaNode(node, { resolver }),
330
+ name: resolver.resolveResponseName(node),
331
+ })
332
+
333
+ return (
334
+ <File
335
+ baseName={meta.file.baseName}
336
+ path={meta.file.path}
337
+ meta={meta.file.meta}
338
+ banner={resolver.resolveBanner(adapter.rootNode, { output, config })}
339
+ footer={resolver.resolveFooter(adapter.rootNode, { output, config })}
340
+ >
341
+ {legacyParamTypes}
342
+ {responseTypes}
343
+ {requestType}
344
+ {legacyResponseType}
345
+ {legacyResponsesType}
346
+ </File>
347
+ )
348
+ },
349
+ })
package/src/index.ts CHANGED
@@ -1,2 +1,10 @@
1
+ export { Enum } from './components/Enum.tsx'
2
+ export { Type } from './components/Type.tsx'
3
+ export { typeGenerator } from './generators/typeGenerator.tsx'
1
4
  export { pluginTs, pluginTsName } from './plugin.ts'
2
- export type { PluginTs } from './types.ts'
5
+ export { functionPrinter } from './printers/functionPrinter.ts'
6
+ export type { PrinterTsFactory, PrinterTsNodes, PrinterTsOptions } from './printers/printerTs.ts'
7
+ export { printerTs } from './printers/printerTs.ts'
8
+ export { resolverTs } from './resolvers/resolverTs.ts'
9
+ export { resolverTsLegacy } from './resolvers/resolverTsLegacy.ts'
10
+ export type { PluginTs, ResolverTs } from './types.ts'
package/src/plugin.ts CHANGED
@@ -1,14 +1,31 @@
1
- import path from 'node:path'
2
- import { camelCase, pascalCase } from '@internals/utils'
3
- import { walk } from '@kubb/ast'
4
- import { definePlugin, type Group, getBarrelFiles, getMode } from '@kubb/core'
5
- import { buildOperation, buildSchema, OperationGenerator, pluginOasName, SchemaGenerator } from '@kubb/plugin-oas'
6
- import { typeGenerator, typeGeneratorV2 } from './generators'
1
+ import { camelCase } from '@internals/utils'
2
+ import { createPlugin, type Group, getPreset, mergeGenerators } from '@kubb/core'
3
+ import { version } from '../package.json'
4
+ import { presets } from './presets.ts'
7
5
  import type { PluginTs } from './types.ts'
8
6
 
7
+ /**
8
+ * Canonical plugin name for `@kubb/plugin-ts`, used to identify the plugin in driver lookups and warnings.
9
+ */
9
10
  export const pluginTsName = 'plugin-ts' satisfies PluginTs['name']
10
11
 
11
- export const pluginTs = definePlugin<PluginTs>((options) => {
12
+ /**
13
+ * The `@kubb/plugin-ts` plugin factory.
14
+ *
15
+ * Generates TypeScript type declarations from an OpenAPI/AST `RootNode`.
16
+ * Walks schemas and operations, delegates rendering to the active generators,
17
+ * and writes barrel files based on `output.barrelType`.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { pluginTs } from '@kubb/plugin-ts'
22
+ *
23
+ * export default defineConfig({
24
+ * plugins: [pluginTs({ output: { path: 'types' }, enumType: 'asConst' })],
25
+ * })
26
+ * ```
27
+ */
28
+ export const pluginTs = createPlugin<PluginTs>((options) => {
12
29
  const {
13
30
  output = { path: 'types', barrelType: 'named' },
14
31
  group,
@@ -16,194 +33,99 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
16
33
  include,
17
34
  override = [],
18
35
  enumType = 'asConst',
36
+ enumTypeSuffix = 'Key',
19
37
  enumKeyCasing = 'none',
20
- enumSuffix = 'enum',
21
- dateType = 'string',
22
- integerType = 'number',
23
- unknownType = 'any',
24
38
  optionalType = 'questionToken',
25
39
  arrayType = 'array',
26
- emptySchemaType = unknownType,
27
40
  syntaxType = 'type',
28
- transformers = {},
29
- mapper = {},
30
41
  paramsCasing,
31
- generators = [typeGenerator, typeGeneratorV2].filter(Boolean),
32
- contentType,
33
- UNSTABLE_NAMING,
42
+ printer,
43
+ compatibilityPreset = 'default',
44
+ resolver: userResolver,
45
+ transformer: userTransformer,
46
+ generators: userGenerators = [],
34
47
  } = options
35
48
 
36
- // @deprecated Will be removed in v5 when collisionDetection defaults to true
37
- const usedEnumNames = {}
49
+ const preset = getPreset({
50
+ preset: compatibilityPreset,
51
+ presets: presets,
52
+ resolver: userResolver,
53
+ transformer: userTransformer,
54
+ generators: userGenerators,
55
+ })
56
+
57
+ const generators = preset.generators ?? []
58
+ const mergedGenerator = mergeGenerators(generators)
59
+
60
+ let resolveNameWarning = false
61
+ let resolvePathWarning = false
38
62
 
39
63
  return {
40
64
  name: pluginTsName,
41
- options: {
42
- output,
43
- transformers,
44
- dateType,
45
- integerType,
46
- optionalType,
47
- arrayType,
48
- enumType,
49
- enumKeyCasing,
50
- enumSuffix,
51
- unknownType,
52
- emptySchemaType,
53
- syntaxType,
54
- group,
55
- override,
56
- mapper,
57
- paramsCasing,
58
- usedEnumNames,
65
+ version,
66
+ get resolver() {
67
+ return preset.resolver
59
68
  },
60
- pre: [pluginOasName],
61
- //resolveOptions(operation|schema): ResolvedOptions
62
- resolvePath(baseName, pathMode, options) {
63
- const root = path.resolve(this.config.root, this.config.output.path)
64
- const mode = pathMode ?? getMode(path.resolve(root, output.path))
65
-
66
- if (mode === 'single') {
67
- /**
68
- * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
69
- * Other plugins then need to call addOrAppend instead of just add from the fileManager class
70
- */
71
- return path.resolve(root, output.path)
69
+ get transformer() {
70
+ return preset.transformer
71
+ },
72
+ get options() {
73
+ return {
74
+ output,
75
+ exclude,
76
+ include,
77
+ override,
78
+ optionalType,
79
+ group: group
80
+ ? ({
81
+ ...group,
82
+ name: (ctx) => {
83
+ if (group.type === 'path') {
84
+ return `${ctx.group.split('/')[1]}`
85
+ }
86
+ return `${camelCase(ctx.group)}Controller`
87
+ },
88
+ } satisfies Group)
89
+ : undefined,
90
+ arrayType,
91
+ enumType,
92
+ enumTypeSuffix,
93
+ enumKeyCasing,
94
+ syntaxType,
95
+ paramsCasing,
96
+ printer,
72
97
  }
73
-
74
- if (group && (options?.group?.path || options?.group?.tag)) {
75
- const groupName: Group['name'] = group?.name
76
- ? group.name
77
- : (ctx) => {
78
- if (group?.type === 'path') {
79
- return `${ctx.group.split('/')[1]}`
80
- }
81
- return `${camelCase(ctx.group)}Controller`
82
- }
83
-
84
- return path.resolve(
85
- root,
86
- output.path,
87
- groupName({
88
- group: group.type === 'path' ? options.group.path! : options.group.tag!,
89
- }),
90
- baseName,
91
- )
98
+ },
99
+ resolvePath(baseName, pathMode, options) {
100
+ if (!resolvePathWarning) {
101
+ this.warn('Do not use resolvePath for pluginTs, use resolverTs.resolvePath instead')
102
+ resolvePathWarning = true
92
103
  }
93
104
 
94
- return path.resolve(root, output.path, baseName)
105
+ return this.plugin.resolver.resolvePath(
106
+ { baseName, pathMode, tag: options?.group?.tag, path: options?.group?.path },
107
+ { root: this.root, output, group: this.plugin.options.group },
108
+ )
95
109
  },
96
110
  resolveName(name, type) {
97
- const resolvedName = pascalCase(name, { isFile: type === 'file' })
98
-
99
- if (type) {
100
- return transformers?.name?.(resolvedName, type) || resolvedName
111
+ if (!resolveNameWarning) {
112
+ this.warn('Do not use resolveName for pluginTs, use resolverTs.default instead')
113
+ resolveNameWarning = true
101
114
  }
102
115
 
103
- return resolvedName
116
+ return this.plugin.resolver.default(name, type)
104
117
  },
105
- async install() {
106
- const { config, fabric, plugin, adapter, rootNode, pluginManager, openInStudio } = this
107
-
108
- const root = path.resolve(config.root, config.output.path)
109
- const mode = getMode(path.resolve(root, output.path))
110
-
111
- if (adapter) {
112
- await openInStudio({ ast: true })
113
-
114
- await walk(
115
- rootNode,
116
- {
117
- async schema(schemaNode) {
118
- const writeTasks = generators.map(async (generator) => {
119
- if (generator.type === 'react' && generator.version === '2') {
120
- await buildSchema(schemaNode, {
121
- adapter,
122
- config,
123
- fabric,
124
- Component: generator.Schema,
125
- plugin,
126
- pluginManager,
127
- mode,
128
- version: generator.version,
129
- })
130
- }
131
- })
132
-
133
- await writeTasks
134
- },
135
- async operation(operationNode) {
136
- const writeTasks = generators.map(async (generator) => {
137
- if (generator.type === 'react' && generator.version === '2') {
138
- await buildOperation(operationNode, {
139
- adapter,
140
- config,
141
- fabric,
142
- Component: generator.Operation,
143
- plugin,
144
- pluginManager,
145
- mode,
146
- version: generator.version,
147
- })
148
- }
149
- })
150
-
151
- await writeTasks
152
- },
153
- },
154
- { depth: 'shallow' },
155
- )
156
-
157
- return
158
- }
159
-
160
- // v1 flow
161
-
162
- const oas = await this.getOas()
163
-
164
- const schemaGenerator = new SchemaGenerator(this.plugin.options, {
165
- fabric: this.fabric,
166
- oas,
167
- pluginManager: this.pluginManager,
168
- events: this.events,
169
- plugin: this.plugin,
170
- contentType,
171
- include: undefined,
172
- override,
173
- mode,
174
- output: output.path,
175
- })
176
-
177
- const schemaFiles = await schemaGenerator.build(...generators)
178
- await this.upsertFile(...schemaFiles)
179
-
180
- const operationGenerator = new OperationGenerator(this.plugin.options, {
181
- fabric: this.fabric,
182
- oas,
183
- pluginManager: this.pluginManager,
184
- events: this.events,
185
- plugin: this.plugin,
186
- contentType,
187
- exclude,
188
- include,
189
- override,
190
- mode,
191
- UNSTABLE_NAMING,
192
- })
193
-
194
- const operationFiles = await operationGenerator.build(...generators)
195
- await this.upsertFile(...operationFiles)
196
-
197
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
198
- type: output.barrelType ?? 'named',
199
- root,
200
- output,
201
- meta: {
202
- pluginName: this.plugin.name,
203
- },
204
- })
205
-
206
- await this.upsertFile(...barrelFiles)
118
+ async schema(node, options) {
119
+ return mergedGenerator.schema?.call(this, node, options)
120
+ },
121
+ async operation(node, options) {
122
+ return mergedGenerator.operation?.call(this, node, options)
123
+ },
124
+ async operations(nodes, options) {
125
+ return mergedGenerator.operations?.call(this, nodes, options)
126
+ },
127
+ async buildStart() {
128
+ await this.openInStudio({ ast: true })
207
129
  },
208
130
  }
209
131
  })
package/src/presets.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { definePresets } from '@kubb/core'
2
+ import { typeGenerator } from './generators/typeGenerator.tsx'
3
+ import { typeGeneratorLegacy } from './generators/typeGeneratorLegacy.tsx'
4
+ import { printerTs } from './printers/printerTs.ts'
5
+ import { resolverTs } from './resolvers/resolverTs.ts'
6
+ import { resolverTsLegacy } from './resolvers/resolverTsLegacy.ts'
7
+ import type { ResolverTs } from './types.ts'
8
+
9
+ /**
10
+ * Built-in preset registry for `@kubb/plugin-ts`.
11
+ *
12
+ * - `default` — uses `resolverTs` and `typeGenerator` (current naming conventions).
13
+ * - `kubbV4` — uses `resolverTsLegacy` and `typeGeneratorLegacy` (Kubb v4 naming conventions).
14
+ */
15
+ export const presets = definePresets<ResolverTs>({
16
+ default: {
17
+ name: 'default',
18
+ resolver: resolverTs,
19
+ generators: [typeGenerator],
20
+ printer: printerTs,
21
+ },
22
+ kubbV4: {
23
+ name: 'kubbV4',
24
+ resolver: resolverTsLegacy,
25
+ generators: [typeGeneratorLegacy],
26
+ printer: printerTs,
27
+ },
28
+ })