@kubb/plugin-ts 5.0.0-alpha.1 → 5.0.0-alpha.10
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/{components-LmqJfxMv.js → components-CRu8IKY3.js} +19 -11
- package/dist/components-CRu8IKY3.js.map +1 -0
- package/dist/{components-9wydyqUx.cjs → components-DeNDKlzf.cjs} +144 -10
- package/dist/components-DeNDKlzf.cjs.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +1 -3
- package/dist/components.js +1 -1
- package/dist/generators.cjs +3 -2
- package/dist/generators.d.ts +60 -48
- package/dist/generators.js +2 -2
- package/dist/index.cjs +2 -1
- package/dist/index.d.ts +41 -2
- package/dist/index.js +2 -2
- package/dist/plugin-BZkBwnEA.js +1269 -0
- package/dist/plugin-BZkBwnEA.js.map +1 -0
- package/dist/plugin-Bunz1oGa.cjs +1322 -0
- package/dist/plugin-Bunz1oGa.cjs.map +1 -0
- package/dist/types-mSXmB8WU.d.ts +298 -0
- package/package.json +8 -8
- package/src/components/Type.tsx +0 -3
- package/src/components/v2/Enum.tsx +67 -0
- package/src/components/v2/Type.tsx +59 -0
- package/src/constants.ts +29 -0
- package/src/factory.ts +14 -16
- package/src/generators/index.ts +1 -0
- package/src/generators/typeGenerator.tsx +46 -48
- package/src/generators/v2/typeGenerator.tsx +167 -0
- package/src/generators/v2/utils.ts +140 -0
- package/src/index.ts +1 -0
- package/src/parser.ts +1 -8
- package/src/plugin.ts +64 -17
- package/src/printer.ts +238 -91
- package/src/resolverTs.ts +77 -0
- package/src/types.ts +144 -15
- package/dist/components-9wydyqUx.cjs.map +0 -1
- package/dist/components-LmqJfxMv.js.map +0 -1
- package/dist/plugin-BHE4J4aP.cjs +0 -508
- package/dist/plugin-BHE4J4aP.cjs.map +0 -1
- package/dist/plugin-DnKRpgGK.js +0 -476
- package/dist/plugin-DnKRpgGK.js.map +0 -1
- package/dist/types-BpeKGgCn.d.ts +0 -170
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { pascalCase } from '@internals/utils'
|
|
2
|
+
import { createProperty, createSchema } from '@kubb/ast'
|
|
3
|
+
import type { OperationNode, ParameterNode, SchemaNode } from '@kubb/ast/types'
|
|
4
|
+
|
|
5
|
+
type ResolveName = (opts: { name: string; type: 'type' | 'function' }) => string
|
|
6
|
+
|
|
7
|
+
type BuildParamsSchemaOptions = {
|
|
8
|
+
params: Array<ParameterNode>
|
|
9
|
+
operationId: string
|
|
10
|
+
resolveName: ResolveName
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Builds an `ObjectSchemaNode` for a group of parameters (path/query/header).
|
|
15
|
+
* Each property is a `ref` schema pointing to the individually-resolved parameter type.
|
|
16
|
+
* The ref name includes the parameter location so generated type names follow
|
|
17
|
+
* the `<OperationId><Location><ParamName>` convention.
|
|
18
|
+
*/
|
|
19
|
+
export function buildParamsSchema({ params, operationId, resolveName }: BuildParamsSchemaOptions): SchemaNode {
|
|
20
|
+
return createSchema({
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: params.map((param) =>
|
|
23
|
+
createProperty({
|
|
24
|
+
name: param.name,
|
|
25
|
+
schema: createSchema({
|
|
26
|
+
type: 'ref',
|
|
27
|
+
name: resolveName({ name: `${operationId} ${pascalCase(param.in)} ${param.name}`, type: 'function' }),
|
|
28
|
+
optional: !param.required,
|
|
29
|
+
}),
|
|
30
|
+
}),
|
|
31
|
+
),
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type BuildOperationSchemaOptions = {
|
|
36
|
+
node: OperationNode
|
|
37
|
+
resolveName: ResolveName
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Builds an `ObjectSchemaNode` representing the `<OperationId>RequestConfig` type:
|
|
42
|
+
* - `data` → request body ref (optional) or `never`
|
|
43
|
+
* - `pathParams` → inline object of path param refs, or `never`
|
|
44
|
+
* - `queryParams` → inline object of query param refs (optional), or `never`
|
|
45
|
+
* - `headerParams` → inline object of header param refs (optional), or `never`
|
|
46
|
+
* - `url` → Express-style template literal (plugin-ts extension, handled by printer)
|
|
47
|
+
*/
|
|
48
|
+
export function buildDataSchemaNode({ node, resolveName }: BuildOperationSchemaOptions): SchemaNode {
|
|
49
|
+
const pathParams = node.parameters.filter((p) => p.in === 'path')
|
|
50
|
+
const queryParams = node.parameters.filter((p) => p.in === 'query')
|
|
51
|
+
const headerParams = node.parameters.filter((p) => p.in === 'header')
|
|
52
|
+
|
|
53
|
+
return createSchema({
|
|
54
|
+
type: 'object',
|
|
55
|
+
deprecated: node.deprecated,
|
|
56
|
+
properties: [
|
|
57
|
+
createProperty({
|
|
58
|
+
name: 'data',
|
|
59
|
+
schema: node.requestBody
|
|
60
|
+
? createSchema({
|
|
61
|
+
type: 'ref',
|
|
62
|
+
name: resolveName({ name: `${node.operationId} Data`, type: 'function' }),
|
|
63
|
+
optional: true,
|
|
64
|
+
})
|
|
65
|
+
: createSchema({ type: 'never', optional: true }),
|
|
66
|
+
}),
|
|
67
|
+
createProperty({
|
|
68
|
+
name: 'pathParams',
|
|
69
|
+
schema:
|
|
70
|
+
pathParams.length > 0
|
|
71
|
+
? buildParamsSchema({ params: pathParams, operationId: node.operationId, resolveName })
|
|
72
|
+
: createSchema({ type: 'never', optional: true }),
|
|
73
|
+
}),
|
|
74
|
+
createProperty({
|
|
75
|
+
name: 'queryParams',
|
|
76
|
+
schema:
|
|
77
|
+
queryParams.length > 0
|
|
78
|
+
? createSchema({ ...buildParamsSchema({ params: queryParams, operationId: node.operationId, resolveName }), optional: true })
|
|
79
|
+
: createSchema({ type: 'never', optional: true }),
|
|
80
|
+
}),
|
|
81
|
+
createProperty({
|
|
82
|
+
name: 'headerParams',
|
|
83
|
+
schema:
|
|
84
|
+
headerParams.length > 0
|
|
85
|
+
? createSchema({ ...buildParamsSchema({ params: headerParams, operationId: node.operationId, resolveName }), optional: true })
|
|
86
|
+
: createSchema({ type: 'never', optional: true }),
|
|
87
|
+
}),
|
|
88
|
+
createProperty({
|
|
89
|
+
name: 'url',
|
|
90
|
+
schema: createSchema({ type: 'url', path: node.path }),
|
|
91
|
+
}),
|
|
92
|
+
],
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Builds an `ObjectSchemaNode` representing `<OperationId>Responses` — keyed by HTTP status code.
|
|
98
|
+
* Numeric status codes produce unquoted numeric keys (e.g. `200:`).
|
|
99
|
+
* All responses are included; those without a schema are represented as a ref to a `never` type.
|
|
100
|
+
*/
|
|
101
|
+
export function buildResponsesSchemaNode({ node, resolveName }: BuildOperationSchemaOptions): SchemaNode | null {
|
|
102
|
+
if (node.responses.length === 0) {
|
|
103
|
+
return null
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return createSchema({
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: node.responses.map((res) =>
|
|
109
|
+
createProperty({
|
|
110
|
+
name: String(res.statusCode),
|
|
111
|
+
schema: createSchema({
|
|
112
|
+
type: 'ref',
|
|
113
|
+
name: resolveName({ name: `${node.operationId} Status ${res.statusCode}`, type: 'function' }),
|
|
114
|
+
}),
|
|
115
|
+
}),
|
|
116
|
+
),
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Builds a `UnionSchemaNode` representing `<OperationId>Response` — all response types in union format.
|
|
122
|
+
* Returns `null` when the operation has no responses with schemas.
|
|
123
|
+
*/
|
|
124
|
+
export function buildResponseUnionSchemaNode({ node, resolveName }: BuildOperationSchemaOptions): SchemaNode | null {
|
|
125
|
+
const responsesWithSchema = node.responses.filter((res) => res.schema)
|
|
126
|
+
|
|
127
|
+
if (responsesWithSchema.length === 0) {
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return createSchema({
|
|
132
|
+
type: 'union',
|
|
133
|
+
members: responsesWithSchema.map((res) =>
|
|
134
|
+
createSchema({
|
|
135
|
+
type: 'ref',
|
|
136
|
+
name: resolveName({ name: `${node.operationId} Status ${res.statusCode}`, type: 'function' }),
|
|
137
|
+
}),
|
|
138
|
+
),
|
|
139
|
+
})
|
|
140
|
+
}
|
package/src/index.ts
CHANGED
package/src/parser.ts
CHANGED
|
@@ -159,7 +159,6 @@ type ParserOptions = {
|
|
|
159
159
|
* @note In Kubb v5, `inlineLiteral` becomes the default.
|
|
160
160
|
*/
|
|
161
161
|
enumType: 'enum' | 'asConst' | 'asPascalConst' | 'constEnum' | 'literal' | 'inlineLiteral'
|
|
162
|
-
mapper?: Record<string, ts.PropertySignature>
|
|
163
162
|
}
|
|
164
163
|
|
|
165
164
|
/**
|
|
@@ -170,7 +169,7 @@ type ParserOptions = {
|
|
|
170
169
|
* @param current - The schema node to parse.
|
|
171
170
|
* @param siblings - Sibling schema nodes, used for context in certain mappings.
|
|
172
171
|
* @param name - The name of the schema or property being parsed.
|
|
173
|
-
* @param options - Parsing options controlling output style, property handling
|
|
172
|
+
* @param options - Parsing options controlling output style, property handling.
|
|
174
173
|
* @returns The generated TypeScript AST node, or `undefined` if the schema keyword is not mapped.
|
|
175
174
|
*/
|
|
176
175
|
export const parse = createParser<ts.Node | null, ParserOptions>({
|
|
@@ -254,12 +253,6 @@ export const parse = createParser<ts.Node | null, ParserOptions>({
|
|
|
254
253
|
const nameSchema = schemas.find((schema) => schema.keyword === schemaKeywords.name) as SchemaKeywordMapper['name']
|
|
255
254
|
const mappedName = nameSchema?.args || name
|
|
256
255
|
|
|
257
|
-
// custom mapper(pluginOptions)
|
|
258
|
-
// Use Object.hasOwn to avoid matching inherited properties like 'toString', 'valueOf', etc.
|
|
259
|
-
if (options.mapper && Object.hasOwn(options.mapper, mappedName)) {
|
|
260
|
-
return options.mapper[mappedName]
|
|
261
|
-
}
|
|
262
|
-
|
|
263
256
|
const isNullish = schemas.some((schema) => schema.keyword === schemaKeywords.nullish)
|
|
264
257
|
const isNullable = schemas.some((schema) => schema.keyword === schemaKeywords.nullable)
|
|
265
258
|
const isOptional = schemas.some((schema) => schema.keyword === schemaKeywords.optional)
|
package/src/plugin.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import { camelCase
|
|
2
|
+
import { camelCase } from '@internals/utils'
|
|
3
3
|
import { walk } from '@kubb/ast'
|
|
4
|
-
import {
|
|
5
|
-
import { buildSchema, OperationGenerator, pluginOasName, SchemaGenerator } from '@kubb/plugin-oas'
|
|
6
|
-
import { typeGenerator } from './generators'
|
|
4
|
+
import { createPlugin, type Group, getBarrelFiles, getMode } from '@kubb/core'
|
|
5
|
+
import { buildOperation, buildSchema, OperationGenerator, pluginOasName, SchemaGenerator } from '@kubb/plugin-oas'
|
|
6
|
+
import { typeGenerator, typeGeneratorV2 } from './generators'
|
|
7
|
+
import { resolverTs } from './resolverTs.ts'
|
|
7
8
|
import type { PluginTs } from './types.ts'
|
|
8
9
|
|
|
9
10
|
export const pluginTsName = 'plugin-ts' satisfies PluginTs['name']
|
|
10
11
|
|
|
11
|
-
export const pluginTs =
|
|
12
|
+
export const pluginTs = createPlugin<PluginTs>((options) => {
|
|
12
13
|
const {
|
|
13
14
|
output = { path: 'types', barrelType: 'named' },
|
|
14
15
|
group,
|
|
@@ -26,9 +27,8 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
26
27
|
emptySchemaType = unknownType,
|
|
27
28
|
syntaxType = 'type',
|
|
28
29
|
transformers = {},
|
|
29
|
-
mapper = {},
|
|
30
30
|
paramsCasing,
|
|
31
|
-
generators = [typeGenerator].filter(Boolean),
|
|
31
|
+
generators = [typeGenerator, typeGeneratorV2].filter(Boolean),
|
|
32
32
|
contentType,
|
|
33
33
|
UNSTABLE_NAMING,
|
|
34
34
|
} = options
|
|
@@ -53,7 +53,6 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
53
53
|
syntaxType,
|
|
54
54
|
group,
|
|
55
55
|
override,
|
|
56
|
-
mapper,
|
|
57
56
|
paramsCasing,
|
|
58
57
|
usedEnumNames,
|
|
59
58
|
},
|
|
@@ -93,7 +92,7 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
93
92
|
return path.resolve(root, output.path, baseName)
|
|
94
93
|
},
|
|
95
94
|
resolveName(name, type) {
|
|
96
|
-
const resolvedName =
|
|
95
|
+
const resolvedName = resolverTs.default(name, type)
|
|
97
96
|
|
|
98
97
|
if (type) {
|
|
99
98
|
return transformers?.name?.(resolvedName, type) || resolvedName
|
|
@@ -102,45 +101,93 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
102
101
|
return resolvedName
|
|
103
102
|
},
|
|
104
103
|
async install() {
|
|
105
|
-
const { config, fabric, plugin } = this
|
|
104
|
+
const { config, fabric, plugin, adapter, rootNode, driver, openInStudio } = this
|
|
106
105
|
|
|
107
106
|
const root = path.resolve(config.root, config.output.path)
|
|
108
107
|
const mode = getMode(path.resolve(root, output.path))
|
|
109
108
|
|
|
110
|
-
if (
|
|
111
|
-
await
|
|
109
|
+
if (adapter) {
|
|
110
|
+
await openInStudio({ ast: true })
|
|
112
111
|
|
|
113
112
|
await walk(
|
|
114
|
-
|
|
113
|
+
rootNode,
|
|
115
114
|
{
|
|
116
115
|
async schema(schemaNode) {
|
|
117
116
|
const writeTasks = generators.map(async (generator) => {
|
|
118
117
|
if (generator.type === 'react' && generator.version === '2') {
|
|
118
|
+
const options = resolverTs.resolveOptions(schemaNode, { options: plugin.options, exclude, include, override })
|
|
119
|
+
|
|
120
|
+
if (options === null) {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
119
124
|
await buildSchema(schemaNode, {
|
|
125
|
+
options,
|
|
126
|
+
adapter,
|
|
120
127
|
config,
|
|
121
128
|
fabric,
|
|
122
129
|
Component: generator.Schema,
|
|
123
130
|
plugin,
|
|
131
|
+
driver,
|
|
132
|
+
mode,
|
|
133
|
+
version: generator.version,
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
await Promise.all(writeTasks)
|
|
139
|
+
},
|
|
140
|
+
async operation(operationNode) {
|
|
141
|
+
const writeTasks = generators.map(async (generator) => {
|
|
142
|
+
if (generator.type === 'react' && generator.version === '2') {
|
|
143
|
+
const options = resolverTs.resolveOptions(operationNode, { options: plugin.options, exclude, include, override })
|
|
144
|
+
|
|
145
|
+
if (options === null) {
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
await buildOperation(operationNode, {
|
|
150
|
+
options,
|
|
151
|
+
adapter,
|
|
152
|
+
config,
|
|
153
|
+
fabric,
|
|
154
|
+
Component: generator.Operation,
|
|
155
|
+
plugin,
|
|
156
|
+
driver,
|
|
157
|
+
mode,
|
|
124
158
|
version: generator.version,
|
|
125
159
|
})
|
|
126
160
|
}
|
|
127
161
|
})
|
|
128
162
|
|
|
129
|
-
await writeTasks
|
|
163
|
+
await Promise.all(writeTasks)
|
|
130
164
|
},
|
|
131
165
|
},
|
|
132
166
|
{ depth: 'shallow' },
|
|
133
167
|
)
|
|
134
168
|
|
|
169
|
+
const barrelFiles = await getBarrelFiles(this.fabric.files, {
|
|
170
|
+
type: output.barrelType ?? 'named',
|
|
171
|
+
root,
|
|
172
|
+
output,
|
|
173
|
+
meta: {
|
|
174
|
+
pluginName: this.plugin.name,
|
|
175
|
+
},
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
await this.upsertFile(...barrelFiles)
|
|
179
|
+
|
|
135
180
|
return
|
|
136
181
|
}
|
|
137
182
|
|
|
183
|
+
// v1 flow
|
|
184
|
+
|
|
138
185
|
const oas = await this.getOas()
|
|
139
186
|
|
|
140
187
|
const schemaGenerator = new SchemaGenerator(this.plugin.options, {
|
|
141
188
|
fabric: this.fabric,
|
|
142
189
|
oas,
|
|
143
|
-
|
|
190
|
+
driver: this.driver,
|
|
144
191
|
events: this.events,
|
|
145
192
|
plugin: this.plugin,
|
|
146
193
|
contentType,
|
|
@@ -156,7 +203,7 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
156
203
|
const operationGenerator = new OperationGenerator(this.plugin.options, {
|
|
157
204
|
fabric: this.fabric,
|
|
158
205
|
oas,
|
|
159
|
-
|
|
206
|
+
driver: this.driver,
|
|
160
207
|
events: this.events,
|
|
161
208
|
plugin: this.plugin,
|
|
162
209
|
contentType,
|
|
@@ -175,7 +222,7 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
175
222
|
root,
|
|
176
223
|
output,
|
|
177
224
|
meta: {
|
|
178
|
-
|
|
225
|
+
pluginName: this.plugin.name,
|
|
179
226
|
},
|
|
180
227
|
})
|
|
181
228
|
|