@kubb/plugin-ts 5.0.0-alpha.22 → 5.0.0-alpha.23

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 (66) hide show
  1. package/dist/index.cjs +1668 -49
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.ts +466 -4
  4. package/dist/index.js +1641 -52
  5. package/dist/index.js.map +1 -1
  6. package/package.json +3 -42
  7. package/src/components/Enum.tsx +1 -1
  8. package/src/components/Type.tsx +3 -5
  9. package/src/generators/typeGenerator.tsx +10 -22
  10. package/src/generators/typeGeneratorLegacy.tsx +28 -38
  11. package/src/index.ts +13 -1
  12. package/src/plugin.ts +42 -23
  13. package/src/presets.ts +16 -34
  14. package/src/printers/functionPrinter.ts +194 -0
  15. package/src/printers/printerTs.ts +6 -6
  16. package/src/resolvers/resolverTs.ts +10 -47
  17. package/src/resolvers/resolverTsLegacy.ts +4 -31
  18. package/src/types.ts +85 -225
  19. package/src/utils.ts +103 -0
  20. package/dist/Type-Bf8raoQX.cjs +0 -124
  21. package/dist/Type-Bf8raoQX.cjs.map +0 -1
  22. package/dist/Type-BpXxT4l_.js +0 -113
  23. package/dist/Type-BpXxT4l_.js.map +0 -1
  24. package/dist/builderTs-COUg3xtQ.cjs +0 -135
  25. package/dist/builderTs-COUg3xtQ.cjs.map +0 -1
  26. package/dist/builderTs-DPpkJKd1.js +0 -131
  27. package/dist/builderTs-DPpkJKd1.js.map +0 -1
  28. package/dist/builders.cjs +0 -3
  29. package/dist/builders.d.ts +0 -23
  30. package/dist/builders.js +0 -2
  31. package/dist/casing-BJHFg-zZ.js +0 -84
  32. package/dist/casing-BJHFg-zZ.js.map +0 -1
  33. package/dist/casing-DHfdqpLi.cjs +0 -107
  34. package/dist/casing-DHfdqpLi.cjs.map +0 -1
  35. package/dist/chunk-ByKO4r7w.cjs +0 -38
  36. package/dist/components.cjs +0 -4
  37. package/dist/components.d.ts +0 -71
  38. package/dist/components.js +0 -2
  39. package/dist/generators-DFDut8o-.js +0 -555
  40. package/dist/generators-DFDut8o-.js.map +0 -1
  41. package/dist/generators-DKd7MYbx.cjs +0 -567
  42. package/dist/generators-DKd7MYbx.cjs.map +0 -1
  43. package/dist/generators.cjs +0 -4
  44. package/dist/generators.d.ts +0 -12
  45. package/dist/generators.js +0 -2
  46. package/dist/printerTs-BcHudagv.cjs +0 -594
  47. package/dist/printerTs-BcHudagv.cjs.map +0 -1
  48. package/dist/printerTs-CMBCOuqd.js +0 -558
  49. package/dist/printerTs-CMBCOuqd.js.map +0 -1
  50. package/dist/printers.cjs +0 -3
  51. package/dist/printers.d.ts +0 -81
  52. package/dist/printers.js +0 -2
  53. package/dist/resolverTsLegacy-CPiqqsO6.js +0 -185
  54. package/dist/resolverTsLegacy-CPiqqsO6.js.map +0 -1
  55. package/dist/resolverTsLegacy-CuR9XbKk.cjs +0 -196
  56. package/dist/resolverTsLegacy-CuR9XbKk.cjs.map +0 -1
  57. package/dist/resolvers.cjs +0 -4
  58. package/dist/resolvers.d.ts +0 -52
  59. package/dist/resolvers.js +0 -2
  60. package/dist/types-CRtcZOCz.d.ts +0 -374
  61. package/src/builders/builderTs.ts +0 -107
  62. package/src/builders/index.ts +0 -1
  63. package/src/components/index.ts +0 -2
  64. package/src/generators/index.ts +0 -2
  65. package/src/printers/index.ts +0 -1
  66. package/src/resolvers/index.ts +0 -2
