@kubb/plugin-ts 5.0.0-alpha.9 → 5.0.0-beta.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.
Files changed (44) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +1 -3
  3. package/dist/index.cjs +1452 -5
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.ts +558 -27
  6. package/dist/index.js +1418 -2
  7. package/dist/index.js.map +1 -0
  8. package/extension.yaml +632 -0
  9. package/package.json +44 -64
  10. package/src/components/{v2/Enum.tsx → Enum.tsx} +33 -17
  11. package/src/components/Type.tsx +31 -161
  12. package/src/constants.ts +10 -0
  13. package/src/factory.ts +283 -35
  14. package/src/generators/typeGenerator.tsx +189 -424
  15. package/src/index.ts +9 -3
  16. package/src/plugin.ts +66 -205
  17. package/src/printers/functionPrinter.ts +197 -0
  18. package/src/printers/printerTs.ts +325 -0
  19. package/src/resolvers/resolverTs.ts +66 -0
  20. package/src/types.ts +233 -221
  21. package/src/utils.ts +130 -0
  22. package/dist/components-CRu8IKY3.js +0 -729
  23. package/dist/components-CRu8IKY3.js.map +0 -1
  24. package/dist/components-DeNDKlzf.cjs +0 -982
  25. package/dist/components-DeNDKlzf.cjs.map +0 -1
  26. package/dist/components.cjs +0 -3
  27. package/dist/components.d.ts +0 -36
  28. package/dist/components.js +0 -2
  29. package/dist/generators.cjs +0 -4
  30. package/dist/generators.d.ts +0 -509
  31. package/dist/generators.js +0 -2
  32. package/dist/plugin-BZkBwnEA.js +0 -1269
  33. package/dist/plugin-BZkBwnEA.js.map +0 -1
  34. package/dist/plugin-Bunz1oGa.cjs +0 -1322
  35. package/dist/plugin-Bunz1oGa.cjs.map +0 -1
  36. package/dist/types-mSXmB8WU.d.ts +0 -298
  37. package/src/components/index.ts +0 -1
  38. package/src/components/v2/Type.tsx +0 -59
  39. package/src/generators/index.ts +0 -2
  40. package/src/generators/v2/typeGenerator.tsx +0 -167
  41. package/src/generators/v2/utils.ts +0 -140
  42. package/src/parser.ts +0 -389
  43. package/src/printer.ts +0 -368
  44. package/src/resolverTs.ts +0 -77
@@ -1,467 +1,232 @@
1
- import { pascalCase } from '@internals/utils'
2
- import type { PluginDriver } from '@kubb/core'
3
- import { useMode, usePluginDriver } from '@kubb/core/hooks'
4
- import { safePrint } from '@kubb/fabric-core/parsers/typescript'
5
- import type { Operation } from '@kubb/oas'
6
- import { isKeyword, type OperationSchemas, type OperationSchema as OperationSchemaType, SchemaGenerator, schemaKeywords } from '@kubb/plugin-oas'
7
- import { createReactGenerator } from '@kubb/plugin-oas/generators'
8
- import { useOas, useOperationManager, useSchemaManager } from '@kubb/plugin-oas/hooks'
9
- import { applyParamsCasing, getBanner, getFooter, getImports, isParameterSchema } from '@kubb/plugin-oas/utils'
10
- import { File } from '@kubb/react-fabric'
11
- import ts from 'typescript'
12
- import { Type } from '../components'
13
- import * as factory from '../factory.ts'
14
- import { createUrlTemplateType, getUnknownType, keywordTypeNodes } from '../factory.ts'
15
- import { pluginTsName } from '../plugin.ts'
1
+ import { ast, defineGenerator } from '@kubb/core'
2
+ import { File, jsxRenderer } from '@kubb/renderer-jsx'
3
+ import { Type } from '../components/Type.tsx'
4
+ import { ENUM_TYPES_WITH_KEY_SUFFIX } from '../constants.ts'
5
+ import { printerTs } from '../printers/printerTs.ts'
16
6
  import type { PluginTs } from '../types'
7
+ import { buildData, buildResponses, buildResponseUnion } from '../utils.ts'
17
8
 
