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

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.
package/dist/index.js CHANGED
@@ -4,8 +4,9 @@ import { source as source$1 } from "./templates/clients/fetch.source.js";
4
4
  import { source as source$2 } from "./templates/config.source.js";
5
5
  import path from "node:path";
6
6
  import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
7
+ import { buildJSDoc, stringify } from "@kubb/ast/utils";
7
8
  import { functionPrinter, pluginTsName } from "@kubb/plugin-ts";
8
- import { Const, File, Function, jsxRendererSync } from "@kubb/renderer-jsx";
9
+ import { Const, File, Function, jsxRenderer } from "@kubb/renderer-jsx";
9
10
  import { Fragment, jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
10
11
  import { pluginZodName } from "@kubb/plugin-zod";
11
12
  //#region ../../internals/utils/src/casing.ts
@@ -19,68 +20,57 @@ import { pluginZodName } from "@kubb/plugin-zod";
19
20
  function toCamelOrPascal(text, pascal) {
20
21
  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) => {
21
22
  if (word.length > 1 && word === word.toUpperCase()) return word;
22
- if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
23
- return word.charAt(0).toUpperCase() + word.slice(1);
23
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
24
24
  }).join("").replace(/[^a-zA-Z0-9]/g, "");
25
25
  }
26
26
  /**
27
- * Splits `text` on `.` and applies `transformPart` to each segment.
28
- * The last segment receives `isLast = true`, all earlier segments receive `false`.
29
- * Segments are joined with `/` to form a file path.
30
- *
31
- * Only splits on dots followed by a letter so that version numbers
32
- * embedded in operationIds (e.g. `v2025.0`) are kept intact.
33
- */
34
- function applyToFileParts(text, transformPart) {
35
- const parts = text.split(/\.(?=[a-zA-Z])/);
36
- return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
37
- }
38
- /**
39
27
  * Converts `text` to camelCase.
40
- * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
41
28
  *
42
- * @example
43
- * camelCase('hello-world') // 'helloWorld'
44
- * camelCase('pet.petId', { isFile: true }) // 'pet/petId'
29
+ * @example Word boundaries
30
+ * `camelCase('hello-world') // 'helloWorld'`
31
+ *
32
+ * @example With a prefix
33
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
45
34
  */
46
- function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
47
- if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
48
- prefix,
49
- suffix
50
- } : {}));
35
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
51
36
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
52
37
  }
53
38
  /**
54
39
  * Converts `text` to PascalCase.
55
- * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
56
40
  *
57
- * @example
58
- * pascalCase('hello-world') // 'HelloWorld'
59
- * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
41
+ * @example Word boundaries
42
+ * `pascalCase('hello-world') // 'HelloWorld'`
43
+ *
44
+ * @example With a suffix
45
+ * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`
60
46
  */
61
- function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
62
- if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
63
- prefix,
64
- suffix
65
- }) : camelCase(part));
47
+ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
66
48
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
67
49
  }
68
50
  //#endregion
69
- //#region ../../internals/utils/src/jsdoc.ts
51
+ //#region ../../internals/utils/src/fs.ts
70
52
  /**
71
- * Builds a JSDoc comment block from an array of lines.
72
- * Returns `fallback` when `comments` is empty so callers always get a usable string.
53
+ * Builds a nested file path from a dotted name. Splits on dots that precede a letter
54
+ * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
55
+ * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
73
56
  *
74
- * @example
75
- * ```ts
76
- * buildJSDoc(['@type string', '@example hello'])
77
- * // '/**\n * @type string\n * @example hello\n *\/\n '
78
- * ```
57
+ * Empty segments are dropped before joining. They arise when the name starts with a dot
58
+ * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
59
+ * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
60
+ * absolute path, letting generated files escape the configured output directory.
61
+ *
62
+ * @example Nested path from a dotted name
63
+ * `toFilePath('pet.petId') // 'pet/petId'`
64
+ *
65
+ * @example PascalCase the final segment
66
+ * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
67
+ *
68
+ * @example Suffix applied to the final segment only
69
+ * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
79
70
  */
80
- function buildJSDoc(comments, options = {}) {
81
- const { indent = " * ", suffix = "\n ", fallback = " " } = options;
82
- if (comments.length === 0) return fallback;
83
- return `/**\n${comments.map((c) => `${indent}${c}`).join("\n")}\n */${suffix}`;
71
+ function toFilePath(name, caseLast = camelCase) {
72
+ const parts = name.split(/\.(?=[a-zA-Z])/);
73
+ return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
84
74
  }
85
75
  //#endregion
86
76
  //#region ../../internals/utils/src/reserved.ts
@@ -206,99 +196,83 @@ function ensureValidVarName(name) {
206
196
  return `_${name}`;
207
197
  }
208
198
  //#endregion
209
- //#region ../../internals/utils/src/urlPath.ts
199
+ //#region ../../internals/utils/src/url.ts
200
+ function transformParam(raw, casing) {
201
+ const param = isValidVarName(raw) ? raw : camelCase(raw);
202
+ return casing === "camelcase" ? camelCase(param) : param;
203
+ }
204
+ function toParamsObject(path, { replacer, casing } = {}) {
205
+ const params = {};
206
+ for (const match of path.matchAll(/\{([^}]+)\}/g)) {
207
+ const param = transformParam(match[1], casing);
208
+ const key = replacer ? replacer(param) : param;
209
+ params[key] = key;
210
+ }
211
+ return Object.keys(params).length > 0 ? params : null;
212
+ }
210
213
  /**
211
- * Parses and transforms an OpenAPI/Swagger path string into various URL formats.
212
- *
213
- * @example
214
- * const p = new URLPath('/pet/{petId}')
215
- * p.URL // '/pet/:petId'
216
- * p.template // '`/pet/${petId}`'
214
+ * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.
217
215
  */