@@ -47,20 +47,20 @@ function buildLegacyResponsesSchemaNode({ node, resolver }: BuildOperationSchema
47
47
  const responseSchema =
48
48
  successResponses.length > 0
49
49
  ? successResponses.length === 1
50
- ? createSchema({ type: 'ref', name: resolver.resolveResponseStatusTypedName(node, successResponses[0]!.statusCode) })
50
+ ? createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
51
51
  : createSchema({
52
52
  type: 'union',
53
- members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusTypedName(node, res.statusCode) })),
53
+ members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
54
54
  })
55
55
  : createSchema({ type: 'any' })
56
56
 
57
57
  const errorsSchema =
58
58
  errorResponses.length > 0
59
59
  ? errorResponses.length === 1
60
- ? createSchema({ type: 'ref', name: resolver.resolveResponseStatusTypedName(node, errorResponses[0]!.statusCode) })
60
+ ? createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, errorResponses[0]!.statusCode) })
61
61
  : createSchema({
62
62
  type: 'union',
63
- members: errorResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusTypedName(node, res.statusCode) })),
63
+ members: errorResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
64
64
  })
65
65
  : createSchema({ type: 'any' })
66
66
 
@@ -71,37 +71,40 @@ function buildLegacyResponsesSchemaNode({ node, resolver }: BuildOperationSchema
71
71
  createProperty({
72
72
  name: 'Request',
73
73
  required: true,
74
- schema: createSchema({ type: 'ref', name: resolver.resolveDataTypedName(node) }),
74
+ schema: createSchema({ type: 'ref', name: resolver.resolveDataName(node) }),
75
75
  }),
76
76
  )
77
77
  }
78
78
 
79
- if (node.parameters.some((p) => p.in === 'query') && resolver.resolveQueryParamsTypedName) {
79
+ const queryParam = node.parameters.find((p) => p.in === 'query')
80
+ if (queryParam) {
80
81
  properties.push(
81
82
  createProperty({
82
83
  name: 'QueryParams',
83
84
  required: true,
84
- schema: createSchema({ type: 'ref', name: resolver.resolveQueryParamsTypedName(node) }),
85
+ schema: createSchema({ type: 'ref', name: resolver.resolveQueryParamsName(node, queryParam) }),
85
86
  }),
86
87
  )
87
88
  }
88
89
 
89
- if (node.parameters.some((p) => p.in === 'path') && resolver.resolvePathParamsTypedName) {
90
+ const pathParam = node.parameters.find((p) => p.in === 'path')
91
+ if (pathParam) {
90
92
  properties.push(
91
93
  createProperty({
92
94
  name: 'PathParams',
93
95
  required: true,
94
- schema: createSchema({ type: 'ref', name: resolver.resolvePathParamsTypedName(node) }),
96
+ schema: createSchema({ type: 'ref', name: resolver.resolvePathParamsName(node, pathParam) }),
95
97
  }),
96
98
  )
97
99
  }
98
100
 
99
- if (node.parameters.some((p) => p.in === 'header') && resolver.resolveHeaderParamsTypedName) {
101
+ const headerParam = node.parameters.find((p) => p.in === 'header')
102
+ if (headerParam) {
100
103
  properties.push(
101
104
  createProperty({
102
105
  name: 'HeaderParams',
103
106
  required: true,
104
- schema: createSchema({ type: 'ref', name: resolver.resolveHeaderParamsTypedName(node) }),
107
+ schema: createSchema({ type: 'ref', name: resolver.resolveHeaderParamsName(node, headerParam) }),
105
108
  }),
106
109
  )
107
110
  }
@@ -122,12 +125,12 @@ function buildLegacyResponseUnionSchemaNode({ node, resolver }: BuildOperationSc
122
125
  }
123
126
 
124
127
  if (successResponses.length === 1) {
125
- return createSchema({ type: 'ref', name: resolver.resolveResponseStatusTypedName(node, successResponses[0]!.statusCode) })
128
+ return createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
126
129
  }
127
130
 
128
131
  return createSchema({
129
132
  type: 'union',
130
- members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusTypedName(node, res.statusCode) })),
133
+ members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
131
134
  })
132
135
  }
133
136
 
