@kubb/plugin-client 5.0.0-beta.42 → 5.0.0-beta.64

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 (39) hide show
  1. package/dist/clients/axios.cjs.map +1 -1
  2. package/dist/clients/axios.js.map +1 -1
  3. package/dist/clients/fetch.cjs.map +1 -1
  4. package/dist/clients/fetch.js.map +1 -1
  5. package/dist/index.cjs +439 -383
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +60 -25
  8. package/dist/index.js +435 -383
  9. package/dist/index.js.map +1 -1
  10. package/dist/templates/clients/axios.source.cjs.map +1 -1
  11. package/dist/templates/clients/axios.source.js.map +1 -1
  12. package/dist/templates/clients/fetch.source.cjs.map +1 -1
  13. package/dist/templates/clients/fetch.source.js.map +1 -1
  14. package/dist/templates/config.source.cjs.map +1 -1
  15. package/dist/templates/config.source.js.map +1 -1
  16. package/package.json +10 -18
  17. package/extension.yaml +0 -1267
  18. package/src/clients/axios.ts +0 -113
  19. package/src/clients/fetch.ts +0 -201
  20. package/src/components/ClassClient.tsx +0 -137
  21. package/src/components/Client.tsx +0 -273
  22. package/src/components/Operations.tsx +0 -29
  23. package/src/components/StaticClassClient.tsx +0 -129
  24. package/src/components/Url.tsx +0 -91
  25. package/src/components/WrapperClient.tsx +0 -33
  26. package/src/functionParams.ts +0 -118
  27. package/src/generators/classClientGenerator.tsx +0 -253
  28. package/src/generators/clientGenerator.tsx +0 -127
  29. package/src/generators/groupedClientGenerator.tsx +0 -82
  30. package/src/generators/operationsGenerator.tsx +0 -34
  31. package/src/generators/staticClassClientGenerator.tsx +0 -232
  32. package/src/index.ts +0 -9
  33. package/src/plugin.ts +0 -160
  34. package/src/resolvers/resolverClient.ts +0 -45
  35. package/src/templates/clients/axios.source.ts +0 -4
  36. package/src/templates/clients/fetch.source.ts +0 -4
  37. package/src/templates/config.source.ts +0 -4
  38. package/src/types.ts +0 -268
  39. package/src/utils.ts +0 -159