218
- var URLPath = class {
219
- /**
220
- * The raw OpenAPI/Swagger path string, e.g. `/pet/{petId}`.
221
- */
222
- path;
223
- #options;
224
- constructor(path, options = {}) {
225
- this.path = path;
226
- this.#options = options;
216
+ var Url$1 = class Url$1 {
217
+ static {
218
+ __name(this, "Url");
227
219
  }
228
- /** Converts the OpenAPI path to Express-style colon syntax, e.g. `/pet/{petId}` → `/pet/:petId`.
220
+ /**
221
+ * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
229
222
  *
230
223
  * @example
231
- * ```ts
232
- * new URLPath('/pet/{petId}').URL // '/pet/:petId'
233
- * ```
224
+ * Url.canParse('https://petstore.swagger.io/v2') // true
225
+ * Url.canParse('/pet/{petId}') // false
234
226
  */
235
- get URL() {
236
- return this.toURLPath();
227
+ static canParse(url, base) {
228
+ return URL.canParse(url, base);
237
229
  }
238
- /** Returns `true` when `path` is a fully-qualified URL (e.g. starts with `https://`).
230
+ /**
231
+ * Converts an OpenAPI/Swagger path to Express-style colon syntax.
239
232
  *
240
233
  * @example
241
- * ```ts
242
- * new URLPath('https://petstore.swagger.io/v2/pet').isURL // true
243
- * new URLPath('/pet/{petId}').isURL // false
244
- * ```
234
+ * Url.toPath('/pet/{petId}') // '/pet/:petId'
245
235
  */
246
- get isURL() {
247
- try {
248
- return !!new URL(this.path).href;
249
- } catch {
250
- return false;
251
- }
236
+ static toPath(path) {
237
+ return path.replace(/\{([^}]+)\}/g, ":$1");
252
238
  }
253
239
  /**
254
- * Converts the OpenAPI path to a TypeScript template literal string.
240
+ * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
241
+ * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,
242
+ * and `casing` controls parameter identifier casing.
255
243
  *
256
244
  * @example
257
- * new URLPath('/pet/{petId}').template // '`/pet/${petId}`'
258
- * new URLPath('/account/monetary-accountID').template // '`/account/${monetaryAccountId}`'
259
- */
260
- get template() {
261
- return this.toTemplateString();
262
- }
263
- /** Returns the path and its extracted params as a structured `URLObject`, or as a stringified expression when `stringify` is set.
245
+ * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
264
246
  *
265
247
  * @example
266
- * ```ts
267
- * new URLPath('/pet/{petId}').object
268
- * // { url: '/pet/:petId', params: { petId: 'petId' } }
269
- * ```
248
+ * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
270
249
  */
271
- get object() {
272
- return this.toObject();
250
+ static toTemplateString(path, { prefix, replacer, casing } = {}) {
251
+ const result = path.split(/\{([^}]+)\}/).map((part, i) => {
252
+ if (i % 2 === 0) return part;
253
+ const param = transformParam(part, casing);
254
+ return `\${${replacer ? replacer(param) : param}}`;
255
+ }).join("");
256
+ return `\`${prefix ?? ""}${result}\``;
273
257
  }
274
- /** Returns a map of path parameter names, or `null` when the path has no parameters.
258
+ /**
259
+ * Returns the path and its extracted params as a structured `URLObject`, or as a stringified
260
+ * expression when `stringify` is set.
275
261
  *
276
262
  * @example
277
- * ```ts
278
- * new URLPath('/pet/{petId}').params // { petId: 'petId' }
279
- * new URLPath('/pet').params // null
280
- * ```
281
- */
282
- get params() {
283
- return this.toParamsObject();
284
- }
285
- #transformParam(raw) {
286
- const param = isValidVarName(raw) ? raw : camelCase(raw);
287
- return this.#options.casing === "camelcase" ? camelCase(param) : param;
288
- }
289
- /**
290
- * Iterates over every `{param}` token in `path`, calling `fn` with the raw token and transformed name.
263
+ * Url.toObject('/pet/{petId}')
264
+ * // { url: '/pet/:petId', params: { petId: 'petId' } }
291
265
  */
292
- #eachParam(fn) {
293
- for (const match of this.path.matchAll(/\{([^}]+)\}/g)) {
294
- const raw = match[1];
295
- fn(raw, this.#transformParam(raw));
296
- }
297
- }
298
- toObject({ type = "path", replacer, stringify } = {}) {
266
+ static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
299
267
  const object = {
300
- url: type === "path" ? this.toURLPath() : this.toTemplateString({ replacer }),
301
- params: this.toParamsObject()
268
+ url: type === "path" ? Url$1.toPath(path) : Url$1.toTemplateString(path, {
269
+ replacer,
270
+ casing
271
+ }),
272
+ params: toParamsObject(path, {
273
+ replacer,
274
+ casing
275
+ })
302
276
  };
303
277
  if (stringify) {
304
278
  if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
@@ -307,50 +281,6 @@ var URLPath = class {
307
281
  }
308
282
  return object;
309
283
  }
310
- /**
311
- * Converts the OpenAPI path to a TypeScript template literal string.
312
- * An optional `replacer` can transform each extracted parameter name before interpolation.
313
- *
314
- * @example
315
- * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
316
- */
317
- toTemplateString({ prefix, replacer } = {}) {
318
- const result = this.path.split(/\{([^}]+)\}/).map((part, i) => {
319
- if (i % 2 === 0) return part;
320
- const param = this.#transformParam(part);
321
- return `\${${replacer ? replacer(param) : param}}`;
322
- }).join("");
323
- return `\`${prefix ?? ""}${result}\``;
324
- }
325
- /**
326
- * Extracts all `{param}` segments from the path and returns them as a key-value map.
327
- * An optional `replacer` transforms each parameter name in both key and value positions.
328
- * Returns `undefined` when no path parameters are found.
329
- *
330
- * @example
331
- * ```ts
332
- * new URLPath('/pet/{petId}/tag/{tagId}').toParamsObject()
333
- * // { petId: 'petId', tagId: 'tagId' }
334
- * ```
335
- */
336
- toParamsObject(replacer) {
337
- const params = {};
338
- this.#eachParam((_raw, param) => {
339
- const key = replacer ? replacer(param) : param;
340
- params[key] = key;
341
- });
342
- return Object.keys(params).length > 0 ? params : null;
343
- }
344
- /** Converts the OpenAPI path to Express-style colon syntax.
345
- *
346
- * @example
347
- * ```ts
348
- * new URLPath('/pet/{petId}').toURLPath() // '/pet/:petId'
349
- * ```
350
- */
351
- toURLPath() {
352
- return this.path.replace(/\{([^}]+)\}/g, ":$1");
353
- }
354
284
  };
355
285
  //#endregion
356
286
  //#region ../../internals/shared/src/operation.ts