@@ -156,8 +159,8 @@ function nameUnnamedEnums(node: SchemaNode, parentName: string): SchemaNode {
156
159
  export const typeGeneratorLegacy = defineGenerator<PluginTs>({
157
160
  name: 'typescript-legacy',
158
161
  type: 'react',
159
- Operation({ node, adapter, options, config }) {
160
- const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, resolver, transformers = [] } = options
162
+ Operation({ node, adapter, options, config, resolver }) {
163
+ const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, transformers = [] } = options
161
164
 
162
165
  const root = path.resolve(config.root, config.output.path)
163
166
  const mode = getMode(path.resolve(root, output.path))
@@ -168,13 +171,11 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
168
171
  function renderSchemaType({
169
172
  node: schemaNode,
170
173
  name,
171
- typedName,
172
174
  description,
173
175
  keysToOmit,
174
176
  }: {
175
177
  node: SchemaNode | null
176
178
  name: string
177
- typedName: string
178
179
  description?: string
179
180
  keysToOmit?: Array<string>
180
181
  }) {
@@ -195,7 +196,6 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
195
196
  imports.map((imp) => <File.Import key={[name, imp.path, imp.isTypeOnly].join('-')} root={file.path} path={imp.path} name={imp.name} isTypeOnly />)}
196
197
  <Type
197
198
  name={name}
198
- typedName={typedName}
199
199
  node={transformedNode}
200
200
  description={description}
201
201
  enumType={enumType}
@@ -222,7 +222,6 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
222
222
  return renderSchemaType({
223
223
  node: res.schema ? nameUnnamedEnums(res.schema, baseResponseName) : res.schema,
224
224
  name: responseName,
225
- typedName: resolver.resolveResponseStatusTypedName(node, res.statusCode),
226
225
  description: res.description,
227
226
  keysToOmit: res.keysToOmit,
228
227
  })
@@ -232,7 +231,6 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
232
231
  ? renderSchemaType({
233
232
  node: nameUnnamedEnums(node.requestBody.schema, resolverTsLegacy.resolveDataName(node)),
234
233
  name: resolver.resolveDataName(node),
235
- typedName: resolver.resolveDataTypedName(node),
236
234
  description: node.requestBody.description ?? node.requestBody.schema.description,
237
235
  keysToOmit: node.requestBody.keysToOmit,
238
236
  })
@@ -241,23 +239,20 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
241
239
  const legacyParamTypes = [
242
240
  pathParams.length > 0
243
241
  ? renderSchemaType({
244
- node: buildGroupedParamsSchema({ params: pathParams, parentName: resolverTsLegacy.resolvePathParamsName!(node) }),
245
- name: resolver.resolvePathParamsName!(node),
246
- typedName: resolver.resolvePathParamsTypedName!(node),
242
+ node: buildGroupedParamsSchema({ params: pathParams, parentName: resolverTsLegacy.resolvePathParamsName(node, pathParams[0]!) }),
243
+ name: resolver.resolvePathParamsName(node, pathParams[0]!),
247
244
  })
248
245
  : null,
249
246
  queryParams.length > 0
250
247
  ? renderSchemaType({
251
- node: buildGroupedParamsSchema({ params: queryParams, parentName: resolverTsLegacy.resolveQueryParamsName!(node) }),
252
- name: resolver.resolveQueryParamsName!(node),
253
- typedName: resolver.resolveQueryParamsTypedName!(node),
248
+ node: buildGroupedParamsSchema({ params: queryParams, parentName: resolverTsLegacy.resolveQueryParamsName(node, queryParams[0]!) }),
249
+ name: resolver.resolveQueryParamsName(node, queryParams[0]!),
254
250
  })
255
251
  : null,
256
252
  headerParams.length > 0
257
253
  ? renderSchemaType({
258
- node: buildGroupedParamsSchema({ params: headerParams, parentName: resolverTsLegacy.resolveHeaderParamsName!(node) }),
259
- name: resolver.resolveHeaderParamsName!(node),
260
- typedName: resolver.resolveHeaderParamsTypedName!(node),
254
+ node: buildGroupedParamsSchema({ params: headerParams, parentName: resolverTsLegacy.resolveHeaderParamsName(node, headerParams[0]!) }),
255
+ name: resolver.resolveHeaderParamsName(node, headerParams[0]!),
261
256
  })
262
257
  : null,
263
258
  ]
@@ -265,13 +260,11 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
265
260
  const legacyResponsesType = renderSchemaType({
266
261
  node: buildLegacyResponsesSchemaNode({ node, resolver }),
267
262
  name: resolver.resolveResponsesName(node),
268
- typedName: resolver.resolveResponsesTypedName(node),
269
263
  })
270
264
 
271
265
  const legacyResponseType = renderSchemaType({
272
266
  node: buildLegacyResponseUnionSchemaNode({ node, resolver }),
273
267
  name: resolver.resolveResponseName(node),
274
- typedName: resolver.resolveResponseTypedName(node),
275
268
  })
276
269
 
277
270
  return (
@@ -290,8 +283,8 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
290
283
  </File>
291
284
  )
292
285
  },
293
- Schema({ node, adapter, options, config }) {
294
- const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, resolver, transformers = [] } = options
286
+ Schema({ node, adapter, options, config, resolver }) {
287
+ const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, transformers = [] } = options
295
288
 
296
289
  const root = path.resolve(config.root, config.output.path)
297
290
  const mode = getMode(path.resolve(root, output.path))
@@ -309,12 +302,10 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
309
302
 
310
303
  const isEnumSchema = !!narrowSchema(node, schemaTypes.enum)
311
304
 
312
- const typedName =
313
- ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyTypedName(node, enumTypeSuffix) : resolver.resolveTypedName(node.name)
305
+ const name = ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveName(node.name)
314
306
 
315
307
  const type = {
316
- name: resolver.resolveName(node.name),
317
- typedName,
308
+ name,
318
309
  file: resolver.resolveFile({ name: node.name, extname: '.ts' }, { root, output, group }),
319
310
  } as const
320
311
 
@@ -332,7 +323,6 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
332
323
  ))}