@@ -1,232 +0,0 @@
1
- import path from 'node:path'
2
- import { operationFileEntry, resolveOperationTypeNames } from '@internals/shared'
3
- import { camelCase } from '@internals/utils'
4
- import { ast, defineGenerator } from '@kubb/core'
5
- import type { ResolverTs } from '@kubb/plugin-ts'
6
- import { pluginTsName } from '@kubb/plugin-ts'
7
- import type { ResolverZod } from '@kubb/plugin-zod'
8
- import { pluginZodName } from '@kubb/plugin-zod'
9
- import { File, jsxRendererSync } from '@kubb/renderer-jsx'
10
- import { StaticClassClient } from '../components/StaticClassClient'
11
- import type { PluginClient } from '../types'
12
-
13
- type OperationData = {
14
- node: ast.OperationNode
15
- name: string
16
- tsResolver: ResolverTs
17
- zodResolver: ResolverZod | null
18
- typeFile: ast.FileNode
19
- zodFile: ast.FileNode | null
20
- }
21
-
22
- type Controller = {
23
- name: string
24
- file: ast.FileNode
25
- operations: Array<OperationData>
26
- }
27
-
28
- function resolveTypeImportNames(node: ast.OperationNode, tsResolver: ResolverTs): Array<string> {
29
- return resolveOperationTypeNames(node, tsResolver, { order: 'body-response-first' })
30
- }
31
-
32
- function resolveZodImportNames(node: ast.OperationNode, zodResolver: ResolverZod): Array<string> {
33
- const names: Array<string | null | undefined> = [
34
- zodResolver.resolveResponseName?.(node),
35
- node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
36
- ]
37
- return names.filter((n): n is string => Boolean(n))
38
- }
39
-
40
- /**
41
- * Built-in `operations` generator for `@kubb/plugin-client` when
42
- * `clientType: 'staticClass'`. Emits one class per tag, with a static method
43
- * per operation so callers can use `Pet.getPetById(...)` without
44
- * instantiating the class.
45
- */
46
- export const staticClassClientGenerator = defineGenerator<PluginClient>({
47
- name: 'staticClassClient',
48
- renderer: jsxRendererSync,
49
- operations(nodes, ctx) {
50
- const { config, driver, resolver, root } = ctx
51
- const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath } = ctx.options
52
- const baseURL = ctx.options.baseURL ?? ctx.meta.baseURL
53
-
54
- const pluginTs = driver.getPlugin(pluginTsName)
55
- if (!pluginTs) return null
56
-
57
- const tsResolver = driver.getResolver(pluginTsName)
58
- const tsPluginOptions = pluginTs.options
59
- const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
60
- const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
61
-
62
- function buildOperationData(node: ast.OperationNode): OperationData {
63
- const typeFile = tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
64
- root,
65
- output: tsPluginOptions?.output ?? output,
66
- group: tsPluginOptions?.group,
67
- })
68
- const zodFile =
69
- zodResolver && pluginZod?.options
70
- ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
71
- root,
72
- output: pluginZod.options?.output ?? output,
73
- group: pluginZod.options?.group ?? undefined,
74
- })
75
- : null
76
-
77
- return {
78
- node: node,
79
- name: resolver.resolveName(node.operationId),
80
- tsResolver,
81
- zodResolver,
82
- typeFile,
83
- zodFile,
84
- }
85
- }
86
-
87
- const controllers = nodes.reduce((acc, operationNode) => {
88
- if (!ast.isHttpOperationNode(operationNode)) return acc
89
- const tag = operationNode.tags[0]
90
- const groupName = tag ? (group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag)) : resolver.resolveGroupName('Client')
91
-
92
- if (!tag && !group) {
93
- const name = resolver.resolveClassName('ApiClient')
94
- const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group: group ?? undefined })
95
- const operationData = buildOperationData(operationNode)
96
- const previous = acc.find((item) => item.file.path === file.path)
97
-
98
- if (previous) {
99
- previous.operations.push(operationData)
100
- } else {
101
- acc.push({ name, file, operations: [operationData] })
102
- }
103
- return acc
104
- }
105
-
106
- if (tag) {
107
- const name = groupName
108
- const file = resolver.resolveFile({ name, extname: '.ts', tag }, { root, output, group: group ?? undefined })
109
- const operationData = buildOperationData(operationNode)
110
- const previous = acc.find((item) => item.file.path === file.path)
111
-
112
- if (previous) {
113
- previous.operations.push(operationData)
114
- } else {
115
- acc.push({ name, file, operations: [operationData] })
116
- }
117
- }
118
-
119
- return acc
120
- }, [] as Array<Controller>)
121
-
122
- function collectTypeImports(ops: Array<OperationData>) {
123
- const typeImportsByFile = new Map<string, Set<string>>()
124
- const typeFilesByPath = new Map<string, ast.FileNode>()
125
-
126
- ops.forEach((op) => {
127
- const names = resolveTypeImportNames(op.node, tsResolver)
128
- if (!typeImportsByFile.has(op.typeFile.path)) {
129
- typeImportsByFile.set(op.typeFile.path, new Set())
130
- }
131
- const imports = typeImportsByFile.get(op.typeFile.path)!
132
- names.forEach((n) => {
133
- imports.add(n)
134
- })
135
- typeFilesByPath.set(op.typeFile.path, op.typeFile)
136
- })
137
-
138
- return { typeImportsByFile, typeFilesByPath }
139
- }
140
-
141
- function collectZodImports(ops: Array<OperationData>) {
142
- const zodImportsByFile = new Map<string, Set<string>>()
143
- const zodFilesByPath = new Map<string, ast.FileNode>()
144
-
145
- ops.forEach((op) => {
146
- if (!op.zodFile || !zodResolver) return
147
- const names = resolveZodImportNames(op.node, zodResolver)
148
- if (!zodImportsByFile.has(op.zodFile.path)) {
149
- zodImportsByFile.set(op.zodFile.path, new Set())
150
- }
151
- const imports = zodImportsByFile.get(op.zodFile.path)!
152
- names.forEach((n) => {
153
- imports.add(n)
154
- })
155
- zodFilesByPath.set(op.zodFile.path, op.zodFile)
156
- })
157
-
158
- return { zodImportsByFile, zodFilesByPath }
159
- }
160
-
161
- return (
162
- <>
163
- {controllers.map(({ name, file, operations: ops }) => {
164
- const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops)
165
- const { zodImportsByFile, zodFilesByPath } =
166
- parser === 'zod' ? collectZodImports(ops) : { zodImportsByFile: new Map<string, Set<string>>(), zodFilesByPath: new Map<string, ast.FileNode>() }
167
- const hasFormData = ops.some((op) => op.node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') ?? false)
168
-
169
- return (
170
- <File
171
- key={file.path}
172
- baseName={file.baseName}
173
- path={file.path}
174
- meta={file.meta}
175
- banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
176
- footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
177
- >
178
- {importPath ? (
179
- <>
180
- <File.Import name={'client'} path={importPath} />
181
- <File.Import name={['mergeConfig']} path={importPath} />
182
- <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={importPath} isTypeOnly />
183
- </>
184
- ) : (
185
- <>
186
- <File.Import name={['client']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
187
- <File.Import name={['mergeConfig']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
188
- <File.Import
189
- name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
190
- root={file.path}
191
- path={path.resolve(root, '.kubb/client.ts')}
192
- isTypeOnly
193
- />
194
- </>
195
- )}
196
-
197
- {hasFormData && <File.Import name={['buildFormData']} root={file.path} path={path.resolve(root, '.kubb/config.ts')} />}
198
-
199
- {Array.from(typeImportsByFile.entries()).map(([filePath, importSet]) => {
200
- const typeFile = typeFilesByPath.get(filePath)
201
- if (!typeFile) return null
202
- const importNames = Array.from(importSet).filter(Boolean)
203
- if (importNames.length === 0) return null
204
- return <File.Import key={filePath} name={importNames} root={file.path} path={typeFile.path} isTypeOnly />
205
- })}
206
-
207
- {parser === 'zod' &&
208
- Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
209
- const zodFile = zodFilesByPath.get(filePath)
210
- if (!zodFile) return null
211
- const importNames = Array.from(importSet).filter(Boolean)
212
- if (importNames.length === 0) return null
213
- return <File.Import key={filePath} name={importNames} root={file.path} path={zodFile.path} />
214
- })}
215
-
216
- <StaticClassClient
217
- name={name}
218
- operations={ops}
219
- baseURL={baseURL}
220
- dataReturnType={dataReturnType}
221
- pathParamsType={pathParamsType}
222
- paramsCasing={paramsCasing}
223
- paramsType={paramsType}
224
- parser={parser}
225
- />
226
- </File>
227
- )
228
- })}
229
- </>
230
- )
231
- },
232
- })
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- export { Client } from './components/Client.tsx'
2
- export { classClientGenerator } from './generators/classClientGenerator.tsx'
3
- export { clientGenerator } from './generators/clientGenerator.tsx'
4
- export { groupedClientGenerator } from './generators/groupedClientGenerator.tsx'
5
- export { operationsGenerator } from './generators/operationsGenerator.tsx'
6
- export { staticClassClientGenerator } from './generators/staticClassClientGenerator.tsx'
7
- export { default, pluginClient, pluginClientName } from './plugin.ts'
8
- export { resolverClient } from './resolvers/resolverClient.ts'
9
- export type { ClientImportPath, PluginClient, ResolverClient } from './types.ts'
package/src/plugin.ts DELETED
@@ -1,160 +0,0 @@
1
- import path from 'node:path'
2
- import { createGroupConfig } from '@internals/shared'
3
-
4
- import { ast, definePlugin } from '@kubb/core'
5
- import { pluginTsName } from '@kubb/plugin-ts'
6
- import { pluginZodName } from '@kubb/plugin-zod'
7
- import { classClientGenerator } from './generators/classClientGenerator.tsx'
8
- import { clientGenerator } from './generators/clientGenerator.tsx'
9
- import { groupedClientGenerator } from './generators/groupedClientGenerator.tsx'
10
- import { operationsGenerator } from './generators/operationsGenerator.tsx'
11
- import { staticClassClientGenerator } from './generators/staticClassClientGenerator.tsx'
12
- import { resolverClient } from './resolvers/resolverClient.ts'
13
- import { source as axiosClientSource } from './templates/clients/axios.source.ts'
14
- import { source as fetchClientSource } from './templates/clients/fetch.source.ts'
15
- import { source as configSource } from './templates/config.source.ts'
16
- import type { PluginClient } from './types.ts'
17
-
18
- /**
19
- * Canonical plugin name for `@kubb/plugin-client`. Used for driver lookups and
20
- * cross-plugin dependency references.
21
- */
22
- export const pluginClientName = 'plugin-client' satisfies PluginClient['name']
23
-
24
- /**
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`.
29
- *
30
- * @example
31
- * ```ts
32
- * import { defineConfig } from 'kubb'
33
- * import { pluginTs } from '@kubb/plugin-ts'
34
- * import { pluginClient } from '@kubb/plugin-client'
35
- *
36
- * export default defineConfig({
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
- * ],
46
- * })
47
- * ```
48
- */
49
- export const pluginClient = definePlugin<PluginClient>((options) => {
50
- const {
51
- output = { path: 'clients', barrelType: 'named' },
52
- group,
53
- exclude = [],
54
- include,
55
- override = [],
56
- urlType = false,
57
- dataReturnType = 'data',
58
- paramsType = 'inline',
59
- pathParamsType = paramsType === 'object' ? 'object' : options.pathParamsType || 'inline',
60
- operations = false,
61
- paramsCasing,
62
- clientType = options.sdk ? 'class' : 'function',
63
- parser = false,
64
- client = 'axios',
65
- importPath,
66
- bundle = false,
67
- sdk,
68
- baseURL,
69
- resolver: userResolver,
70
- transformer: userTransformer,
71
- } = options
72
-
73
- const resolvedImportPath = importPath ?? (!bundle ? `@kubb/plugin-client/clients/${client}` : undefined)
74
-
75
- const selectedGenerators =
76
- options.generators ??
77
- [
78
- clientType === 'staticClass' ? staticClassClientGenerator : clientType === 'class' ? classClientGenerator : clientGenerator,
79
- group && clientType === 'function' ? groupedClientGenerator : null,
80
- operations ? operationsGenerator : null,
81
- ].filter((x): x is NonNullable<typeof x> => Boolean(x))
82
-
83
- const groupConfig = createGroupConfig(group, { suffix: 'Controller' })
84
-
85
- return {
86
- name: pluginClientName,
87
- options,
88
- dependencies: [pluginTsName, parser === 'zod' ? pluginZodName : null].filter((dependency): dependency is string => Boolean(dependency)),
89
- hooks: {
90
- 'kubb:plugin:setup'(ctx) {
91
- const resolver = userResolver ? { ...resolverClient, ...userResolver } : resolverClient
92
-
93
- ctx.setOptions({
94
- client,
95
- clientType,
96
- bundle,
97
- output,
98
- exclude,
99
- include,
100
- override,
101
- group: groupConfig,
102
- parser,
103
- dataReturnType,
104
- importPath: resolvedImportPath,
105
- baseURL,
106
- paramsType,
107
- paramsCasing,
108
- pathParamsType,
109
- urlType,
110
- sdk,
111
- resolver,
112
- })
113
- ctx.setResolver(resolver)
114
- if (userTransformer) {
115
- ctx.setTransformer(userTransformer)
116
- }
117
- for (const gen of selectedGenerators) {
118
- ctx.addGenerator(gen)
119
- }
120
-
121
- const root = path.resolve(ctx.config.root, ctx.config.output.path)
122
-
123
- const isRelativePath = resolvedImportPath?.startsWith('.')
124
-
125
- if (!isRelativePath) {
126
- const isInlineSource = bundle && !resolvedImportPath
127
-
128
- ctx.injectFile({
129
- baseName: 'client.ts',
130
- path: path.resolve(root, '.kubb/client.ts'),
131
- sources: [
132
- ast.createSource({
133
- name: 'client',
134
- nodes: isInlineSource ? [ast.createText(client === 'fetch' ? fetchClientSource : axiosClientSource)] : [],
135
- isExportable: true,
136
- isIndexable: true,
137
- }),
138
- ],
139
- exports: !isInlineSource && resolvedImportPath ? [ast.createExport({ path: resolvedImportPath })] : [],
140
- })
141
- }
142
-
143
- ctx.injectFile({
144
- baseName: 'config.ts',
145
- path: path.resolve(root, '.kubb/config.ts'),
146
- sources: [
147
- ast.createSource({
148
- name: 'config',
149
- nodes: [ast.createText(configSource)],
150
- isExportable: false,
151
- isIndexable: false,
152
- }),
153
- ],
154
- })
155
- },
156
- },
157
- }
158
- })
159
-
160
- export default pluginClient
@@ -1,45 +0,0 @@
1
- import { camelCase, ensureValidVarName, pascalCase } from '@internals/utils'
2
- import { defineResolver } from '@kubb/core'
3
- import type { PluginClient } from '../types.ts'
4
-
5
- /**
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.
9
- *
10
- * @example Resolve client function and class names
11
- * ```ts
12
- * import { resolverClient } from '@kubb/plugin-client'
13
- *
14
- * resolverClient.default('list pets', 'function') // 'listPets'
15
- * resolverClient.resolveClassName('pet') // 'Pet'
16
- * resolverClient.resolveUrlName(operationNode) // 'getShowPetByIdUrl'
17
- * ```
18
- */
19
- export const resolverClient = defineResolver<PluginClient>(() => ({
20
- name: 'default',
21
- pluginName: 'plugin-client',
22
- default(name, type) {
23
- const resolved = camelCase(name, { isFile: type === 'file' })
24
- return type === 'file' ? resolved : ensureValidVarName(resolved)
25
- },
26
- resolveName(name) {
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`
44
- },
45
- }))
@@ -1,4 +0,0 @@
1
- // @ts-expect-error - import attributes are handled at build time by importAttributeTextPlugin
2
- import content from '../../../templates/clients/axios.ts' with { type: 'text' }
3
-
4
- export const source = content as string
@@ -1,4 +0,0 @@
1
- // @ts-expect-error - import attributes are handled at build time by importAttributeTextPlugin
2
- import content from '../../../templates/clients/fetch.ts' with { type: 'text' }
3
-
4
- export const source = content as string
@@ -1,4 +0,0 @@
1
- // @ts-expect-error - import attributes are handled at build time by importAttributeTextPlugin
2
- import content from '../../templates/config.ts' with { type: 'text' }
3
-
4
- export const source = content as string