@kubb/plugin-ts 5.0.0-alpha.29 → 5.0.0-alpha.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-ts",
3
- "version": "5.0.0-alpha.29",
3
+ "version": "5.0.0-alpha.30",
4
4
  "description": "TypeScript code generation plugin for Kubb, transforming OpenAPI schemas into TypeScript interfaces, types, and utility functions.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -53,8 +53,8 @@
53
53
  "@kubb/react-fabric": "0.15.1",
54
54
  "remeda": "^2.33.7",
55
55
  "typescript": "5.9.3",
56
- "@kubb/ast": "5.0.0-alpha.29",
57
- "@kubb/core": "5.0.0-alpha.29"
56
+ "@kubb/ast": "5.0.0-alpha.30",
57
+ "@kubb/core": "5.0.0-alpha.30"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@kubb/react-fabric": "0.15.1"
@@ -1,7 +1,6 @@
1
- import path from 'node:path'
2
- import { caseParams, narrowSchema, schemaTypes, transform } from '@kubb/ast'
1
+ import { caseParams, narrowSchema, schemaTypes } from '@kubb/ast'
3
2
  import type { SchemaNode } from '@kubb/ast/types'
4
- import { defineGenerator, getMode } from '@kubb/core'
3
+ import { defineGenerator } from '@kubb/core'
5
4
  import { File } from '@kubb/react-fabric'
6
5
  import { Type } from '../components/Type.tsx'
7
6
  import { ENUM_TYPES_WITH_KEY_SUFFIX } from '../constants.ts'
@@ -11,18 +10,14 @@ import { buildData, buildResponses, buildResponseUnion } from '../utils.ts'
11
10
 