333
324
  <Type
334
325
  name={type.name}
335
- typedName={type.typedName}
336
326
  node={transformedNode}
337
327
  enumType={enumType}
338
328
  enumTypeSuffix={enumTypeSuffix}
package/src/index.ts CHANGED
@@ -1,2 +1,14 @@
1
+ export { Enum } from './components/Enum.tsx'
2
+ export { Type } from './components/Type.tsx'
3
+
4
+ export { typeGenerator } from './generators/typeGenerator.tsx'
5
+
1
6
  export { pluginTs, pluginTsName } from './plugin.ts'
2
- export type { PluginTs } from './types.ts'
7
+
8
+ export { functionPrinter } from './printers/functionPrinter.ts'
9
+ export { printerTs } from './printers/printerTs.ts'
10
+
11
+ export { resolverTs } from './resolvers/resolverTs.ts'
12
+ export { resolverTsLegacy } from './resolvers/resolverTsLegacy.ts'
13
+
14
+ export type { PluginTs, ResolverTs } from './types.ts'
package/src/plugin.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import path from 'node:path'
2
+ import { camelCase } from '@internals/utils'
2
3
  import { walk } from '@kubb/ast'
3
- import { createPlugin, getBarrelFiles, renderOperation, renderSchema } from '@kubb/core'
4
- import { getPreset } from './presets.ts'
4
+ import { createPlugin, type Group, getBarrelFiles, getPreset, renderOperation, renderSchema } from '@kubb/core'
5
+ import { presets } from './presets.ts'
5
6
  import type { PluginTs } from './types.ts'
6
7
 