18
- function printCombinedSchema({ name, schemas, driver }: { name: string; schemas: OperationSchemas; driver: PluginDriver }): string {
19
- const properties: Record<string, ts.TypeNode> = {}
20
-
21
- if (schemas.response) {
22
- properties['response'] = factory.createUnionDeclaration({
23
- nodes: schemas.responses.map((res) => {
24
- const identifier = driver.resolveName({
25
- name: res.name,
26
- pluginName: pluginTsName,
27
- type: 'function',
28
- })
29
-
30
- return factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined)
31
- }),
32
- })!
33
- }
34
-
35
- if (schemas.request) {
36
- const identifier = driver.resolveName({
37
- name: schemas.request.name,
38
- pluginName: pluginTsName,
39
- type: 'function',
40
- })
41
- properties['request'] = factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined)
42
- }
43
-
44
- if (schemas.pathParams) {
45
- const identifier = driver.resolveName({
46
- name: schemas.pathParams.name,
47
- pluginName: pluginTsName,
48
- type: 'function',
49
- })
50
- properties['pathParams'] = factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined)
51
- }
52
-
53
- if (schemas.queryParams) {
54
- const identifier = driver.resolveName({
55
- name: schemas.queryParams.name,
56
- pluginName: pluginTsName,
57
- type: 'function',
58
- })
59
- properties['queryParams'] = factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined)
60
- }
61
-
62
- if (schemas.headerParams) {
63
- const identifier = driver.resolveName({
64
- name: schemas.headerParams.name,
65
- pluginName: pluginTsName,
66
- type: 'function',
67
- })
68
- properties['headerParams'] = factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined)
69
- }
70
-
71
- if (schemas.errors) {
72
- properties['errors'] = factory.createUnionDeclaration({
73
- nodes: schemas.errors.map((error) => {
74
- const identifier = driver.resolveName({
75
- name: error.name,
76
- pluginName: pluginTsName,
77
- type: 'function',
78
- })
79
-
80
- return factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined)
81
- }),
82
- })!
83
- }
84
-
85
- const namespaceNode = factory.createTypeAliasDeclaration({
86
- name,
87
- type: factory.createTypeLiteralNode(
88
- Object.keys(properties)
89
- .map((key) => {
90
- const type = properties[key]
91
- if (!type) {
92
- return undefined
93
- }
94
-
95
- return factory.createPropertySignature({
96
- name: pascalCase(key),
97
- type,
98
- })
99
- })
100
- .filter(Boolean),
101
- ),
102
- modifiers: [factory.modifiers.export],
103
- })
104
-
105
- return safePrint(namespaceNode)
106
- }
107
-
108
- function printRequestSchema({
109
- baseName,
110
- operation,
111
- schemas,
112
- driver,
113
- }: {
114
- baseName: string
115
- operation: Operation
116
- schemas: OperationSchemas
117
- driver: PluginDriver
118
- }): string {
119
- const name = driver.resolveName({
120
- name: `${baseName} Request`,
121
- pluginName: pluginTsName,
122
- type: 'type',
123
- })
124
-
125
- const results: string[] = []
126
-
127
- // Generate DataRequest type
128
- const dataRequestProperties: ts.PropertySignature[] = []
129
-
130
- if (schemas.request) {
131
- const identifier = driver.resolveName({
132
- name: schemas.request.name,
133
- pluginName: pluginTsName,
134
- type: 'type',
135
- })
136
- dataRequestProperties.push(
137
- factory.createPropertySignature({
138
- name: 'data',
139
- questionToken: true,
140
- type: factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined),
141
- }),
142
- )
143
- } else {
144
- dataRequestProperties.push(
145
- factory.createPropertySignature({
146
- name: 'data',
147
- questionToken: true,
148
- type: keywordTypeNodes.never,
149
- }),
150
- )
151
- }
9
+ export const typeGenerator = defineGenerator<PluginTs>({
10
+ name: 'typescript',
11
+ renderer: jsxRenderer,
12
+ schema(node, ctx) {
13
+ const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, printer } = ctx.options
14
+ const { adapter, config, resolver, root } = ctx
152
15
 
153
- // Add pathParams property
154
- if (schemas.pathParams) {
155
- const identifier = driver.resolveName({
156
- name: schemas.pathParams.name,
157
- pluginName: pluginTsName,
158
- type: 'type',
159
- })
160
- dataRequestProperties.push(
161
- factory.createPropertySignature({
162
- name: 'pathParams',
163
- type: factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined),
164
- }),
165
- )
166
- } else {
167
- dataRequestProperties.push(
168
- factory.createPropertySignature({
169
- name: 'pathParams',
170
- questionToken: true,
171
- type: keywordTypeNodes.never,
172
- }),
173
- )
174
- }
16
+ if (!node.name) {
17
+ return
18
+ }
19
+ const mode = ctx.getMode(output)
20
+ // Build a set of schema names that are enums so the ref handler and getImports
21
+ // callback can use the suffixed type name (e.g. `StatusKey`) for those refs.
22
+ const enumSchemaNames = new Set((adapter.inputNode?.schemas ?? []).filter((s) => ast.narrowSchema(s, ast.schemaTypes.enum) && s.name).map((s) => s.name!))
23
+
24
+ function resolveImportName(schemaName: string): string {
25
+ if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) {
26
+ return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix)
27
+ }
28
+ return resolver.resolveTypeName(schemaName)
29
+ }
175
30
 
