@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
@@ -1,16 +1,16 @@
1
1
  import { isValidVarName, URLPath } from '@internals/utils'
2
- import { getDefaultValue, isOptional, type Operation } from '@kubb/oas'
3
- import type { OperationSchemas } from '@kubb/plugin-oas'
4
- import { getComments, getParamsMapping, getPathParams } from '@kubb/plugin-oas/utils'
5
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
6
- import type { FabricReactNode } from '@kubb/react-fabric/types'
2
+ import { 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, Function } from '@kubb/renderer-jsx'
7
+ import type { KubbReactNode } from '@kubb/renderer-jsx/types'
8
+ import { createFunctionParams } from '../functionParams.ts'
7
9
  import type { PluginClient } from '../types.ts'
10
+ import { buildParamsMapping, getComments } from '../utils.ts'
8
11
  import { Url } from './Url.tsx'
9
12
 
10
13
  type Props = {
11
- /**
12
- * Name of the function
13
- */
14
14
  name: string
15
15
  urlName?: string
16
16
  isExportable?: boolean
@@ -24,106 +24,43 @@ type Props = {
24
24
  paramsType: PluginClient['resolvedOptions']['pathParamsType']
25
25
  pathParamsType: PluginClient['resolvedOptions']['pathParamsType']
26
26
  parser: PluginClient['resolvedOptions']['parser'] | undefined
27
- typeSchemas: OperationSchemas
28
- zodSchemas: OperationSchemas | undefined
29
- operation: Operation
30
- children?: FabricReactNode
27
+ node: ast.OperationNode
28
+ tsResolver: ResolverTs
29
+ zodResolver?: ResolverZod
30
+ children?: KubbReactNode
31
31
  }
32
32
 
33
33
  type GetParamsProps = {
34
34
  paramsCasing: PluginClient['resolvedOptions']['paramsCasing']
35
35
  paramsType: PluginClient['resolvedOptions']['paramsType']
36
36
  pathParamsType: PluginClient['resolvedOptions']['pathParamsType']
37
- typeSchemas: OperationSchemas
37
+ node: ast.OperationNode
38
+ tsResolver: ResolverTs
38
39
  isConfigurable: boolean
39
40
  }
40
41
 
41
- function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas, isConfigurable }: GetParamsProps) {
42
- if (paramsType === 'object') {
43
- const pathParams = getPathParams(typeSchemas.pathParams, {
44
- typed: true,
45
- casing: paramsCasing,
46
- })
47
-
48
- const children = {
49
- ...pathParams,
50
- data: typeSchemas.request?.name
51
- ? {
52
- type: typeSchemas.request?.name,
53
- optional: isOptional(typeSchemas.request?.schema),
54
- }
55
- : undefined,
56
- params: typeSchemas.queryParams?.name
57
- ? {
58
- type: typeSchemas.queryParams?.name,
59
- optional: isOptional(typeSchemas.queryParams?.schema),
60
- }
61
- : undefined,
62
- headers: typeSchemas.headerParams?.name
63
- ? {
64
- type: typeSchemas.headerParams?.name,
65
- optional: isOptional(typeSchemas.headerParams?.schema),
66
- }
67
- : undefined,
68
- }
42
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
69
43
 
70
- // Check if all children are optional or undefined
71
- const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
44
+ function getParams({ paramsType, paramsCasing, pathParamsType, node, tsResolver, isConfigurable }: GetParamsProps): ast.FunctionParametersNode {
45
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined
72
46
 
73
- return FunctionParams.factory({
74
- data: {
75
- mode: 'object',
76
- children,
77
- default: allChildrenAreOptional ? '{}' : undefined,
78
- },
79
- config: isConfigurable
80
- ? {
81
- type: typeSchemas.request?.name
82
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
83
- : 'Partial<RequestConfig> & { client?: Client }',
47
+ return ast.createOperationParams(node, {
48
+ paramsType,
49
+ pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
50
+ paramsCasing,
51
+ resolver: tsResolver,
52
+ extraParams: isConfigurable
53
+ ? [
54
+ ast.createFunctionParameter({
55
+ name: 'config',
56
+ type: ast.createParamsType({
57
+ variant: 'reference',
58
+ name: requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }',
59
+ }),
84
60
  default: '{}',
85
- }
86
- : undefined,
87
- })
88
- }
89
-
90
- return FunctionParams.factory({
91
- pathParams: typeSchemas.pathParams?.name
92
- ? {
93
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
94
- children: getPathParams(typeSchemas.pathParams, {
95
- typed: true,
96
- casing: paramsCasing,
97
61
  }),
98
- default: getDefaultValue(typeSchemas.pathParams?.schema),
99
- }
100
- : undefined,
101
- data: typeSchemas.request?.name
102
- ? {
103
- type: typeSchemas.request?.name,
104
- optional: isOptional(typeSchemas.request?.schema),
105
- }
106
- : undefined,
107
- params: typeSchemas.queryParams?.name
108
- ? {
109
- type: typeSchemas.queryParams?.name,
110
- optional: isOptional(typeSchemas.queryParams?.schema),
111
- }
112
- : undefined,
113
- headers: typeSchemas.headerParams?.name
114
- ? {
115
- type: typeSchemas.headerParams?.name,
116
- optional: isOptional(typeSchemas.headerParams?.schema),
117
- }
118
- : undefined,
119
- config: isConfigurable
120
- ? {
121
- type: typeSchemas.request?.name
122
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
123
- : 'Partial<RequestConfig> & { client?: Client }',
124
- default: '{}',
125
- }
126
- : undefined,
62
+ ]
63
+ : [],
127
64
  })
128
65
  }
129
66
 
@@ -132,60 +69,86 @@ export function Client({
132
69
  isExportable = true,
133
70
  isIndexable = true,
134
71
  returnType,
135
- typeSchemas,
136
72
  baseURL,
137
73
  dataReturnType,
138
74
  parser,
139
- zodSchemas,
140
75
  paramsType,
141
76
  paramsCasing,
142
77
  pathParamsType,
143
- operation,
78
+ node,
79
+ tsResolver,
80
+ zodResolver,
144
81
  urlName,
145
82
  children,
146
83
  isConfigurable = true,
147
- }: Props): FabricReactNode {
148
- const path = new URLPath(operation.path)
149
- const contentType = operation.getContentType()
84
+ }: Props): KubbReactNode {
85
+ const path = new URLPath(node.path)
86
+ const contentType = node.requestBody?.content?.[0]?.contentType ?? 'application/json'
150
87
  const isFormData = contentType === 'multipart/form-data'
151
88
 
152
- // Generate parameter mappings when paramsCasing is used
153
- // Apply to pathParams, queryParams and headerParams
154
- const pathParamsMapping = paramsCasing ? getParamsMapping(typeSchemas.pathParams, { casing: paramsCasing }) : undefined
155
- const queryParamsMapping = paramsCasing ? getParamsMapping(typeSchemas.queryParams, { casing: paramsCasing }) : undefined
156
- const headerParamsMapping = paramsCasing ? getParamsMapping(typeSchemas.headerParams, { casing: paramsCasing }) : undefined
89
+ const originalPathParams = node.parameters.filter((p) => p.in === 'path')
90
+ const casedPathParams = ast.caseParams(originalPathParams, paramsCasing)
91
+ const originalQueryParams = node.parameters.filter((p) => p.in === 'query')
92
+ const casedQueryParams = ast.caseParams(originalQueryParams, paramsCasing)
93
+ const originalHeaderParams = node.parameters.filter((p) => p.in === 'header')
94
+ const casedHeaderParams = ast.caseParams(originalHeaderParams, paramsCasing)
95
+
96
+ const pathParamsMapping = paramsCasing && !urlName ? buildParamsMapping(originalPathParams, casedPathParams) : undefined
97
+ const queryParamsMapping = paramsCasing ? buildParamsMapping(originalQueryParams, casedQueryParams) : undefined
98
+ const headerParamsMapping = paramsCasing ? buildParamsMapping(originalHeaderParams, casedHeaderParams) : undefined
99
+
100
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined
101
+ const responseName = tsResolver.resolveResponseName(node)
102
+ const queryParamsName = originalQueryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, originalQueryParams[0]!) : undefined
103
+ const headerParamsName = originalHeaderParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, originalHeaderParams[0]!) : undefined
104
+
105
+ const zodResponseName = zodResolver && parser === 'zod' ? zodResolver.resolveResponseName?.(node) : undefined
106
+ const zodRequestName = zodResolver && parser === 'zod' && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined
107
+
108
+ const errorNames = node.responses
109
+ .filter((r) => {
110
+ const code = Number.parseInt(r.statusCode, 10)
111
+ return code >= 400
112
+ })
113
+ .map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode))
157
114
 
