@kubb/plugin-client 5.0.0-alpha.8 → 5.0.0-beta.3

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 (60) 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/package.json +67 -84
  23. package/src/clients/axios.ts +5 -1
  24. package/src/clients/fetch.ts +5 -1
  25. package/src/components/ClassClient.tsx +45 -142
  26. package/src/components/Client.tsx +90 -129
  27. package/src/components/Operations.tsx +10 -10
  28. package/src/components/StaticClassClient.tsx +44 -138
  29. package/src/components/Url.tsx +38 -48
  30. package/src/components/WrapperClient.tsx +3 -3
  31. package/src/functionParams.ts +118 -0
  32. package/src/generators/classClientGenerator.tsx +148 -171
  33. package/src/generators/clientGenerator.tsx +95 -82
  34. package/src/generators/groupedClientGenerator.tsx +50 -52
  35. package/src/generators/operationsGenerator.tsx +11 -18
  36. package/src/generators/staticClassClientGenerator.tsx +178 -183
  37. package/src/index.ts +9 -2
  38. package/src/plugin.ts +115 -145
  39. package/src/resolvers/resolverClient.ts +22 -0
  40. package/src/types.ts +104 -44
  41. package/src/utils.ts +180 -0
  42. package/templates/clients/axios.ts +5 -2
  43. package/templates/clients/fetch.ts +5 -2
  44. package/dist/StaticClassClient-By-aMAe4.cjs +0 -677
  45. package/dist/StaticClassClient-By-aMAe4.cjs.map +0 -1
  46. package/dist/StaticClassClient-CCn9g9eF.js +0 -636
  47. package/dist/StaticClassClient-CCn9g9eF.js.map +0 -1
  48. package/dist/components.cjs +0 -7
  49. package/dist/components.d.ts +0 -216
  50. package/dist/components.js +0 -2
  51. package/dist/generators-BYUJaeZP.js +0 -723
  52. package/dist/generators-BYUJaeZP.js.map +0 -1
  53. package/dist/generators-DTxD9FDY.cjs +0 -753
  54. package/dist/generators-DTxD9FDY.cjs.map +0 -1
  55. package/dist/generators.cjs +0 -7
  56. package/dist/generators.d.ts +0 -488
  57. package/dist/generators.js +0 -2
  58. package/dist/types-DBQdg-BV.d.ts +0 -169
  59. package/src/components/index.ts +0 -5
  60. package/src/generators/index.ts +0 -5
package/dist/index.cjs CHANGED
@@ -1,127 +1,1769 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_chunk = require("./chunk-ByKO4r7w.cjs");
3
- const require_StaticClassClient = require("./StaticClassClient-By-aMAe4.cjs");
4
- const require_generators = require("./generators-DTxD9FDY.cjs");
5
6
  const require_templates_clients_axios_source = require("./templates/clients/axios.source.cjs");
6
7
  const require_templates_clients_fetch_source = require("./templates/clients/fetch.source.cjs");
7
8
  const require_templates_config_source = require("./templates/config.source.cjs");
8
9
  let node_path = require("node:path");
10
+ let node_path$1 = require_chunk.__toESM(node_path, 1);
9
11
  node_path = require_chunk.__toESM(node_path);
10
12
  let _kubb_core = require("@kubb/core");
11
- let _kubb_plugin_oas = require("@kubb/plugin-oas");
13
+ let _kubb_plugin_ts = require("@kubb/plugin-ts");
14
+ let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
15
+ let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
12
16
  let _kubb_plugin_zod = require("@kubb/plugin-zod");