176
- // Add queryParams property
177
- if (schemas.queryParams) {
178
- const identifier = driver.resolveName({
179
- name: schemas.queryParams.name,
180
- pluginName: pluginTsName,
181
- type: 'type',
31
+ const imports = adapter.getImports(node, (schemaName) => ({
32
+ name: resolveImportName(schemaName),
33
+ path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
34
+ }))
35
+
36
+ const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum)
37
+
38
+ const meta = {
39
+ name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveTypeName(node.name),
40
+ file: resolver.resolveFile({ name: node.name, extname: '.ts' }, { root, output, group }),
41
+ } as const
42
+
43
+ const schemaPrinter = printerTs({
44
+ optionalType,
45
+ arrayType,
46
+ enumType,
47
+ enumTypeSuffix,
48
+ name: meta.name,
49
+ syntaxType,
50
+ description: node.description,
51
+ resolver,
52
+ enumSchemaNames,
53
+ nodes: printer?.nodes,
182
54
  })
183
- dataRequestProperties.push(
184
- factory.createPropertySignature({
185
- name: 'queryParams',
186
- questionToken: true,
187
- type: factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined),
188
- }),
189
- )
190
- } else {
191
- dataRequestProperties.push(
192
- factory.createPropertySignature({
193
- name: 'queryParams',
194
- questionToken: true,
195
- type: keywordTypeNodes.never,
196
- }),
197
- )
198
- }
199
55
 
