@kubb/plugin-client 5.0.0-beta.3 → 5.0.0-beta.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.
Files changed (42) hide show
  1. package/README.md +24 -4
  2. package/dist/clients/axios.cjs +25 -3
  3. package/dist/clients/axios.cjs.map +1 -1
  4. package/dist/clients/axios.d.ts +9 -2
  5. package/dist/clients/axios.js +25 -3
  6. package/dist/clients/axios.js.map +1 -1
  7. package/dist/clients/fetch.cjs +20 -2
  8. package/dist/clients/fetch.cjs.map +1 -1
  9. package/dist/clients/fetch.d.ts +9 -2
  10. package/dist/clients/fetch.js +20 -2
  11. package/dist/clients/fetch.js.map +1 -1
  12. package/dist/index.cjs +524 -301
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +150 -84
  15. package/dist/index.js +525 -302
  16. package/dist/index.js.map +1 -1
  17. package/dist/templates/clients/axios.source.cjs +1 -1
  18. package/dist/templates/clients/axios.source.js +1 -1
  19. package/dist/templates/clients/fetch.source.cjs +1 -1
  20. package/dist/templates/clients/fetch.source.js +1 -1
  21. package/extension.yaml +1293 -0
  22. package/package.json +11 -17
  23. package/src/clients/axios.ts +41 -7
  24. package/src/clients/fetch.ts +30 -3
  25. package/src/components/ClassClient.tsx +17 -19
  26. package/src/components/Client.tsx +68 -51
  27. package/src/components/StaticClassClient.tsx +17 -19
  28. package/src/components/Url.tsx +7 -9
  29. package/src/components/WrapperClient.tsx +9 -5
  30. package/src/functionParams.ts +8 -8
  31. package/src/generators/classClientGenerator.tsx +40 -38
  32. package/src/generators/clientGenerator.tsx +32 -35
  33. package/src/generators/groupedClientGenerator.tsx +14 -8
  34. package/src/generators/operationsGenerator.tsx +12 -6
  35. package/src/generators/staticClassClientGenerator.tsx +34 -32
  36. package/src/plugin.ts +24 -11
  37. package/src/resolvers/resolverClient.ts +31 -8
  38. package/src/types.ts +90 -53
  39. package/src/utils.ts +30 -53
  40. package/templates/clients/axios.ts +0 -73
  41. package/templates/clients/fetch.ts +0 -96
  42. package/templates/config.ts +0 -43
@@ -1,12 +1,13 @@
1
1
  import path from 'node:path'
2
- import { camelCase, pascalCase } from '@internals/utils'
2
+ import { resolveOperationTypeNames } from '@internals/shared'
3
+ import { camelCase } from '@internals/utils'
3
4
  import type { ast } from '@kubb/core'
4
5
  import { defineGenerator } from '@kubb/core'
5
6
  import type { ResolverTs } from '@kubb/plugin-ts'
6
7
  import { pluginTsName } from '@kubb/plugin-ts'
7
8
  import type { ResolverZod } from '@kubb/plugin-zod'
8
9
  import { pluginZodName } from '@kubb/plugin-zod'
9
- import { File, jsxRenderer } from '@kubb/renderer-jsx'
10
+ import { File, jsxRendererSync } from '@kubb/renderer-jsx'
10
11
  import { StaticClassClient } from '../components/StaticClassClient'
11
12
  import type { PluginClient } from '../types'
12
13
 
@@ -14,9 +15,9 @@ type OperationData = {
14
15
  node: ast.OperationNode
15
16
  name: string
16
17
  tsResolver: ResolverTs
17
- zodResolver: ResolverZod | undefined
18
+ zodResolver: ResolverZod | null
18
19
  typeFile: ast.FileNode
19
- zodFile: ast.FileNode | undefined
20
+ zodFile: ast.FileNode | null
20
21
  }
21
22
 