158
115
  const headers = [
159
116
  contentType !== 'application/json' && contentType !== 'multipart/form-data' ? `'Content-Type': '${contentType}'` : undefined,
160
- typeSchemas.headerParams?.name ? (headerParamsMapping ? '...mappedHeaders' : '...headers') : undefined,
117
+ headerParamsName ? (headerParamsMapping ? '...mappedHeaders' : '...headers') : undefined,
161
118
  ].filter(Boolean)
162
119
 
163
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
120
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
164
121
 
165
- const generics = [typeSchemas.response.name, TError, typeSchemas.request?.name || 'unknown'].filter(Boolean)
166
- const params = getParams({
122
+ const generics = [responseName, TError, requestName || 'unknown'].filter(Boolean)
123
+ const paramsNode = getParams({
167
124
  paramsType,
168
125
  paramsCasing,
169
126
  pathParamsType,
170
- typeSchemas,
127
+ node,
128
+ tsResolver,
171
129
  isConfigurable,
172
130
  })
173
- const urlParams = Url.getParams({
131
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
132
+
133
+ const urlParamsNode = Url.getParams({
174
134
  paramsType,
175
135
  paramsCasing,
176
136
  pathParamsType,
177
- typeSchemas,
137
+ node,
138
+ tsResolver,
178
139
  })
140
+ const callPrinter = functionPrinter({ mode: 'call' })
141
+ const urlParamsCall = callPrinter.print(urlParamsNode) ?? ''
179
142
 
180
- const clientParams = FunctionParams.factory({
143
+ const clientParams = createFunctionParams({
181
144
  config: {
182
145
  mode: 'object',
183
146
  children: {
184
147
  method: {
185
- value: JSON.stringify(operation.method.toUpperCase()),
148
+ value: JSON.stringify(node.method.toUpperCase()),
186
149
  },
187
150
  url: {
188
- value: urlName ? `${urlName}(${urlParams.toCall()}).url.toString()` : path.template,
151
+ value: urlName ? `${urlName}(${urlParamsCall}).url.toString()` : path.template,
189
152
  },
190
153
  baseURL:
191
154
  baseURL && !urlName
@@ -193,8 +156,8 @@ export function Client({
193
156
  value: `\`${baseURL}\``,
194
157
  }
195
158
  : undefined,
196
- params: typeSchemas.queryParams?.name ? (queryParamsMapping ? { value: 'mappedParams' } : {}) : undefined,
197
- data: typeSchemas.request?.name
159
+ params: queryParamsName ? (queryParamsMapping ? { value: 'mappedParams' } : {}) : undefined,
160
+ data: requestName
198
161
  ? {
199
162
  value: isFormData ? 'formData as FormData' : 'requestData',
200
163
  }
@@ -217,8 +180,8 @@ export function Client({
217
180
  children
218
181
  ) : (
219
182
  <>
220
- {dataReturnType === 'full' && parser === 'zod' && zodSchemas && `return {...res, data: ${zodSchemas.response.name}.parse(res.data)}`}
221
- {dataReturnType === 'data' && parser === 'zod' && zodSchemas && `return ${zodSchemas.response.name}.parse(res.data)`}
183
+ {dataReturnType === 'full' && parser === 'zod' && zodResponseName && `return {...res, data: ${zodResponseName}.parse(res.data)}`}
184
+ {dataReturnType === 'data' && parser === 'zod' && zodResponseName && `return ${zodResponseName}.parse(res.data)`}
222
185
  {dataReturnType === 'full' && parser === 'client' && 'return res'}
223
186
  {dataReturnType === 'data' && parser === 'client' && 'return res.data'}
224
187
  </>
@@ -233,9 +196,9 @@ export function Client({
233
196
  name={name}
234
197
  async
235
198
  export={isExportable}
236
- params={params.toConstructor()}
199
+ params={paramsSignature}
237
200
  JSDoc={{
238
- comments: getComments(operation),
201
+ comments: getComments(node),
239
202
  }}
240
203
  returnType={returnType}
241
204
  >
@@ -244,7 +207,7 @@ export function Client({
244
207
  <br />
245
208
  {pathParamsMapping &&
246
209
  Object.entries(pathParamsMapping)
247
- .filter(([originalName, camelCaseName]) => originalName !== camelCaseName && isValidVarName(originalName))
210
+ .filter(([originalName, camelCaseName]) => isValidVarName(originalName) && originalName !== camelCaseName)
248
211
  .map(([originalName, camelCaseName]) => `const ${originalName} = ${camelCaseName}`)
249
212
  .join('\n')}
250
213
  {pathParamsMapping && (
@@ -253,7 +216,7 @@ export function Client({
253
216
  <br />
254
217
  </>
255
218
  )}
256
- {queryParamsMapping && typeSchemas.queryParams?.name && (
219
+ {queryParamsMapping && queryParamsName && (
257
220
  <>
258
221
  {`const mappedParams = params ? { ${Object.entries(queryParamsMapping)
259
222
  .map(([originalName, camelCaseName]) => `"${originalName}": params.${camelCaseName}`)
@@ -262,7 +225,7 @@ export function Client({
262
225
  <br />
263
226
  </>
264
227
  )}
265
- {headerParamsMapping && typeSchemas.headerParams?.name && (
228
+ {headerParamsMapping && headerParamsName && (
266
229
  <>
267
230
  {`const mappedHeaders = headers ? { ${Object.entries(headerParamsMapping)
268
231
  .map(([originalName, camelCaseName]) => `"${originalName}": headers.${camelCaseName}`)
@@ -271,11 +234,9 @@ export function Client({
271
234
  <br />
272
235
  </>
273
236
  )}
274
- {parser === 'zod' && zodSchemas?.request?.name
275
- ? `const requestData = ${zodSchemas.request.name}.parse(data)`
276
- : typeSchemas?.request?.name && 'const requestData = data'}
237
+ {parser === 'zod' && zodRequestName ? `const requestData = ${zodRequestName}.parse(data)` : requestName && 'const requestData = data'}
277
238
  <br />
278
- {isFormData && typeSchemas?.request?.name && 'const formData = buildFormData(requestData)'}
239
+ {isFormData && requestName && 'const formData = buildFormData(requestData)'}
279
240
  <br />
280
241
  {isConfigurable
281
242
  ? `const res = await request<${generics.join(', ')}>(${clientParams.toCall()})`
@@ -1,20 +1,20 @@
1
1
  import { URLPath } from '@internals/utils'
2
- import type { HttpMethod, Operation } from '@kubb/oas'
3
- import { Const, File } from '@kubb/react-fabric'
4
- import type { FabricReactNode } from '@kubb/react-fabric/types'
2
+ import type { ast } from '@kubb/core'
3
+ import { Const, File } from '@kubb/renderer-jsx'
4
+ import type { KubbReactNode } from '@kubb/renderer-jsx/types'
5
5
 
6
6
  type OperationsProps = {
7
7
  name: string
8
- operations: Array<Operation>
8
+ nodes: Array<ast.OperationNode>
9
9
  }
10
10
 
11
- export function Operations({ name, operations }: OperationsProps): FabricReactNode {
12
- const operationsObject: Record<string, { path: string; method: HttpMethod }> = {}
11
+ export function Operations({ name, nodes }: OperationsProps): KubbReactNode {
12
+ const operationsObject: Record<string, { path: string; method: string }> = {}
13
13
 
14
- operations.forEach((operation) => {
15
- operationsObject[operation.getOperationId()] = {
16
- path: new URLPath(operation.path).URL,
17
- method: operation.method,
14
+ nodes.forEach((node) => {
15
+ operationsObject[node.operationId] = {
16
+ path: new URLPath(node.path).URL,
17
+ method: node.method.toLowerCase(),
18
18
  }
19
19
  })
20
20
 
@@ -1,36 +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'
9
+ import { buildClassClientParams, buildFormDataLine, buildGenerics, buildHeaders, buildRequestDataLine, buildReturnStatement, getComments } from '../utils.ts'
8
10
  import { Client } from './Client.tsx'
9
11
 
12
+ type OperationData = {
13
+ node: ast.OperationNode
14
+ name: string
15
+ tsResolver: ResolverTs
16
+ zodResolver?: ResolverZod
17
+ }
18
+
10
19
  type Props = {
11
20
  name: string
12
21
  isExportable?: boolean
13
22
  isIndexable?: boolean
14
- operations: Array<{
15
- operation: Operation
16
- name: string
17
- typeSchemas: OperationSchemas
18
- zodSchemas: OperationSchemas | undefined
19
- }>
23
+ operations: Array<OperationData>
20
24
  baseURL: string | undefined
21
25
  dataReturnType: PluginClient['resolvedOptions']['dataReturnType']
22
26
  paramsCasing: PluginClient['resolvedOptions']['paramsCasing']
23
27
  paramsType: PluginClient['resolvedOptions']['pathParamsType']
24
28
  pathParamsType: PluginClient['resolvedOptions']['pathParamsType']
25
29
  parser: PluginClient['resolvedOptions']['parser'] | undefined
26
- children?: FabricReactNode
30
+ children?: KubbReactNode
27
31
  }
28
32
 
29
33
  type GenerateMethodProps = {
30
- operation: Operation
34
+ node: ast.OperationNode
31
35
  name: string
32
- typeSchemas: OperationSchemas
33
- zodSchemas: OperationSchemas | undefined
36
+ tsResolver: ResolverTs
37
+ zodResolver?: ResolverZod
34
38
  baseURL: string | undefined
35
39
  dataReturnType: PluginClient['resolvedOptions']['dataReturnType']
36
40
  parser: PluginClient['resolvedOptions']['parser'] | undefined
@@ -39,115 +43,13 @@ type GenerateMethodProps = {
39
43
  pathParamsType: PluginClient['resolvedOptions']['pathParamsType']
40
44
  }
41
45
 
42
- function buildHeaders(contentType: string, hasHeaderParams: boolean): Array<string> {
43
- return [
44
- contentType !== 'application/json' && contentType !== 'multipart/form-data' ? `'Content-Type': '${contentType}'` : undefined,
45
- hasHeaderParams ? '...headers' : undefined,
46
- ].filter(Boolean) as Array<string>
47
- }
48
-
49
- function buildGenerics(typeSchemas: OperationSchemas): Array<string> {
50
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
51
- return [typeSchemas.response.name, TError, typeSchemas.request?.name || 'unknown'].filter(Boolean)
52
- }
53
-
54
- function buildClientParams({
55
- operation,
56
- path,
57
- baseURL,
58
- typeSchemas,
59
- isFormData,
60
- headers,
61
- }: {
62
- operation: Operation
63
- path: URLPath
64
- baseURL: string | undefined
65
- typeSchemas: OperationSchemas
66
- isFormData: boolean
67
- headers: Array<string>
68
- }) {
69
- return FunctionParams.factory({
70
- config: {
71
- mode: 'object',
72
- children: {
73
- requestConfig: {
74
- mode: 'inlineSpread',
75
- },
76
- method: {
77
- value: JSON.stringify(operation.method.toUpperCase()),
78
- },
79
- url: {
80
- value: path.template,
81
- },
82
- baseURL: baseURL
83
- ? {
84
- value: JSON.stringify(baseURL),
85
- }
86
- : undefined,
87
- params: typeSchemas.queryParams?.name ? {} : undefined,
88
- data: typeSchemas.request?.name
89
- ? {
90
- value: isFormData ? 'formData as FormData' : 'requestData',
91
- }
92
- : undefined,
93
- headers: headers.length
94
- ? {
95
- value: `{ ${headers.join(', ')}, ...requestConfig.headers }`,
96
- }
97
- : undefined,
98
- },
99
- },
100
- })
101
- }
102
-
103
- function buildRequestDataLine({
104
- parser,
105
- zodSchemas,
106
- typeSchemas,
107
- }: {
108
- parser: PluginClient['resolvedOptions']['parser'] | undefined
109
- zodSchemas: OperationSchemas | undefined
110
- typeSchemas: OperationSchemas
111
- }): string {
112
- if (parser === 'zod' && zodSchemas?.request?.name) {
113
- return `const requestData = ${zodSchemas.request.name}.parse(data)`
114
- }
115
- if (typeSchemas?.request?.name) {
116
- return 'const requestData = data'
117
- }
118
- return ''
119
- }
120
-
121
- function buildFormDataLine(isFormData: boolean, hasRequest: boolean): string {
122
- return isFormData && hasRequest ? 'const formData = buildFormData(requestData)' : ''
123
- }
124
-
125
- function buildReturnStatement({
126
- dataReturnType,
127
- parser,
128
- zodSchemas,
129
- }: {
130
- dataReturnType: PluginClient['resolvedOptions']['dataReturnType']
131
- parser: PluginClient['resolvedOptions']['parser'] | undefined
132
- zodSchemas: OperationSchemas | undefined
133
- }): string {
134
- if (dataReturnType === 'full' && parser === 'zod' && zodSchemas) {
135
- return `return {...res, data: ${zodSchemas.response.name}.parse(res.data)}`
136
- }
137
- if (dataReturnType === 'data' && parser === 'zod' && zodSchemas) {
138
- return `return ${zodSchemas.response.name}.parse(res.data)`
139
- }
140
- if (dataReturnType === 'full' && parser === 'client') {
141
- return 'return res'
142
- }
143
- return 'return res.data'
144
- }
46
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
145
47
 
146
48
  function generateMethod({
147
- operation,
49
+ node,
148
50
  name,
149
- typeSchemas,
150
- zodSchemas,
51
+ tsResolver,
52
+ zodResolver,
151
53
  baseURL,
152
54
  dataReturnType,
153
55
  parser,
@@ -155,18 +57,23 @@ function generateMethod({
155
57
  paramsCasing,
156
58
  pathParamsType,
157
59
  }: GenerateMethodProps): string {
158
- const path = new URLPath(operation.path, { casing: paramsCasing })
159
- const contentType = operation.getContentType()
60
+ const path = new URLPath(node.path, { casing: paramsCasing })
61
+ const contentType = node.requestBody?.content?.[0]?.contentType ?? 'application/json'
160
62
  const isFormData = contentType === 'multipart/form-data'
161
- const headers = buildHeaders(contentType, !!typeSchemas.headerParams?.name)
162
- const generics = buildGenerics(typeSchemas)
163
- const params = Client.getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas, isConfigurable: true })
164
- const clientParams = buildClientParams({ operation, path, baseURL, typeSchemas, isFormData, headers })
165
- const jsdoc = buildJSDoc(getComments(operation))
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 = Client.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))
166
73
 
167
- const requestDataLine = buildRequestDataLine({ parser, zodSchemas, typeSchemas })
168
- const formDataLine = buildFormDataLine(isFormData, !!typeSchemas?.request?.name)
169
- const returnStatement = buildReturnStatement({ dataReturnType, parser, zodSchemas })
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 })
170
77
 
171
78
  const methodBody = [
172
79
  'const { client: request = fetch, ...requestConfig } = mergeConfig(this.#config, config)',
@@ -180,8 +87,7 @@ function generateMethod({
180
87
  .map((line) => ` ${line}`)
181
88
  .join('\n')
182
89
 
183
- // Indent static method by 2 spaces, body by 4 spaces (matching snapshot)
184
- return `${jsdoc} static async ${name}(${params.toConstructor()}) {\n${methodBody}\n }`
90
+ return `${jsdoc} static async ${name}(${paramsSignature}) {\n${methodBody}\n }`
185
91
  }
186
92
 
187
93
  export function StaticClassClient({
@@ -196,13 +102,13 @@ export function StaticClassClient({
196
102
  paramsCasing,
197
103
  pathParamsType,
198
104
  children,
199
- }: Props): FabricReactNode {
200
- const methods = operations.map(({ operation, name: methodName, typeSchemas, zodSchemas }) =>
105
+ }: Props): KubbReactNode {
106
+ const methods = operations.map(({ node, name: methodName, tsResolver, zodResolver }) =>
201
107
  generateMethod({
202
- operation,
108
+ node,
203
109
  name: methodName,
204
- typeSchemas,
205
- zodSchemas,
110
+ tsResolver,
111
+ zodResolver,
206
112
  baseURL,
207
113
  dataReturnType,
208
114
  parser,