7
8
  /**
@@ -45,7 +46,9 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
45
46
  generators: userGenerators = [],
46
47
  } = options
47
48
 
48
- const { resolver, transformers, generators } = getPreset(compatibilityPreset, {
49
+ const preset = getPreset({
50
+ preset: compatibilityPreset,
51
+ presets: presets,
49
52
  resolvers: userResolvers,
50
53
  transformers: userTransformers,
51
54
  generators: userGenerators,
@@ -56,40 +59,54 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
56
59
 
57
60
  return {
58
61
  name: pluginTsName,
59
- options: {
60
- output,
61
- optionalType,
62
- group,
63
- arrayType,
64
- enumType,
65
- enumTypeSuffix,
66
- enumKeyCasing,
67
- syntaxType,
68
- paramsCasing,
69
- resolver,
70
- transformers,
62
+ get resolver() {
63
+ return preset.resolver
64
+ },
65
+ get options() {
66
+ return {
67
+ output,
68
+ optionalType,
69
+ group: group
70
+ ? ({
71
+ ...options.group,
72
+ name: (ctx) => {
73
+ if (options.group?.type === 'path') {
74
+ return `${ctx.group.split('/')[1]}`
75
+ }
76
+ return `${camelCase(ctx.group)}Controller`
77
+ },
78
+ } as Group)
79
+ : undefined,
80
+ arrayType,
81
+ enumType,
82
+ enumTypeSuffix,
83
+ enumKeyCasing,
84
+ syntaxType,
85
+ paramsCasing,
86
+ transformers: preset.transformers,
87
+ }
71
88
  },
72
89
  resolvePath(baseName, pathMode, options) {
73
90
  if (!resolvePathWarning) {
74
- this.driver.events.emit('warn', 'Do not use resolvePath for pluginTs, use resolverTs.resolvePath instead')
91
+ this.events.emit('warn', 'Do not use resolvePath for pluginTs, use resolverTs.resolvePath instead')
75
92
  resolvePathWarning = true
76
93
  }
77
94
 
78
- return resolver.resolvePath(
95
+ return this.plugin.resolver.resolvePath(
79
96
  { baseName, pathMode, tag: options?.group?.tag, path: options?.group?.path },
80
- { root: path.resolve(this.config.root, this.config.output.path), output, group },
97
+ { root: path.resolve(this.config.root, this.config.output.path), output, group: this.plugin.options.group },
81
98
  )
82
99
  },
83
100
  resolveName(name, type) {
84
101
  if (!resolveNameWarning) {
85
- this.driver.events.emit('warn', 'Do not use resolveName for pluginTs, use resolverTs.default instead')
102
+ this.events.emit('warn', 'Do not use resolveName for pluginTs, use resolverTs.default instead')
86
103
  resolveNameWarning = true
87
104
  }
88
105
 
89
- return resolver.default(name, type)
106
+ return this.plugin.resolver.default(name, type)
90
107
  },
91
108
  async install() {
92
- const { config, fabric, plugin, adapter, rootNode, driver, openInStudio } = this
109
+ const { config, fabric, plugin, adapter, rootNode, driver, openInStudio, resolver } = this
93
110
 
94
111
  const root = path.resolve(config.root, config.output.path)
95
112
 
@@ -102,7 +119,7 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
102
119
  await walk(rootNode, {
103
120
  depth: 'shallow',
104
121
  async schema(schemaNode) {
105
- const writeTasks = generators.map(async (generator) => {
122
+ const writeTasks = preset.generators.map(async (generator) => {
106
123
  if (generator.type === 'react' && generator.version === '2') {
107
124
  const options = resolver.resolveOptions(schemaNode, { options: plugin.options, exclude, include, override })
108
125
 
@@ -112,6 +129,7 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
112
129
 
113
130
  await renderSchema(schemaNode, {
114
131
  options,
132
+ resolver,
115
133
  adapter,
116
134
  config,
117
135
  fabric,
@@ -125,7 +143,7 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
125
143
  await Promise.all(writeTasks)
126
144
  },
127
145
  async operation(operationNode) {
128
- const writeTasks = generators.map(async (generator) => {
146
+ const writeTasks = preset.generators.map(async (generator) => {
129
147
  if (generator.type === 'react' && generator.version === '2') {
130
148
  const options = resolver.resolveOptions(operationNode, { options: plugin.options, exclude, include, override })
131
149
 
@@ -135,6 +153,7 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
135
153
 
136
154
  await renderOperation(operationNode, {
137
155
  options,
156
+ resolver,
138
157
  adapter,
139
158
  config,
140
159
  fabric,
package/src/presets.ts CHANGED
@@ -1,8 +1,9 @@
1
- import type { Visitor } from '@kubb/ast/types'
2
- import { type CompatibilityPreset, definePreset, definePresets, type Generator, getPreset as getCorePreset } from '@kubb/core'
3
- import { typeGenerator, typeGeneratorLegacy } from './generators/index.ts'
4
- import { resolverTs, resolverTsLegacy } from './resolvers/index.ts'
5
- import type { PluginTs, ResolverTs } from './types.ts'
1
+ import { definePresets } from '@kubb/core'
2
+ import { typeGenerator } from './generators/typeGenerator.tsx'
3
+ import { typeGeneratorLegacy } from './generators/typeGeneratorLegacy.tsx'
4
+ import { resolverTs } from './resolvers/resolverTs.ts'
5
+ import { resolverTsLegacy } from './resolvers/resolverTsLegacy.ts'
6
+ import type { ResolverTs } from './types.ts'
6
7
 
7
8
  /**
8
9
  * Built-in preset registry for `@kubb/plugin-ts`.
@@ -11,33 +12,14 @@ import type { PluginTs, ResolverTs } from './types.ts'
11
12
  * - `kubbV4` — uses `resolverTsLegacy` and `typeGeneratorLegacy` (Kubb v4 naming conventions).
12
13
  */
