@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.
Files changed (41) hide show
  1. package/dist/{components-LmqJfxMv.js → components-CRu8IKY3.js} +19 -11
  2. package/dist/components-CRu8IKY3.js.map +1 -0
  3. package/dist/{components-9wydyqUx.cjs → components-DeNDKlzf.cjs} +144 -10
  4. package/dist/components-DeNDKlzf.cjs.map +1 -0
  5. package/dist/components.cjs +1 -1
  6. package/dist/components.d.ts +1 -3
  7. package/dist/components.js +1 -1
  8. package/dist/generators.cjs +3 -2
  9. package/dist/generators.d.ts +60 -48
  10. package/dist/generators.js +2 -2
  11. package/dist/index.cjs +2 -1
  12. package/dist/index.d.ts +41 -2
  13. package/dist/index.js +2 -2
  14. package/dist/plugin-BZkBwnEA.js +1269 -0
  15. package/dist/plugin-BZkBwnEA.js.map +1 -0
  16. package/dist/plugin-Bunz1oGa.cjs +1322 -0
  17. package/dist/plugin-Bunz1oGa.cjs.map +1 -0
  18. package/dist/types-mSXmB8WU.d.ts +298 -0
  19. package/package.json +8 -8
  20. package/src/components/Type.tsx +0 -3
  21. package/src/components/v2/Enum.tsx +67 -0
  22. package/src/components/v2/Type.tsx +59 -0
  23. package/src/constants.ts +29 -0
  24. package/src/factory.ts +14 -16
  25. package/src/generators/index.ts +1 -0
  26. package/src/generators/typeGenerator.tsx +46 -48
  27. package/src/generators/v2/typeGenerator.tsx +167 -0
  28. package/src/generators/v2/utils.ts +140 -0
  29. package/src/index.ts +1 -0
  30. package/src/parser.ts +1 -8
  31. package/src/plugin.ts +64 -17
  32. package/src/printer.ts +238 -91
  33. package/src/resolverTs.ts +77 -0
  34. package/src/types.ts +144 -15
  35. package/dist/components-9wydyqUx.cjs.map +0 -1
  36. package/dist/components-LmqJfxMv.js.map +0 -1
  37. package/dist/plugin-BHE4J4aP.cjs +0 -508
  38. package/dist/plugin-BHE4J4aP.cjs.map +0 -1
  39. package/dist/plugin-DnKRpgGK.js +0 -476
  40. package/dist/plugin-DnKRpgGK.js.map +0 -1
  41. 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
@@ -1,2 +1,3 @@
1
1
  export { pluginTs, pluginTsName } from './plugin.ts'
2
+ export { resolverTs } from './resolverTs.ts'
2
3
  export type { PluginTs } from './types.ts'
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, and custom mappers.
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, pascalCase } from '@internals/utils'
2
+ import { camelCase } from '@internals/utils'
3
3
  import { walk } from '@kubb/ast'
4
- import { definePlugin, type Group, getBarrelFiles, getMode } from '@kubb/core'
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 = definePlugin<PluginTs>((options) => {
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 = pascalCase(name, { isFile: type === 'file' })
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 (this.rootNode) {
111
- await this.openInStudio({ ast: true })
109
+ if (adapter) {
110
+ await openInStudio({ ast: true })
112
111
 
113
112
  await walk(
114
- this.rootNode,
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
- pluginManager: this.pluginManager,
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
- pluginManager: this.pluginManager,
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
- pluginKey: this.plugin.key,
225
+ pluginName: this.plugin.name,
179
226
  },
180
227
  })
181
228