@kubb/plugin-client 5.0.0-alpha.9 → 5.0.0-beta.4

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 (61) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +4 -4
  3. package/dist/clients/axios.cjs +2 -2
  4. package/dist/clients/axios.cjs.map +1 -1
  5. package/dist/clients/axios.d.ts +4 -4
  6. package/dist/clients/axios.js +1 -1
  7. package/dist/clients/axios.js.map +1 -1
  8. package/dist/clients/fetch.cjs +1 -1
  9. package/dist/clients/fetch.cjs.map +1 -1
  10. package/dist/clients/fetch.d.ts +2 -2
  11. package/dist/clients/fetch.js +1 -1
  12. package/dist/clients/fetch.js.map +1 -1
  13. package/dist/index.cjs +1739 -97
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +324 -4
  16. package/dist/index.js +1725 -95
  17. package/dist/index.js.map +1 -1
  18. package/dist/templates/clients/axios.source.cjs +1 -1
  19. package/dist/templates/clients/axios.source.js +1 -1
  20. package/dist/templates/clients/fetch.source.cjs +1 -1
  21. package/dist/templates/clients/fetch.source.js +1 -1
  22. package/extension.yaml +776 -0
  23. package/package.json +67 -84
  24. package/src/clients/axios.ts +5 -1
  25. package/src/clients/fetch.ts +5 -1
  26. package/src/components/ClassClient.tsx +45 -142
  27. package/src/components/Client.tsx +90 -129
  28. package/src/components/Operations.tsx +10 -10
  29. package/src/components/StaticClassClient.tsx +44 -138
  30. package/src/components/Url.tsx +38 -48
  31. package/src/components/WrapperClient.tsx +3 -3
  32. package/src/functionParams.ts +118 -0
  33. package/src/generators/classClientGenerator.tsx +148 -171
  34. package/src/generators/clientGenerator.tsx +95 -82
  35. package/src/generators/groupedClientGenerator.tsx +50 -52
  36. package/src/generators/operationsGenerator.tsx +11 -18
  37. package/src/generators/staticClassClientGenerator.tsx +178 -183
  38. package/src/index.ts +9 -2
  39. package/src/plugin.ts +115 -145
  40. package/src/resolvers/resolverClient.ts +22 -0
  41. package/src/types.ts +104 -44
  42. package/src/utils.ts +180 -0
  43. package/templates/clients/axios.ts +5 -2
  44. package/templates/clients/fetch.ts +5 -2
  45. package/dist/StaticClassClient-By-aMAe4.cjs +0 -677
  46. package/dist/StaticClassClient-By-aMAe4.cjs.map +0 -1
  47. package/dist/StaticClassClient-CCn9g9eF.js +0 -636
  48. package/dist/StaticClassClient-CCn9g9eF.js.map +0 -1
  49. package/dist/components.cjs +0 -7
  50. package/dist/components.d.ts +0 -216
  51. package/dist/components.js +0 -2
  52. package/dist/generators-BYUJaeZP.js +0 -723
  53. package/dist/generators-BYUJaeZP.js.map +0 -1
  54. package/dist/generators-DTxD9FDY.cjs +0 -753
  55. package/dist/generators-DTxD9FDY.cjs.map +0 -1
  56. package/dist/generators.cjs +0 -7
  57. package/dist/generators.d.ts +0 -517
  58. package/dist/generators.js +0 -2
  59. package/dist/types-DBQdg-BV.d.ts +0 -169
  60. package/src/components/index.ts +0 -5
  61. package/src/generators/index.ts +0 -5