13
14
  export const presets = definePresets<ResolverTs>({
14
- default: definePreset('default', { resolvers: [resolverTs], generators: [typeGenerator] }),
15
- kubbV4: definePreset('kubbV4', { resolvers: [resolverTsLegacy], generators: [typeGeneratorLegacy] }),
15
+ default: {
16
+ name: 'default',
17
+ resolvers: [resolverTs],
18
+ generators: [typeGenerator],
19
+ },
20
+ kubbV4: {
21
+ name: 'kubbV4',
22
+ resolvers: [resolverTsLegacy],
23
+ generators: [typeGeneratorLegacy],
24
+ },
16
25
  })
17
-
18
- type GetPresetOptions = {
19
- resolvers: Array<ResolverTs>
20
- transformers: Array<Visitor>
21
- generators: Array<Generator<PluginTs>>
22
- }
23
-
24
- /**
25
- * Resolves a compatibility preset for `plugin-ts`, merging user-supplied resolvers,
26
- * transformers, and generators on top of the built-in preset defaults.
27
- *
28
- * `resolverTs` is always prepended to the resolver list as the baseline.
29
- *
30
- * @example
31
- * ```ts
32
- * const preset = getPreset('kubbV4', { resolvers: [], transformers: [], generators: [] })
33
- * ```
34
- */
35
- export function getPreset(preset: CompatibilityPreset, { resolvers, transformers, generators }: GetPresetOptions) {
36
- return getCorePreset({
37
- preset,
38
- presets,
39
- resolvers: [resolverTs, ...(resolvers ?? [])],
40
- transformers,
41
- generators,
42
- })
43
- }
@@ -0,0 +1,194 @@
1
+ import type { PrinterFactoryOptions } from '@kubb/ast'
2
+ import { createPrinterFactory } from '@kubb/ast'
3
+ import type { FunctionNode, FunctionNodeType, FunctionParameterNode, FunctionParametersNode, ParameterGroupNode, TypeNode } from '@kubb/ast/types'
4
+
5
+ /**
6
+ * Maps each function-printer handler key to its concrete node type.
7
+ */
8
+ export type FunctionNodeByType = {
9
+ functionParameter: FunctionParameterNode
10
+ parameterGroup: ParameterGroupNode
11
+ functionParameters: FunctionParametersNode
12
+ type: TypeNode
13
+ }
14
+
15
+ const kindToHandlerKey = {
16
+ FunctionParameter: 'functionParameter',
17
+ ParameterGroup: 'parameterGroup',
18
+ FunctionParameters: 'functionParameters',
19
+ Type: 'type',
20
+ } satisfies Record<string, FunctionNodeType>
21
+
22
+ /**
23
+ * Creates a function-parameter printer factory.
24
+ *
25
+ * Uses `createPrinterFactory` and dispatches handlers by `node.kind`
26
+ * (for function nodes) rather than by `node.type` (for schema nodes).
27
+ */
28
+ export const defineFunctionPrinter = createPrinterFactory<FunctionNode, FunctionNodeType, FunctionNodeByType>((node) => kindToHandlerKey[node.kind])
29
+
30
+ export type FunctionPrinterOptions = {
31
+ /**
32
+ * Rendering modes supported by `functionPrinter`.
33
+ *
34
+ * | Mode | Output example | Use case |
35
+ * |---------------|---------------------------------------------|---------------------------------|
36
+ * | `declaration` | `id: string, config: Config = {}` | Function parameter declaration |
37
+ * | `call` | `id, { method, url }` | Function call arguments |
38
+ * | `keys` | `{ id, config }` | Key names only (destructuring) |
39
+ * | `values` | `{ id: id, config: config }` | Key/value object entries |
40
+ */
41
+ mode: 'declaration' | 'call' | 'keys' | 'values'
42
+ /**
43
+ * Optional transformation applied to every parameter name before printing.
44
+ */
45
+ transformName?: (name: string) => string
46
+ /**
47
+ * Optional transformation applied to every type string before printing.
48
+ */
49
+ transformType?: (type: string) => string
50
+ }
51
+
52
+ type DefaultPrinter = PrinterFactoryOptions<'functionParameters', FunctionPrinterOptions, string>
53
+
54
+ function rank(param: FunctionParameterNode | ParameterGroupNode): number {
55
+ if (param.kind === 'ParameterGroup') {
56
+ if (param.default) return 2
57
+ const isOptional = param.optional ?? param.properties.every((p) => p.optional || p.default !== undefined)
58
+ return isOptional ? 1 : 0
59
+ }
60
+ if (param.rest) return 3
61
+ if (param.default) return 2
62
+ return param.optional ? 1 : 0
63
+ }
64
+
65
+ function sortParams(params: ReadonlyArray<FunctionParameterNode | ParameterGroupNode>): Array<FunctionParameterNode | ParameterGroupNode> {
66
+ return [...params].sort((a, b) => rank(a) - rank(b))
67
+ }
68
+
69
+ function sortChildParams(params: Array<FunctionParameterNode>): Array<FunctionParameterNode> {
70
+ return [...params].sort((a, b) => rank(a) - rank(b))
71
+ }
72
+
73
+ /**
74
+ * Default function-signature printer.
75
+ * Covers the four standard output modes used across Kubb plugins.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * const printer = functionPrinter({ mode: 'declaration' })
80
+ *
81
+ * const sig = createFunctionParameters({
82
+ * params: [
83
+ * createFunctionParameter({ name: 'petId', type: 'string', optional: false }),
84
+ * createFunctionParameter({ name: 'config', type: 'Config', optional: false, default: '{}' }),
85
+ * ],
86
+ * })
87
+ *
88
+ * printer.print(sig) // → "petId: string, config: Config = {}"
89
+ * ```
90
+ */
91
+ export const functionPrinter = defineFunctionPrinter<DefaultPrinter>((options) => ({
92
+ name: 'functionParameters',
93
+ options,
94
+ nodes: {
95
+ type(node) {
96
+ if (node.variant === 'member') {
97
+ return `${node.base}['${node.key}']`
98
+ }
99
+ if (node.variant === 'struct') {
100
+ const parts = node.properties.map((p) => {
101
+ const typeStr = this.transform(p.type)
102
+ return p.optional ? `${p.name}?: ${typeStr}` : `${p.name}: ${typeStr}`
103
+ })
104
+ return `{ ${parts.join('; ')} }`
105
+ }
106
+ if (node.variant === 'reference') {
107
+ return node.name
108
+ }
109
+ return null
110
+ },
111
+ functionParameter(node) {
112
+ const { mode, transformName, transformType } = this.options
113
+ const name = transformName ? transformName(node.name) : node.name
114
+
115
+ const rawType = node.type ? this.transform(node.type) : undefined
116
+ const type = rawType != null && transformType ? transformType(rawType) : rawType
117
+
118
+ if (mode === 'keys' || mode === 'values') {
119
+ return node.rest ? `...${name}` : name
120
+ }
121
+
122
+ if (mode === 'call') {
123
+ return node.rest ? `...${name}` : name
124
+ }
125
+
126
+ if (node.rest) {
127
+ return type ? `...${name}: ${type}` : `...${name}`
128
+ }
129
+ if (type) {
130
+ if (node.optional) return `${name}?: ${type}`
131
+ return node.default ? `${name}: ${type} = ${node.default}` : `${name}: ${type}`
132
+ }
133
+ return node.default ? `${name} = ${node.default}` : name
134
+ },
135
+ parameterGroup(node) {
136
+ const { mode, transformName, transformType } = this.options
137
+ const sorted = sortChildParams(node.properties)
138
+ const isOptional = node.optional ?? sorted.every((p) => p.optional || p.default !== undefined)
139
+
140
+ if (node.inline) {
141
+ return sorted
142
+ .map((p) => this.transform(p))
143
+ .filter(Boolean)
144
+ .join(', ')
145
+ }
146
+
147
+ if (mode === 'keys' || mode === 'values') {
148
+ const keys = sorted.map((p) => p.name).join(', ')
149
+ return `{ ${keys} }`
150
+ }
151
+
152
+ if (mode === 'call') {
153
+ const keys = sorted.map((p) => p.name).join(', ')
154
+ return `{ ${keys} }`
155
+ }
156
+
157
+ const names = sorted.map((p) => {
158
+ const n = transformName ? transformName(p.name) : p.name
159
+
160
+ return n
161
+ })
162
+
163
+ const nameStr = names.length ? `{ ${names.join(', ')} }` : undefined
164
+ if (!nameStr) return null
165
+
166
+ let typeAnnotation: string | undefined = node.type ? (this.transform(node.type) ?? undefined) : undefined
167
+ if (!typeAnnotation) {
168
+ const typeParts = sorted
169
+ .filter((p) => p.type)
170
+ .map((p) => {
171
+ const rawT = p.type ? this.transform(p.type) : undefined
172
+ const t = rawT != null && transformType ? transformType(rawT) : rawT
173
+ return p.optional || p.default !== undefined ? `${p.name}?: ${t}` : `${p.name}: ${t}`
174
+ })
175
+ typeAnnotation = typeParts.length ? `{ ${typeParts.join('; ')} }` : undefined
176
+ }
177
+
178
+ if (typeAnnotation) {
179
+ if (isOptional) return `${nameStr}: ${typeAnnotation} = ${node.default ?? '{}'}`
180
+ return node.default ? `${nameStr}: ${typeAnnotation} = ${node.default}` : `${nameStr}: ${typeAnnotation}`
181
+ }
182
+
183
+ return node.default ? `${nameStr} = ${node.default}` : nameStr
184
+ },
185
+ functionParameters(node) {
186
+ const sorted = sortParams(node.params)
187
+
188
+ return sorted
189
+ .map((p) => this.transform(p))
190
+ .filter(Boolean)
191
+ .join(', ')
192
+ },
193
+ },
194
+ }))
@@ -37,7 +37,7 @@ type TsOptions = {
37
37
  * When set, `printer.print(node)` produces a full `type Name = …` declaration.
38
38
  * When omitted, `printer.print(node)` returns the raw type node.
39
39
  */
40
- typeName?: string
40
+ name?: string
41
41
 
42
42
  /**
43
43
  * JSDoc `@description` comment added to the generated type or interface declaration.
@@ -272,7 +272,7 @@ export const printerTs = definePrinter<TsPrinter>((options) => {
272
272
 
273
273
  const resolvedName =
274
274
  ENUM_TYPES_WITH_KEY_SUFFIX.has(this.options.enumType) && this.options.enumTypeSuffix
275
- ? this.options.resolver.resolveEnumKeyTypedName(node as unknown as SchemaNode, this.options.enumTypeSuffix)
275
+ ? this.options.resolver.resolveEnumKeyName(node as unknown as SchemaNode, this.options.enumTypeSuffix)
276
276
  : this.options.resolver.default(node.name, 'type')
277
277
 
278
278
  return factory.createTypeReferenceNode(resolvedName, undefined)
@@ -360,16 +360,16 @@ export const printerTs = definePrinter<TsPrinter>((options) => {
360
360
  type = factory.createUnionDeclaration({ nodes: [type, factory.keywordTypeNodes.undefined] })
361
361
  }
362
362
 
363
- // Without typeName, return the type node as-is (no declaration wrapping).
364
- const { typeName, syntaxType = 'type', description, keysToOmit } = this.options
365
- if (!typeName) {
363
+ // Without name, return the type node as-is (no declaration wrapping).
364
+ const { name, syntaxType = 'type', description, keysToOmit } = this.options
365
+ if (!name) {
366
366
  return safePrint(type)
367
367
  }
368
368
 
369
369
  const useTypeGeneration = syntaxType === 'type' || type.kind === factory.syntaxKind.union || !!keysToOmit?.length
370
370
 
371
371
  const typeNode = factory.createTypeDeclaration({
372
- name: typeName,
372
+ name,
373
373
  isExportable: true,
374
374
  type: keysToOmit?.length
375
375
  ? factory.createOmitDeclaration({