17
+ //#region ../../internals/utils/src/casing.ts
18
+ /**
19
+ * Shared implementation for camelCase and PascalCase conversion.
20
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
21
+ * and capitalizes each word according to `pascal`.
22
+ *
23
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
24
+ */
25
+ function toCamelOrPascal(text, pascal) {
26
+ return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
27
+ if (word.length > 1 && word === word.toUpperCase()) return word;
28
+ if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
29
+ return word.charAt(0).toUpperCase() + word.slice(1);
30
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
31
+ }
32
+ /**
33
+ * Splits `text` on `.` and applies `transformPart` to each segment.
34
+ * The last segment receives `isLast = true`, all earlier segments receive `false`.
35
+ * Segments are joined with `/` to form a file path.
36
+ *
37
+ * Only splits on dots followed by a letter so that version numbers
38
+ * embedded in operationIds (e.g. `v2025.0`) are kept intact.
39
+ */
40
+ function applyToFileParts(text, transformPart) {
41
+ const parts = text.split(/\.(?=[a-zA-Z])/);
42
+ return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
43
+ }
44
+ /**
45
+ * Converts `text` to camelCase.
46
+ * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
47
+ *
48
+ * @example
49
+ * camelCase('hello-world') // 'helloWorld'
50
+ * camelCase('pet.petId', { isFile: true }) // 'pet/petId'
51
+ */
52
+ function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
53
+ if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
54
+ prefix,
55
+ suffix
56
+ } : {}));
57
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
58
+ }
59
+ /**
60
+ * Converts `text` to PascalCase.
61
+ * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
62
+ *
63
+ * @example
64
+ * pascalCase('hello-world') // 'HelloWorld'
65
+ * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
66
+ */
67
+ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
68
+ if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
69
+ prefix,
70
+ suffix
71
+ }) : camelCase(part));
72
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
73
+ }
74
+ //#endregion
75
+ //#region ../../internals/utils/src/jsdoc.ts
76
+ /**
77
+ * Builds a JSDoc comment block from an array of lines.
78
+ * Returns `fallback` when `comments` is empty so callers always get a usable string.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * buildJSDoc(['@type string', '@example hello'])
83
+ * // '/**\n * @type string\n * @example hello\n *\/\n '
84
+ * ```
85
+ */
86
+ function buildJSDoc(comments, options = {}) {
87
+ const { indent = " * ", suffix = "\n ", fallback = " " } = options;
88
+ if (comments.length === 0) return fallback;
89
+ return `/**\n${comments.map((c) => `${indent}${c}`).join("\n")}\n */${suffix}`;
90
+ }
91
+ //#endregion
92
+ //#region ../../internals/utils/src/reserved.ts
93
+ /**
94
+ * JavaScript and Java reserved words.
95
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
96
+ */
97
+ const reservedWords = new Set([
98
+ "abstract",
99
+ "arguments",
100
+ "boolean",
101
+ "break",
102
+ "byte",
103
+ "case",
104
+ "catch",
105
+ "char",
106
+ "class",
107
+ "const",
108
+ "continue",
109
+ "debugger",
110
+ "default",
111
+ "delete",
112
+ "do",
113
+ "double",
114
+ "else",
115
+ "enum",
116
+ "eval",
117
+ "export",
118
+ "extends",
119
+ "false",
120
+ "final",
121
+ "finally",
122
+ "float",
123
+ "for",
124
+ "function",
125
+ "goto",
126
+ "if",
127
+ "implements",
128
+ "import",
129
+ "in",
130
+ "instanceof",
131
+ "int",
132
+ "interface",
133
+ "let",
134
+ "long",
135
+ "native",
136
+ "new",
137
+ "null",
138
+ "package",
139
+ "private",
140
+ "protected",
141
+ "public",
142
+ "return",
143
+ "short",
144
+ "static",
145
+ "super",
146
+ "switch",
147
+ "synchronized",
148
+ "this",
149
+ "throw",
150
+ "throws",
151
+ "transient",
152
+ "true",
153
+ "try",
154
+ "typeof",
155
+ "var",
156
+ "void",
157
+ "volatile",
158
+ "while",
159
+ "with",
160
+ "yield",
161
+ "Array",
162
+ "Date",
163
+ "hasOwnProperty",
164
+ "Infinity",
165
+ "isFinite",
166
+ "isNaN",
167
+ "isPrototypeOf",
168
+ "length",
169
+ "Math",
170
+ "name",
171
+ "NaN",
172
+ "Number",
173
+ "Object",
174
+ "prototype",
175
+ "String",
176
+ "toString",
177
+ "undefined",
178
+ "valueOf"
179
+ ]);
180
+ /**
181
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * isValidVarName('status') // true
186
+ * isValidVarName('class') // false (reserved word)
187
+ * isValidVarName('42foo') // false (starts with digit)
188
+ * ```
189
+ */
190
+ function isValidVarName(name) {
191
+ if (!name || reservedWords.has(name)) return false;
192
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
193
+ }
194
+ //#endregion
195
+ //#region ../../internals/utils/src/urlPath.ts
196
+ /**
197
+ * Parses and transforms an OpenAPI/Swagger path string into various URL formats.
198
+ *
199
+ * @example
200
+ * const p = new URLPath('/pet/{petId}')
201
+ * p.URL // '/pet/:petId'
202
+ * p.template // '`/pet/${petId}`'
203
+ */
204
+ var URLPath = class {
205
+ /**
206
+ * The raw OpenAPI/Swagger path string, e.g. `/pet/{petId}`.
207
+ */
208
+ path;
209
+ #options;
210
+ constructor(path, options = {}) {
211
+ this.path = path;
212
+ this.#options = options;
213
+ }
214
+ /** Converts the OpenAPI path to Express-style colon syntax, e.g. `/pet/{petId}` → `/pet/:petId`.
215
+ *
216
+ * @example
217
+ * ```ts
218
+ * new URLPath('/pet/{petId}').URL // '/pet/:petId'
219
+ * ```
220
+ */
221
+ get URL() {
222
+ return this.toURLPath();
223
+ }
224
+ /** Returns `true` when `path` is a fully-qualified URL (e.g. starts with `https://`).
225
+ *
226
+ * @example
227
+ * ```ts
228
+ * new URLPath('https://petstore.swagger.io/v2/pet').isURL // true
229
+ * new URLPath('/pet/{petId}').isURL // false
230
+ * ```
231
+ */
232
+ get isURL() {
233
+ try {
234
+ return !!new URL(this.path).href;
235
+ } catch {
236
+ return false;
237
+ }
238
+ }
239
+ /**
240
+ * Converts the OpenAPI path to a TypeScript template literal string.
241
+ *
242
+ * @example
243
+ * new URLPath('/pet/{petId}').template // '`/pet/${petId}`'
244
+ * new URLPath('/account/monetary-accountID').template // '`/account/${monetaryAccountId}`'
245
+ */
246
+ get template() {
247
+ return this.toTemplateString();
248
+ }
249
+ /** Returns the path and its extracted params as a structured `URLObject`, or as a stringified expression when `stringify` is set.
250
+ *
251
+ * @example
252
+ * ```ts
253
+ * new URLPath('/pet/{petId}').object
254
+ * // { url: '/pet/:petId', params: { petId: 'petId' } }
255
+ * ```
256
+ */
257
+ get object() {
258
+ return this.toObject();
259
+ }
260
+ /** Returns a map of path parameter names, or `undefined` when the path has no parameters.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * new URLPath('/pet/{petId}').params // { petId: 'petId' }
265
+ * new URLPath('/pet').params // undefined
266
+ * ```
267
+ */
268
+ get params() {
269
+ return this.getParams();
270
+ }
271
+ #transformParam(raw) {
272
+ const param = isValidVarName(raw) ? raw : camelCase(raw);
273
+ return this.#options.casing === "camelcase" ? camelCase(param) : param;
274
+ }
275
+ /**
276
+ * Iterates over every `{param}` token in `path`, calling `fn` with the raw token and transformed name.
277
+ */
278
+ #eachParam(fn) {
279
+ for (const match of this.path.matchAll(/\{([^}]+)\}/g)) {
280
+ const raw = match[1];
281
+ fn(raw, this.#transformParam(raw));
282
+ }
283
+ }
284
+ toObject({ type = "path", replacer, stringify } = {}) {
285
+ const object = {
286
+ url: type === "path" ? this.toURLPath() : this.toTemplateString({ replacer }),
287
+ params: this.getParams()
288
+ };
289
+ if (stringify) {
290
+ if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
291
+ if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
292
+ return `{ url: '${object.url}' }`;
293
+ }
294
+ return object;
295
+ }
296
+ /**
297
+ * Converts the OpenAPI path to a TypeScript template literal string.
298
+ * An optional `replacer` can transform each extracted parameter name before interpolation.
299
+ *
300
+ * @example
301
+ * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
302
+ */
303
+ toTemplateString({ prefix = "", replacer } = {}) {
304
+ return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
305
+ if (i % 2 === 0) return part;
306
+ const param = this.#transformParam(part);
307
+ return `\${${replacer ? replacer(param) : param}}`;
308
+ }).join("")}\``;
309
+ }
310
+ /**
311
+ * Extracts all `{param}` segments from the path and returns them as a key-value map.
312
+ * An optional `replacer` transforms each parameter name in both key and value positions.
313
+ * Returns `undefined` when no path parameters are found.
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * new URLPath('/pet/{petId}/tag/{tagId}').getParams()
318
+ * // { petId: 'petId', tagId: 'tagId' }
319
+ * ```
320
+ */
321
+ getParams(replacer) {
322
+ const params = {};
323
+ this.#eachParam((_raw, param) => {
324
+ const key = replacer ? replacer(param) : param;
325
+ params[key] = key;
326
+ });
327
+ return Object.keys(params).length > 0 ? params : void 0;
328
+ }
329
+ /** Converts the OpenAPI path to Express-style colon syntax.
330
+ *
331
+ * @example
332
+ * ```ts
333
+ * new URLPath('/pet/{petId}').toURLPath() // '/pet/:petId'
334
+ * ```
335
+ */
336
+ toURLPath() {
337
+ return this.path.replace(/\{([^}]+)\}/g, ":$1");
338
+ }
339
+ };
340
+ //#endregion
341
+ //#region src/functionParams.ts
342
+ const declarationPrinter$4 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
343
+ const callPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
344
+ function isGroup(spec) {
345
+ return "children" in spec;
346
+ }
347
+ function createType(type) {
348
+ return type ? _kubb_core.ast.createParamsType({
349
+ variant: "reference",
350
+ name: type
351
+ }) : void 0;
352
+ }
353
+ function createDeclarationLeaf(name, spec) {
354
+ if (spec.default !== void 0) return _kubb_core.ast.createFunctionParameter({
355
+ name,
356
+ type: createType(spec.type),
357
+ default: spec.default,
358
+ rest: spec.mode === "inlineSpread"
359
+ });
360
+ return _kubb_core.ast.createFunctionParameter({
361
+ name,
362
+ type: createType(spec.type),
363
+ optional: !!spec.optional,
364
+ rest: spec.mode === "inlineSpread"
365
+ });
366
+ }
367
+ function createDeclarationParam(name, spec) {
368
+ if (isGroup(spec)) return _kubb_core.ast.createParameterGroup({
369
+ inline: spec.mode === "inlineSpread",
370
+ default: spec.default,
371
+ properties: Object.entries(spec.children).filter(([, child]) => child !== void 0).map(([childName, child]) => createDeclarationLeaf(childName, child))
372
+ });
373
+ return createDeclarationLeaf(name, spec);
374
+ }
375
+ function createCallParam(name, spec) {
376
+ if (isGroup(spec)) return _kubb_core.ast.createParameterGroup({
377
+ inline: spec.mode === "inlineSpread",
378
+ properties: Object.entries(spec.children).filter(([, child]) => child !== void 0).map(([childName, child]) => _kubb_core.ast.createFunctionParameter({
379
+ name: child?.mode === "inlineSpread" ? spec.mode === "inlineSpread" ? child.value ?? childName : `...${child.value ?? childName}` : child?.value ? `${childName}: ${child.value}` : childName,
380
+ rest: spec.mode === "inlineSpread" && child?.mode === "inlineSpread"
381
+ }))
382
+ });
383
+ return _kubb_core.ast.createFunctionParameter({
384
+ name: spec.value ?? name,
385
+ rest: spec.mode === "inlineSpread"
386
+ });
387
+ }
388
+ /**
389
+ * Creates function parameter builders for generating function signatures and calls.
390
+ * Returns utilities to output constructor signatures (`toConstructor()`) or call expressions (`toCall()`).
391
+ */
392
+ function createFunctionParams(params) {
393
+ const entries = Object.entries(params).filter(([, spec]) => spec !== void 0);
394
+ return {
395
+ toConstructor() {
396
+ return declarationPrinter$4.print(_kubb_core.ast.createFunctionParameters({ params: entries.map(([name, spec]) => createDeclarationParam(name, spec)) })) ?? "";
397
+ },
398
+ toCall() {
399
+ return callPrinter.print(_kubb_core.ast.createFunctionParameters({ params: entries.map(([name, spec]) => createCallParam(name, spec)) })) ?? "";
400
+ }
401
+ };
402
+ }
403
+ //#endregion
404
+ //#region src/utils.ts
405
+ /**
406
+ * Extracts documentation comments from an operation node.
407
+ * Includes description, summary, link, and deprecation information.
408
+ */
409
+ function getComments(node) {
410
+ return [
411
+ node.description && `@description ${node.description}`,
412
+ node.summary && `@summary ${node.summary}`,
413
+ node.path && `{@link ${new URLPath(node.path).URL}}`,
414
+ node.deprecated && "@deprecated"
415
+ ].filter((x) => Boolean(x)).flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((x) => Boolean(x));
416
+ }
417
+ /**
418
+ * Builds a mapping of original parameter names to their transformed (cased) names.
419
+ * Returns undefined if no names have changed.
420
+ */
421
+ function buildParamsMapping(originalParams, casedParams) {
422
+ const mapping = {};
423
+ let hasChanged = false;
424
+ originalParams.forEach((param, i) => {
425
+ const casedName = casedParams[i]?.name ?? param.name;
426
+ mapping[param.name] = casedName;
427
+ if (param.name !== casedName) hasChanged = true;
428
+ });
429
+ return hasChanged ? mapping : void 0;
430
+ }
431
+ /**
432
+ * Builds HTTP headers array for a client request.
433
+ * Includes Content-Type (if not default) and spreads header parameters if present.
434
+ */
435
+ function buildHeaders(contentType, hasHeaderParams) {
436
+ return [contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : void 0, hasHeaderParams ? "...headers" : void 0].filter(Boolean);
437
+ }
438
+ /**
439
+ * Builds TypeScript generic parameters for a client method.
440
+ * Includes response type, error type, and optional request type.
441
+ */
442
+ function buildGenerics(node, tsResolver) {
443
+ const responseName = tsResolver.resolveResponseName(node);
444
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0;
445
+ const errorNames = node.responses.filter((r) => Number.parseInt(r.statusCode, 10) >= 400).map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
446
+ return [
447
+ responseName,
448
+ `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
449
+ requestName || "unknown"
450
+ ].filter(Boolean);
451
+ }
452
+ /**
453
+ * Builds the parameters object for a class-based client method.
454
+ * Includes URL, method, base URL, headers, and request/response data.
455
+ */
456
+ function buildClassClientParams({ node, path, baseURL, tsResolver, isFormData, headers }) {
457
+ const queryParamsName = node.parameters.filter((p) => p.in === "query").length > 0 ? tsResolver.resolveQueryParamsName(node, node.parameters.filter((p) => p.in === "query")[0]) : void 0;
458
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0;
459
+ return createFunctionParams({ config: {
460
+ mode: "object",
461
+ children: {
462
+ requestConfig: { mode: "inlineSpread" },
463
+ method: { value: JSON.stringify(node.method.toUpperCase()) },
464
+ url: { value: path.template },
465
+ baseURL: baseURL ? { value: JSON.stringify(baseURL) } : void 0,
466
+ params: queryParamsName ? {} : void 0,
467
+ data: requestName ? { value: isFormData ? "formData as FormData" : "requestData" } : void 0,
468
+ headers: headers.length ? { value: `{ ${headers.join(", ")}, ...requestConfig.headers }` } : void 0
469
+ }
470
+ } });
471
+ }
472
+ /**
473
+ * Builds the request data parsing line for client methods.
474
+ * Applies Zod validation if configured, otherwise uses data directly.
475
+ */
476
+ function buildRequestDataLine({ parser, node, zodResolver }) {
477
+ const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0;
478
+ if (parser === "zod" && zodRequestName) return `const requestData = ${zodRequestName}.parse(data)`;
479
+ if (node.requestBody?.content?.[0]?.schema) return "const requestData = data";
480
+ return "";
481
+ }
482
+ /**
483
+ * Builds the form data conversion line for file upload requests.
484
+ * Returns empty string if not applicable.
485
+ */
486
+ function buildFormDataLine(isFormData, hasRequest) {
487
+ return isFormData && hasRequest ? "const formData = buildFormData(requestData)" : "";
488
+ }
489
+ /**
490
+ * Builds the return statement for a client method.
491
+ * Applies Zod validation to response data if configured, otherwise returns raw response.
492
+ */
493
+ function buildReturnStatement({ dataReturnType, parser, node, zodResolver }) {
494
+ const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : void 0;
495
+ if (dataReturnType === "full" && parser === "zod" && zodResponseName) return `return {...res, data: ${zodResponseName}.parse(res.data)}`;
496
+ if (dataReturnType === "data" && parser === "zod" && zodResponseName) return `return ${zodResponseName}.parse(res.data)`;
497
+ if (dataReturnType === "full" && parser === "client") return "return res";
498
+ return "return res.data";
499
+ }
500
+ //#endregion
501
+ //#region src/components/Url.tsx
502
+ const declarationPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
503
+ function getParams$1({ paramsType, paramsCasing, pathParamsType, node, tsResolver }) {
504
+ const urlNode = {
505
+ ...node,
506
+ parameters: node.parameters.filter((p) => p.in === "path"),
507
+ requestBody: void 0
508
+ };
509
+ return _kubb_core.ast.createOperationParams(urlNode, {
510
+ paramsType: paramsType === "object" ? "object" : "inline",
511
+ pathParamsType: paramsType === "object" ? "object" : pathParamsType === "object" ? "object" : "inline",
512
+ paramsCasing,
513
+ resolver: tsResolver
514
+ });
515
+ }
516
+ require_chunk.__name(getParams$1, "getParams");
517
+ function Url({ name, isExportable = true, isIndexable = true, baseURL, paramsType, paramsCasing, pathParamsType, node, tsResolver }) {
518
+ const path = new URLPath(node.path);
519
+ const paramsNode = getParams$1({
520
+ paramsType,
521
+ paramsCasing,
522
+ pathParamsType,
523
+ node,
524
+ tsResolver
525
+ });
526
+ const paramsSignature = declarationPrinter$3.print(paramsNode) ?? "";
527
+ const originalPathParams = node.parameters.filter((p) => p.in === "path");
528
+ const casedPathParams = _kubb_core.ast.caseParams(originalPathParams, paramsCasing);
529
+ const pathParamsMapping = paramsCasing ? buildParamsMapping(originalPathParams, casedPathParams) : void 0;
530
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
531
+ name,
532
+ isExportable,
533
+ isIndexable,
534
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.Function, {
535
+ name,
536
+ export: isExportable,
537
+ params: paramsSignature,
538
+ children: [
539
+ pathParamsMapping && Object.entries(pathParamsMapping).filter(([originalName, camelCaseName]) => isValidVarName(originalName) && originalName !== camelCaseName).map(([originalName, camelCaseName]) => `const ${originalName} = ${camelCaseName}`).join("\n"),
540
+ pathParamsMapping && Object.keys(pathParamsMapping).length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
541
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Const, {
542
+ name: "res",
543
+ children: `{ method: '${node.method.toUpperCase()}', url: ${path.toTemplateString({ prefix: baseURL })} as const }`
544
+ }),
545
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
546
+ "return res"
547
+ ]
548
+ })
549
+ });
550
+ }
551
+ Url.getParams = getParams$1;
552
+ //#endregion
553
+ //#region src/components/Client.tsx
554
+ const declarationPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
555
+ function getParams({ paramsType, paramsCasing, pathParamsType, node, tsResolver, isConfigurable }) {
556
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0;
557
+ return _kubb_core.ast.createOperationParams(node, {
558
+ paramsType,
559
+ pathParamsType: paramsType === "object" ? "object" : pathParamsType === "object" ? "object" : "inline",
560
+ paramsCasing,
561
+ resolver: tsResolver,
562
+ extraParams: isConfigurable ? [_kubb_core.ast.createFunctionParameter({
563
+ name: "config",
564
+ type: _kubb_core.ast.createParamsType({
565
+ variant: "reference",
566
+ name: requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : "Partial<RequestConfig> & { client?: Client }"
567
+ }),
568
+ default: "{}"
569
+ })] : []
570
+ });
571
+ }
572
+ function Client({ name, isExportable = true, isIndexable = true, returnType, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType, node, tsResolver, zodResolver, urlName, children, isConfigurable = true }) {
573
+ const path = new URLPath(node.path);
574
+ const contentType = node.requestBody?.content?.[0]?.contentType ?? "application/json";
575
+ const isFormData = contentType === "multipart/form-data";
576
+ const originalPathParams = node.parameters.filter((p) => p.in === "path");
577
+ const casedPathParams = _kubb_core.ast.caseParams(originalPathParams, paramsCasing);
578
+ const originalQueryParams = node.parameters.filter((p) => p.in === "query");
579
+ const casedQueryParams = _kubb_core.ast.caseParams(originalQueryParams, paramsCasing);
580
+ const originalHeaderParams = node.parameters.filter((p) => p.in === "header");
581
+ const casedHeaderParams = _kubb_core.ast.caseParams(originalHeaderParams, paramsCasing);
582
+ const pathParamsMapping = paramsCasing && !urlName ? buildParamsMapping(originalPathParams, casedPathParams) : void 0;
583
+ const queryParamsMapping = paramsCasing ? buildParamsMapping(originalQueryParams, casedQueryParams) : void 0;
584
+ const headerParamsMapping = paramsCasing ? buildParamsMapping(originalHeaderParams, casedHeaderParams) : void 0;
585
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0;
586
+ const responseName = tsResolver.resolveResponseName(node);
587
+ const queryParamsName = originalQueryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, originalQueryParams[0]) : void 0;
588
+ const headerParamsName = originalHeaderParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, originalHeaderParams[0]) : void 0;
589
+ const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : void 0;
590
+ const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0;
591
+ const errorNames = node.responses.filter((r) => {
592
+ return Number.parseInt(r.statusCode, 10) >= 400;
593
+ }).map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
594
+ const headers = [contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : void 0, headerParamsName ? headerParamsMapping ? "...mappedHeaders" : "...headers" : void 0].filter(Boolean);
595
+ const generics = [
596
+ responseName,
597
+ `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
598
+ requestName || "unknown"
599
+ ].filter(Boolean);
600
+ const paramsNode = getParams({
601
+ paramsType,
602
+ paramsCasing,
603
+ pathParamsType,
604
+ node,
605
+ tsResolver,
606
+ isConfigurable
607
+ });
608
+ const paramsSignature = declarationPrinter$2.print(paramsNode) ?? "";
609
+ const urlParamsNode = Url.getParams({
610
+ paramsType,
611
+ paramsCasing,
612
+ pathParamsType,
613
+ node,
614
+ tsResolver
615
+ });
616
+ const urlParamsCall = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" }).print(urlParamsNode) ?? "";
617
+ const clientParams = createFunctionParams({ config: {
618
+ mode: "object",
619
+ children: {
620
+ method: { value: JSON.stringify(node.method.toUpperCase()) },
621
+ url: { value: urlName ? `${urlName}(${urlParamsCall}).url.toString()` : path.template },
622
+ baseURL: baseURL && !urlName ? { value: `\`${baseURL}\`` } : void 0,
623
+ params: queryParamsName ? queryParamsMapping ? { value: "mappedParams" } : {} : void 0,
624
+ data: requestName ? { value: isFormData ? "formData as FormData" : "requestData" } : void 0,
625
+ requestConfig: isConfigurable ? { mode: "inlineSpread" } : void 0,
626
+ headers: headers.length ? { value: isConfigurable ? `{ ${headers.join(", ")}, ...requestConfig.headers }` : `{ ${headers.join(", ")} }` } : void 0
627
+ }
628
+ } });
629
+ const childrenElement = children ? children : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
630
+ dataReturnType === "full" && parser === "zod" && zodResponseName && `return {...res, data: ${zodResponseName}.parse(res.data)}`,
631
+ dataReturnType === "data" && parser === "zod" && zodResponseName && `return ${zodResponseName}.parse(res.data)`,
632
+ dataReturnType === "full" && parser === "client" && "return res",
633
+ dataReturnType === "data" && parser === "client" && "return res.data"
634
+ ] });
635
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
636
+ name,
637
+ isExportable,
638
+ isIndexable,
639
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.Function, {
640
+ name,
641
+ async: true,
642
+ export: isExportable,
643
+ params: paramsSignature,
644
+ JSDoc: { comments: getComments(node) },
645
+ returnType,
646
+ children: [
647
+ isConfigurable ? "const { client: request = fetch, ...requestConfig } = config" : "",
648
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
649
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
650
+ pathParamsMapping && Object.entries(pathParamsMapping).filter(([originalName, camelCaseName]) => isValidVarName(originalName) && originalName !== camelCaseName).map(([originalName, camelCaseName]) => `const ${originalName} = ${camelCaseName}`).join("\n"),
651
+ pathParamsMapping && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {})] }),
652
+ queryParamsMapping && queryParamsName && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
653
+ `const mappedParams = params ? { ${Object.entries(queryParamsMapping).map(([originalName, camelCaseName]) => `"${originalName}": params.${camelCaseName}`).join(", ")} } : undefined`,
654
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
655
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {})
656
+ ] }),
657
+ headerParamsMapping && headerParamsName && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
658
+ `const mappedHeaders = headers ? { ${Object.entries(headerParamsMapping).map(([originalName, camelCaseName]) => `"${originalName}": headers.${camelCaseName}`).join(", ")} } : undefined`,
659
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
660
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {})
661
+ ] }),
662
+ parser === "zod" && zodRequestName ? `const requestData = ${zodRequestName}.parse(data)` : requestName && "const requestData = data",
663
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
664
+ isFormData && requestName && "const formData = buildFormData(requestData)",
665
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
666
+ isConfigurable ? `const res = await request<${generics.join(", ")}>(${clientParams.toCall()})` : `const res = await fetch<${generics.join(", ")}>(${clientParams.toCall()})`,
667
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
668
+ childrenElement
669
+ ]
670
+ })
671
+ })] });
672
+ }
673
+ Client.getParams = getParams;
674
+ //#endregion
675
+ //#region src/components/ClassClient.tsx
676
+ const declarationPrinter$1 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
677
+ function generateMethod$1({ node, name, tsResolver, zodResolver, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType }) {
678
+ const path = new URLPath(node.path, { casing: paramsCasing });
679
+ const contentType = node.requestBody?.content?.[0]?.contentType ?? "application/json";
680
+ const isFormData = contentType === "multipart/form-data";
681
+ const headers = buildHeaders(contentType, !!(node.parameters.filter((p) => p.in === "header").length > 0 ? tsResolver.resolveHeaderParamsName(node, node.parameters.filter((p) => p.in === "header")[0]) : void 0));
682
+ const generics = buildGenerics(node, tsResolver);
683
+ const paramsNode = ClassClient.getParams({
684
+ paramsType,
685
+ paramsCasing,
686
+ pathParamsType,
687
+ node,
688
+ tsResolver,
689
+ isConfigurable: true
690
+ });
691
+ const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
692
+ const clientParams = buildClassClientParams({
693
+ node,
694
+ path,
695
+ baseURL,
696
+ tsResolver,
697
+ isFormData,
698
+ headers
699
+ });
700
+ const jsdoc = buildJSDoc(getComments(node));
701
+ const requestDataLine = buildRequestDataLine({
702
+ parser,
703
+ node,
704
+ zodResolver
705
+ });
706
+ const formDataLine = buildFormDataLine(isFormData, !!node.requestBody?.content?.[0]?.schema);
707
+ const returnStatement = buildReturnStatement({
708
+ dataReturnType,
709
+ parser,
710
+ node,
711
+ zodResolver
712
+ });
713
+ return `${jsdoc}async ${name}(${paramsSignature}) {\n${[
714
+ "const { client: request = fetch, ...requestConfig } = mergeConfig(this.#config, config)",
715
+ "",
716
+ requestDataLine,
717
+ formDataLine,
718
+ `const res = await request<${generics.join(", ")}>(${clientParams.toCall()})`,
719
+ returnStatement
720
+ ].filter(Boolean).map((line) => ` ${line}`).join("\n")}\n }`;
721
+ }
722
+ require_chunk.__name(generateMethod$1, "generateMethod");
723
+ function ClassClient({ name, isExportable = true, isIndexable = true, operations, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType, children }) {
724
+ const classCode = `export class ${name} {
725
+ #config: Partial<RequestConfig> & { client?: Client }
726
+
727
+ constructor(config: Partial<RequestConfig> & { client?: Client } = {}) {
728
+ this.#config = config
729
+ }
730
+
731
+ ${operations.map(({ node, name: methodName, tsResolver, zodResolver }) => generateMethod$1({
732
+ node,
733
+ name: methodName,
734
+ tsResolver,
735
+ zodResolver,
736
+ baseURL,
737
+ dataReturnType,
738
+ parser,
739
+ paramsType,
740
+ paramsCasing,
741
+ pathParamsType
742
+ })).join("\n\n")}
743
+ }`;
744
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File.Source, {
745
+ name,
746
+ isExportable,
747
+ isIndexable,
748
+ children: [classCode, children]
749
+ });
750
+ }
751
+ ClassClient.getParams = Client.getParams;
752
+ //#endregion
753
+ //#region src/components/WrapperClient.tsx
754
+ function WrapperClient({ name, classNames, isExportable = true, isIndexable = true }) {
755
+ const classCode = `export class ${name} {
756
+ ${classNames.map((className) => ` readonly ${camelCase(className)}: ${className}`).join("\n")}
757
+
758
+ constructor(config: Partial<RequestConfig> & { client?: Client } = {}) {
759
+ ${classNames.map((className) => ` this.${camelCase(className)} = new ${className}(config)`).join("\n")}
760
+ }
761
+ }`;
762
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
763
+ name,
764
+ isExportable,
765
+ isIndexable,
766
+ children: classCode
767
+ });
768
+ }
769
+ //#endregion
770
+ //#region src/generators/classClientGenerator.tsx
771
+ function resolveTypeImportNames$1(node, tsResolver) {
772
+ return [
773
+ node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
774
+ tsResolver.resolveResponseName(node),
775
+ ...node.parameters.filter((p) => p.in === "path").map((p) => tsResolver.resolvePathParamsName(node, p)),
776
+ ...node.parameters.filter((p) => p.in === "query").map((p) => tsResolver.resolveQueryParamsName(node, p)),
777
+ ...node.parameters.filter((p) => p.in === "header").map((p) => tsResolver.resolveHeaderParamsName(node, p)),
778
+ ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
779
+ ].filter((n) => Boolean(n));
780
+ }
781
+ require_chunk.__name(resolveTypeImportNames$1, "resolveTypeImportNames");
782
+ function resolveZodImportNames$1(node, zodResolver) {
783
+ return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter((n) => Boolean(n));
784
+ }
785
+ require_chunk.__name(resolveZodImportNames$1, "resolveZodImportNames");
786
+ const classClientGenerator = (0, _kubb_core.defineGenerator)({
787
+ name: "classClient",
788
+ renderer: _kubb_renderer_jsx.jsxRenderer,
789
+ operations(nodes, ctx) {
790
+ const { adapter, config, driver, resolver, root } = ctx;
791
+ const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath, sdk } = ctx.options;
792
+ const baseURL = ctx.options.baseURL ?? adapter.inputNode?.meta?.baseURL;
793
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
794
+ if (!pluginTs) return null;
795
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
796
+ const tsPluginOptions = pluginTs.options;
797
+ const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
798
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
799
+ function buildOperationData(node) {
800
+ const typeFile = tsResolver.resolveFile({
801
+ name: node.operationId,
802
+ extname: ".ts",
803
+ tag: node.tags[0] ?? "default",
804
+ path: node.path
805
+ }, {
806
+ root,
807
+ output: tsPluginOptions?.output ?? output,
808
+ group: tsPluginOptions?.group
809
+ });
810
+ const zodFile = zodResolver && pluginZod?.options ? zodResolver.resolveFile({
811
+ name: node.operationId,
812
+ extname: ".ts",
813
+ tag: node.tags[0] ?? "default",
814
+ path: node.path
815
+ }, {
816
+ root,
817
+ output: pluginZod.options?.output ?? output,
818
+ group: pluginZod.options?.group
819
+ }) : void 0;
820
+ return {
821
+ node,
822
+ name: resolver.resolveName(node.operationId),
823
+ tsResolver,
824
+ zodResolver,
825
+ typeFile,
826
+ zodFile
827
+ };
828
+ }
829
+ const controllers = nodes.reduce((acc, operationNode) => {
830
+ const tag = operationNode.tags[0];
831
+ const groupName = tag ? group?.name?.({ group: camelCase(tag) }) ?? pascalCase(tag) : "Client";
832
+ if (!tag && !group) {
833
+ const name = "ApiClient";
834
+ const file = resolver.resolveFile({
835
+ name,
836
+ extname: ".ts"
837
+ }, {
838
+ root,
839
+ output,
840
+ group
841
+ });
842
+ const operationData = buildOperationData(operationNode);
843
+ const previous = acc.find((item) => item.file.path === file.path);
844
+ if (previous) previous.operations.push(operationData);
845
+ else acc.push({
846
+ name,
847
+ file,
848
+ operations: [operationData]
849
+ });
850
+ } else if (tag) {
851
+ const name = groupName;
852
+ const file = resolver.resolveFile({
853
+ name,
854
+ extname: ".ts",
855
+ tag
856
+ }, {
857
+ root,
858
+ output,
859
+ group
860
+ });
861
+ const operationData = buildOperationData(operationNode);
862
+ const previous = acc.find((item) => item.file.path === file.path);
863
+ if (previous) previous.operations.push(operationData);
864
+ else acc.push({
865
+ name,
866
+ file,
867
+ operations: [operationData]
868
+ });
869
+ }
870
+ return acc;
871
+ }, []);
872
+ function collectTypeImports(ops) {
873
+ const typeImportsByFile = /* @__PURE__ */ new Map();
874
+ const typeFilesByPath = /* @__PURE__ */ new Map();
875
+ ops.forEach((op) => {
876
+ const names = resolveTypeImportNames$1(op.node, tsResolver);
877
+ if (!typeImportsByFile.has(op.typeFile.path)) typeImportsByFile.set(op.typeFile.path, /* @__PURE__ */ new Set());
878
+ const imports = typeImportsByFile.get(op.typeFile.path);
879
+ names.forEach((n) => {
880
+ imports.add(n);
881
+ });
882
+ typeFilesByPath.set(op.typeFile.path, op.typeFile);
883
+ });
884
+ return {
885
+ typeImportsByFile,
886
+ typeFilesByPath
887
+ };
888
+ }
889
+ function collectZodImports(ops) {
890
+ const zodImportsByFile = /* @__PURE__ */ new Map();
891
+ const zodFilesByPath = /* @__PURE__ */ new Map();
892
+ ops.forEach((op) => {
893
+ if (!op.zodFile || !zodResolver) return;
894
+ const names = resolveZodImportNames$1(op.node, zodResolver);
895
+ if (!zodImportsByFile.has(op.zodFile.path)) zodImportsByFile.set(op.zodFile.path, /* @__PURE__ */ new Set());
896
+ const imports = zodImportsByFile.get(op.zodFile.path);
897
+ names.forEach((n) => {
898
+ imports.add(n);
899
+ });
900
+ zodFilesByPath.set(op.zodFile.path, op.zodFile);
901
+ });
902
+ return {
903
+ zodImportsByFile,
904
+ zodFilesByPath
905
+ };
906
+ }
907
+ const files = controllers.map(({ name, file, operations: ops }) => {
908
+ const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops);
909
+ const { zodImportsByFile, zodFilesByPath } = parser === "zod" ? collectZodImports(ops) : {
910
+ zodImportsByFile: /* @__PURE__ */ new Map(),
911
+ zodFilesByPath: /* @__PURE__ */ new Map()
912
+ };
913
+ const hasFormData = ops.some((op) => op.node.requestBody?.content?.[0]?.contentType === "multipart/form-data");
914
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
915
+ baseName: file.baseName,
916
+ path: file.path,
917
+ meta: file.meta,
918
+ banner: resolver.resolveBanner(adapter.inputNode, {
919
+ output,
920
+ config
921
+ }),
922
+ footer: resolver.resolveFooter(adapter.inputNode, {
923
+ output,
924
+ config
925
+ }),
926
+ children: [
927
+ importPath ? /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
928
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
929
+ name: "fetch",
930
+ path: importPath
931
+ }),
932
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
933
+ name: ["mergeConfig"],
934
+ path: importPath
935
+ }),
936
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
937
+ name: [
938
+ "Client",
939
+ "RequestConfig",
940
+ "ResponseErrorConfig"
941
+ ],
942
+ path: importPath,
943
+ isTypeOnly: true
944
+ })
945
+ ] }) : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
946
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
947
+ name: ["fetch"],
948
+ root: file.path,
949
+ path: node_path.default.resolve(root, ".kubb/client.ts")
950
+ }),
951
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
952
+ name: ["mergeConfig"],
953
+ root: file.path,
954
+ path: node_path.default.resolve(root, ".kubb/client.ts")
955
+ }),
956
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
957
+ name: [
958
+ "Client",
959
+ "RequestConfig",
960
+ "ResponseErrorConfig"
961
+ ],
962
+ root: file.path,
963
+ path: node_path.default.resolve(root, ".kubb/client.ts"),
964
+ isTypeOnly: true
965
+ })
966
+ ] }),
967
+ hasFormData && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
968
+ name: ["buildFormData"],
969
+ root: file.path,
970
+ path: node_path.default.resolve(root, ".kubb/config.ts")
971
+ }),
972
+ Array.from(typeImportsByFile.entries()).map(([filePath, importSet]) => {
973
+ const typeFile = typeFilesByPath.get(filePath);
974
+ if (!typeFile) return null;
975
+ const importNames = Array.from(importSet).filter(Boolean);
976
+ if (importNames.length === 0) return null;
977
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
978
+ name: importNames,
979
+ root: file.path,
980
+ path: typeFile.path,
981
+ isTypeOnly: true
982
+ }, filePath);
983
+ }),
984
+ parser === "zod" && Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
985
+ const zodFile = zodFilesByPath.get(filePath);
986
+ if (!zodFile) return null;
987
+ const importNames = Array.from(importSet).filter(Boolean);
988
+ if (importNames.length === 0) return null;
989
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
990
+ name: importNames,
991
+ root: file.path,
992
+ path: zodFile.path
993
+ }, filePath);
994
+ }),
995
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(ClassClient, {
996
+ name,
997
+ operations: ops,
998
+ baseURL,
999
+ dataReturnType,
1000
+ pathParamsType,
1001
+ paramsCasing,
1002
+ paramsType,
1003
+ parser
1004
+ })
1005
+ ]
1006
+ }, file.path);
1007
+ });
1008
+ if (sdk) {
1009
+ const sdkFile = resolver.resolveFile({
1010
+ name: sdk.className,
1011
+ extname: ".ts"
1012
+ }, {
1013
+ root,
1014
+ output,
1015
+ group
1016
+ });
1017
+ files.push(/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1018
+ baseName: sdkFile.baseName,
1019
+ path: sdkFile.path,
1020
+ meta: sdkFile.meta,
1021
+ banner: resolver.resolveBanner(adapter.inputNode, {
1022
+ output,
1023
+ config
1024
+ }),
1025
+ footer: resolver.resolveFooter(adapter.inputNode, {
1026
+ output,
1027
+ config
1028
+ }),
1029
+ children: [
1030
+ importPath ? /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1031
+ name: ["Client", "RequestConfig"],
1032
+ path: importPath,
1033
+ isTypeOnly: true
1034
+ }) : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1035
+ name: ["Client", "RequestConfig"],
1036
+ root: sdkFile.path,
1037
+ path: node_path.default.resolve(root, ".kubb/client.ts"),
1038
+ isTypeOnly: true
1039
+ }),
1040
+ controllers.map(({ name, file }) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1041
+ name: [name],
1042
+ root: sdkFile.path,
1043
+ path: file.path
1044
+ }, name)),
1045
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(WrapperClient, {
1046
+ name: sdk.className,
1047
+ classNames: controllers.map(({ name }) => name)
1048
+ })
1049
+ ]
1050
+ }, sdkFile.path));
1051
+ }
1052
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: files });
1053
+ }
1054
+ });
1055
+ //#endregion
1056
+ //#region src/generators/clientGenerator.tsx
1057
+ const clientGenerator = (0, _kubb_core.defineGenerator)({
1058
+ name: "client",
1059
+ renderer: _kubb_renderer_jsx.jsxRenderer,
1060
+ operation(node, ctx) {
1061
+ const { adapter, config, driver, resolver, root } = ctx;
1062
+ const { output, urlType, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath, group } = ctx.options;
1063
+ const baseURL = ctx.options.baseURL ?? adapter.inputNode?.meta?.baseURL;
1064
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1065
+ if (!pluginTs) return null;
1066
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1067
+ const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1068
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1069
+ const casedParams = _kubb_core.ast.caseParams(node.parameters, paramsCasing);
1070
+ const pathParams = casedParams.filter((p) => p.in === "path");
1071
+ const queryParams = casedParams.filter((p) => p.in === "query");
1072
+ const headerParams = casedParams.filter((p) => p.in === "header");
1073
+ const importedTypeNames = [
1074
+ ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
1075
+ ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
1076
+ ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
1077
+ node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
1078
+ tsResolver.resolveResponseName(node),
1079
+ ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
1080
+ ].filter(Boolean);
1081
+ const importedZodNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter(Boolean) : [];
1082
+ const meta = {
1083
+ name: resolver.resolveName(node.operationId),
1084
+ urlName: `get${resolver.resolveName(node.operationId).charAt(0).toUpperCase()}${resolver.resolveName(node.operationId).slice(1)}Url`,
1085
+ file: resolver.resolveFile({
1086
+ name: node.operationId,
1087
+ extname: ".ts",
1088
+ tag: node.tags[0] ?? "default",
1089
+ path: node.path
1090
+ }, {
1091
+ root,
1092
+ output,
1093
+ group
1094
+ }),
1095
+ fileTs: tsResolver.resolveFile({
1096
+ name: node.operationId,
1097
+ extname: ".ts",
1098
+ tag: node.tags[0] ?? "default",
1099
+ path: node.path
1100
+ }, {
1101
+ root,
1102
+ output: pluginTs.options?.output ?? output,
1103
+ group: pluginTs.options?.group
1104
+ }),
1105
+ fileZod: zodResolver && pluginZod?.options ? zodResolver.resolveFile({
1106
+ name: node.operationId,
1107
+ extname: ".ts",
1108
+ tag: node.tags[0] ?? "default",
1109
+ path: node.path
1110
+ }, {
1111
+ root,
1112
+ output: pluginZod.options.output ?? output,
1113
+ group: pluginZod.options?.group
1114
+ }) : void 0
1115
+ };
1116
+ const isFormData = node.requestBody?.content?.[0]?.contentType === "multipart/form-data";
1117
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1118
+ baseName: meta.file.baseName,
1119
+ path: meta.file.path,
1120
+ meta: meta.file.meta,
1121
+ banner: resolver.resolveBanner(adapter.inputNode, {
1122
+ output,
1123
+ config
1124
+ }),
1125
+ footer: resolver.resolveFooter(adapter.inputNode, {
1126
+ output,
1127
+ config
1128
+ }),
1129
+ children: [
1130
+ importPath ? /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1131
+ name: "fetch",
1132
+ path: importPath
1133
+ }), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1134
+ name: [
1135
+ "Client",
1136
+ "RequestConfig",
1137
+ "ResponseErrorConfig"
1138
+ ],
1139
+ path: importPath,
1140
+ isTypeOnly: true
1141
+ })] }) : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1142
+ name: ["fetch"],
1143
+ root: meta.file.path,
1144
+ path: node_path.default.resolve(root, ".kubb/client.ts")
1145
+ }), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1146
+ name: [
1147
+ "Client",
1148
+ "RequestConfig",
1149
+ "ResponseErrorConfig"
1150
+ ],
1151
+ root: meta.file.path,
1152
+ path: node_path.default.resolve(root, ".kubb/client.ts"),
1153
+ isTypeOnly: true
1154
+ })] }),
1155
+ isFormData && node.requestBody?.content?.[0]?.schema && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1156
+ name: ["buildFormData"],
1157
+ root: meta.file.path,
1158
+ path: node_path.default.resolve(root, ".kubb/config.ts")
1159
+ }),
1160
+ meta.fileZod && importedZodNames.length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1161
+ name: importedZodNames,
1162
+ root: meta.file.path,
1163
+ path: meta.fileZod.path
1164
+ }),
1165
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1166
+ name: Array.from(new Set(importedTypeNames)),
1167
+ root: meta.file.path,
1168
+ path: meta.fileTs.path,
1169
+ isTypeOnly: true
1170
+ }),
1171
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(Url, {
1172
+ name: meta.urlName,
1173
+ baseURL,
1174
+ pathParamsType,
1175
+ paramsCasing,
1176
+ paramsType,
1177
+ node,
1178
+ tsResolver,
1179
+ isIndexable: urlType === "export",
1180
+ isExportable: urlType === "export"
1181
+ }),
1182
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(Client, {
1183
+ name: meta.name,
1184
+ urlName: meta.urlName,
1185
+ baseURL,
1186
+ dataReturnType,
1187
+ pathParamsType,
1188
+ paramsCasing,
1189
+ paramsType,
1190
+ node,
1191
+ tsResolver,
1192
+ zodResolver,
1193
+ parser
1194
+ })
1195
+ ]
1196
+ });
1197
+ }
1198
+ });
1199
+ //#endregion
1200
+ //#region src/generators/groupedClientGenerator.tsx
1201
+ const groupedClientGenerator = (0, _kubb_core.defineGenerator)({
1202
+ name: "groupedClient",
1203
+ renderer: _kubb_renderer_jsx.jsxRenderer,
1204
+ operations(nodes, ctx) {
1205
+ const { config, resolver, adapter, root } = ctx;
1206
+ const { output, group } = ctx.options;
1207
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: nodes.reduce((acc, operationNode) => {
1208
+ if (group?.type === "tag") {
1209
+ const tag = operationNode.tags[0];
1210
+ const name = tag ? group?.name?.({ group: camelCase(tag) }) : void 0;
1211
+ if (!tag || !name) return acc;
1212
+ const file = resolver.resolveFile({
1213
+ name,
1214
+ extname: ".ts",
1215
+ tag
1216
+ }, {
1217
+ root,
1218
+ output,
1219
+ group
1220
+ });
1221
+ const clientFile = resolver.resolveFile({
1222
+ name: operationNode.operationId,
1223
+ extname: ".ts",
1224
+ tag: operationNode.tags[0] ?? "default",
1225
+ path: operationNode.path
1226
+ }, {
1227
+ root,
1228
+ output,
1229
+ group
1230
+ });
1231
+ const client = {
1232
+ name: resolver.resolveName(operationNode.operationId),
1233
+ file: clientFile
1234
+ };
1235
+ const previous = acc.find((item) => item.file.path === file.path);
1236
+ if (previous) previous.clients.push(client);
1237
+ else acc.push({
1238
+ name,
1239
+ file,
1240
+ clients: [client]
1241
+ });
1242
+ }
1243
+ return acc;
1244
+ }, []).map(({ name, file, clients }) => {
1245
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1246
+ baseName: file.baseName,
1247
+ path: file.path,
1248
+ meta: file.meta,
1249
+ banner: resolver.resolveBanner(adapter.inputNode, {
1250
+ output,
1251
+ config
1252
+ }),
1253
+ footer: resolver.resolveFooter(adapter.inputNode, {
1254
+ output,
1255
+ config
1256
+ }),
1257
+ children: [clients.map((client) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1258
+ name: [client.name],
1259
+ root: file.path,
1260
+ path: client.file.path
1261
+ }, client.name)), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
1262
+ name,
1263
+ isExportable: true,
1264
+ isIndexable: true,
1265
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function, {
1266
+ export: true,
1267
+ name,
1268
+ children: `return { ${clients.map((client) => client.name).join(", ")} }`
1269
+ })
1270
+ })]
1271
+ }, file.path);
1272
+ }) });
1273
+ }
1274
+ });
1275
+ //#endregion
1276
+ //#region src/components/Operations.tsx
1277
+ function Operations({ name, nodes }) {
1278
+ const operationsObject = {};
1279
+ nodes.forEach((node) => {
1280
+ operationsObject[node.operationId] = {
1281
+ path: new URLPath(node.path).URL,
1282
+ method: node.method.toLowerCase()
1283
+ };
1284
+ });
1285
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
1286
+ name,
1287
+ isExportable: true,
1288
+ isIndexable: true,
1289
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Const, {
1290
+ name,
1291
+ export: true,
1292
+ children: JSON.stringify(operationsObject, void 0, 2)
1293
+ })
1294
+ });
1295
+ }
1296
+ //#endregion
1297
+ //#region src/generators/operationsGenerator.tsx
1298
+ const operationsGenerator = (0, _kubb_core.defineGenerator)({
1299
+ name: "client",
1300
+ renderer: _kubb_renderer_jsx.jsxRenderer,
1301
+ operations(nodes, ctx) {
1302
+ const { config, resolver, adapter, root } = ctx;
1303
+ const { output, group } = ctx.options;
1304
+ const name = "operations";
1305
+ const file = resolver.resolveFile({
1306
+ name,
1307
+ extname: ".ts"
1308
+ }, {
1309
+ root,
1310
+ output,
1311
+ group
1312
+ });
1313
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File, {
1314
+ baseName: file.baseName,
1315
+ path: file.path,
1316
+ meta: file.meta,
1317
+ banner: resolver.resolveBanner(adapter.inputNode, {
1318
+ output,
1319
+ config
1320
+ }),
1321
+ footer: resolver.resolveFooter(adapter.inputNode, {
1322
+ output,
1323
+ config
1324
+ }),
1325
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(Operations, {
1326
+ name,
1327
+ nodes
1328
+ })
1329
+ });
1330
+ }
1331
+ });
1332
+ //#endregion
1333
+ //#region src/components/StaticClassClient.tsx
1334
+ const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1335
+ function generateMethod({ node, name, tsResolver, zodResolver, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType }) {
1336
+ const path = new URLPath(node.path, { casing: paramsCasing });
1337
+ const contentType = node.requestBody?.content?.[0]?.contentType ?? "application/json";
1338
+ const isFormData = contentType === "multipart/form-data";
1339
+ const headers = buildHeaders(contentType, !!(node.parameters.filter((p) => p.in === "header").length > 0 ? tsResolver.resolveHeaderParamsName(node, node.parameters.filter((p) => p.in === "header")[0]) : void 0));
1340
+ const generics = buildGenerics(node, tsResolver);
1341
+ const paramsNode = Client.getParams({
1342
+ paramsType,
1343
+ paramsCasing,
1344
+ pathParamsType,
1345
+ node,
1346
+ tsResolver,
1347
+ isConfigurable: true
1348
+ });
1349
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
1350
+ const clientParams = buildClassClientParams({
1351
+ node,
1352
+ path,
1353
+ baseURL,
1354
+ tsResolver,
1355
+ isFormData,
1356
+ headers
1357
+ });
1358
+ const jsdoc = buildJSDoc(getComments(node));
1359
+ const requestDataLine = buildRequestDataLine({
1360
+ parser,
1361
+ node,
1362
+ zodResolver
1363
+ });
1364
+ const formDataLine = buildFormDataLine(isFormData, !!node.requestBody?.content?.[0]?.schema);
1365
+ const returnStatement = buildReturnStatement({
1366
+ dataReturnType,
1367
+ parser,
1368
+ node,
1369
+ zodResolver
1370
+ });
1371
+ return `${jsdoc} static async ${name}(${paramsSignature}) {\n${[
1372
+ "const { client: request = fetch, ...requestConfig } = mergeConfig(this.#config, config)",
1373
+ "",
1374
+ requestDataLine,
1375
+ formDataLine,
1376
+ `const res = await request<${generics.join(", ")}>(${clientParams.toCall()})`,
1377
+ returnStatement
1378
+ ].filter(Boolean).map((line) => ` ${line}`).join("\n")}\n }`;
1379
+ }
1380
+ function StaticClassClient({ name, isExportable = true, isIndexable = true, operations, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType, children }) {
1381
+ const classCode = `export class ${name} {\n static #config: Partial<RequestConfig> & { client?: Client } = {}\n\n${operations.map(({ node, name: methodName, tsResolver, zodResolver }) => generateMethod({
1382
+ node,
1383
+ name: methodName,
1384
+ tsResolver,
1385
+ zodResolver,
1386
+ baseURL,
1387
+ dataReturnType,
1388
+ parser,
1389
+ paramsType,
1390
+ paramsCasing,
1391
+ pathParamsType
1392
+ })).join("\n\n")}\n}`;
1393
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File.Source, {
1394
+ name,
1395
+ isExportable,
1396
+ isIndexable,
1397
+ children: [classCode, children]
1398
+ });
1399
+ }
1400
+ StaticClassClient.getParams = Client.getParams;
1401
+ //#endregion
1402
+ //#region src/generators/staticClassClientGenerator.tsx
1403
+ function resolveTypeImportNames(node, tsResolver) {
1404
+ return [
1405
+ node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
1406
+ tsResolver.resolveResponseName(node),
1407
+ ...node.parameters.filter((p) => p.in === "path").map((p) => tsResolver.resolvePathParamsName(node, p)),
1408
+ ...node.parameters.filter((p) => p.in === "query").map((p) => tsResolver.resolveQueryParamsName(node, p)),
1409
+ ...node.parameters.filter((p) => p.in === "header").map((p) => tsResolver.resolveHeaderParamsName(node, p)),
1410
+ ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
1411
+ ].filter((n) => Boolean(n));
1412
+ }
1413
+ function resolveZodImportNames(node, zodResolver) {
1414
+ return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter((n) => Boolean(n));
1415
+ }
1416
+ const staticClassClientGenerator = (0, _kubb_core.defineGenerator)({
1417
+ name: "staticClassClient",
1418
+ renderer: _kubb_renderer_jsx.jsxRenderer,
1419
+ operations(nodes, ctx) {
1420
+ const { adapter, config, driver, resolver, root } = ctx;
1421
+ const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath } = ctx.options;
1422
+ const baseURL = ctx.options.baseURL ?? adapter.inputNode?.meta?.baseURL;
1423
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1424
+ if (!pluginTs) return null;
1425
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1426
+ const tsPluginOptions = pluginTs.options;
1427
+ const pluginZod = parser === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1428
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1429
+ function buildOperationData(node) {
1430
+ const typeFile = tsResolver.resolveFile({
1431
+ name: node.operationId,
1432
+ extname: ".ts",
1433
+ tag: node.tags[0] ?? "default",
1434
+ path: node.path
1435
+ }, {
1436
+ root,
1437
+ output: tsPluginOptions?.output ?? output,
1438
+ group: tsPluginOptions?.group
1439
+ });
1440
+ const zodFile = zodResolver && pluginZod?.options ? zodResolver.resolveFile({
1441
+ name: node.operationId,
1442
+ extname: ".ts",
1443
+ tag: node.tags[0] ?? "default",
1444
+ path: node.path
1445
+ }, {
1446
+ root,
1447
+ output: pluginZod.options?.output ?? output,
1448
+ group: pluginZod.options?.group
1449
+ }) : void 0;
1450
+ return {
1451
+ node,
1452
+ name: resolver.resolveName(node.operationId),
1453
+ tsResolver,
1454
+ zodResolver,
1455
+ typeFile,
1456
+ zodFile
1457
+ };
1458
+ }
1459
+ const controllers = nodes.reduce((acc, operationNode) => {
1460
+ const tag = operationNode.tags[0];
1461
+ const groupName = tag ? group?.name?.({ group: camelCase(tag) }) ?? pascalCase(tag) : "Client";
1462
+ if (!tag && !group) {
1463
+ const name = "ApiClient";
1464
+ const file = resolver.resolveFile({
1465
+ name,
1466
+ extname: ".ts"
1467
+ }, {
1468
+ root,
1469
+ output,
1470
+ group
1471
+ });
1472
+ const operationData = buildOperationData(operationNode);
1473
+ const previous = acc.find((item) => item.file.path === file.path);
1474
+ if (previous) previous.operations.push(operationData);
1475
+ else acc.push({
1476
+ name,
1477
+ file,
1478
+ operations: [operationData]
1479
+ });
1480
+ } else if (tag) {
1481
+ const name = groupName;
1482
+ const file = resolver.resolveFile({
1483
+ name,
1484
+ extname: ".ts",
1485
+ tag
1486
+ }, {
1487
+ root,
1488
+ output,
1489
+ group
1490
+ });
1491
+ const operationData = buildOperationData(operationNode);
1492
+ const previous = acc.find((item) => item.file.path === file.path);
1493
+ if (previous) previous.operations.push(operationData);
1494
+ else acc.push({
1495
+ name,
1496
+ file,
1497
+ operations: [operationData]
1498
+ });
1499
+ }
1500
+ return acc;
1501
+ }, []);
1502
+ function collectTypeImports(ops) {
1503
+ const typeImportsByFile = /* @__PURE__ */ new Map();
1504
+ const typeFilesByPath = /* @__PURE__ */ new Map();
1505
+ ops.forEach((op) => {
1506
+ const names = resolveTypeImportNames(op.node, tsResolver);
1507
+ if (!typeImportsByFile.has(op.typeFile.path)) typeImportsByFile.set(op.typeFile.path, /* @__PURE__ */ new Set());
1508
+ const imports = typeImportsByFile.get(op.typeFile.path);
1509
+ names.forEach((n) => {
1510
+ imports.add(n);
1511
+ });
1512
+ typeFilesByPath.set(op.typeFile.path, op.typeFile);
1513
+ });
1514
+ return {
1515
+ typeImportsByFile,
1516
+ typeFilesByPath
1517
+ };
1518
+ }
1519
+ function collectZodImports(ops) {
1520
+ const zodImportsByFile = /* @__PURE__ */ new Map();
1521
+ const zodFilesByPath = /* @__PURE__ */ new Map();
1522
+ ops.forEach((op) => {
1523
+ if (!op.zodFile || !zodResolver) return;
1524
+ const names = resolveZodImportNames(op.node, zodResolver);
1525
+ if (!zodImportsByFile.has(op.zodFile.path)) zodImportsByFile.set(op.zodFile.path, /* @__PURE__ */ new Set());
1526
+ const imports = zodImportsByFile.get(op.zodFile.path);
1527
+ names.forEach((n) => {
1528
+ imports.add(n);
1529
+ });
1530
+ zodFilesByPath.set(op.zodFile.path, op.zodFile);
1531
+ });
1532
+ return {
1533
+ zodImportsByFile,
1534
+ zodFilesByPath
1535
+ };
1536
+ }
1537
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: controllers.map(({ name, file, operations: ops }) => {
1538
+ const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops);
1539
+ const { zodImportsByFile, zodFilesByPath } = parser === "zod" ? collectZodImports(ops) : {
1540
+ zodImportsByFile: /* @__PURE__ */ new Map(),
1541
+ zodFilesByPath: /* @__PURE__ */ new Map()
1542
+ };
1543
+ const hasFormData = ops.some((op) => op.node.requestBody?.content?.[0]?.contentType === "multipart/form-data");
1544
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1545
+ baseName: file.baseName,
1546
+ path: file.path,
1547
+ meta: file.meta,
1548
+ banner: resolver.resolveBanner(adapter.inputNode, {
1549
+ output,
1550
+ config
1551
+ }),
1552
+ footer: resolver.resolveFooter(adapter.inputNode, {
1553
+ output,
1554
+ config
1555
+ }),
1556
+ children: [
1557
+ importPath ? /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1558
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1559
+ name: "fetch",
1560
+ path: importPath
1561
+ }),
1562
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1563
+ name: ["mergeConfig"],
1564
+ path: importPath
1565
+ }),
1566
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1567
+ name: [
1568
+ "Client",
1569
+ "RequestConfig",
1570
+ "ResponseErrorConfig"
1571
+ ],
1572
+ path: importPath,
1573
+ isTypeOnly: true
1574
+ })
1575
+ ] }) : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1576
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1577
+ name: ["fetch"],
1578
+ root: file.path,
1579
+ path: node_path.default.resolve(root, ".kubb/client.ts")
1580
+ }),
1581
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1582
+ name: ["mergeConfig"],
1583
+ root: file.path,
1584
+ path: node_path.default.resolve(root, ".kubb/client.ts")
1585
+ }),
1586
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1587
+ name: [
1588
+ "Client",
1589
+ "RequestConfig",
1590
+ "ResponseErrorConfig"
1591
+ ],
1592
+ root: file.path,
1593
+ path: node_path.default.resolve(root, ".kubb/client.ts"),
1594
+ isTypeOnly: true
1595
+ })
1596
+ ] }),
1597
+ hasFormData && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1598
+ name: ["buildFormData"],
1599
+ root: file.path,
1600
+ path: node_path.default.resolve(root, ".kubb/config.ts")
1601
+ }),
1602
+ Array.from(typeImportsByFile.entries()).map(([filePath, importSet]) => {
1603
+ const typeFile = typeFilesByPath.get(filePath);
1604
+ if (!typeFile) return null;
1605
+ const importNames = Array.from(importSet).filter(Boolean);
1606
+ if (importNames.length === 0) return null;
1607
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1608
+ name: importNames,
1609
+ root: file.path,
1610
+ path: typeFile.path,
1611
+ isTypeOnly: true
1612
+ }, filePath);
1613
+ }),
1614
+ parser === "zod" && Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
1615
+ const zodFile = zodFilesByPath.get(filePath);
1616
+ if (!zodFile) return null;
1617
+ const importNames = Array.from(importSet).filter(Boolean);
1618
+ if (importNames.length === 0) return null;
1619
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1620
+ name: importNames,
1621
+ root: file.path,
1622
+ path: zodFile.path
1623
+ }, filePath);
1624
+ }),
1625
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(StaticClassClient, {
1626
+ name,
1627
+ operations: ops,
1628
+ baseURL,
1629
+ dataReturnType,
1630
+ pathParamsType,
1631
+ paramsCasing,
1632
+ paramsType,
1633
+ parser
1634
+ })
1635
+ ]
1636
+ }, file.path);
1637
+ }) });
1638
+ }
1639
+ });
1640
+ //#endregion
1641
+ //#region src/resolvers/resolverClient.ts
1642
+ /**
1643
+ * Naming convention resolver for client plugin.
1644
+ *
1645
+ * Provides default naming helpers using camelCase for functions and file paths.
1646
+ *
1647
+ * @example
1648
+ * `resolverClient.default('list pets', 'function') // → 'listPets'`
1649
+ */
1650
+ const resolverClient = (0, _kubb_core.defineResolver)((ctx) => ({
1651
+ name: "default",
1652
+ pluginName: "plugin-client",
1653
+ default(name, type) {
1654
+ return camelCase(name, { isFile: type === "file" });
1655
+ },
1656
+ resolveName(name) {
1657
+ return ctx.default(name, "function");
1658
+ }
1659
+ }));
1660
+ //#endregion
13
1661
  //#region src/plugin.ts
