@kubb/plugin-ts 5.0.0-alpha.3 → 5.0.0-alpha.31
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.
- package/dist/index.cjs +1806 -3
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +590 -4
- package/dist/index.js +1776 -2
- package/dist/index.js.map +1 -0
- package/package.json +7 -27
- package/src/components/Enum.tsx +82 -0
- package/src/components/Type.tsx +29 -162
- package/src/constants.ts +39 -0
- package/src/factory.ts +134 -49
- package/src/generators/typeGenerator.tsx +165 -428
- package/src/generators/typeGeneratorLegacy.tsx +349 -0
- package/src/index.ts +9 -1
- package/src/plugin.ts +98 -176
- package/src/presets.ts +28 -0
- package/src/printers/functionPrinter.ts +196 -0
- package/src/printers/printerTs.ts +310 -0
- package/src/resolvers/resolverTs.ts +66 -0
- package/src/resolvers/resolverTsLegacy.ts +60 -0
- package/src/types.ts +258 -98
- package/src/utils.ts +131 -0
- package/dist/components-CRjwjdyE.js +0 -725
- package/dist/components-CRjwjdyE.js.map +0 -1
- package/dist/components-DI0aTIBg.cjs +0 -978
- package/dist/components-DI0aTIBg.cjs.map +0 -1
- package/dist/components.cjs +0 -3
- package/dist/components.d.ts +0 -38
- package/dist/components.js +0 -2
- package/dist/generators.cjs +0 -4
- package/dist/generators.d.ts +0 -503
- package/dist/generators.js +0 -2
- package/dist/plugin-D5rCK1zO.cjs +0 -992
- package/dist/plugin-D5rCK1zO.cjs.map +0 -1
- package/dist/plugin-DmwgRHK8.js +0 -944
- package/dist/plugin-DmwgRHK8.js.map +0 -1
- package/dist/types-BpeKGgCn.d.ts +0 -170
- package/src/components/index.ts +0 -1
- package/src/components/v2/Type.tsx +0 -165
- package/src/generators/index.ts +0 -2
- package/src/generators/v2/typeGenerator.tsx +0 -196
- package/src/parser.ts +0 -396
- 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
|
|
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
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
printer,
|
|
43
|
+
compatibilityPreset = 'default',
|
|
44
|
+
resolver: userResolver,
|
|
45
|
+
transformer: userTransformer,
|
|
46
|
+
generators: userGenerators = [],
|
|
34
47
|
} = options
|
|
35
48
|
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
116
|
+
return this.plugin.resolver.default(name, type)
|
|
104
117
|
},
|
|
105
|
-
async
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
+
})
|