22
23
  type Controller = {
@@ -26,40 +27,38 @@ type Controller = {
26
27
  }
27
28
 
28
29
  function resolveTypeImportNames(node: ast.OperationNode, tsResolver: ResolverTs): Array<string> {
29
- const names: Array<string | undefined> = [
30
- node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined,
31
- tsResolver.resolveResponseName(node),
32
- ...node.parameters.filter((p) => p.in === 'path').map((p) => tsResolver.resolvePathParamsName(node, p)),
33
- ...node.parameters.filter((p) => p.in === 'query').map((p) => tsResolver.resolveQueryParamsName(node, p)),
34
- ...node.parameters.filter((p) => p.in === 'header').map((p) => tsResolver.resolveHeaderParamsName(node, p)),
35
- ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
36
- ]
37
- return names.filter((n): n is string => Boolean(n))
30
+ return resolveOperationTypeNames(node, tsResolver, { order: 'body-response-first' })
38
31
  }
39
32
 
40
33
  function resolveZodImportNames(node: ast.OperationNode, zodResolver: ResolverZod): Array<string> {
41
- const names: Array<string | undefined> = [
34
+ const names: Array<string | null | undefined> = [
42
35
  zodResolver.resolveResponseName?.(node),
43
- node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined,
36
+ node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
44
37
  ]
45
38
  return names.filter((n): n is string => Boolean(n))
46
39
  }
47
40
 
41
+ /**
42
+ * Built-in `operations` generator for `@kubb/plugin-client` when
43
+ * `clientType: 'staticClass'`. Emits one class per tag, with a static method
44
+ * per operation so callers can use `Pet.getPetById(...)` without
45
+ * instantiating the class.
46
+ */
48
47
  export const staticClassClientGenerator = defineGenerator<PluginClient>({
49
48
  name: 'staticClassClient',
50
- renderer: jsxRenderer,
49
+ renderer: jsxRendererSync,
51
50
  operations(nodes, ctx) {
52
- const { adapter, config, driver, resolver, root } = ctx
51
+ const { config, driver, resolver, root } = ctx
53
52
  const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath } = ctx.options
54
- const baseURL = ctx.options.baseURL ?? adapter.inputNode?.meta?.baseURL
53
+ const baseURL = ctx.options.baseURL ?? ctx.meta.baseURL
55
54
 
56
55
  const pluginTs = driver.getPlugin(pluginTsName)
57
56
  if (!pluginTs) return null
58
57
 
59
58
  const tsResolver = driver.getResolver(pluginTsName)
60
59
  const tsPluginOptions = pluginTs.options
61
- const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
62
- const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
60
+ const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
61
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
63
62
 
64
63
  function buildOperationData(node: ast.OperationNode): OperationData {
65
64
  const typeFile = tsResolver.resolveFile(
@@ -70,9 +69,9 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
70
69
  zodResolver && pluginZod?.options
71
70
  ? zodResolver.resolveFile(
72
71
  { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
73
- { root, output: pluginZod.options?.output ?? output, group: pluginZod.options?.group },
72
+ { root, output: pluginZod.options?.output ?? output, group: pluginZod.options?.group ?? undefined },
74
73
  )
75
- : undefined
74
+ : null
76
75
 
77
76
  return {
78
77
  node: node,
@@ -86,11 +85,11 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
86
85
 
87
86
  const controllers = nodes.reduce((acc, operationNode) => {
88
87
  const tag = operationNode.tags[0]
89
- const groupName = tag ? (group?.name?.({ group: camelCase(tag) }) ?? pascalCase(tag)) : 'Client'
88
+ const groupName = tag ? (group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag)) : resolver.resolveGroupName('Client')
90
89
 
91
90
  if (!tag && !group) {
92
- const name = 'ApiClient'
93
- const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group })
91
+ const name = resolver.resolveClassName('ApiClient')
92
+ const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group: group ?? undefined })
94
93
  const operationData = buildOperationData(operationNode)
95
94
  const previous = acc.find((item) => item.file.path === file.path)
96
95
 
@@ -99,9 +98,12 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
99
98
  } else {
100
99
  acc.push({ name, file, operations: [operationData] })
101
100
  }
102
- } else if (tag) {
101
+ return acc
102
+ }
103
+
104
+ if (tag) {
103
105
  const name = groupName
104
- const file = resolver.resolveFile({ name, extname: '.ts', tag }, { root, output, group })
106
+ const file = resolver.resolveFile({ name, extname: '.ts', tag }, { root, output, group: group ?? undefined })
105
107
  const operationData = buildOperationData(operationNode)
106
108
  const previous = acc.find((item) => item.file.path === file.path)
107
109
 
@@ -160,7 +162,7 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
160
162
  const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops)
161
163
  const { zodImportsByFile, zodFilesByPath } =
162
164
  parser === 'zod' ? collectZodImports(ops) : { zodImportsByFile: new Map<string, Set<string>>(), zodFilesByPath: new Map<string, ast.FileNode>() }
163
- const hasFormData = ops.some((op) => op.node.requestBody?.content?.[0]?.contentType === 'multipart/form-data')
165
+ const hasFormData = ops.some((op) => op.node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') ?? false)
164
166
 
165
167
  return (
166
168
  <File
@@ -168,18 +170,18 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
168
170
  baseName={file.baseName}
169
171
  path={file.path}
170
172
  meta={file.meta}
171
- banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
172
- footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
173
+ banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
174
+ footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
173
175
  >
174
176
  {importPath ? (
175
177
  <>
176
- <File.Import name={'fetch'} path={importPath} />
178
+ <File.Import name={'client'} path={importPath} />
177
179
  <File.Import name={['mergeConfig']} path={importPath} />
178
180
  <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={importPath} isTypeOnly />
179
181
  </>
180
182
  ) : (
181
183
  <>
182
- <File.Import name={['fetch']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
184
+ <File.Import name={['client']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
183
185
  <File.Import name={['mergeConfig']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
184
186
  <File.Import
185
187
  name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
package/src/plugin.ts CHANGED
@@ -16,20 +16,33 @@ import { source as configSource } from './templates/config.source.ts'
16
16
  import type { PluginClient } from './types.ts'
17
17
 
18
18
  /**
19
- * Canonical plugin name for `@kubb/plugin-client`, used in driver lookups and warnings.
19
+ * Canonical plugin name for `@kubb/plugin-client`. Used for driver lookups and
20
+ * cross-plugin dependency references.
20
21
  */
21
22
  export const pluginClientName = 'plugin-client' satisfies PluginClient['name']
22
23
 
23
24
  /**
24
- * Generates type-safe HTTP client functions or classes from an OpenAPI specification.
25
- * Creates client APIs by walking operations and delegating to generators.
26
- * Writes barrel files based on the configured `barrelType`.
25
+ * Generates one HTTP client function per OpenAPI operation. Each function has
26
+ * typed path params, query params, body, and response, so callers use the API
27
+ * like any other typed function. Ships with `axios` and `fetch` runtimes; bring
28
+ * your own by setting `importPath`.
27
29
  *
28
- * @example Client generator
30
+ * @example
29
31
  * ```ts
30
- * import pluginClient from '@kubb/plugin-client'
32
+ * import { defineConfig } from 'kubb'
33
+ * import { pluginTs } from '@kubb/plugin-ts'
34
+ * import { pluginClient } from '@kubb/plugin-client'
35
+ *
31
36
  * export default defineConfig({
32
- * plugins: [pluginClient({ output: { path: 'clients' } })]
37
+ * input: { path: './petStore.yaml' },
38
+ * output: { path: './src/gen' },
39
+ * plugins: [
40
+ * pluginTs(),
41
+ * pluginClient({
42
+ * output: { path: './clients' },
43
+ * client: 'fetch',
44
+ * }),
45
+ * ],
33
46
  * })
34
47
  * ```
35
48
  */
@@ -63,8 +76,8 @@ export const pluginClient = definePlugin<PluginClient>((options) => {
63
76
  options.generators ??
64
77
  [
65
78
  clientType === 'staticClass' ? staticClassClientGenerator : clientType === 'class' ? classClientGenerator : clientGenerator,
66
- group && clientType === 'function' ? groupedClientGenerator : undefined,
67
- operations ? operationsGenerator : undefined,
79
+ group && clientType === 'function' ? groupedClientGenerator : null,
80
+ operations ? operationsGenerator : null,
68
81
  ].filter((x): x is NonNullable<typeof x> => Boolean(x))
69
82
 
70
83
  const groupConfig = group
@@ -79,12 +92,12 @@ export const pluginClient = definePlugin<PluginClient>((options) => {
79
92
  return `${camelCase(ctx.group)}Controller`
80
93
  },
81
94
  } satisfies Group)
82
- : undefined
95
+ : null
83
96
 
84
97
  return {
85
98
  name: pluginClientName,
86
99
  options,
87
- dependencies: [pluginTsName, parser === 'zod' ? pluginZodName : undefined].filter(Boolean),
100
+ dependencies: [pluginTsName, parser === 'zod' ? pluginZodName : null].filter((dependency): dependency is string => Boolean(dependency)),
88
101
  hooks: {
89
102
  'kubb:plugin:setup'(ctx) {
90
103
  const resolver = userResolver ? { ...resolverClient, ...userResolver } : resolverClient
@@ -1,22 +1,45 @@
1
- import { camelCase } from '@internals/utils'
1
+ import { camelCase, ensureValidVarName, pascalCase } from '@internals/utils'
2
2
  import { defineResolver } from '@kubb/core'
3
3
  import type { PluginClient } from '../types.ts'
4
4
 
5
5
  /**
6
- * Naming convention resolver for client plugin.
6
+ * Default resolver used by `@kubb/plugin-client`. Decides the names and file
7
+ * paths for every generated client function or class. Functions and files use
8
+ * camelCase; classes and tag groups use PascalCase.
7
9
  *
8
- * Provides default naming helpers using camelCase for functions and file paths.
10
+ * @example Resolve client function and class names
11
+ * ```ts
12
+ * import { resolverClient } from '@kubb/plugin-client'
9
13
  *
10
- * @example
11
- * `resolverClient.default('list pets', 'function') // 'listPets'`
14
+ * resolverClient.default('list pets', 'function') // 'listPets'
15
+ * resolverClient.resolveClassName('pet') // 'Pet'
16
+ * resolverClient.resolveUrlName(operationNode) // 'getShowPetByIdUrl'
17
+ * ```
12
18
  */
13
- export const resolverClient = defineResolver<PluginClient>((ctx) => ({
19
+ export const resolverClient = defineResolver<PluginClient>(() => ({
14
20
  name: 'default',
15
21
  pluginName: 'plugin-client',
16
22
  default(name, type) {
17
- return camelCase(name, { isFile: type === 'file' })
23
+ const resolved = camelCase(name, { isFile: type === 'file' })
24
+ return type === 'file' ? resolved : ensureValidVarName(resolved)
18
25
  },
19
26
  resolveName(name) {
20
- return ctx.default(name, 'function')
27
+ return this.default(name, 'function')
28
+ },
29
+ resolvePathName(name, type) {
30
+ return this.default(name, type)
31
+ },
32
+ resolveClassName(name) {
33
+ return ensureValidVarName(pascalCase(name))
34
+ },
35
+ resolveGroupName(name) {
36
+ return ensureValidVarName(pascalCase(name))
37
+ },
38
+ resolveClientPropertyName(name) {
39
+ return ensureValidVarName(camelCase(name))
40
+ },
41
+ resolveUrlName(node) {
42
+ const name = this.resolveName(node.operationId)
43
+ return `get${name.charAt(0).toUpperCase()}${name.slice(1)}Url`
21
44
  },
22
45
  }))
package/src/types.ts CHANGED
@@ -7,10 +7,34 @@ import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginF
7
7
  export type ResolverClient = Resolver & {
8
8
  /**
9
9
  * Resolves the function name for a given raw operation name.
10
+ *
10
11
  * @example Resolving operation names
11
12
  * `resolver.resolveName('show pet by id') // -> 'showPetById'`
12
13
  */
13
14
  resolveName(this: ResolverClient, name: string): string
15
+ /**
16
+ * Resolves the output file name for a client module.
17
+ */
18
+ resolvePathName(this: ResolverClient, name: string, type?: 'file' | 'function' | 'type' | 'const'): string
19
+ /**
20
+ * Resolves the generated class name for class-based clients.
21
+ */
22
+ resolveClassName(this: ResolverClient, name: string): string
23
+ /**
24
+ * Resolves the generated class name for tag-based client groups.
25
+ */
26
+ resolveGroupName(this: ResolverClient, name: string): string
27
+ /**
28
+ * Resolves the generated SDK facade property name for a client class.
29
+ */
30
+ resolveClientPropertyName(this: ResolverClient, name: string): string
31
+ /**
32
+ * Resolves the URL helper function name for an operation.
33
+ *
34
+ * @example Resolving URL helper names
35
+ * `resolver.resolveUrlName(node) // -> 'getShowPetByIdUrl'`
36
+ */
37
+ resolveUrlName(this: ResolverClient, node: ast.OperationNode): string
14
38
  }
15
39
 
16
40
  /**
@@ -22,9 +46,10 @@ export type ResolverClient = Resolver & {
22
46
  export type ClientImportPath =
23
47
  | {
24
48
  /**
25
- * Which client should be used to do the HTTP calls.
26
- * - 'axios' uses axios client for HTTP requests.
27
- * - 'fetch' uses native fetch API for HTTP requests.
49
+ * HTTP client used by the generated code.
50
+ * - `'axios'` imports from `@kubb/plugin-client/clients/axios`. Requires `axios` at runtime.
51
+ * - `'fetch'` imports from `@kubb/plugin-client/clients/fetch`. Uses the global `fetch`.
52
+ *
28
53
  * @default 'axios'
29
54
  */
30
55
  client?: 'axios' | 'fetch'
@@ -33,9 +58,12 @@ export type ClientImportPath =
33
58
  | {
34
59
  client?: never
35
60
  /**
36
- * Client import path for API calls.
37
- * Used as `import client from '${importPath}'`.
38
- * Accepts relative and absolute paths; path changes are not performed.
61
+ * Path to a custom client module. Generated files import their HTTP runtime from here
62
+ * instead of `@kubb/plugin-client/clients/{client}`. Accepts both relative paths and
63
+ * bare module specifiers; the value is used as-is.
64
+ *
65
+ * @note When combined with a query plugin, the module must export `Client`,
66
+ * `RequestConfig`, and `ResponseErrorConfig` types.
39
67
  */
40
68
  importPath: string
41
69
  /**
@@ -57,29 +85,28 @@ export type ClientImportPath =
57
85
  type ParamsTypeOptions =
58
86
  | {
59
87
  /**
60
- * All parameters path, query, headers, and body are merged into a single
88
+ * Every operation parameter (path, query, headers, body) is wrapped in a single
61
89
  * destructured object argument.
62
- * - 'object' returns the params and pathParams as an object.
63
- * @default 'inline'
64
90
  */
65
91
  paramsType: 'object'
66
92
  /**
67
93
  * `pathParamsType` has no effect when `paramsType` is `'object'`.
68
- * Path params are already inside the single destructured object.
94
+ * Path params already live inside the single destructured object.
69
95
  */
70
96
  pathParamsType?: never
71
97
  }
72
98
  | {
73
99
  /**
74
- * Each parameter group is emitted as a separate function argument.
75
- * - 'inline' returns the params as comma separated params.
100
+ * Each parameter group is emitted as a separate positional function argument.
101
+ *
76
102
  * @default 'inline'
77
103
  */
78
104
  paramsType?: 'inline'
79
105
  /**
80
- * Controls how path parameters are arranged within the inline argument list.
81
- * - 'object' groups path params into a destructured object: `{ petId }: PathParams`.
82
- * - 'inline' emits each path param as its own argument: `petId: string`.
106
+ * How URL path parameters are arranged inside the inline argument list.
107
+ * - `'object'` groups them into one destructured object: `{ petId }: PathParams`.
108
+ * - `'inline'` emits each path param as its own argument: `petId: string`.
109
+ *
83
110
  * @default 'inline'
84
111
  */
85
112
  pathParamsType?: 'object' | 'inline'
@@ -87,87 +114,96 @@ type ParamsTypeOptions =
87
114
 
88
115
  export type Options = {
89
116
  /**
90
- * Specify the export location for the files and define the behavior of the output.
91
- * @default { path: 'clients', barrelType: 'named' }
117
+ * Where the generated client files are written and how they are exported.
118
+ *
119
+ * @default { path: 'clients', barrel: { type: 'named' } }
92
120
  */
93
121
  output?: Output
94
122
  /**
95
- * Group the clients based on the provided name.
123
+ * Split generated files into subfolders based on the operation's tag.
96
124
  */
97
125
  group?: Group
98
126
  /**
99
- * Array containing exclude parameters to exclude/skip tags/operations/methods/paths.
127
+ * Skip operations matching at least one entry in the list.
100
128
  */
101
129
  exclude?: Array<Exclude>
102
130
  /**
103
- * Array containing include parameters to include tags/operations/methods/paths.
131
+ * Restrict generation to operations matching at least one entry in the list.
104
132
  */
105
133
  include?: Array<Include>
106
134
  /**
107
- * Array containing override parameters to override `options` based on tags/operations/methods/paths.
135
+ * Apply a different options object to operations matching a pattern.
108
136
  */
109
137
  override?: Array<Override<ResolvedOptions>>
110
138
  /**
111
- * Create `operations.ts` file with all operations grouped by methods.
139
+ * Emit an `operations.ts` file that re-exports every generated function grouped by HTTP method.
140
+ *
112
141
  * @default false
113
142
  */
114
143
  operations?: boolean
115
144
  /**
116
- * Export urls that are used by operation x.
117
- * - 'export' makes them part of your barrel file.
118
- * - false does not make them exportable.
145
+ * Whether to also export the URL builder helpers (`get<Operation>Url`).
146
+ * - `'export'` exposes them via the barrel.
147
+ * - `false` keeps them private.
148
+ *
119
149
  * @default false
120
- * @example getGetPetByIdUrl
121
150
  */
122
151
  urlType?: 'export' | false
123
152
  /**
124
- * Allows you to set a custom base url for all generated calls.
153
+ * Base URL prepended to every request. When omitted, falls back to the adapter's
154
+ * server URL (typically `servers[0].url`).
125
155
  */
126
156
  baseURL?: string
127
157
  /**
128
- * ReturnType that is used when calling the client.
129
- * - 'data' returns ResponseConfig[data].
130
- * - 'full' returns ResponseConfig.
158
+ * Shape of the value returned by each generated client function.
159
+ * - `'data'` only the response body.
160
+ * - `'full'` the full response config (body, status, headers, request).
161
+ *
131
162
  * @default 'data'
132
163
  */
133
164
  dataReturnType?: 'data' | 'full'
134
165
  /**
135
- * How to style your params, by default no casing is applied.
136
- * - 'camelcase' uses camelCase for pathParams, queryParams and headerParams names
137
- * @note response types (data/body) are not affected by this option
166
+ * Rename parameter properties in the generated client (path, query, headers).
167
+ * The HTTP request still uses the original spec names; Kubb writes the mapping for you.
168
+ *
169
+ * @note Use the same value on `@kubb/plugin-ts` so types stay compatible.
138
170
  */
139
171
  paramsCasing?: 'camelcase'
140
172
  /**
141
- * Which parser can be used before returning the data.
142
- * - 'client' returns the data as-is from the client.
143
- * - 'zod' uses @kubb/plugin-zod to parse the data.
173
+ * Validator applied to response bodies before they are returned to the caller.
174
+ * - `'client'` no validation. Trusts the API.
175
+ * - `'zod'` pipes responses through schemas from `@kubb/plugin-zod`.
176
+ *
144
177
  * @default 'client'
145
178
  */
146
179
  parser?: 'client' | 'zod'
147
180
  /**
148
- * How to generate the client code.
149
- * - 'function' generates standalone functions for each operation.
150
- * - 'class' generates a class with methods for each operation.
151
- * - 'staticClass' generates a class with static methods for each operation.
181
+ * Shape of the generated client.
182
+ * - `'function'` one standalone async function per operation.
183
+ * - `'class'` one class per tag with instance methods.
184
+ * - `'staticClass'` one class per tag with static methods.
185
+ *
152
186
  * @default 'function'
187
+ * @note Only `'function'` is compatible with query plugins.
153
188
  */
154
189
  clientType?: 'function' | 'class' | 'staticClass'
155
190
  /**
156
- * Bundle the selected client into the generated `.kubb` directory.
157
- * When disabled the generated clients will import the shared runtime from `@kubb/plugin-client/clients/*`.
191
+ * Copy the HTTP client runtime into the generated output so consumers do not need
192
+ * `@kubb/plugin-client` at runtime. When `false`, generated files import from
193
+ * `@kubb/plugin-client/clients/{client}`.
194
+ *
158
195
  * @default false
159
- * In version 5 of Kubb this is by default true
160
196
  */
161
197
  bundle?: boolean
162
198
  /**
163
- * Generate an SDK facade class that composes all tag-based client classes into a single entry point.
164
- * Setting this option automatically enables `clientType: 'class'`.
199
+ * Generate a single SDK class composing every tag-based client into one entry point.
200
+ * Automatically enables `clientType: 'class'`.
201
+ *
165
202
  * @example
166
203
  * ```ts
167
204
  * pluginClient({
168
205
  * sdk: { className: 'PetStoreSDK' },
169
206
  * })
170
- * // Generates a class with a shared constructor config and one property per tag:
171
207
  * // class PetStoreSDK {
172
208
  * // readonly petController: petController
173
209
  * // readonly storeController: storeController
@@ -177,22 +213,23 @@ export type Options = {
177
213
  */
178
214
  sdk?: {
179
215
  /**
180
- * Name of the generated SDK facade class.
216
+ * Name of the generated SDK facade class. Also the file name.
181
217
  */
182
218
  className: string
183
219
  }
184
220
  /**
185
- * Override individual resolver methods. Any method you omit falls back to the
186
- * preset resolver's implementation. Use `this.default(...)` to call it.
221
+ * Override how names and file paths are built for the generated client.
222
+ * Methods you omit fall back to the default resolver. `this` is bound to the
223
+ * full resolver, so `this.default(name)` delegates to the built-in implementation.
187
224
  */
188
225
  resolver?: Partial<ResolverClient> & ThisType<ResolverClient>
189
226
  /**
190
- * Single AST visitor applied to each node before printing.
191
- * Return `null` or `undefined` from a method to leave the node unchanged.
227
+ * AST visitor applied to each operation node before code is printed.
228
+ * Return `null` or `undefined` to leave the node unchanged.
192
229
  */
193
230
  transformer?: ast.Visitor
194
231
  /**
195
- * Define some generators next to the client generators.
232
+ * Custom generators that run alongside the built-in client generators.
196
233
  */
197
234
  generators?: Array<Generator<PluginClient>>
198
235
  } & ClientImportPath &
@@ -203,7 +240,7 @@ type ResolvedOptions = {
203
240
  exclude: Array<Exclude>
204
241
  include: Array<Include> | undefined
205
242
  override: Array<Override<ResolvedOptions>>
206
- group: Group | undefined
243
+ group: Group | null
207
244
  client: Options['client']
208
245
  clientType: NonNullable<Options['clientType']>
209
246
  bundle: NonNullable<Options['bundle']>