1662
+ /**
1663
+ * Canonical plugin name for `@kubb/plugin-client`, used in driver lookups and warnings.
1664
+ */
14
1665
  const pluginClientName = "plugin-client";
15
- const pluginClient = (0, _kubb_core.createPlugin)((options) => {
1666
+ /**
1667
+ * Generates type-safe HTTP client functions or classes from an OpenAPI specification.
1668
+ * Creates client APIs by walking operations and delegating to generators.
1669
+ * Writes barrel files based on the configured `barrelType`.
1670
+ *
1671
+ * @example Client generator
1672
+ * ```ts
1673
+ * import pluginClient from '@kubb/plugin-client'
1674
+ * export default defineConfig({
1675
+ * plugins: [pluginClient({ output: { path: 'clients' } })]
1676
+ * })
1677
+ * ```
1678
+ */
1679
+ const pluginClient = (0, _kubb_core.definePlugin)((options) => {
16
1680
  const { output = {
17
1681
  path: "clients",
18
1682
  barrelType: "named"
19
- }, group, urlType = false, exclude = [], include, override = [], transformers = {}, dataReturnType = "data", paramsType = "inline", pathParamsType = paramsType === "object" ? "object" : options.pathParamsType || "inline", operations = false, baseURL, paramsCasing, clientType = "function", parser = "client", client = "axios", importPath, contentType, bundle = false, wrapper } = options;
1683
+ }, group, exclude = [], include, override = [], urlType = false, dataReturnType = "data", paramsType = "inline", pathParamsType = paramsType === "object" ? "object" : options.pathParamsType || "inline", operations = false, paramsCasing, clientType = options.sdk ? "class" : "function", parser = "client", client = "axios", importPath, bundle = false, sdk, baseURL, resolver: userResolver, transformer: userTransformer } = options;
20
1684
  const resolvedImportPath = importPath ?? (!bundle ? `@kubb/plugin-client/clients/${client}` : void 0);
21
- const defaultGenerators = [
22
- clientType === "staticClass" ? require_generators.staticClassClientGenerator : clientType === "class" ? require_generators.classClientGenerator : require_generators.clientGenerator,
23
- group && clientType === "function" ? require_generators.groupedClientGenerator : void 0,
24
- operations ? require_generators.operationsGenerator : void 0
1685
+ const selectedGenerators = options.generators ?? [
1686
+ clientType === "staticClass" ? staticClassClientGenerator : clientType === "class" ? classClientGenerator : clientGenerator,
1687
+ group && clientType === "function" ? groupedClientGenerator : void 0,
1688
+ operations ? operationsGenerator : void 0
25
1689
  ].filter((x) => Boolean(x));
26
- const generators = options.generators ?? defaultGenerators;
1690
+ const groupConfig = group ? {
1691
+ ...group,
1692
+ name: group.name ? group.name : (ctx) => {
1693
+ if (group.type === "path") return `${ctx.group.split("/")[1]}`;
1694
+ return `${camelCase(ctx.group)}Controller`;
1695
+ }
1696
+ } : void 0;
27
1697
  return {
28
1698
  name: pluginClientName,
29
- options: {
30
- client,
31
- clientType,
32
- bundle,
33
- output,
34
- group,
35
- parser,
36
- dataReturnType,
37
- importPath: resolvedImportPath,
38
- paramsType,
39
- paramsCasing,
40
- pathParamsType,
41
- baseURL,
42
- urlType,
43
- wrapper
44
- },
45
- pre: [_kubb_plugin_oas.pluginOasName, parser === "zod" ? _kubb_plugin_zod.pluginZodName : void 0].filter(Boolean),
46
- resolvePath(baseName, pathMode, options) {
47
- const root = node_path.default.resolve(this.config.root, this.config.output.path);
48
- if ((pathMode ?? (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path))) === "single")
49
- /**
50
- * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
51
- * Other plugins then need to call addOrAppend instead of just add from the fileManager class
52
- */
53
- return node_path.default.resolve(root, output.path);
54
- if (group && (options?.group?.path || options?.group?.tag)) {
55
- const groupName = group?.name ? group.name : (ctx) => {
56
- if (group?.type === "path") return `${ctx.group.split("/")[1]}`;
57
- return `${require_StaticClassClient.camelCase(ctx.group)}Controller`;
58
- };
59
- return node_path.default.resolve(root, output.path, groupName({ group: group.type === "path" ? options.group.path : options.group.tag }), baseName);
60
- }
61
- return node_path.default.resolve(root, output.path, baseName);
62
- },
63
- resolveName(name, type) {
64
- const resolvedName = require_StaticClassClient.camelCase(name, { isFile: type === "file" });
65
- if (type) return transformers?.name?.(resolvedName, type) || resolvedName;
66
- return resolvedName;
67
- },
68
- async install() {
69
- const root = node_path.default.resolve(this.config.root, this.config.output.path);
70
- const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
71
- const oas = await this.getOas();
72
- const baseURL = await this.getBaseURL();
73
- if (bundle && !this.plugin.options.importPath) await this.addFile({
74
- baseName: "fetch.ts",
75
- path: node_path.default.resolve(root, ".kubb/fetch.ts"),
76
- sources: [{
77
- name: "fetch",
78
- value: this.plugin.options.client === "fetch" ? require_templates_clients_fetch_source.source : require_templates_clients_axios_source.source,
79
- isExportable: true,
80
- isIndexable: true
81
- }],
82
- imports: [],
83
- exports: []
1699
+ options,
1700
+ dependencies: [_kubb_plugin_ts.pluginTsName, parser === "zod" ? _kubb_plugin_zod.pluginZodName : void 0].filter(Boolean),
1701
+ hooks: { "kubb:plugin:setup"(ctx) {
1702
+ const resolver = userResolver ? {
1703
+ ...resolverClient,
1704
+ ...userResolver
1705
+ } : resolverClient;
1706
+ ctx.setOptions({
1707
+ client,
1708
+ clientType,
1709
+ bundle,
1710
+ output,
1711
+ exclude,
1712
+ include,
1713
+ override,
1714
+ group: groupConfig,
1715
+ parser,
1716
+ dataReturnType,
1717
+ importPath: resolvedImportPath,
1718
+ baseURL,
1719
+ paramsType,
1720
+ paramsCasing,
1721
+ pathParamsType,
1722
+ urlType,
1723
+ sdk,
1724
+ resolver
84
1725
  });
85
- await this.addFile({
1726
+ ctx.setResolver(resolver);
1727
+ if (userTransformer) ctx.setTransformer(userTransformer);
1728
+ for (const gen of selectedGenerators) ctx.addGenerator(gen);
1729
+ const root = node_path$1.default.resolve(ctx.config.root, ctx.config.output.path);
1730
+ if (!resolvedImportPath?.startsWith(".")) {
1731
+ const isInlineSource = bundle && !resolvedImportPath;
1732
+ ctx.injectFile({
1733
+ baseName: "client.ts",
1734
+ path: node_path$1.default.resolve(root, ".kubb/client.ts"),
1735
+ sources: [_kubb_core.ast.createSource({
1736
+ name: "client",
1737
+ nodes: isInlineSource ? [_kubb_core.ast.createText(client === "fetch" ? require_templates_clients_fetch_source.source : require_templates_clients_axios_source.source)] : [],
1738
+ isExportable: true,
1739
+ isIndexable: true
1740
+ })],
1741
+ exports: !isInlineSource && resolvedImportPath ? [_kubb_core.ast.createExport({ path: resolvedImportPath })] : []
1742
+ });
1743
+ }
1744
+ ctx.injectFile({
86
1745
  baseName: "config.ts",
87
- path: node_path.default.resolve(root, ".kubb/config.ts"),
88
- sources: [{
1746
+ path: node_path$1.default.resolve(root, ".kubb/config.ts"),
1747
+ sources: [_kubb_core.ast.createSource({
89
1748
  name: "config",
90
- value: require_templates_config_source.source,
1749
+ nodes: [_kubb_core.ast.createText(require_templates_config_source.source)],
91
1750
  isExportable: false,
92
1751
  isIndexable: false
93
- }],
94
- imports: [],
95
- exports: []
1752
+ })]
96
1753
  });
97
- const files = await new _kubb_plugin_oas.OperationGenerator(baseURL ? {
98
- ...this.plugin.options,
99
- baseURL
100
- } : this.plugin.options, {
101
- fabric: this.fabric,
102
- oas,
103
- driver: this.driver,
104
- events: this.events,
105
- plugin: this.plugin,
106
- contentType,
107
- exclude,
108
- include,
109
- override,
110
- mode
111
- }).build(...generators);
112
- await this.upsertFile(...files);
113
- const barrelFiles = await (0, _kubb_core.getBarrelFiles)(this.fabric.files, {
114
- type: output.barrelType ?? "named",
115
- root,
116
- output,
117
- meta: { pluginName: this.plugin.name }
118
- });
119
- await this.upsertFile(...barrelFiles);
120
- }
1754
+ } }
121
1755
  };
122
1756
  });
123
1757
  //#endregion
1758
+ exports.Client = Client;
1759
+ exports.classClientGenerator = classClientGenerator;
1760
+ exports.clientGenerator = clientGenerator;
1761
+ exports.default = pluginClient;
1762
+ exports.groupedClientGenerator = groupedClientGenerator;
1763
+ exports.operationsGenerator = operationsGenerator;
124
1764
  exports.pluginClient = pluginClient;
125
1765
  exports.pluginClientName = pluginClientName;
1766
+ exports.resolverClient = resolverClient;
1767
+ exports.staticClassClientGenerator = staticClassClientGenerator;
126
1768
 
127
1769
  //# sourceMappingURL=index.cjs.map