@@ -376,7 +306,7 @@ function operationFileEntry(node, name, extname = ".ts") {
376
306
  function getOperationLink(node, link) {
377
307
  if (!link) return null;
378
308
  if (typeof link === "function") return link(node) ?? null;
379
- if (link === "urlPath") return node.path ? `{@link ${new URLPath(node.path).URL}}` : null;
309
+ if (link === "urlPath") return node.path ? `{@link ${Url$1.toPath(node.path)}}` : null;
380
310
  return node.path ? `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}` : null;
381
311
  }
382
312
  function getContentTypeInfo(node) {
@@ -467,6 +397,19 @@ function resolveSuccessNames(node, resolver) {
467
397
  function resolveStatusCodeNames(node, resolver) {
468
398
  return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
469
399
  }
400
+ /**
401
+ * Builds the discriminated union type string for `dataReturnType: 'full'` return shapes.
402
+ * Each member is `{ status: N; data: StatusNType; statusText: string }`.
403
+ */
404
+ function buildStatusUnionType(node, resolver) {
405
+ const members = node.responses.map((r) => {
406
+ const typeName = resolver.resolveResponseStatusName(node, r.statusCode);
407
+ const statusCode = Number.parseInt(r.statusCode, 10);
408
+ return `{ status: ${Number.isNaN(statusCode) ? "number" : String(statusCode)}; data: ${typeName}; statusText: string }`;
409
+ });
410
+ if (members.length === 1) return members[0];
411
+ return `(${members.join(" | ")})`;
412
+ }
470
413
  const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
471
414
  function resolveOperationTypeNames(node, resolver, options = {}) {
472
415
  const cacheKey = `${node.operationId}\0${options.paramsCasing ?? ""}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${(options.exclude ?? []).join(",")}`;
@@ -506,26 +449,24 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
506
449
  * shared default naming so every plugin groups output consistently:
507
450
  *
508
451
  * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
509
- * - other groups use `${camelCase(group)}${suffix}` (e.g. `petController`).
452
+ * - other groups use the camelCased group (`pet store``petStore`).
510
453
  *
511
454
  * A user-provided `group.name` always wins over the default namer, so callers stay in
512
455
  * control of their output folders. Returns `null` when grouping is disabled, matching the
513
456
  * per-plugin convention.
514
457
  *
515
458
  * @param group - The user-supplied group option, or `undefined` to disable grouping.
516
- * @param options.suffix - Appended to non-`path` group names, e.g. `'Controller'` or `'Requests'`.
517
459
  *
518
460
  * @example
519
461
  * ```ts
520
- * createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-client, …
521
- * createGroupConfig(group, { suffix: 'Requests' }) // plugin-cypress, plugin-mcp
462
+ * createGroupConfig(group) // shared across every plugin
522
463
  * ```
523
464
  */
524
- function createGroupConfig(group, options) {
465
+ function createGroupConfig(group) {
525
466
  if (!group) return null;
526
467
  const defaultName = (ctx) => {
527
468
  if (group.type === "path") return `${ctx.group.split("/")[1]}`;
528
- return `${camelCase(ctx.group)}${options.suffix}`;
469
+ return camelCase(ctx.group);
529
470
  };
530
471
  return {
531
472
  ...group,
@@ -608,6 +549,143 @@ function createFunctionParams(params) {
608
549
  };
609
550
  }
610
551
  //#endregion
552
+ //#region src/utils.ts
553
+ /**
554
+ * Returns `true` when any direction of the parser uses Zod (used for dependency checks).
555
+ */
556
+ function isParserEnabled(parser) {
557
+ if (!parser) return false;
558
+ if (parser === "zod") return true;
559
+ return !!(parser.request || parser.response);
560
+ }
561
+ /**
562
+ * Returns `'zod'` when request body parsing is enabled, `null` otherwise.
563
+ * The string shorthand `'zod'` also enables request body parsing (existing behavior).
564
+ */
565
+ function resolveRequestParser(parser) {
566
+ if (!parser) return null;
567
+ if (parser === "zod") return "zod";
568
+ return parser.request ?? null;
569
+ }
570
+ /**
571
+ * Returns `'zod'` when query-parameters parsing is enabled, `null` otherwise.
572
+ * Only the object form `{ request: 'zod' }` enables query-params parsing.
573
+ * The string shorthand `'zod'` does not, preserving its existing behavior.
574
+ */
575
+ function resolveQueryParamsParser(parser) {
576
+ if (!parser || parser === "zod") return null;
577
+ return parser.request ?? null;
578
+ }
579
+ /**
580
+ * Returns `'zod'` when response-direction parsing is enabled, `null` otherwise.
581
+ * `parser: 'zod'` (string shorthand) maps to response parsing and returns `'zod'`.
582
+ */
583
+ function resolveResponseParser(parser) {
584
+ if (!parser) return null;
585
+ if (parser === "zod") return "zod";
586
+ return parser.response ?? null;
587
+ }
588
+ /**
589
+ * Builds HTTP headers array for a client request.
590
+ * Includes Content-Type (if not default) and spreads header parameters if present.
591
+ */
592
+ function buildHeaders(contentType, hasHeaderParams) {
593
+ return [contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : null, hasHeaderParams ? "...headers" : null].filter(Boolean);
594
+ }
595
+ /**
596
+ * Returns the generic type arguments — response, error, and request body — for a generated
597
+ * client call.
598
+ *
599
+ * When `dataReturnType` is `'full'`, the response generic widens to a union of all documented
600
+ * status types. When `parser` is `'zod'` and a request body schema exists, the request type
601
+ * uses `z.output<typeof schema>` to reflect post-transform types (e.g. date coercion).
602
+ */
603
+ function buildGenerics(node, tsResolver, options = {}) {
604
+ const allStatusNames = node.responses.map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
605
+ const successNames = resolveSuccessNames(node, tsResolver);
606
+ const responseName = options.dataReturnType === "full" ? allStatusNames.length > 0 ? allStatusNames.join(" | ") : tsResolver.resolveResponseName(node) : successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
607
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
608
+ const errorNames = node.responses.filter((r) => Number.parseInt(r.statusCode, 10) >= 400).map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
609
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
610
+ const zodRequestName = options.parser === "zod" && options.zodResolver && node.requestBody?.content?.[0]?.schema ? options.zodResolver.resolveDataName?.(node) ?? null : null;
611
+ return [
612
+ responseName,
613
+ TError,
614
+ zodRequestName ? `z.output<typeof ${zodRequestName}>` : requestName || "unknown"
615
+ ].filter(Boolean);
616
+ }
617
+ /**
618
+ * Builds the parameters object for a class-based client method.
619
+ * Includes URL, method, base URL, headers, and request/response data.
620
+ */
621
+ function buildClassClientParams({ node, url, baseURL, tsResolver, isFormData, isMultipleContentTypes, hasFormData, headers, zodQueryParamsName }) {
622
+ const { query: queryParams } = getOperationParameters(node);
623
+ const queryParamsName = queryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, queryParams[0]) : null;
624
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
625
+ const responseType = getResponseType(node);
626
+ return createFunctionParams({ config: {
627
+ mode: "object",
628
+ children: {
629
+ requestConfig: { mode: "inlineSpread" },
630
+ method: { value: JSON.stringify(ast.isHttpOperationNode(node) ? node.method.toUpperCase() : "") },
631
+ url: { value: url },
632
+ baseURL: baseURL ? { value: JSON.stringify(baseURL) } : null,
633
+ params: queryParamsName ? zodQueryParamsName ? { value: "requestParams" } : {} : null,
634
+ data: requestName ? { value: isMultipleContentTypes && hasFormData ? "contentType === 'multipart/form-data' ? formData as FormData : requestData" : isFormData ? "formData as FormData" : "requestData" } : null,
635
+ contentType: isMultipleContentTypes ? {} : null,
636
+ responseType: responseType ? { value: JSON.stringify(responseType) } : null,
637
+ headers: headers.length ? { value: `{ ${headers.join(", ")}, ...requestConfig.headers }` } : null
638
+ }
639
+ } });
640
+ }
641
+ /**
642
+ * Builds the request data parsing line for client methods.
643
+ * Applies Zod validation when `parser.request === 'zod'`, otherwise assigns data directly.
644
+ */
645
+ function buildRequestDataLine({ parser, node, zodResolver }) {
646
+ const requestParser = resolveRequestParser(parser);
647
+ const zodRequestName = zodResolver && requestParser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null;
648
+ if (requestParser === "zod" && zodRequestName) return `const requestData = ${zodRequestName}.parse(data)`;
649
+ if (node.requestBody?.content?.[0]?.schema) return "const requestData = data";
650
+ return "";
651
+ }
652
+ /**
653
+ * Builds the query parameters parsing line for client methods.
654
+ * Returns an empty string when no query params exist or query-params parsing is not enabled.
655
+ * Only the object form `parser: { request: 'zod' }` triggers this. `parser: 'zod'` does not.
656
+ */
657
+ function buildQueryParamsLine({ parser, node, zodResolver }) {
658
+ if (resolveQueryParamsParser(parser) !== "zod" || !zodResolver) return "";
659
+ const { query: queryParams } = getOperationParameters(node);
660
+ if (queryParams.length === 0) return "";
661
+ const zodQueryParamsName = zodResolver.resolveQueryParamsName?.(node, queryParams[0]);
662
+ if (!zodQueryParamsName) return "";
663
+ return `const requestParams = ${zodQueryParamsName}.parse(params)`;
664
+ }
665
+ /**
666
+ * Builds the form data conversion line for file upload requests.
667
+ * Returns empty string if not applicable.
668
+ */
669
+ function buildFormDataLine(isFormData, hasRequest) {
670
+ return isFormData && hasRequest ? "const formData = buildFormData(requestData)" : "";
671
+ }
672
+ /**
673
+ * Builds the return statement for a client method.
674
+ * When `dataReturnType` is `'full'`, casts the response to the status-discriminated union type.
675
+ * When `parser.response` is `'zod'`, pipes the response body through the Zod schema before returning.
676
+ */
677
+ function buildReturnStatement({ dataReturnType, parser, node, zodResolver, tsResolver }) {
678
+ const responseParser = resolveResponseParser(parser);
679
+ const zodResponseName = zodResolver && responseParser === "zod" ? zodResolver.resolveResponseName?.(node) : null;
680
+ if (dataReturnType === "full" && tsResolver) {
681
+ const unionType = buildStatusUnionType(node, tsResolver);
682
+ if (responseParser === "zod" && zodResponseName) return `return {...res, data: ${zodResponseName}.parse(res.data)} as ${unionType}`;
683
+ return `return res as ${unionType}`;
684
+ }
685
+ if (dataReturnType === "data" && responseParser === "zod" && zodResponseName) return `return ${zodResponseName}.parse(res.data)`;
686
+ return "return res.data";
687
+ }
688
+ //#endregion
611
689
  //#region src/components/Url.tsx
612
690
  const declarationPrinter$3 = functionPrinter({ mode: "declaration" });
613
691
  function buildUrlParamsNode({ paramsType, paramsCasing, pathParamsType, node, tsResolver }) {
@@ -625,7 +703,6 @@ function buildUrlParamsNode({ paramsType, paramsCasing, pathParamsType, node, ts
625
703
  }
626
704
  function Url({ name, isExportable = true, isIndexable = true, baseURL, paramsType, paramsCasing, pathParamsType, node, tsResolver }) {
627
705
  if (!ast.isHttpOperationNode(node)) return null;
628
- const path = new URLPath(node.path);
629
706
  const paramsNode = buildUrlParamsNode({
630
707
  paramsType,
631
708
  paramsCasing,
@@ -650,7 +727,7 @@ function Url({ name, isExportable = true, isIndexable = true, baseURL, paramsTyp
650
727
  pathParamsMapping && Object.keys(pathParamsMapping).length > 0 && /* @__PURE__ */ jsx("br", {}),
651
728
  /* @__PURE__ */ jsx(Const, {
652
729
  name: "res",
653
- children: `{ method: '${node.method.toUpperCase()}', url: ${path.toTemplateString({ prefix: baseURL })} as const }`
730
+ children: `{ method: '${node.method.toUpperCase()}', url: ${Url$1.toTemplateString(node.path, { prefix: baseURL })} as const }`
654
731
  }),
655
732
  /* @__PURE__ */ jsx("br", {}),
656
733
  "return res"
@@ -679,7 +756,6 @@ function buildClientParamsNode({ paramsType, paramsCasing, pathParamsType, node,
679
756
  }
680
757
  function Client({ name, isExportable = true, isIndexable = true, returnType, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType, node, tsResolver, zodResolver, urlName, children, isConfigurable = true }) {
681
758
  if (!ast.isHttpOperationNode(node)) return null;
682
- const path = new URLPath(node.path);
683
759
  const { defaultContentType: contentType, isMultipleContentTypes, hasFormData } = getContentTypeInfo(node);
684
760
  const isFormData = !isMultipleContentTypes && contentType === "multipart/form-data";
685
761
  const responseType = getResponseType(node);
@@ -693,16 +769,22 @@ function Client({ name, isExportable = true, isIndexable = true, returnType, bas
693
769
  const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
694
770
  const queryParamsName = originalQueryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, originalQueryParams[0]) : null;
695
771
  const headerParamsName = originalHeaderParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, originalHeaderParams[0]) : null;
696
- const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : null;
697
- const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null;
772
+ const requestParser = resolveRequestParser(parser);
773
+ const responseParser = resolveResponseParser(parser);
774
+ const zodResponseName = zodResolver && responseParser === "zod" ? zodResolver.resolveResponseName?.(node) : null;
775
+ const zodRequestName = zodResolver && requestParser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null;
776
+ const queryParamsParser = resolveQueryParamsParser(parser);
777
+ const zodQueryParamsName = zodResolver && queryParamsParser === "zod" && originalQueryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, originalQueryParams[0]) : null;
698
778
  const errorNames = node.responses.filter((r) => {
699
779
  return Number.parseInt(r.statusCode, 10) >= 400;
700
780
  }).map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
701
781
  const headers = [!isMultipleContentTypes && contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : null, headerParamsName ? headerParamsMapping ? "...mappedHeaders" : "...headers" : null].filter(Boolean);
782
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
783
+ const allStatusNames = node.responses.map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
702
784
  const generics = [
703
- responseName,
704
- `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
705
- requestName || "unknown"
785
+ dataReturnType === "full" ? allStatusNames.length > 0 ? allStatusNames.join(" | ") : responseName : responseName,
786
+ TError,
787
+ parser === "zod" && zodRequestName ? `z.output<typeof ${zodRequestName}>` : requestName || "unknown"
706
788
  ].filter(Boolean);
707
789
  const paramsNode = buildClientParamsNode({
708
790
  paramsType,
@@ -724,22 +806,23 @@ function Client({ name, isExportable = true, isIndexable = true, returnType, bas
724
806
  const clientParams = createFunctionParams({ config: {
725
807
  mode: "object",
726
808
  children: {
727
- method: { value: JSON.stringify(node.method.toUpperCase()) },
728
- url: { value: urlName ? `${urlName}(${urlParamsCall}).url.toString()` : path.template },
809
+ method: { value: stringify(node.method.toUpperCase()) },
810
+ url: { value: urlName ? `${urlName}(${urlParamsCall}).url.toString()` : Url$1.toTemplateString(node.path) },
729
811
  baseURL: baseURL && !urlName ? { value: `\`${baseURL}\`` } : null,
730
- params: queryParamsName ? queryParamsMapping ? { value: "mappedParams" } : {} : null,
812
+ params: queryParamsName ? zodQueryParamsName ? { value: "requestParams" } : queryParamsMapping ? { value: "mappedParams" } : {} : null,
731
813
  data: requestName ? { value: isMultipleContentTypes && hasFormData ? "contentType === 'multipart/form-data' ? formData as FormData : requestData" : isFormData ? "formData as FormData" : "requestData" } : null,
732
814
  contentType: isConfigurable && isMultipleContentTypes ? {} : null,
733
- responseType: responseType ? { value: JSON.stringify(responseType) } : null,
815
+ responseType: responseType ? { value: stringify(responseType) } : null,
734
816
  requestConfig: isConfigurable ? { mode: "inlineSpread" } : null,
735
817
  headers: headers.length ? { value: isConfigurable ? `{ ${headers.join(", ")}, ...requestConfig.headers }` : `{ ${headers.join(", ")} }` } : null
736
818
  }
737
819
  } });
820
+ const statusUnionType = dataReturnType === "full" ? buildStatusUnionType(node, tsResolver) : null;
738
821
  const childrenElement = children ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
739
- dataReturnType === "full" && parser === "zod" && zodResponseName && `return {...res, data: ${zodResponseName}.parse(res.data)}`,
740
- dataReturnType === "data" && parser === "zod" && zodResponseName && `return ${zodResponseName}.parse(res.data)`,
741
- dataReturnType === "full" && parser !== "zod" && "return res",
742
- dataReturnType === "data" && parser !== "zod" && "return res.data"
822
+ dataReturnType === "full" && responseParser === "zod" && zodResponseName && statusUnionType && `return {...res, data: ${zodResponseName}.parse(res.data)} as ${statusUnionType}`,
823
+ dataReturnType === "full" && responseParser !== "zod" && statusUnionType && `return res as ${statusUnionType}`,
824
+ dataReturnType === "data" && responseParser === "zod" && zodResponseName && `return ${zodResponseName}.parse(res.data)`,
825
+ dataReturnType === "data" && responseParser !== "zod" && "return res.data"
743
826
  ] });
744
827
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("br", {}), /* @__PURE__ */ jsx(File.Source, {
745
828
  name,
@@ -757,23 +840,14 @@ function Client({ name, isExportable = true, isIndexable = true, returnType, bas
757
840
  }) },
758
841
  returnType,
759
842
  children: [
760
- isConfigurable ? `const { client: request = client, ${isMultipleContentTypes ? `contentType = ${JSON.stringify(contentType)}, ` : ""}...requestConfig } = config` : "",
761
- /* @__PURE__ */ jsx("br", {}),
843
+ isConfigurable ? `const { client: request = client, ${isMultipleContentTypes ? `contentType = ${stringify(contentType)}, ` : ""}...requestConfig } = config` : "",
762
844
  /* @__PURE__ */ jsx("br", {}),
763
845
  pathParamsMapping && Object.entries(pathParamsMapping).filter(([originalName, camelCaseName]) => isValidVarName(originalName) && originalName !== camelCaseName).map(([originalName, camelCaseName]) => `const ${originalName} = ${camelCaseName}`).join("\n"),
764
- pathParamsMapping && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("br", {}), /* @__PURE__ */ jsx("br", {})] }),
765
- queryParamsMapping && queryParamsName && /* @__PURE__ */ jsxs(Fragment, { children: [
766
- `const mappedParams = params ? { ${Object.entries(queryParamsMapping).map(([originalName, camelCaseName]) => `"${originalName}": params.${camelCaseName}`).join(", ")} } : undefined`,
767
- /* @__PURE__ */ jsx("br", {}),
768
- /* @__PURE__ */ jsx("br", {})
769
- ] }),
770
- headerParamsMapping && headerParamsName && /* @__PURE__ */ jsxs(Fragment, { children: [
771
- `const mappedHeaders = headers ? { ${Object.entries(headerParamsMapping).map(([originalName, camelCaseName]) => `"${originalName}": headers.${camelCaseName}`).join(", ")} } : undefined`,
772
- /* @__PURE__ */ jsx("br", {}),
773
- /* @__PURE__ */ jsx("br", {})
774
- ] }),
775
- parser === "zod" && zodRequestName ? `const requestData = ${zodRequestName}.parse(data)` : requestName && "const requestData = data",
776
- /* @__PURE__ */ jsx("br", {}),
846
+ pathParamsMapping && /* @__PURE__ */ jsx("br", {}),
847
+ queryParamsMapping && queryParamsName && /* @__PURE__ */ jsxs(Fragment, { children: [`const mappedParams = params ? { ${Object.entries(queryParamsMapping).map(([originalName, camelCaseName]) => `"${originalName}": params.${camelCaseName}`).join(", ")} } : undefined`, /* @__PURE__ */ jsx("br", {})] }),
848
+ headerParamsMapping && headerParamsName && /* @__PURE__ */ jsxs(Fragment, { children: [`const mappedHeaders = headers ? { ${Object.entries(headerParamsMapping).map(([originalName, camelCaseName]) => `"${originalName}": headers.${camelCaseName}`).join(", ")} } : undefined`, /* @__PURE__ */ jsx("br", {})] }),
849
+ requestParser === "zod" && zodRequestName ? `const requestData = ${zodRequestName}.parse(data)` : requestName && "const requestData = data",
850
+ zodQueryParamsName && `const requestParams = ${zodQueryParamsName}.parse(params)`,
777
851
  (isFormData || isMultipleContentTypes && hasFormData) && requestName && "const formData = buildFormData(requestData)",
778
852
  /* @__PURE__ */ jsx("br", {}),
779
853
  isConfigurable ? `const res = await request<${generics.join(", ")}>(${clientParams.toCall()})` : `const res = await client<${generics.join(", ")}>(${clientParams.toCall()})`,
@@ -784,93 +858,20 @@ function Client({ name, isExportable = true, isIndexable = true, returnType, bas
784
858
  })] });
785
859
  }
786
860
  //#endregion
787
- //#region src/utils.ts
788
- /**
789
- * Builds HTTP headers array for a client request.
790
- * Includes Content-Type (if not default) and spreads header parameters if present.
791
- */
792
- function buildHeaders(contentType, hasHeaderParams) {
793
- return [contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : null, hasHeaderParams ? "...headers" : null].filter(Boolean);
794
- }
795
- /**
796
- * Builds TypeScript generic parameters for a client method.
797
- * Includes response type, error type, and optional request type.
798
- */
799
- function buildGenerics(node, tsResolver) {
800
- const successNames = resolveSuccessNames(node, tsResolver);
801
- const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
802
- const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
803
- const errorNames = node.responses.filter((r) => Number.parseInt(r.statusCode, 10) >= 400).map((r) => tsResolver.resolveResponseStatusName(node, r.statusCode));
804
- return [
805
- responseName,
806
- `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
807
- requestName || "unknown"
808
- ].filter(Boolean);
809
- }
810
- /**
811
- * Builds the parameters object for a class-based client method.
812
- * Includes URL, method, base URL, headers, and request/response data.
813
- */
814
- function buildClassClientParams({ node, path, baseURL, tsResolver, isFormData, isMultipleContentTypes, hasFormData, headers }) {
815
- const { query: queryParams } = getOperationParameters(node);
816
- const queryParamsName = queryParams.length > 0 ? tsResolver.resolveQueryParamsName(node, queryParams[0]) : null;
817
- const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
818
- const responseType = getResponseType(node);
819
- return createFunctionParams({ config: {
820
- mode: "object",
821
- children: {
822
- requestConfig: { mode: "inlineSpread" },
823
- method: { value: JSON.stringify(ast.isHttpOperationNode(node) ? node.method.toUpperCase() : "") },
824
- url: { value: path.template },
825
- baseURL: baseURL ? { value: JSON.stringify(baseURL) } : null,
826
- params: queryParamsName ? {} : null,
827
- data: requestName ? { value: isMultipleContentTypes && hasFormData ? "contentType === 'multipart/form-data' ? formData as FormData : requestData" : isFormData ? "formData as FormData" : "requestData" } : null,
828
- contentType: isMultipleContentTypes ? {} : null,
829
- responseType: responseType ? { value: JSON.stringify(responseType) } : null,
830
- headers: headers.length ? { value: `{ ${headers.join(", ")}, ...requestConfig.headers }` } : null
831
- }
832
- } });
833
- }
834
- /**
835
- * Builds the request data parsing line for client methods.
836
- * Applies Zod validation if configured, otherwise uses data directly.
837
- */
838
- function buildRequestDataLine({ parser, node, zodResolver }) {
839
- const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null;
840
- if (parser === "zod" && zodRequestName) return `const requestData = ${zodRequestName}.parse(data)`;
841
- if (node.requestBody?.content?.[0]?.schema) return "const requestData = data";
842
- return "";
843
- }
844
- /**
845
- * Builds the form data conversion line for file upload requests.
846
- * Returns empty string if not applicable.
847
- */
848
- function buildFormDataLine(isFormData, hasRequest) {
849
- return isFormData && hasRequest ? "const formData = buildFormData(requestData)" : "";
850
- }
851
- /**
852
- * Builds the return statement for a client method.
853
- * Applies Zod validation to response data if configured, otherwise returns raw response.
854
- */
855
- function buildReturnStatement({ dataReturnType, parser, node, zodResolver }) {
856
- const zodResponseName = zodResolver && parser === "zod" ? zodResolver.resolveResponseName?.(node) : null;
857
- if (dataReturnType === "full" && parser === "zod" && zodResponseName) return `return {...res, data: ${zodResponseName}.parse(res.data)}`;
858
- if (dataReturnType === "data" && parser === "zod" && zodResponseName) return `return ${zodResponseName}.parse(res.data)`;
859
- if (dataReturnType === "full" && parser !== "zod") return "return res";
860
- return "return res.data";
861
- }
862
- //#endregion
863
861
  //#region src/components/ClassClient.tsx
864
862
  const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
865
863
  function generateMethod$1({ node, name, tsResolver, zodResolver, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType }) {
866
864
  if (!ast.isHttpOperationNode(node)) return "";
867
- const path = new URLPath(node.path, { casing: paramsCasing });
868
865
  const { defaultContentType: contentType, isMultipleContentTypes, hasFormData } = getContentTypeInfo(node);
869
866
  const isFormData = !isMultipleContentTypes && contentType === "multipart/form-data";
870
867
  const { header: headerParams } = getOperationParameters(node);
871
868
  const headerParamsName = headerParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, headerParams[0]) : null;
872
869
  const headers = isMultipleContentTypes ? headerParamsName ? ["...headers"] : [] : buildHeaders(contentType, !!headerParamsName);
873
- const generics = buildGenerics(node, tsResolver);
870
+ const generics = buildGenerics(node, tsResolver, {
871
+ dataReturnType,
872
+ zodResolver,
873
+ parser
874
+ });
874
875
  const paramsNode = buildClientParamsNode({
875
876
  paramsType,
876
877
  paramsCasing,
@@ -880,15 +881,18 @@ function generateMethod$1({ node, name, tsResolver, zodResolver, baseURL, dataRe
880
881
  isConfigurable: true
881
882
  });
882
883
  const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
884
+ const { query: queryParams } = getOperationParameters(node);
885
+ const zodQueryParamsName = zodResolver && resolveQueryParamsParser(parser) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null;
883
886
  const clientParams = buildClassClientParams({
884
887
  node,
885
- path,
888
+ url: Url$1.toTemplateString(node.path, { casing: paramsCasing }),
886
889
  baseURL,
887
890
  tsResolver,
888
891
  isFormData,
889
892
  isMultipleContentTypes,
890
893
  hasFormData,
891
- headers
894
+ headers,
895
+ zodQueryParamsName
892
896
  });
893
897
  const jsdoc = buildJSDoc(buildOperationComments(node, {
894
898
  link: "urlPath",
@@ -900,17 +904,24 @@ function generateMethod$1({ node, name, tsResolver, zodResolver, baseURL, dataRe
900
904
  node,
901
905
  zodResolver
902
906
  });
907
+ const queryParamsLine = buildQueryParamsLine({
908
+ parser,
909
+ node,
910
+ zodResolver
911
+ });
903
912
  const formDataLine = buildFormDataLine(isFormData || isMultipleContentTypes && hasFormData, !!node.requestBody?.content?.[0]?.schema);
904
913
  const returnStatement = buildReturnStatement({
905
914
  dataReturnType,
906
915
  parser,
907
916
  node,
908
- zodResolver
917
+ zodResolver,
918
+ tsResolver
909
919
  });
910
920
  return `${jsdoc}async ${name}(${paramsSignature}) {\n${[
911
- `const { client: request = client, ${isMultipleContentTypes ? `contentType = ${JSON.stringify(contentType)}, ` : ""}...requestConfig } = mergeConfig(this.#config, config)`,
921
+ `const { client: request = client, ${isMultipleContentTypes ? `contentType = ${stringify(contentType)}, ` : ""}...requestConfig } = mergeConfig(this.#config, config)`,
912
922
  "",
913
923
  requestDataLine,
924
+ queryParamsLine,
914
925
  formDataLine,
915
926
  `const res = await request<${generics.join(", ")}>(${clientParams.toCall()})`,
916
927
  returnStatement
@@ -968,8 +979,13 @@ function resolveTypeImportNames$1(node, tsResolver) {
968
979
  return resolveOperationTypeNames(node, tsResolver, { order: "body-response-first" });
969
980
  }
970
981
  __name(resolveTypeImportNames$1, "resolveTypeImportNames");
971
- function resolveZodImportNames$1(node, zodResolver) {
972
- return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null].filter((n) => Boolean(n));
982
+ function resolveZodImportNames$1(node, zodResolver, parser) {
983
+ const { query: queryParams } = getOperationParameters(node);
984
+ return [
985
+ resolveResponseParser(parser) === "zod" ? zodResolver.resolveResponseName?.(node) : null,
986
+ resolveRequestParser(parser) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
987
+ resolveQueryParamsParser(parser) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null
988
+ ].filter((n) => Boolean(n));
973
989
  }
974
990
  __name(resolveZodImportNames$1, "resolveZodImportNames");
975
991
  /**
@@ -979,7 +995,7 @@ __name(resolveZodImportNames$1, "resolveZodImportNames");
979
995
  */
980
996
  const classClientGenerator = defineGenerator({
981
997
  name: "classClient",
982
- renderer: jsxRendererSync,
998
+ renderer: jsxRenderer,
983
999
  operations(nodes, ctx) {
984
1000
  const { config, driver, resolver, root } = ctx;
985
1001
  const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath, sdk } = ctx.options;
@@ -988,7 +1004,7 @@ const classClientGenerator = defineGenerator({
988
1004
  if (!pluginTs) return null;
989
1005
  const tsResolver = driver.getResolver(pluginTsName);
990
1006
  const tsPluginOptions = pluginTs.options;
991
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
1007
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
992
1008
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
993
1009
  function buildOperationData(node) {
994
1010
  const typeFile = tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
@@ -1013,7 +1029,7 @@ const classClientGenerator = defineGenerator({
1013
1029
  const controllers = nodes.reduce((acc, operationNode) => {
1014
1030
  if (!ast.isHttpOperationNode(operationNode)) return acc;
1015
1031
  const tag = operationNode.tags[0];
1016
- const groupName = tag ? group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag) : resolver.resolveGroupName("Client");
1032
+ const groupName = tag ? group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag) : resolver.resolveClassName("Client");
1017
1033
  if (!tag && !group) {
1018
1034
  const name = resolver.resolveClassName("ApiClient");
1019
1035
  const file = resolver.resolveFile({
@@ -1080,7 +1096,7 @@ const classClientGenerator = defineGenerator({
1080
1096
  const zodFilesByPath = /* @__PURE__ */ new Map();
1081
1097
  ops.forEach((op) => {
1082
1098
  if (!op.zodFile || !zodResolver) return;
1083
- const names = resolveZodImportNames$1(op.node, zodResolver);
1099
+ const names = resolveZodImportNames$1(op.node, zodResolver, parser);
1084
1100
  if (!zodImportsByFile.has(op.zodFile.path)) zodImportsByFile.set(op.zodFile.path, /* @__PURE__ */ new Set());
1085
1101
  const imports = zodImportsByFile.get(op.zodFile.path);
1086
1102
  names.forEach((n) => {
@@ -1095,7 +1111,7 @@ const classClientGenerator = defineGenerator({
1095
1111
  }
1096
1112
  const files = controllers.map(({ name, file, operations: ops }) => {
1097
1113
  const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops);
1098
- const { zodImportsByFile, zodFilesByPath } = parser === "zod" ? collectZodImports(ops) : {
1114
+ const { zodImportsByFile, zodFilesByPath } = isParserEnabled(parser) ? collectZodImports(ops) : {
1099
1115
  zodImportsByFile: /* @__PURE__ */ new Map(),
1100
1116
  zodFilesByPath: /* @__PURE__ */ new Map()
1101
1117
  };
@@ -1166,6 +1182,11 @@ const classClientGenerator = defineGenerator({
1166
1182
  root: file.path,
1167
1183
  path: path.resolve(root, ".kubb/config.ts")
1168
1184
  }),
1185
+ parser === "zod" && zodResolver && ops.some((op) => op.node.requestBody?.content?.[0]?.schema != null) && /* @__PURE__ */ jsx(File.Import, {
1186
+ name: ["z"],
1187
+ path: "zod",
1188
+ isTypeOnly: true
1189
+ }),
1169
1190
  Array.from(typeImportsByFile.entries()).map(([filePath, importSet]) => {
1170
1191
  const typeFile = typeFilesByPath.get(filePath);
1171
1192
  if (!typeFile) return null;
@@ -1178,7 +1199,7 @@ const classClientGenerator = defineGenerator({
1178
1199
  isTypeOnly: true
1179
1200
  }, filePath);
1180
1201
  }),
1181
- parser === "zod" && Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
1202
+ isParserEnabled(parser) && Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
1182
1203
  const zodFile = zodFilesByPath.get(filePath);
1183
1204
  if (!zodFile) return null;
1184
1205
  const importNames = Array.from(importSet).filter(Boolean);
@@ -1269,7 +1290,7 @@ const classClientGenerator = defineGenerator({
1269
1290
  */
1270
1291
  const clientGenerator = defineGenerator({
1271
1292
  name: "client",
1272
- renderer: jsxRendererSync,
1293
+ renderer: jsxRenderer,
1273
1294
  operation(node, ctx) {
1274
1295
  if (!ast.isHttpOperationNode(node)) return null;
1275
1296
  const { config, driver, resolver, root } = ctx;
@@ -1278,10 +1299,16 @@ const clientGenerator = defineGenerator({
1278
1299
  const pluginTs = driver.getPlugin(pluginTsName);
1279
1300
  if (!pluginTs) return null;
1280
1301
  const tsResolver = driver.getResolver(pluginTsName);
1281
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
1302
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
1282
1303
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1283
1304
  const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing });
1284
- const importedZodNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null].filter((name) => Boolean(name)) : [];
1305
+ const { query: queryParams } = getOperationParameters(node);
1306
+ const importedZodNames = zodResolver ? [
1307
+ resolveResponseParser(parser) === "zod" ? zodResolver.resolveResponseName?.(node) : null,
1308
+ resolveRequestParser(parser) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
1309
+ resolveQueryParamsParser(parser) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null
1310
+ ].filter((name) => Boolean(name)) : [];
1311
+ const zodRequestName = zodResolver && parser === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) ?? null : null;
1285
1312
  const meta = {
1286
1313
  name: resolver.resolveName(node.operationId),
1287
1314
  urlName: resolver.resolveUrlName(node),
@@ -1353,6 +1380,11 @@ const clientGenerator = defineGenerator({
1353
1380
  root: meta.file.path,
1354
1381
  path: path.resolve(root, ".kubb/config.ts")
1355
1382
  }),
1383
+ zodRequestName && /* @__PURE__ */ jsx(File.Import, {
1384
+ name: ["z"],
1385
+ path: "zod",
1386
+ isTypeOnly: true
1387
+ }),
1356
1388
  meta.fileZod && importedZodNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1357
1389
  name: importedZodNames,
1358
1390
  root: meta.file.path,
@@ -1402,7 +1434,7 @@ const clientGenerator = defineGenerator({
1402
1434
  */
1403
1435
  const groupedClientGenerator = defineGenerator({
1404
1436
  name: "groupedClient",
1405
- renderer: jsxRendererSync,
1437
+ renderer: jsxRenderer,
1406
1438
  operations(nodes, ctx) {
1407
1439
  const { config, resolver, root } = ctx;
1408
1440
  const { output, group } = ctx.options;
@@ -1485,29 +1517,7 @@ const groupedClientGenerator = defineGenerator({
1485
1517
  }
1486
1518
  });
1487
1519
  //#endregion
1488
- //#region src/components/Operations.tsx
1489
- function Operations({ name, nodes }) {
1490
- const operationsObject = {};
1491
- nodes.forEach((node) => {
1492
- if (!ast.isHttpOperationNode(node)) return;
1493
- operationsObject[node.operationId] = {
1494
- path: new URLPath(node.path).URL,
1495
- method: node.method.toLowerCase()
1496
- };
1497
- });
1498
- return /* @__PURE__ */ jsx(File.Source, {
1499
- name,
1500
- isExportable: true,
1501
- isIndexable: true,
1502
- children: /* @__PURE__ */ jsx(Const, {
1503
- name,
1504
- export: true,
1505
- children: JSON.stringify(operationsObject, void 0, 2)
1506
- })
1507
- });
1508
- }
1509
- //#endregion
1510
- //#region src/generators/operationsGenerator.tsx
1520
+ //#region src/generators/operationsGenerator.ts
1511
1521
  /**
1512
1522
  * Generates an `operations.ts` file that re-exports every operation grouped
1513
1523
  * by HTTP method. Enabled when `pluginClient({ operations: true })`. Useful
@@ -1516,7 +1526,6 @@ function Operations({ name, nodes }) {
1516
1526
  */
1517
1527
  const operationsGenerator = defineGenerator({
1518
1528
  name: "client",
1519
- renderer: jsxRendererSync,
1520
1529
  operations(nodes, ctx) {
1521
1530
  const { config, resolver, root } = ctx;
1522
1531
  const { output, group } = ctx.options;
@@ -1529,7 +1538,15 @@ const operationsGenerator = defineGenerator({
1529
1538
  output,
1530
1539
  group: group ?? void 0
1531
1540
  });
1532
- return /* @__PURE__ */ jsx(File, {
1541
+ const operationsObject = {};
1542
+ for (const node of nodes) {
1543
+ if (!ast.isHttpOperationNode(node)) continue;
1544
+ operationsObject[node.operationId] = {
1545
+ path: Url$1.toPath(node.path),
1546
+ method: node.method.toLowerCase()
1547
+ };
1548
+ }
1549
+ return [ast.createFile({
1533
1550
  baseName: file.baseName,
1534
1551
  path: file.path,
1535
1552
  meta: file.meta,
@@ -1549,11 +1566,17 @@ const operationsGenerator = defineGenerator({
1549
1566
  baseName: file.baseName
1550
1567
  }
1551
1568
  }),
1552
- children: /* @__PURE__ */ jsx(Operations, {
1569
+ sources: [ast.createSource({
1553
1570
  name,
1554
- nodes: nodes.filter(ast.isHttpOperationNode)
1555
- })
1556
- });
1571
+ isExportable: true,
1572
+ isIndexable: true,
1573
+ nodes: [ast.createConst({
1574
+ name,
1575
+ export: true,
1576
+ nodes: [ast.createText(JSON.stringify(operationsObject, void 0, 2))]
1577
+ })]
1578
+ })]
1579
+ })];
1557
1580
  }
1558
1581
  });
1559
1582
  //#endregion
@@ -1561,13 +1584,16 @@ const operationsGenerator = defineGenerator({
1561
1584
  const declarationPrinter = functionPrinter({ mode: "declaration" });
1562
1585
  function generateMethod({ node, name, tsResolver, zodResolver, baseURL, dataReturnType, parser, paramsType, paramsCasing, pathParamsType }) {
1563
1586
  if (!ast.isHttpOperationNode(node)) return "";
1564
- const path = new URLPath(node.path, { casing: paramsCasing });
1565
1587
  const { defaultContentType: contentType, isMultipleContentTypes, hasFormData } = getContentTypeInfo(node);
1566
1588
  const isFormData = !isMultipleContentTypes && contentType === "multipart/form-data";
1567
1589
  const { header: headerParams } = getOperationParameters(node);
1568
1590
  const headerParamsName = headerParams.length > 0 ? tsResolver.resolveHeaderParamsName(node, headerParams[0]) : null;
1569
1591
  const headers = isMultipleContentTypes ? headerParamsName ? ["...headers"] : [] : buildHeaders(contentType, !!headerParamsName);
1570
- const generics = buildGenerics(node, tsResolver);
1592
+ const generics = buildGenerics(node, tsResolver, {
1593
+ dataReturnType,
1594
+ zodResolver,
1595
+ parser
1596
+ });
1571
1597
  const paramsNode = buildClientParamsNode({
1572
1598
  paramsType,
1573
1599
  paramsCasing,
@@ -1577,15 +1603,18 @@ function generateMethod({ node, name, tsResolver, zodResolver, baseURL, dataRetu
1577
1603
  isConfigurable: true
1578
1604
  });
1579
1605
  const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
1606
+ const { query: queryParams } = getOperationParameters(node);
1607
+ const zodQueryParamsName = zodResolver && resolveQueryParamsParser(parser) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null;
1580
1608
  const clientParams = buildClassClientParams({
1581
1609
  node,
1582
- path,
1610
+ url: Url$1.toTemplateString(node.path, { casing: paramsCasing }),
1583
1611
  baseURL,
1584
1612
  tsResolver,
1585
1613
  isFormData,
1586
1614
  isMultipleContentTypes,
1587
1615
  hasFormData,
1588
- headers
1616
+ headers,
1617
+ zodQueryParamsName
1589
1618
  });
1590
1619
  const jsdoc = buildJSDoc(buildOperationComments(node, {
1591
1620
  link: "urlPath",
@@ -1597,17 +1626,24 @@ function generateMethod({ node, name, tsResolver, zodResolver, baseURL, dataRetu
1597
1626
  node,
1598
1627
  zodResolver
1599
1628
  });
1629
+ const queryParamsLine = buildQueryParamsLine({
1630
+ parser,
1631
+ node,
1632
+ zodResolver
1633
+ });
1600
1634
  const formDataLine = buildFormDataLine(isFormData || isMultipleContentTypes && hasFormData, !!node.requestBody?.content?.[0]?.schema);
1601
1635
  const returnStatement = buildReturnStatement({
1602
1636
  dataReturnType,
1603
1637
  parser,
1604
1638
  node,
1605
- zodResolver
1639
+ zodResolver,
1640
+ tsResolver
1606
1641
  });
1607
1642
  return `${jsdoc} static async ${name}(${paramsSignature}) {\n${[
1608
- `const { client: request = client, ${isMultipleContentTypes ? `contentType = ${JSON.stringify(contentType)}, ` : ""}...requestConfig } = mergeConfig(this.#config, config)`,
1643
+ `const { client: request = client, ${isMultipleContentTypes ? `contentType = ${stringify(contentType)}, ` : ""}...requestConfig } = mergeConfig(this.#config, config)`,
1609
1644
  "",
1610
1645
  requestDataLine,
1646
+ queryParamsLine,
1611
1647
  formDataLine,
1612
1648
  `const res = await request<${generics.join(", ")}>(${clientParams.toCall()})`,
1613
1649
  returnStatement
@@ -1638,8 +1674,13 @@ function StaticClassClient({ name, isExportable = true, isIndexable = true, oper
1638
1674
  function resolveTypeImportNames(node, tsResolver) {
1639
1675
  return resolveOperationTypeNames(node, tsResolver, { order: "body-response-first" });
1640
1676
  }
1641
- function resolveZodImportNames(node, zodResolver) {
1642
- return [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null].filter((n) => Boolean(n));
1677
+ function resolveZodImportNames(node, zodResolver, parser) {
1678
+ const { query: queryParams } = getOperationParameters(node);
1679
+ return [
1680
+ resolveResponseParser(parser) === "zod" ? zodResolver.resolveResponseName?.(node) : null,
1681
+ resolveRequestParser(parser) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
1682
+ resolveQueryParamsParser(parser) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null
1683
+ ].filter((n) => Boolean(n));
1643
1684
  }
1644
1685
  /**
1645
1686
  * Built-in `operations` generator for `@kubb/plugin-client` when
@@ -1649,7 +1690,7 @@ function resolveZodImportNames(node, zodResolver) {
1649
1690
  */
1650
1691
  const staticClassClientGenerator = defineGenerator({
1651
1692
  name: "staticClassClient",
1652
- renderer: jsxRendererSync,
1693
+ renderer: jsxRenderer,
1653
1694
  operations(nodes, ctx) {
1654
1695
  const { config, driver, resolver, root } = ctx;
1655
1696
  const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath } = ctx.options;
@@ -1658,7 +1699,7 @@ const staticClassClientGenerator = defineGenerator({
1658
1699
  if (!pluginTs) return null;
1659
1700
  const tsResolver = driver.getResolver(pluginTsName);
1660
1701
  const tsPluginOptions = pluginTs.options;
1661
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
1702
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
1662
1703
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1663
1704
  function buildOperationData(node) {
1664
1705
  const typeFile = tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
@@ -1683,7 +1724,7 @@ const staticClassClientGenerator = defineGenerator({
1683
1724
  const controllers = nodes.reduce((acc, operationNode) => {
1684
1725
  if (!ast.isHttpOperationNode(operationNode)) return acc;
1685
1726
  const tag = operationNode.tags[0];
1686
- const groupName = tag ? group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag) : resolver.resolveGroupName("Client");
1727
+ const groupName = tag ? group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag) : resolver.resolveClassName("Client");
1687
1728
  if (!tag && !group) {
1688
1729
  const name = resolver.resolveClassName("ApiClient");
1689
1730
  const file = resolver.resolveFile({
@@ -1748,7 +1789,7 @@ const staticClassClientGenerator = defineGenerator({
1748
1789
  const zodFilesByPath = /* @__PURE__ */ new Map();
1749
1790
  ops.forEach((op) => {
1750
1791
  if (!op.zodFile || !zodResolver) return;
1751
- const names = resolveZodImportNames(op.node, zodResolver);
1792
+ const names = resolveZodImportNames(op.node, zodResolver, parser);
1752
1793
  if (!zodImportsByFile.has(op.zodFile.path)) zodImportsByFile.set(op.zodFile.path, /* @__PURE__ */ new Set());
1753
1794
  const imports = zodImportsByFile.get(op.zodFile.path);
1754
1795
  names.forEach((n) => {
@@ -1763,7 +1804,7 @@ const staticClassClientGenerator = defineGenerator({
1763
1804
  }
1764
1805
  return /* @__PURE__ */ jsx(Fragment, { children: controllers.map(({ name, file, operations: ops }) => {
1765
1806
  const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops);
1766
- const { zodImportsByFile, zodFilesByPath } = parser === "zod" ? collectZodImports(ops) : {
1807
+ const { zodImportsByFile, zodFilesByPath } = isParserEnabled(parser) ? collectZodImports(ops) : {
1767
1808
  zodImportsByFile: /* @__PURE__ */ new Map(),
1768
1809
  zodFilesByPath: /* @__PURE__ */ new Map()
1769
1810
  };
@@ -1834,6 +1875,11 @@ const staticClassClientGenerator = defineGenerator({
1834
1875
  root: file.path,
1835
1876
  path: path.resolve(root, ".kubb/config.ts")
1836
1877
  }),
1878
+ parser === "zod" && zodResolver && ops.some((op) => op.node.requestBody?.content?.[0]?.schema != null) && /* @__PURE__ */ jsx(File.Import, {
1879
+ name: ["z"],
1880
+ path: "zod",
1881
+ isTypeOnly: true
1882
+ }),
1837
1883
  Array.from(typeImportsByFile.entries()).map(([filePath, importSet]) => {
1838
1884
  const typeFile = typeFilesByPath.get(filePath);
1839
1885
  if (!typeFile) return null;
@@ -1846,7 +1892,7 @@ const staticClassClientGenerator = defineGenerator({
1846
1892
  isTypeOnly: true
1847
1893
  }, filePath);
1848
1894
  }),
1849
- parser === "zod" && Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
1895
+ isParserEnabled(parser) && Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
1850
1896
  const zodFile = zodFilesByPath.get(filePath);
1851
1897
  if (!zodFile) return null;
1852
1898
  const importNames = Array.from(importSet).filter(Boolean);
@@ -1885,6 +1931,7 @@ const staticClassClientGenerator = defineGenerator({
1885
1931
  *
1886
1932
  * resolverClient.default('list pets', 'function') // 'listPets'
1887
1933
  * resolverClient.resolveClassName('pet') // 'Pet'
1934
+ * resolverClient.resolveGroupName('pet') // 'PetClient'
1888
1935
  * resolverClient.resolveUrlName(operationNode) // 'getShowPetByIdUrl'
1889
1936
  * ```
1890
1937
  */
@@ -1892,8 +1939,8 @@ const resolverClient = defineResolver(() => ({
1892
1939
  name: "default",
1893
1940
  pluginName: "plugin-client",
1894
1941
  default(name, type) {
1895
- const resolved = camelCase(name, { isFile: type === "file" });
1896
- return type === "file" ? resolved : ensureValidVarName(resolved);
1942
+ if (type === "file") return toFilePath(name);
1943
+ return ensureValidVarName(camelCase(name));
1897
1944
  },
1898
1945
  resolveName(name) {
1899
1946
  return this.default(name, "function");
@@ -1905,7 +1952,7 @@ const resolverClient = defineResolver(() => ({
1905
1952
  return ensureValidVarName(pascalCase(name));
1906
1953
  },
1907
1954
  resolveGroupName(name) {
1908
- return ensureValidVarName(pascalCase(name));
1955
+ return ensureValidVarName(pascalCase(`${name} Client`));
1909
1956
  },
1910
1957
  resolveClientPropertyName(name) {
1911
1958
  return ensureValidVarName(camelCase(name));
@@ -1950,7 +1997,7 @@ const pluginClientName = "plugin-client";
1950
1997
  const pluginClient = definePlugin((options) => {
1951
1998
  const { output = {
1952
1999
  path: "clients",
1953
- barrelType: "named"
2000
+ barrel: { type: "named" }
1954
2001
  }, 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 = false, client = "axios", importPath, bundle = false, sdk, baseURL, resolver: userResolver, transformer: userTransformer } = options;
1955
2002
  const resolvedImportPath = importPath ?? (!bundle ? `@kubb/plugin-client/clients/${client}` : void 0);
1956
2003
  const selectedGenerators = options.generators ?? [
@@ -1958,11 +2005,11 @@ const pluginClient = definePlugin((options) => {
1958
2005
  group && clientType === "function" ? groupedClientGenerator : null,
1959
2006
  operations ? operationsGenerator : null
1960
2007
  ].filter((x) => Boolean(x));
1961
- const groupConfig = createGroupConfig(group, { suffix: "Controller" });
2008
+ const groupConfig = createGroupConfig(group);
1962
2009
  return {
1963
2010
  name: pluginClientName,
1964
2011
  options,
1965
- dependencies: [pluginTsName, parser === "zod" ? pluginZodName : null].filter((dependency) => Boolean(dependency)),
2012
+ dependencies: [pluginTsName, isParserEnabled(parser) ? pluginZodName : null].filter((dependency) => Boolean(dependency)),
1966
2013
  hooks: { "kubb:plugin:setup"(ctx) {
1967
2014
  const resolver = userResolver ? {
1968
2015
  ...resolverClient,
@@ -2020,6 +2067,6 @@ const pluginClient = definePlugin((options) => {
2020
2067
  };
2021
2068
  });
2022
2069
  //#endregion
2023
- export { Client, classClientGenerator, clientGenerator, pluginClient as default, pluginClient, groupedClientGenerator, operationsGenerator, pluginClientName, resolverClient, staticClassClientGenerator };
2070
+ export { Client, classClientGenerator, clientGenerator, pluginClient as default, pluginClient, groupedClientGenerator, isParserEnabled, operationsGenerator, pluginClientName, resolveQueryParamsParser, resolveRequestParser, resolveResponseParser, resolverClient, staticClassClientGenerator };
2024
2071
 
2025
2072
  //# sourceMappingURL=index.js.map