200
- // Add headerParams property
201
- if (schemas.headerParams) {
202
- const identifier = driver.resolveName({
203
- name: schemas.headerParams.name,
204
- pluginName: pluginTsName,
205
- type: 'type',
206
- })
207
- dataRequestProperties.push(
208
- factory.createPropertySignature({
209
- name: 'headerParams',
210
- questionToken: true,
211
- type: factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined),
212
- }),
213
- )
214
- } else {
215
- dataRequestProperties.push(
216
- factory.createPropertySignature({
217
- name: 'headerParams',
218
- questionToken: true,
219
- type: keywordTypeNodes.never,
220
- }),
56
+ return (
57
+ <File
58
+ baseName={meta.file.baseName}
59
+ path={meta.file.path}
60
+ meta={meta.file.meta}
61
+ banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
62
+ footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
63
+ >
64
+ {mode === 'split' &&
65
+ imports.map((imp) => (
66
+ <File.Import key={[node.name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
67
+ ))}
68
+ <Type
69
+ name={meta.name}
70
+ node={node}
71
+ enumType={enumType}
72
+ enumTypeSuffix={enumTypeSuffix}
73
+ enumKeyCasing={enumKeyCasing}
74
+ resolver={resolver}
75
+ printer={schemaPrinter}
76
+ />
77
+ </File>
221
78
  )
222
- }
223
-
224
- // Add url property with template literal type
225
- dataRequestProperties.push(
226
- factory.createPropertySignature({
227
- name: 'url',
228
- type: createUrlTemplateType(operation.path),
229
- }),
230
- )
231
-
232
- const dataRequestNode = factory.createTypeAliasDeclaration({
233
- name,
234
- type: factory.createTypeLiteralNode(dataRequestProperties),
235
- modifiers: [factory.modifiers.export],
236
- })
79
+ },
80
+ operation(node, ctx) {
81
+ const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, printer } = ctx.options
82
+ const { adapter, config, resolver, root } = ctx
237
83
 
238
- results.push(safePrint(dataRequestNode))
84
+ const mode = ctx.getMode(output)
239
85
 
240
- return results.join('\n\n')
241
- }
86
+ const params = ast.caseParams(node.parameters, paramsCasing)
242
87
 
243
- function printResponseSchema({
244
- baseName,
245
- schemas,
246
- driver,
247
- unknownType,
248
- }: {
249
- baseName: string
250
- schemas: OperationSchemas
251
- driver: PluginDriver
252
- unknownType: PluginTs['resolvedOptions']['unknownType']
253
- }): string {
254
- const results: string[] = []
88
+ const meta = {
89
+ file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
90
+ } as const
255
91
 
256
- const name = driver.resolveName({
257
- name: `${baseName} ResponseData`,
258
- pluginName: pluginTsName,
259
- type: 'type',
260
- })
92
+ // Build a set of schema names that are enums so the ref handler and getImports
93
+ // callback can use the suffixed type name (e.g. `StatusKey`) for those refs.
94
+ const enumSchemaNames = new Set((adapter.inputNode?.schemas ?? []).filter((s) => ast.narrowSchema(s, ast.schemaTypes.enum) && s.name).map((s) => s.name!))
261
95
 
262
- // Generate Responses type (mapping status codes to response types)
263
- if (schemas.responses && schemas.responses.length > 0) {
264
- const responsesProperties: ts.PropertySignature[] = schemas.responses.map((res) => {
265
- const identifier = driver.resolveName({
266
- name: res.name,
267
- pluginName: pluginTsName,
268
- type: 'type',
269
- })
96
+ function resolveImportName(schemaName: string): string {
97
+ if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) {
98
+ return resolver.resolveEnumKeyName({ name: schemaName }, enumTypeSuffix)
99
+ }
100
+ return resolver.resolveTypeName(schemaName)
101
+ }
270
102
 
271
- return factory.createPropertySignature({
272
- name: res.statusCode?.toString() ?? 'default',
273
- type: factory.createTypeReferenceNode(factory.createIdentifier(identifier), undefined),
103
+ function renderSchemaType({ schema, name, keysToOmit }: { schema: ast.SchemaNode | null; name: string; keysToOmit?: Array<string> }) {
104
+ if (!schema) return null
105
+
106
+ const imports = adapter.getImports(schema, (schemaName) => ({
107
+ name: resolveImportName(schemaName),
108
+ path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
109
+ }))
110
+
111
+ const schemaPrinter = printerTs({
112
+ optionalType,
113
+ arrayType,
114
+ enumType,
115
+ enumTypeSuffix,
116
+ name,
117
+ syntaxType,
118
+ description: schema.description,
119
+ keysToOmit,
120
+ resolver,
121
+ enumSchemaNames,
122
+ nodes: printer?.nodes,
274
123
  })
275
- })
276
-
277
- const responsesNode = factory.createTypeAliasDeclaration({
278
- name: `${baseName}Responses`,
279
- type: factory.createTypeLiteralNode(responsesProperties),
280
- modifiers: [factory.modifiers.export],
281
- })
282
-
283
- results.push(safePrint(responsesNode))
284
-
285
- // Generate Response type (union via indexed access)
286
- const responseNode = factory.createTypeAliasDeclaration({
287
- name,
288
- type: factory.createIndexedAccessTypeNode(
289
- factory.createTypeReferenceNode(factory.createIdentifier(`${baseName}Responses`), undefined),
290
- factory.createTypeOperatorNode(
291
- ts.SyntaxKind.KeyOfKeyword,
292
- factory.createTypeReferenceNode(factory.createIdentifier(`${baseName}Responses`), undefined),
293
- ),
294
- ),
295
- modifiers: [factory.modifiers.export],
296
- })
297
-
298
- results.push(safePrint(responseNode))
299
- } else {
300
- const responseNode = factory.createTypeAliasDeclaration({
301
- name,
302
- modifiers: [factory.modifiers.export],
303
- type: getUnknownType(unknownType),
304
- })
305
-
306
- results.push(safePrint(responseNode))
307
- }
308
-
309
- return results.join('\n\n')
310
- }
311
-
312
- export const typeGenerator = createReactGenerator<PluginTs>({
313
- name: 'typescript',
314
- Operation({ operation, generator, plugin }) {
315
- const {
316
- options,
317
- options: { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, unknownType, paramsCasing },
318
- } = plugin
319
-
320
- const mode = useMode()
321
- const driver = usePluginDriver()
322
-
323
- const oas = useOas()
324
- const { getSchemas, getFile, getName, getGroup } = useOperationManager(generator)
325
- const schemaManager = useSchemaManager()
326
-
327
- const name = getName(operation, { type: 'type', pluginName: pluginTsName })
328
-
329
- const file = getFile(operation)
330
- const schemas = getSchemas(operation)
331
- const schemaGenerator = new SchemaGenerator(options, {
332
- fabric: generator.context.fabric,
333
- oas,
334
- events: generator.context.events,
335
- plugin,
336
- driver,
337
- mode,
338
- override: options.override,
339
- })
340
-
341
- const operationSchemas = [schemas.pathParams, schemas.queryParams, schemas.headerParams, schemas.statusCodes, schemas.request, schemas.response]
342
- .flat()
343
- .filter(Boolean)
344
-
345
- const mapOperationSchema = ({ name, schema, description, keysToOmit, ...options }: OperationSchemaType) => {
346
- // Apply paramsCasing transformation to pathParams, queryParams, and headerParams (not response)
347
- const shouldTransform = paramsCasing && isParameterSchema(name)
348
- const transformedSchema = shouldTransform ? applyParamsCasing(schema, paramsCasing) : schema
349
-
350
- const tree = schemaGenerator.parse({ schema: transformedSchema, name, parentName: null })
351
- const imports = getImports(tree)
352
- const group = options.operation ? getGroup(options.operation) : undefined
353
-
354
- const type = {
355
- name: schemaManager.getName(name, { type: 'type' }),
356
- typedName: schemaManager.getName(name, { type: 'type' }),
357
- file: schemaManager.getFile(options.operationName || name, { group }),
358
- }
359
124
 
360
125
  return (
361
126
  <>
362
127
  {mode === 'split' &&
363
128
  imports.map((imp) => (
364
- <File.Import key={[name, imp.name, imp.path, imp.isTypeOnly].join('-')} root={file.path} path={imp.path} name={imp.name} isTypeOnly />
129
+ <File.Import key={[name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
365
130
  ))}
366
131
  <Type
367
- name={type.name}
368
- typedName={type.typedName}
369
- description={description}
370
- tree={tree}
371
- schema={transformedSchema}
132
+ name={name}
133
+ node={schema}
372
134
  enumType={enumType}
135
+ enumTypeSuffix={enumTypeSuffix}
373
136
  enumKeyCasing={enumKeyCasing}
374
- optionalType={optionalType}
375
- arrayType={arrayType}
376
- keysToOmit={keysToOmit}
377
- syntaxType={syntaxType}
137
+ resolver={resolver}
138
+ printer={schemaPrinter}
378
139
  />
379
140
  </>
380
141
  )
381
142
  }
382
143
 
383
- const responseName = schemaManager.getName(schemas.response.name, {
384
- type: 'type',
385
- })
386
-
387
- const combinedSchemaName = operation.method === 'get' ? `${name}Query` : `${name}Mutation`
144
+ const paramTypes = params.map((param) =>
145
+ renderSchemaType({
146
+ schema: param.schema,
147
+ name: resolver.resolveParamName(node, param),
148
+ }),
149
+ )
388
150
 
389
- return (
390
- <File
391
- baseName={file.baseName}
392
- path={file.path}
393
- meta={file.meta}
394
- banner={getBanner({ oas, output: plugin.options.output, config: driver.config })}
395
- footer={getFooter({ oas, output: plugin.options.output })}
396
- >
397
- {operationSchemas.map(mapOperationSchema)}
151
+ const requestType = node.requestBody?.content?.[0]?.schema
152
+ ? renderSchemaType({
153
+ schema: {
154
+ ...node.requestBody.content![0]!.schema!,
155
+ description: node.requestBody.description ?? node.requestBody.content![0]!.schema!.description,
156
+ },
157
+ name: resolver.resolveDataName(node),
158
+ keysToOmit: node.requestBody.content![0]!.keysToOmit,
159
+ })
160
+ : null
398
161
 
399
- {generator.context.UNSTABLE_NAMING ? (
400
- <>
401
- <File.Source name={`${name}Request`} isExportable isIndexable isTypeOnly>
402
- {printRequestSchema({ baseName: name, operation, schemas, driver })}
403
- </File.Source>
404
- <File.Source name={responseName} isExportable isIndexable isTypeOnly>
405
- {printResponseSchema({ baseName: name, schemas, driver, unknownType })}
406
- </File.Source>
407
- </>
408
- ) : (
409
- <File.Source name={combinedSchemaName} isExportable isIndexable isTypeOnly>
410
- {printCombinedSchema({ name: combinedSchemaName, schemas, driver })}
411
- </File.Source>
412
- )}
413
- </File>
162
+ const responseTypes = node.responses.map((res) =>
163
+ renderSchemaType({
164
+ schema: res.schema,
165
+ name: resolver.resolveResponseStatusName(node, res.statusCode),
166
+ keysToOmit: res.keysToOmit,
167
+ }),
414
168
  )
415
- },
416
- Schema({ schema, plugin }) {
417
- const {
418
- options: { enumType, enumKeyCasing, syntaxType, optionalType, arrayType, output },
419
- } = plugin
420
- const mode = useMode()
421
169
 
422
- const oas = useOas()
423
- const driver = usePluginDriver()
170
+ const dataType = renderSchemaType({
171
+ schema: buildData({ ...node, parameters: params }, { resolver }),
172
+ name: resolver.resolveRequestConfigName(node),
173
+ })
174
+
175
+ const responsesType = renderSchemaType({
176
+ schema: buildResponses(node, { resolver }),
177
+ name: resolver.resolveResponsesName(node),
178
+ })
424
179
 
425
- const { getName, getFile } = useSchemaManager()
426
- const imports = getImports(schema.tree)
427
- const schemaFromTree = schema.tree.find((item) => item.keyword === schemaKeywords.schema)
180
+ const responseType = (() => {
181
+ if (!node.responses.some((res) => res.schema)) {
182
+ return null
183
+ }
428
184
 
429
- let typedName = getName(schema.name, { type: 'type' })
185
+ const responseName = resolver.resolveResponseName(node)
186
+
187
+ // Skip generating the response union type when an imported component schema
188
+ // has the same resolved name to avoid redeclaration errors.
189
+ const responsesWithSchema = node.responses.filter((res) => res.schema)
190
+ const importedNames = new Set(
191
+ responsesWithSchema.flatMap((res) =>
192
+ res.schema
193
+ ? adapter
194
+ .getImports(res.schema, (schemaName) => ({
195
+ name: resolveImportName(schemaName),
196
+ path: '',
197
+ }))
198
+ .flatMap((imp) => (Array.isArray(imp.name) ? imp.name : [imp.name]))
199
+ : [],
200
+ ),
201
+ )
430
202
 
431
- if (['asConst', 'asPascalConst'].includes(enumType) && schemaFromTree && isKeyword(schemaFromTree, schemaKeywords.enum)) {
432
- typedName = typedName += 'Key' //Suffix for avoiding collisions (https://github.com/kubb-labs/kubb/issues/1873)
433
- }
203
+ if (importedNames.has(responseName)) {
204
+ return null
205
+ }
434
206
 
435
- const type = {
436
- name: getName(schema.name, { type: 'function' }),
437
- typedName,
438
- file: getFile(schema.name),
439
- }
207
+ return renderSchemaType({
208
+ schema: {
209
+ ...buildResponseUnion(node, { resolver })!,
210
+ description: 'Union of all possible responses',
211
+ },
212
+ name: responseName,
213
+ })
214
+ })()
440
215
 
441
216
  return (
442
217
  <File
443
- baseName={type.file.baseName}
444
- path={type.file.path}
445
- meta={type.file.meta}
446
- banner={getBanner({ oas, output, config: driver.config })}
447
- footer={getFooter({ oas, output })}
218
+ baseName={meta.file.baseName}
219
+ path={meta.file.path}
220
+ meta={meta.file.meta}
221
+ banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
222
+ footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
448
223
  >
449
- {mode === 'split' &&
450
- imports.map((imp) => (
451
- <File.Import key={[schema.name, imp.path, imp.isTypeOnly].join('-')} root={type.file.path} path={imp.path} name={imp.name} isTypeOnly />
452
- ))}
453
- <Type
454
- name={type.name}
455
- typedName={type.typedName}
456
- description={schema.value.description}
457
- tree={schema.tree}
458
- schema={schema.value}
459
- enumType={enumType}
460
- enumKeyCasing={enumKeyCasing}
461
- optionalType={optionalType}
462
- arrayType={arrayType}
463
- syntaxType={syntaxType}
464
- />
224
+ {paramTypes}
225
+ {responseTypes}
226
+ {requestType}
227
+ {dataType}
228
+ {responsesType}
229
+ {responseType}
465
230
  </File>
466
231
  )
467
232
  },
package/src/index.ts CHANGED
@@ -1,3 +1,9 @@
1
- export { pluginTs, pluginTsName } from './plugin.ts'
2
- export { resolverTs } from './resolverTs.ts'
3
- export type { PluginTs } from './types.ts'
1
+ export { Enum } from './components/Enum.tsx'
2
+ export { Type } from './components/Type.tsx'
3
+ export { typeGenerator } from './generators/typeGenerator.tsx'
4
+ export { default, pluginTs, pluginTsName } from './plugin.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 type { PluginTs, ResolverTs } from './types.ts'