package/package.json CHANGED
@@ -1,34 +1,67 @@
1
1
  {
2
2
  "name": "@kubb/plugin-client",
3
- "version": "5.0.0-alpha.9",
3
+ "version": "5.0.0-beta.4",
4
4
  "description": "API client generator plugin for Kubb, creating type-safe HTTP clients (Axios, Fetch) from OpenAPI specifications for making API requests.",
5
5
  "keywords": [
6
6
  "api-client",
7
- "http-client",
8
- "sdk-generator",
9
7
  "axios",
10
- "fetch",
11
- "rest-api",
12
- "typescript",
13
- "type-safety",
14
- "type-safe",
15
- "openapi",
16
- "swagger",
17
- "oas",
18
8
  "code-generator",
19
9
  "codegen",
10
+ "fetch",
11
+ "http-client",
12
+ "kubb",
13
+ "oas",
14
+ "openapi",
20
15
  "plugins",
21
- "kubb"
16
+ "rest-api",
17
+ "sdk-generator",
18
+ "swagger",
19
+ "type-safe",
20
+ "type-safety",
21
+ "typescript"
22
22
  ],
23
+ "license": "MIT",
24
+ "author": "stijnvanhulle",
23
25
  "repository": {
24
26
  "type": "git",
25
- "url": "git+https://github.com/kubb-labs/kubb.git",
27
+ "url": "git+https://github.com/kubb-labs/plugins.git",
26
28
  "directory": "packages/plugin-client"
27
29
  },
28
- "license": "MIT",
29
- "author": "stijnvanhulle",
30
- "sideEffects": false,
30
+ "files": [
31
+ "src",
32
+ "dist",
33
+ "templates",
34
+ "extension.yaml",
35
+ "*.d.ts",
36
+ "*.d.cts",
37
+ "!/**/**.test.**",
38
+ "!/**/__tests__/**",
39
+ "!/**/__snapshots__/**"
40
+ ],
31
41
  "type": "module",
42
+ "sideEffects": false,
43
+ "main": "./dist/index.cjs",
44
+ "module": "./dist/index.js",
45
+ "types": "./dist/index.d.ts",
46
+ "typesVersions": {
47
+ "*": {
48
+ "clients/axios": [
49
+ "./dist/clients/axios.d.ts"
50
+ ],
51
+ "clients/fetch": [
52
+ "./dist/clients/fetch.d.ts"
53
+ ],
54
+ "templates/config.source": [
55
+ "./dist/templates/config.source.d.ts"
56
+ ],
57
+ "templates/clients/axios.source": [
58
+ "./dist/templates/clients/axios.source.d.ts"
59
+ ],
60
+ "templates/clients/fetch.source": [
61
+ "./dist/templates/clients/fetch.source.d.ts"
62
+ ]
63
+ }
64
+ },
32
65
  "exports": {
33
66
  ".": {
34
67
  "import": "./dist/index.js",
@@ -42,14 +75,6 @@
42
75
  "import": "./dist/clients/fetch.js",
43
76
  "require": "./dist/clients/fetch.cjs"
44
77
  },
45
- "./components": {
46
- "import": "./dist/components.js",
47
- "require": "./dist/components.cjs"
48
- },
49
- "./generators": {
50
- "import": "./dist/generators.js",
51
- "require": "./dist/generators.cjs"
52
- },
53
78
  "./templates/clients/axios.source": {
54
79
  "import": "./dist/templates/clients/axios.source.js",
55
80
  "require": "./dist/templates/clients/axios.source.cjs"
@@ -64,65 +89,22 @@
64
89
  },
65
90
  "./package.json": "./package.json"
66
91
  },
67
- "types": "./dist/index.d.ts",
68
- "typesVersions": {
69
- "*": {
70
- "components": [
71
- "./dist/components.d.ts"
72
- ],
73
- "generators": [
74
- "./dist/generators.d.ts"
75
- ],
76
- "clients/axios": [
77
- "./dist/clients/axios.d.ts"
78
- ],
79
- "clients/fetch": [
80
- "./dist/clients/fetch.d.ts"
81
- ],
82
- "templates/config.source": [
83
- "./dist/templates/config.source.d.ts"
84
- ],
85
- "templates/clients/axios.source": [
86
- "./dist/templates/clients/axios.source.d.ts"
87
- ],
88
- "templates/clients/fetch.source": [
89
- "./dist/templates/clients/fetch.source.d.ts"
90
- ]
91
- }
92
+ "publishConfig": {
93
+ "access": "public",
94
+ "registry": "https://registry.npmjs.org/"
92
95
  },
93
- "files": [
94
- "src",
95
- "dist",
96
- "templates",
97
- "*.d.ts",
98
- "*.d.cts",
99
- "!/**/**.test.**",
100
- "!/**/__tests__/**",
101
- "!/**/__snapshots__/**"
102
- ],
103
- "size-limit": [
104
- {
105
- "path": "./dist/*.js",
106
- "limit": "510 KiB",
107
- "gzip": true
108
- }
109
- ],
110
96
  "dependencies": {
111
- "@kubb/fabric-core": "0.14.0",
112
- "@kubb/react-fabric": "0.14.0",
113
- "@kubb/core": "5.0.0-alpha.9",
114
- "@kubb/oas": "5.0.0-alpha.9",
115
- "@kubb/plugin-oas": "5.0.0-alpha.9",
116
- "@kubb/plugin-ts": "5.0.0-alpha.9",
117
- "@kubb/plugin-zod": "5.0.0-alpha.9"
97
+ "@kubb/core": "5.0.0-beta.4",
98
+ "@kubb/renderer-jsx": "5.0.0-beta.4",
99
+ "@kubb/plugin-ts": "5.0.0-beta.4",
100
+ "@kubb/plugin-zod": "5.0.0-beta.4"
118
101
  },
119
102
  "devDependencies": {
120
- "axios": "^1.13.6",
103
+ "axios": "^1.15.2",
121
104
  "@internals/utils": "0.0.0"
122
105
  },
123
106
  "peerDependencies": {
124
- "@kubb/fabric-core": "0.14.0",
125
- "@kubb/react-fabric": "0.14.0",
107
+ "@kubb/renderer-jsx": "5.0.0-beta.4",
126
108
  "axios": "^1.7.2"
127
109
  },
128
110
  "peerDependenciesMeta": {
@@ -130,20 +112,21 @@
130
112
  "optional": true
131
113
  }
132
114
  },
115
+ "size-limit": [
116
+ {
117
+ "path": "./dist/*.js",
118
+ "limit": "510 KiB",
119
+ "gzip": true
120
+ }
121
+ ],
133
122
  "engines": {
134
123
  "node": ">=22"
135
124
  },
136
- "publishConfig": {
137
- "access": "public",
138
- "registry": "https://registry.npmjs.org/"
139
- },
140
- "main": "./dist/index.cjs",
141
- "module": "./dist/index.js",
142
125
  "scripts": {
143
126
  "build": "tsdown && size-limit",
144
127
  "clean": "npx rimraf ./dist",
145
- "lint": "bun biome lint .",
146
- "lint:fix": "bun biome lint --fix --unsafe .",
128
+ "lint": "oxlint .",
129
+ "lint:fix": "oxlint --fix .",
147
130
  "release": "pnpm publish --no-git-check",
148
131
  "release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
149
132
  "start": "tsdown --watch",
@@ -32,7 +32,10 @@ export type ResponseConfig<TData = unknown> = {
32
32
 
33
33
  export type ResponseErrorConfig<TError = unknown> = AxiosError<TError>
34
34
 
35
- export type Client = <TResponseData, _TError = unknown, TRequestData = unknown>(config: RequestConfig<TRequestData>) => Promise<ResponseConfig<TResponseData>>
35
+ export type Client = <TResponseData, _TError = unknown, TRequestData = unknown>(
36
+ config: RequestConfig<TRequestData>,
37
+ request?: unknown,
38
+ ) => Promise<ResponseConfig<TResponseData>>
36
39
 
37
40
  let _config: Partial<RequestConfig> = {
38
41
  baseURL: typeof AXIOS_BASE !== 'undefined' ? AXIOS_BASE : undefined,
@@ -63,6 +66,7 @@ export const axiosInstance = axios.create(getConfig())
63
66
 
64
67
  export const client = async <TResponseData, TError = unknown, TRequestData = unknown>(
65
68
  config: RequestConfig<TRequestData>,
69
+ _request?: unknown,
66
70
  ): Promise<ResponseConfig<TResponseData>> => {
67
71
  return axiosInstance.request<TResponseData, ResponseConfig<TResponseData>>(mergeConfig(getConfig(), config)).catch((e: AxiosError<TError>) => {
68
72
  throw e
@@ -52,10 +52,14 @@ export const mergeConfig = <T extends RequestConfig>(...configs: Array<Partial<T
52
52
 
53
53
  export type ResponseErrorConfig<TError = unknown> = TError
54
54
 
55
- export type Client = <TResponseData, _TError = unknown, TRequestData = unknown>(config: RequestConfig<TRequestData>) => Promise<ResponseConfig<TResponseData>>
55
+ export type Client = <TResponseData, _TError = unknown, TRequestData = unknown>(
56
+ config: RequestConfig<TRequestData>,
57
+ request?: unknown,
58
+ ) => Promise<ResponseConfig<TResponseData>>
56
59
 
57
60
  export const client = async <TResponseData, _TError = unknown, RequestData = unknown>(
58
61
  paramsConfig: RequestConfig<RequestData>,
62
+ _request?: unknown,
59
63
  ): Promise<ResponseConfig<TResponseData>> => {
60
64
  const normalizedParams = new URLSearchParams()
61
65
 
@@ -1,40 +1,40 @@
1
1
  import { buildJSDoc, URLPath } from '@internals/utils'
2
- import type { Operation } from '@kubb/oas'
3
- import type { OperationSchemas } from '@kubb/plugin-oas'
4
- import { getComments } from '@kubb/plugin-oas/utils'
5
- import { File, FunctionParams } from '@kubb/react-fabric'
6
- import type { FabricReactNode } from '@kubb/react-fabric/types'
2
+ import type { ast } from '@kubb/core'
3
+ import type { ResolverTs } from '@kubb/plugin-ts'
4
+ import { functionPrinter } from '@kubb/plugin-ts'
5
+ import type { ResolverZod } from '@kubb/plugin-zod'
6
+ import { File } from '@kubb/renderer-jsx'
7
+ import type { KubbReactNode } from '@kubb/renderer-jsx/types'
7
8
  import type { PluginClient } from '../types.ts'
8
-
9
+ import { buildClassClientParams, buildFormDataLine, buildGenerics, buildHeaders, buildRequestDataLine, buildReturnStatement, getComments } from '../utils.ts'
9
10
  import { Client } from './Client.tsx'
10
11
 
12
+ type OperationData = {
13
+ node: ast.OperationNode
14
+ name: string
15
+ tsResolver: ResolverTs
16
+ zodResolver?: ResolverZod
17
+ }
18
+
11
19
  type Props = {
12
- /**
13
- * Name of the class
14
- */
15
20
  name: string
16
21
  isExportable?: boolean
17
22
  isIndexable?: boolean
18
- operations: Array<{
19
- operation: Operation
20
- name: string
21
- typeSchemas: OperationSchemas
22
- zodSchemas: OperationSchemas | undefined
23
- }>
23
+ operations: Array<OperationData>
24
24
  baseURL: string | undefined
25
25
  dataReturnType: PluginClient['resolvedOptions']['dataReturnType']
26
26
  paramsCasing: PluginClient['resolvedOptions']['paramsCasing']
27
27
  paramsType: PluginClient['resolvedOptions']['pathParamsType']
28
28
  pathParamsType: PluginClient['resolvedOptions']['pathParamsType']
29
29
  parser: PluginClient['resolvedOptions']['parser'] | undefined
30
- children?: FabricReactNode
30
+ children?: KubbReactNode
31
31
  }
32
32
 
33
33
  type GenerateMethodProps = {
34
- operation: Operation
34
+ node: ast.OperationNode
35
35
  name: string
36
- typeSchemas: OperationSchemas
37
- zodSchemas: OperationSchemas | undefined
36
+ tsResolver: ResolverTs
37
+ zodResolver?: ResolverZod
38
38
  baseURL: string | undefined
39
39
  dataReturnType: PluginClient['resolvedOptions']['dataReturnType']
40
40
  parser: PluginClient['resolvedOptions']['parser'] | undefined
@@ -43,115 +43,13 @@ type GenerateMethodProps = {
43
43
  pathParamsType: PluginClient['resolvedOptions']['pathParamsType']
44
44
  }
45
45
 
46
- function buildHeaders(contentType: string, hasHeaderParams: boolean): Array<string> {
47
- return [
48
- contentType !== 'application/json' && contentType !== 'multipart/form-data' ? `'Content-Type': '${contentType}'` : undefined,
49
- hasHeaderParams ? '...headers' : undefined,
50
- ].filter(Boolean) as Array<string>
51
- }
52
-
53
- function buildGenerics(typeSchemas: OperationSchemas): Array<string> {
54
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
55
- return [typeSchemas.response.name, TError, typeSchemas.request?.name || 'unknown'].filter(Boolean)
56
- }
57
-
58
- function buildClientParams({
59
- operation,
60
- path,
61
- baseURL,
62
- typeSchemas,
63
- isFormData,
64
- headers,
65
- }: {
66
- operation: Operation
67
- path: URLPath
68
- baseURL: string | undefined
69
- typeSchemas: OperationSchemas
70
- isFormData: boolean
71
- headers: Array<string>
72
- }) {
73
- return FunctionParams.factory({
74
- config: {
75
- mode: 'object',
76
- children: {
77
- requestConfig: {
78
- mode: 'inlineSpread',
79
- },
80
- method: {
81
- value: JSON.stringify(operation.method.toUpperCase()),
82
- },
83
- url: {
84
- value: path.template,
85
- },
86
- baseURL: baseURL
87
- ? {
88
- value: JSON.stringify(baseURL),
89
- }
90
- : undefined,
91
- params: typeSchemas.queryParams?.name ? {} : undefined,
92
- data: typeSchemas.request?.name
93
- ? {
94
- value: isFormData ? 'formData as FormData' : 'requestData',
95
- }
96
- : undefined,
97
- headers: headers.length
98
- ? {
99
- value: `{ ${headers.join(', ')}, ...requestConfig.headers }`,
100
- }
101
- : undefined,
102
- },
103
- },
104
- })
105
- }
106
-
107
- function buildRequestDataLine({
108
- parser,
109
- zodSchemas,
110
- typeSchemas,
111
- }: {
112
- parser: PluginClient['resolvedOptions']['parser'] | undefined
113
- zodSchemas: OperationSchemas | undefined
114
- typeSchemas: OperationSchemas
115
- }): string {
116
- if (parser === 'zod' && zodSchemas?.request?.name) {
117
- return `const requestData = ${zodSchemas.request.name}.parse(data)`
118
- }
119
- if (typeSchemas?.request?.name) {
120
- return 'const requestData = data'
121
- }
122
- return ''
123
- }
124
-
125
- function buildFormDataLine(isFormData: boolean, hasRequest: boolean): string {
126
- return isFormData && hasRequest ? 'const formData = buildFormData(requestData)' : ''
127
- }
128
-
129
- function buildReturnStatement({
130
- dataReturnType,
131
- parser,
132
- zodSchemas,
133
- }: {
134
- dataReturnType: PluginClient['resolvedOptions']['dataReturnType']
135
- parser: PluginClient['resolvedOptions']['parser'] | undefined
136
- zodSchemas: OperationSchemas | undefined
137
- }): string {
138
- if (dataReturnType === 'full' && parser === 'zod' && zodSchemas) {
139
- return `return {...res, data: ${zodSchemas.response.name}.parse(res.data)}`
140
- }
141
- if (dataReturnType === 'data' && parser === 'zod' && zodSchemas) {
142
- return `return ${zodSchemas.response.name}.parse(res.data)`
143
- }
144
- if (dataReturnType === 'full' && parser === 'client') {
145
- return 'return res'
146
- }
147
- return 'return res.data'
148
- }
46
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
149
47
 
150
48
  function generateMethod({
151
- operation,
49
+ node,
152
50
  name,
153
- typeSchemas,
154
- zodSchemas,
51
+ tsResolver,
52
+ zodResolver,
155
53
  baseURL,
156
54
  dataReturnType,
157
55
  parser,
@@ -159,18 +57,23 @@ function generateMethod({
159
57
  paramsCasing,
160
58
  pathParamsType,
161
59
  }: GenerateMethodProps): string {
162
- const path = new URLPath(operation.path, { casing: paramsCasing })
163
- const contentType = operation.getContentType()
60
+ const path = new URLPath(node.path, { casing: paramsCasing })
61
+ const contentType = node.requestBody?.content?.[0]?.contentType ?? 'application/json'
164
62
  const isFormData = contentType === 'multipart/form-data'
165
- const headers = buildHeaders(contentType, !!typeSchemas.headerParams?.name)
166
- const generics = buildGenerics(typeSchemas)
167
- const params = ClassClient.getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas, isConfigurable: true })
168
- const clientParams = buildClientParams({ operation, path, baseURL, typeSchemas, isFormData, headers })
169
- const jsdoc = buildJSDoc(getComments(operation))
170
-
171
- const requestDataLine = buildRequestDataLine({ parser, zodSchemas, typeSchemas })
172
- const formDataLine = buildFormDataLine(isFormData, !!typeSchemas?.request?.name)
173
- const returnStatement = buildReturnStatement({ dataReturnType, parser, zodSchemas })
63
+ const headerParamsName =
64
+ node.parameters.filter((p) => p.in === 'header').length > 0
65
+ ? tsResolver.resolveHeaderParamsName(node, node.parameters.filter((p) => p.in === 'header')[0]!)
66
+ : undefined
67
+ const headers = buildHeaders(contentType, !!headerParamsName)
68
+ const generics = buildGenerics(node, tsResolver)
69
+ const paramsNode = ClassClient.getParams({ paramsType, paramsCasing, pathParamsType, node, tsResolver, isConfigurable: true })
70
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
71
+ const clientParams = buildClassClientParams({ node, path, baseURL, tsResolver, isFormData, headers })
72
+ const jsdoc = buildJSDoc(getComments(node))
73
+
74
+ const requestDataLine = buildRequestDataLine({ parser, node, zodResolver })
75
+ const formDataLine = buildFormDataLine(isFormData, !!node.requestBody?.content?.[0]?.schema)
76
+ const returnStatement = buildReturnStatement({ dataReturnType, parser, node, zodResolver })
174
77
 
175
78
  const methodBody = [
176
79
  'const { client: request = fetch, ...requestConfig } = mergeConfig(this.#config, config)',
@@ -184,7 +87,7 @@ function generateMethod({
184
87
  .map((line) => ` ${line}`)
185
88
  .join('\n')
186
89
 
187
- return `${jsdoc}async ${name}(${params.toConstructor()}) {\n${methodBody}\n }`
90
+ return `${jsdoc}async ${name}(${paramsSignature}) {\n${methodBody}\n }`
188
91
  }
189
92
 
190
93
  export function ClassClient({
@@ -199,13 +102,13 @@ export function ClassClient({
199
102
  paramsCasing,
200
103
  pathParamsType,
201
104
  children,
202
- }: Props): FabricReactNode {
203
- const methods = operations.map(({ operation, name: methodName, typeSchemas, zodSchemas }) =>
105
+ }: Props): KubbReactNode {
106
+ const methods = operations.map(({ node, name: methodName, tsResolver, zodResolver }) =>
204
107
  generateMethod({
205
- operation,
108
+ node,
206
109
  name: methodName,
207
- typeSchemas,
208
- zodSchemas,
110
+ tsResolver,
111
+ zodResolver,
209
112
  baseURL,
210
113
  dataReturnType,
211
114
  parser,