12
11
  export const typeGenerator = defineGenerator<PluginTs>({
13
12
  name: 'typescript',
14
- type: 'react',
15
- Schema({ node, adapter, options, config, resolver, plugin }) {
13
+ schema(node, options) {
16
14
  const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, printer } = options
15
+ const { adapter, config, resolver, root } = this
17
16
 
18
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node
19
-
20
- if (!transformedNode.name) {
17
+ if (!node.name) {
21
18
  return
22
19
  }
23
-
24
- const root = path.resolve(config.root, config.output.path)
25
- const mode = getMode(path.resolve(root, output.path))
20
+ const mode = this.getMode(output)
26
21
  // Build a set of schema names that are enums so the ref handler and getImports
27
22
  // callback can use the suffixed type name (e.g. `StatusKey`) for those refs.
28
23
  const enumSchemaNames = new Set((adapter.rootNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name!))
@@ -34,19 +29,16 @@ export const typeGenerator = defineGenerator<PluginTs>({
34
29
  return resolver.resolveTypeName(schemaName)
35
30
  }
36
31
 
37
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
32
+ const imports = adapter.getImports(node, (schemaName) => ({
38
33
  name: resolveImportName(schemaName),
39
34
  path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
40
35
  }))
41
36
 
42
- const isEnumSchema = !!narrowSchema(transformedNode, schemaTypes.enum)
37
+ const isEnumSchema = !!narrowSchema(node, schemaTypes.enum)
43
38
 
44
39
  const meta = {
45
- name:
46
- ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema
47
- ? resolver.resolveEnumKeyName(transformedNode, enumTypeSuffix)
48
- : resolver.resolveTypeName(transformedNode.name),
49
- file: resolver.resolveFile({ name: transformedNode.name, extname: '.ts' }, { root, output, group }),
40
+ name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveTypeName(node.name),
41
+ file: resolver.resolveFile({ name: node.name, extname: '.ts' }, { root, output, group }),
50
42
  } as const
51
43
 
52
44
  const schemaPrinter = printerTs({
@@ -56,7 +48,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
56
48
  enumTypeSuffix,
57
49
  name: meta.name,
58
50
  syntaxType,
59
- description: transformedNode.description,
51
+ description: node.description,
60
52
  resolver,
61
53
  enumSchemaNames,
62
54
  nodes: printer?.nodes,
@@ -72,11 +64,11 @@ export const typeGenerator = defineGenerator<PluginTs>({
72
64
  >
73
65
  {mode === 'split' &&
74
66
  imports.map((imp) => (
75
- <File.Import key={[transformedNode.name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
67
+ <File.Import key={[node.name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
76
68
  ))}
77
69
  <Type
78
70
  name={meta.name}
79
- node={transformedNode}
71
+ node={node}
80
72
  enumType={enumType}
81
73
  enumTypeSuffix={enumTypeSuffix}
82
74
  enumKeyCasing={enumKeyCasing}
@@ -86,21 +78,16 @@ export const typeGenerator = defineGenerator<PluginTs>({
86
78
  </File>
87
79
  )
88
80
  },
89
- Operation({ node, adapter, options, config, resolver, plugin }) {
81
+ operation(node, options) {
90
82
  const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, printer } = options
83
+ const { adapter, config, resolver, root } = this
91
84
 
92
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node
93
-
94
- const root = path.resolve(config.root, config.output.path)
95
- const mode = getMode(path.resolve(root, output.path))
85
+ const mode = this.getMode(output)
96
86
 
97
- const params = caseParams(transformedNode.parameters, paramsCasing)
87
+ const params = caseParams(node.parameters, paramsCasing)
98
88
 
99
89
  const meta = {
100
- file: resolver.resolveFile(
101
- { name: transformedNode.operationId, extname: '.ts', tag: transformedNode.tags[0] ?? 'default', path: transformedNode.path },
102
- { root, output, group },
103
- ),
90
+ file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
104
91
  } as const
105
92
 
106
93
  // Build a set of schema names that are enums so the ref handler and getImports
@@ -158,47 +145,47 @@ export const typeGenerator = defineGenerator<PluginTs>({
158
145
  const paramTypes = params.map((param) =>
159
146
  renderSchemaType({
160
147
  schema: param.schema,
161
- name: resolver.resolveParamName(transformedNode, param),
148
+ name: resolver.resolveParamName(node, param),
162
149
  }),
163
150
  )
164
151
 
165
- const requestType = transformedNode.requestBody?.schema
152
+ const requestType = node.requestBody?.schema
166
153
  ? renderSchemaType({
167
154
  schema: {
168
- ...transformedNode.requestBody.schema,
169
- description: transformedNode.requestBody.description ?? transformedNode.requestBody.schema.description,
155
+ ...node.requestBody.schema,
156
+ description: node.requestBody.description ?? node.requestBody.schema.description,
170
157
  },
171
- name: resolver.resolveDataName(transformedNode),
172
- keysToOmit: transformedNode.requestBody.keysToOmit,
158
+ name: resolver.resolveDataName(node),
159
+ keysToOmit: node.requestBody.keysToOmit,
173
160
  })
174
161
  : null
175
162
 
176
- const responseTypes = transformedNode.responses.map((res) =>
163
+ const responseTypes = node.responses.map((res) =>
177
164
  renderSchemaType({
178
165
  schema: res.schema,
179
- name: resolver.resolveResponseStatusName(transformedNode, res.statusCode),
166
+ name: resolver.resolveResponseStatusName(node, res.statusCode),
180
167
  keysToOmit: res.keysToOmit,
181
168
  }),
182
169
  )
183
170
 
184
171
  const dataType = renderSchemaType({
185
- schema: buildData({ ...transformedNode, parameters: params }, { resolver }),
186
- name: resolver.resolveRequestConfigName(transformedNode),
172
+ schema: buildData({ ...node, parameters: params }, { resolver }),
173
+ name: resolver.resolveRequestConfigName(node),
187
174
  })
188
175
 
189
176
  const responsesType = renderSchemaType({
190
- schema: buildResponses(transformedNode, { resolver }),
191
- name: resolver.resolveResponsesName(transformedNode),
177
+ schema: buildResponses(node, { resolver }),
178
+ name: resolver.resolveResponsesName(node),
192
179
  })
193
180
 
194
181
  const responseType = renderSchemaType({
195
- schema: transformedNode.responses.some((res) => res.schema)
182
+ schema: node.responses.some((res) => res.schema)
196
183
  ? {
197
- ...buildResponseUnion(transformedNode, { resolver })!,
184
+ ...buildResponseUnion(node, { resolver })!,
198
185
  description: 'Union of all possible responses',
199
186
  }
200
187
  : null,
201
- name: resolver.resolveResponseName(transformedNode),
188
+ name: resolver.resolveResponseName(node),
202
189
  })
203
190
 
204
191
  return (
@@ -1,8 +1,7 @@
1
- import path from 'node:path'
2
1
  import { pascalCase } from '@internals/utils'
3
2
  import { caseParams, createProperty, createSchema, narrowSchema, schemaTypes, transform } from '@kubb/ast'
4
3
  import type { OperationNode, ParameterNode, SchemaNode } from '@kubb/ast/types'
5
- import { defineGenerator, getMode } from '@kubb/core'
4
+ import { defineGenerator } from '@kubb/core'
6
5
  import { File } from '@kubb/react-fabric'
7
6
  import { Type } from '../components/Type.tsx'
8
7
  import { ENUM_TYPES_WITH_KEY_SUFFIX } from '../constants.ts'
@@ -158,32 +157,26 @@ function nameUnnamedEnums(node: SchemaNode, parentName: string): SchemaNode {
158
157
 
159
158
  export const typeGeneratorLegacy = defineGenerator<PluginTs>({
160
159
  name: 'typescript-legacy',
161
- type: 'react',
162
- Schema({ node, adapter, options, config, resolver, plugin }) {
160
+ schema(node, options) {
163
161
  const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group } = options
162
+ const { adapter, config, resolver, root } = this
164
163
 
165
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node
166
-
167
- if (!transformedNode.name) {
164
+ if (!node.name) {
168
165
  return
169
166
  }
170
167
 
171
- const root = path.resolve(config.root, config.output.path)
172
- const mode = getMode(path.resolve(root, output.path))
168
+ const mode = this.getMode(output)
173
169
 
174
- const imports = adapter.getImports(transformedNode, (schemaName) => ({
170
+ const imports = adapter.getImports(node, (schemaName) => ({
175
171
  name: resolver.resolveTypeName(schemaName),
176
172
  path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
177
173
  }))
178
174
 
179
- const isEnumSchema = !!narrowSchema(transformedNode, schemaTypes.enum)
175
+ const isEnumSchema = !!narrowSchema(node, schemaTypes.enum)
180
176
 
181
177
  const meta = {
182
- name:
183
- ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema
184
- ? resolver.resolveEnumKeyName(transformedNode, enumTypeSuffix)
185
- : resolver.resolveTypeName(transformedNode.name),
186
- file: resolver.resolveFile({ name: transformedNode.name, extname: '.ts' }, { root, output, group }),
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 }),
187
180
  } as const
188
181
 
189
182
  const schemaPrinter = printerTs({
@@ -193,7 +186,7 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
193
186
  enumTypeSuffix,
194
187
  name: meta.name,
195
188
  syntaxType,
196
- description: transformedNode.description,
189
+ description: node.description,
197
190
  resolver,
198
191
  })
199
192
 
@@ -207,11 +200,11 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
207
200
  >
208
201
  {mode === 'split' &&
209
202
  imports.map((imp) => (
210
- <File.Import key={[transformedNode.name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
203
+ <File.Import key={[node.name, imp.path, imp.isTypeOnly].join('-')} root={meta.file.path} path={imp.path} name={imp.name} isTypeOnly />
211
204
  ))}
212
205
  <Type
213
206
  name={meta.name}
214
- node={transformedNode}
207
+ node={node}
215
208
  enumType={enumType}
216
209
  enumTypeSuffix={enumTypeSuffix}
217
210
  enumKeyCasing={enumKeyCasing}
@@ -221,20 +214,15 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
221
214
  </File>
222
215
  )
223
216
  },
224
- Operation({ node, adapter, options, config, resolver, plugin }) {
217
+ operation(node, options) {
225
218
  const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output } = options
219
+ const { adapter, config, resolver, root } = this
226
220
 
227
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node
228
-
229
- const root = path.resolve(config.root, config.output.path)
230
- const mode = getMode(path.resolve(root, output.path))
221
+ const mode = this.getMode(output)
231
222
  const params = caseParams(node.parameters, paramsCasing)
232
223
 
233
224
  const meta = {
234
- file: resolver.resolveFile(
235
- { name: transformedNode.operationId, extname: '.ts', tag: transformedNode.tags[0] ?? 'default', path: transformedNode.path },
236
- { root, output, group },
237
- ),
225
+ file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
238
226
  } as const
239
227
 
240
228
  function renderSchemaType({
package/src/plugin.ts CHANGED
@@ -1,8 +1,6 @@
1
- import path from 'node:path'
2
1
  import { camelCase } from '@internals/utils'
3
- import { walk } from '@kubb/ast'
4
- import type { OperationNode } from '@kubb/ast/types'
5
- import { createPlugin, type Group, getBarrelFiles, getPreset, runGeneratorOperation, runGeneratorOperations, runGeneratorSchema } from '@kubb/core'
2
+ import { createPlugin, type Group, getPreset, mergeGenerators } from '@kubb/core'
3
+ import { version } from '../package.json'
6
4
  import { presets } from './presets.ts'
7
5
  import type { PluginTs } from './types.ts'
8
6
 
@@ -56,11 +54,15 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
56
54
  generators: userGenerators,
57
55
  })
58
56
 
57
+ const generators = preset.generators ?? []
58
+ const mergedGenerator = mergeGenerators(generators)
59
+
59
60
  let resolveNameWarning = false
60
61
  let resolvePathWarning = false
61
62
 
62
63
  return {
63
64
  name: pluginTsName,
65
+ version,
64
66
  get resolver() {
65
67
  return preset.resolver
66
68
  },
@@ -70,6 +72,9 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
70
72
  get options() {
71
73
  return {
72
74
  output,
75
+ exclude,
76
+ include,
77
+ override,
73
78
  optionalType,
74
79
  group: group
75
80
  ? ({
@@ -93,65 +98,34 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
93
98
  },
94
99
  resolvePath(baseName, pathMode, options) {
95
100
  if (!resolvePathWarning) {
96
- this.events.emit('warn', 'Do not use resolvePath for pluginTs, use resolverTs.resolvePath instead')
101
+ this.warn('Do not use resolvePath for pluginTs, use resolverTs.resolvePath instead')
97
102
  resolvePathWarning = true
98
103
  }
99
104
 
100
105
  return this.plugin.resolver.resolvePath(
101
106
  { baseName, pathMode, tag: options?.group?.tag, path: options?.group?.path },
102
- { root: path.resolve(this.config.root, this.config.output.path), output, group: this.plugin.options.group },
107
+ { root: this.root, output, group: this.plugin.options.group },
103
108
  )
104
109
  },
105
110
  resolveName(name, type) {
106
111
  if (!resolveNameWarning) {
107
- this.events.emit('warn', 'Do not use resolveName for pluginTs, use resolverTs.default instead')
112
+ this.warn('Do not use resolveName for pluginTs, use resolverTs.default instead')
108
113
  resolveNameWarning = true
109
114
  }
110
115
 
111
116
  return this.plugin.resolver.default(name, type)
112
117
  },
113
- async install() {
114
- const { config, fabric, plugin, adapter, rootNode, driver, openInStudio, resolver } = this
115
-
116
- const root = path.resolve(config.root, config.output.path)
117
-
118
- if (!adapter) {
119
- throw new Error(`[${pluginTsName}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`)
120
- }
121
-
122
- await openInStudio({ ast: true })
123
-
124
- const collectedOperations: Array<OperationNode> = []
125
- const generatorContext = { generators: preset.generators, plugin, resolver, exclude, include, override, fabric, adapter, config, driver }
126
-
127
- await walk(rootNode, {
128
- depth: 'shallow',
129
- async schema(schemaNode) {
130
- await runGeneratorSchema(schemaNode, generatorContext)
131
- },
132
- async operation(operationNode) {
133
- const baseOptions = resolver.resolveOptions(operationNode, { options: plugin.options, exclude, include, override })
134
-
135
- if (baseOptions !== null) {
136
- collectedOperations.push(operationNode)
137
- }
138
-
139
- await runGeneratorOperation(operationNode, generatorContext)
140
- },
141
- })
142
-
143
- await runGeneratorOperations(collectedOperations, generatorContext)
144
-
145
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
146
- type: output.barrelType ?? 'named',
147
- root,
148
- output,
149
- meta: {
150
- pluginName: this.plugin.name,
151
- },
152
- })
153
-
154
- 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 })
155
129
  },
156
130
  }
157
131
  })
package/src/types.ts CHANGED
@@ -276,7 +276,7 @@ export type Options = {
276
276
  */
277
277
  transformer?: Visitor
278
278
  /**
279
- * Override individual printer node handlers to customise rendering of specific schema types.
279
+ * Override individual printer node handlers to customize rendering of specific schema types.
280
280
  *
281
281
  * Each key is a `SchemaType` (e.g. `'date'`, `'string'`). The function replaces the
282
282
  * built-in handler for that type. Use `this.transform` to recurse into nested schema nodes.
@@ -302,6 +302,9 @@ export type Options = {
302
302
 
303
303
  type ResolvedOptions = {
304
304
  output: Output
305
+ exclude: Array<Exclude>
306
+ include: Array<Include> | undefined
307
+ override: Array<Override<ResolvedOptions>>
305
308
  group: Group | undefined
306
309
  enumType: NonNullable<Options['enumType']>
307
310
  enumTypeSuffix: NonNullable<Options['enumTypeSuffix']>
@@ -314,3 +317,11 @@ type ResolvedOptions = {
314
317
  }
315
318
 
316
319
  export type PluginTs = PluginFactoryOptions<'plugin-ts', Options, ResolvedOptions, never, ResolvePathOptions, ResolverTs>
320
+
321
+ declare global {
322
+ namespace Kubb {
323
+ interface PluginRegistry {
324
+ 'plugin-ts': PluginTs
325
+ }
326
+ }
327
+ }