@kubb/plugin-ts 5.0.0-alpha.1 → 5.0.0-alpha.11
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-CJ29AwE2.cjs +1320 -0
- package/dist/plugin-CJ29AwE2.cjs.map +1 -0
- package/dist/plugin-D60XNJSD.js +1267 -0
- package/dist/plugin-D60XNJSD.js.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 -19
- 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 {
|
|
6
|
-
import { typeGenerator } from './generators'
|
|
4
|
+
import { createPlugin, type Group, getBarrelFiles, getMode, renderOperation, renderSchema } from '@kubb/core'
|
|
5
|
+
import { 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,91 @@ 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') {
|
|
119
|
-
|
|
118
|
+
const options = resolverTs.resolveOptions(schemaNode, { options: plugin.options, exclude, include, override })
|
|
119
|
+
|
|
120
|
+
if (options === null) {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
await renderSchema(schemaNode, {
|
|
125
|
+
options,
|
|
126
|
+
adapter,
|
|
120
127
|
config,
|
|
121
128
|
fabric,
|
|
122
129
|
Component: generator.Schema,
|
|
123
130
|
plugin,
|
|
124
|
-
|
|
131
|
+
driver,
|
|
132
|
+
mode,
|
|
125
133
|
})
|
|
126
134
|
}
|
|
127
135
|
})
|
|
128
136
|
|
|
129
|
-
await writeTasks
|
|
137
|
+
await Promise.all(writeTasks)
|
|
138
|
+
},
|
|
139
|
+
async operation(operationNode) {
|
|
140
|
+
const writeTasks = generators.map(async (generator) => {
|
|
141
|
+
if (generator.type === 'react' && generator.version === '2') {
|
|
142
|
+
const options = resolverTs.resolveOptions(operationNode, { options: plugin.options, exclude, include, override })
|
|
143
|
+
|
|
144
|
+
if (options === null) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
await renderOperation(operationNode, {
|
|
149
|
+
options,
|
|
150
|
+
adapter,
|
|
151
|
+
config,
|
|
152
|
+
fabric,
|
|
153
|
+
Component: generator.Operation,
|
|
154
|
+
plugin,
|
|
155
|
+
driver,
|
|
156
|
+
mode,
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
await Promise.all(writeTasks)
|
|
130
162
|
},
|
|
131
163
|
},
|
|
132
164
|
{ depth: 'shallow' },
|
|
133
165
|
)
|
|
134
166
|
|
|
167
|
+
const barrelFiles = await getBarrelFiles(this.fabric.files, {
|
|
168
|
+
type: output.barrelType ?? 'named',
|
|
169
|
+
root,
|
|
170
|
+
output,
|
|
171
|
+
meta: {
|
|
172
|
+
pluginName: this.plugin.name,
|
|
173
|
+
},
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
await this.upsertFile(...barrelFiles)
|
|
177
|
+
|
|
135
178
|
return
|
|
136
179
|
}
|
|
137
180
|
|
|
181
|
+
// v1 flow
|
|
182
|
+
|
|
138
183
|
const oas = await this.getOas()
|
|
139
184
|
|
|
140
185
|
const schemaGenerator = new SchemaGenerator(this.plugin.options, {
|
|
141
186
|
fabric: this.fabric,
|
|
142
187
|
oas,
|
|
143
|
-
|
|
188
|
+
driver: this.driver,
|
|
144
189
|
events: this.events,
|
|
145
190
|
plugin: this.plugin,
|
|
146
191
|
contentType,
|
|
@@ -156,7 +201,7 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
156
201
|
const operationGenerator = new OperationGenerator(this.plugin.options, {
|
|
157
202
|
fabric: this.fabric,
|
|
158
203
|
oas,
|
|
159
|
-
|
|
204
|
+
driver: this.driver,
|
|
160
205
|
events: this.events,
|
|
161
206
|
plugin: this.plugin,
|
|
162
207
|
contentType,
|
|
@@ -175,7 +220,7 @@ export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
|
175
220
|
root,
|
|
176
221
|
output,
|
|
177
222
|
meta: {
|
|
178
|
-
|
|
223
|
+
pluginName: this.plugin.name,
|
|
179
224
|
},
|
|
180
225
|
})
|
|
181
226
|
|