@kubb/plugin-vue-query 5.0.0-beta.64 → 5.0.0-beta.73

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
@@ -1,14 +1,38 @@
1
- import "./chunk-C0LytTxp.js";
2
- import { m as camelCase, s as queryKeyTransformer, u as mutationKeyTransformer } from "./components-CAlEf7Oh.js";
3
- import { n as mutationGenerator, r as infiniteQueryGenerator, t as queryGenerator } from "./generators-fWBjs0CN.js";
1
+ import "./rolldown-runtime-C0LytTxp.js";
4
2
  import path from "node:path";
5
- import { ast, definePlugin, defineResolver } from "@kubb/core";
6
- import { isParserEnabled, pluginClientName } from "@kubb/plugin-client";
7
- import { source } from "@kubb/plugin-client/templates/clients/axios.source";
8
- import { source as source$1 } from "@kubb/plugin-client/templates/clients/fetch.source";
9
- import { source as source$2 } from "@kubb/plugin-client/templates/config.source";
10
- import { pluginTsName } from "@kubb/plugin-ts";
3
+ import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
4
+ import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, createTypeLiteral, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
11
5
  import { pluginZodName } from "@kubb/plugin-zod";
6
+ import { File, Function, Type, jsxRenderer } from "@kubb/renderer-jsx";
7
+ import { Fragment, jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
8
+ import { getNestedAccessor } from "@kubb/ast/utils";
9
+ //#region ../../internals/utils/src/casing.ts
10
+ /**
11
+ * Shared implementation for camelCase and PascalCase conversion.
12
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
13
+ * and capitalizes each word according to `pascal`.
14
+ *
15
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
16
+ */
17
+ function toCamelOrPascal(text, pascal) {
18
+ 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) => {
19
+ if (word.length > 1 && word === word.toUpperCase()) return word;
20
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
21
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
22
+ }
23
+ /**
24
+ * Converts `text` to camelCase.
25
+ *
26
+ * @example Word boundaries
27
+ * `camelCase('hello-world') // 'helloWorld'`
28
+ *
29
+ * @example With a prefix
30
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
31
+ */
32
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
33
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
34
+ }
35
+ //#endregion
12
36
  //#region ../../internals/utils/src/fs.ts
13
37
  /**
14
38
  * Builds a nested file path from a dotted name. Splits on dots that precede a letter
@@ -34,6 +58,393 @@ function toFilePath(name, caseLast = camelCase) {
34
58
  return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
35
59
  }
36
60
  //#endregion
61
+ //#region ../../internals/utils/src/reserved.ts
62
+ /**
63
+ * JavaScript and Java reserved words.
64
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
65
+ */
66
+ const reservedWords = new Set([
67
+ "abstract",
68
+ "arguments",
69
+ "boolean",
70
+ "break",
71
+ "byte",
72
+ "case",
73
+ "catch",
74
+ "char",
75
+ "class",
76
+ "const",
77
+ "continue",
78
+ "debugger",
79
+ "default",
80
+ "delete",
81
+ "do",
82
+ "double",
83
+ "else",
84
+ "enum",
85
+ "eval",
86
+ "export",
87
+ "extends",
88
+ "false",
89
+ "final",
90
+ "finally",
91
+ "float",
92
+ "for",
93
+ "function",
94
+ "goto",
95
+ "if",
96
+ "implements",
97
+ "import",
98
+ "in",
99
+ "instanceof",
100
+ "int",
101
+ "interface",
102
+ "let",
103
+ "long",
104
+ "native",
105
+ "new",
106
+ "null",
107
+ "package",
108
+ "private",
109
+ "protected",
110
+ "public",
111
+ "return",
112
+ "short",
113
+ "static",
114
+ "super",
115
+ "switch",
116
+ "synchronized",
117
+ "this",
118
+ "throw",
119
+ "throws",
120
+ "transient",
121
+ "true",
122
+ "try",
123
+ "typeof",
124
+ "var",
125
+ "void",
126
+ "volatile",
127
+ "while",
128
+ "with",
129
+ "yield",
130
+ "Array",
131
+ "Date",
132
+ "hasOwnProperty",
133
+ "Infinity",
134
+ "isFinite",
135
+ "isNaN",
136
+ "isPrototypeOf",
137
+ "length",
138
+ "Math",
139
+ "name",
140
+ "NaN",
141
+ "Number",
142
+ "Object",
143
+ "prototype",
144
+ "String",
145
+ "toString",
146
+ "undefined",
147
+ "valueOf"
148
+ ]);
149
+ /**
150
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * isValidVarName('status') // true
155
+ * isValidVarName('class') // false (reserved word)
156
+ * isValidVarName('42foo') // false (starts with digit)
157
+ * ```
158
+ */
159
+ function isValidVarName(name) {
160
+ if (!name || reservedWords.has(name)) return false;
161
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
162
+ }
163
+ //#endregion
164
+ //#region ../../internals/utils/src/url.ts
165
+ function transformParam(raw, casing) {
166
+ const param = isValidVarName(raw) ? raw : camelCase(raw);
167
+ return casing === "camelcase" ? camelCase(param) : param;
168
+ }
169
+ function toParamsObject(path, { replacer, casing } = {}) {
170
+ const params = {};
171
+ for (const match of path.matchAll(/\{([^}]+)\}/g)) {
172
+ const param = transformParam(match[1], casing);
173
+ const key = replacer ? replacer(param) : param;
174
+ params[key] = key;
175
+ }
176
+ return Object.keys(params).length > 0 ? params : null;
177
+ }
178
+ /**
179
+ * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.
180
+ */
181
+ var Url = class Url {
182
+ /**
183
+ * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
184
+ *
185
+ * @example
186
+ * Url.canParse('https://petstore.swagger.io/v2') // true
187
+ * Url.canParse('/pet/{petId}') // false
188
+ */
189
+ static canParse(url, base) {
190
+ return URL.canParse(url, base);
191
+ }
192
+ /**
193
+ * Converts an OpenAPI/Swagger path to Express-style colon syntax.
194
+ *
195
+ * @example
196
+ * Url.toPath('/pet/{petId}') // '/pet/:petId'
197
+ */
198
+ static toPath(path) {
199
+ return path.replace(/\{([^}]+)\}/g, ":$1");
200
+ }
201
+ /**
202
+ * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
203
+ * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,
204
+ * and `casing` controls parameter identifier casing.
205
+ *
206
+ * @example
207
+ * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
208
+ *
209
+ * @example
210
+ * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
211
+ */
212
+ static toTemplateString(path, { prefix, replacer, casing } = {}) {
213
+ const result = path.split(/\{([^}]+)\}/).map((part, i) => {
214
+ if (i % 2 === 0) return part;
215
+ const param = transformParam(part, casing);
216
+ return `\${${replacer ? replacer(param) : param}}`;
217
+ }).join("");
218
+ return `\`${prefix ?? ""}${result}\``;
219
+ }
220
+ /**
221
+ * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
222
+ * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
223
+ * names are camelCased to match the generated `path` type, and `prefix` is prepended inside the
224
+ * literal. Shared by the client and cypress generators that pass a grouped `path` object.
225
+ *
226
+ * @example
227
+ * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
228
+ */
229
+ static toGroupedTemplateString(path, { prefix } = {}) {
230
+ return Url.toTemplateString(path, {
231
+ prefix,
232
+ casing: "camelcase",
233
+ replacer: (name) => `path.${name}`
234
+ });
235
+ }
236
+ /**
237
+ * Returns the path and its extracted params as a structured `URLObject`, or as a stringified
238
+ * expression when `stringify` is set.
239
+ *
240
+ * @example
241
+ * Url.toObject('/pet/{petId}')
242
+ * // { url: '/pet/:petId', params: { petId: 'petId' } }
243
+ */
244
+ static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
245
+ const object = {
246
+ url: type === "path" ? Url.toPath(path) : Url.toTemplateString(path, {
247
+ replacer,
248
+ casing
249
+ }),
250
+ params: toParamsObject(path, {
251
+ replacer,
252
+ casing
253
+ })
254
+ };
255
+ if (stringify) {
256
+ if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
257
+ if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
258
+ return `{ url: '${object.url}' }`;
259
+ }
260
+ return object;
261
+ }
262
+ };
263
+ //#endregion
264
+ //#region ../../internals/shared/src/params.ts
265
+ const caseParamsCache = /* @__PURE__ */ new WeakMap();
266
+ /**
267
+ * Applies camelCase to parameter names and returns a new array without mutating the input.
268
+ *
269
+ * Run it before handing parameters to schema builders so output property keys get the right casing
270
+ * while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
271
+ * original array is returned unchanged. Results are cached per input array.
272
+ */
273
+ function caseParams(params, casing) {
274
+ if (!casing) return params;
275
+ const cached = caseParamsCache.get(params);
276
+ if (cached) return cached;
277
+ const result = params.map((param) => ({
278
+ ...param,
279
+ name: camelCase(param.name)
280
+ }));
281
+ caseParamsCache.set(params, result);
282
+ return result;
283
+ }
284
+ //#endregion
285
+ //#region ../../internals/shared/src/operation.ts
286
+ /**
287
+ * Builds the `ResolverFileParams` every operation generator passes to
288
+ * `resolver.resolveFile`: a file named `name`, tagged by the operation's first
289
+ * tag (or `'default'`), at the operation's path. Centralizes the entry object
290
+ * that was repeated at dozens of call sites across the client and query plugins.
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })
295
+ * ```
296
+ */
297
+ function operationFileEntry(node, name, extname = ".ts") {
298
+ return {
299
+ name,
300
+ extname,
301
+ tag: node.tags[0] ?? "default",
302
+ path: node.path
303
+ };
304
+ }
305
+ function getOperationLink(node, link) {
306
+ if (!link) return null;
307
+ if (typeof link === "function") return link(node) ?? null;
308
+ if (link === "urlPath") return node.path ? `{@link ${Url.toPath(node.path)}}` : null;
309
+ return node.path ? `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}` : null;
310
+ }
311
+ function getContentTypeInfo(node) {
312
+ const contentTypes = node.requestBody?.content?.map((e) => e.contentType) ?? [];
313
+ const isMultipleContentTypes = contentTypes.length > 1;
314
+ return {
315
+ contentTypes,
316
+ isMultipleContentTypes,
317
+ contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
318
+ defaultContentType: contentTypes[0] ?? "application/json",
319
+ hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
320
+ };
321
+ }
322
+ function buildRequestConfigType(node) {
323
+ const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node);
324
+ const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
325
+ const contentTypeProp = isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null;
326
+ return contentTypeProp ? `${configType} & { ${contentTypeProp} }` : configType;
327
+ }
328
+ /**
329
+ * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
330
+ * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a
331
+ * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a
332
+ * content type for.
333
+ */
334
+ function buildClientOptionType() {
335
+ return `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
336
+ }
337
+ /**
338
+ * Which of the grouped request options an operation carries.
339
+ */
340
+ function getRequestGroups(node) {
341
+ const { path, query, header } = getOperationParameters(node);
342
+ return {
343
+ path: path.length > 0,
344
+ query: query.length > 0,
345
+ body: Boolean(node.requestBody?.content?.[0]?.schema),
346
+ headers: header.length > 0
347
+ };
348
+ }
349
+ /**
350
+ * Resolves which grouped request options an operation carries together with whether each group
351
+ * holds a required member. The grouped parameter stays optional only when nothing inside it is
352
+ * required, matching the generated `RequestConfig` type.
353
+ */
354
+ function getRequestGroupOptionality(node) {
355
+ const groups = getRequestGroups(node);
356
+ const { path, query, header } = getOperationParameters(node);
357
+ const hasRequiredPath = path.some((param) => param.required);
358
+ const hasRequiredQuery = query.some((param) => param.required);
359
+ const hasRequiredHeader = header.some((param) => param.required);
360
+ return {
361
+ groups,
362
+ hasRequiredPath,
363
+ hasRequiredQuery,
364
+ hasRequiredHeader,
365
+ isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body
366
+ };
367
+ }
368
+ function buildOperationComments(node, options = {}) {
369
+ const { link = "pathTemplate", linkPosition = "afterDeprecated", splitLines = false } = options;
370
+ const linkComment = getOperationLink(node, link);
371
+ const filteredComments = (linkPosition === "beforeDeprecated" ? [
372
+ node.description && `@description ${node.description}`,
373
+ node.summary && `@summary ${node.summary}`,
374
+ linkComment,
375
+ node.deprecated && "@deprecated"
376
+ ] : [
377
+ node.description && `@description ${node.description}`,
378
+ node.summary && `@summary ${node.summary}`,
379
+ node.deprecated && "@deprecated",
380
+ linkComment
381
+ ]).filter((comment) => Boolean(comment));
382
+ if (!splitLines) return filteredComments;
383
+ return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
384
+ }
385
+ function getOperationParameters(node, options = {}) {
386
+ const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
387
+ return {
388
+ path: params.filter((param) => param.in === "path"),
389
+ query: params.filter((param) => param.in === "query"),
390
+ header: params.filter((param) => param.in === "header"),
391
+ cookie: params.filter((param) => param.in === "cookie")
392
+ };
393
+ }
394
+ function getStatusCodeNumber(statusCode) {
395
+ const code = Number(statusCode);
396
+ return Number.isNaN(code) ? null : code;
397
+ }
398
+ function isSuccessStatusCode(statusCode) {
399
+ const code = getStatusCodeNumber(statusCode);
400
+ return code !== null && code >= 200 && code < 300;
401
+ }
402
+ function isErrorStatusCode(statusCode) {
403
+ const code = getStatusCodeNumber(statusCode);
404
+ return code !== null && code >= 400;
405
+ }
406
+ function resolveErrorNames(node, resolver) {
407
+ return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
408
+ }
409
+ function resolveSuccessNames(node, resolver) {
410
+ return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
411
+ }
412
+ function resolveStatusCodeNames(node, resolver) {
413
+ return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
414
+ }
415
+ const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
416
+ function resolveOperationTypeNames(node, resolver, options = {}) {
417
+ const cacheKey = `${node.operationId}\0${options.paramsCasing ?? ""}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
418
+ let byResolver = typeNamesByResolver.get(resolver);
419
+ if (byResolver) {
420
+ const cached = byResolver.get(cacheKey);
421
+ if (cached) return cached;
422
+ } else {
423
+ byResolver = /* @__PURE__ */ new Map();
424
+ typeNamesByResolver.set(resolver, byResolver);
425
+ }
426
+ const { path, query, header } = getOperationParameters(node, { paramsCasing: options.paramsCasing });
427
+ const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
428
+ const exclude = new Set(options.exclude ?? []);
429
+ const paramNames = options.includeParams === false ? [] : [
430
+ ...path.map((param) => resolver.resolvePathParamsName(node, param)),
431
+ ...query.map((param) => resolver.resolveQueryParamsName(node, param)),
432
+ ...header.map((param) => resolver.resolveHeaderParamsName(node, param))
433
+ ];
434
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)];
435
+ const result = (options.order === "body-response-first" ? [
436
+ ...bodyAndResponseNames,
437
+ ...paramNames,
438
+ ...responseStatusNames
439
+ ] : [
440
+ ...paramNames,
441
+ ...bodyAndResponseNames,
442
+ ...responseStatusNames
443
+ ]).filter((name) => Boolean(name) && !exclude.has(name));
444
+ byResolver.set(cacheKey, result);
445
+ return result;
446
+ }
447
+ //#endregion
37
448
  //#region ../../internals/shared/src/group.ts
38
449
  /**
39
450
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -65,6 +476,1183 @@ function createGroupConfig(group) {
65
476
  };
66
477
  }
67
478
  //#endregion
479
+ //#region ../../internals/client/src/builders/parser.ts
480
+ /**
481
+ * Returns `true` when any direction of the parser uses zod (used for dependency checks).
482
+ */
483
+ function isParserEnabled(parser) {
484
+ if (!parser) return false;
485
+ if (parser === "zod") return true;
486
+ return Boolean(parser.request || parser.response);
487
+ }
488
+ //#endregion
489
+ //#region ../../internals/client/src/resolveClient.ts
490
+ /**
491
+ * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
492
+ * operation, shared so the selection rules and diagnostics stay in one place.
493
+ *
494
+ * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered
495
+ * contract client plugin (plugin-fetch or plugin-axios) and never emits its own inline client:
496
+ *
497
+ * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
498
+ * imports and calls them.
499
+ * - `error` — no client plugin is registered, several are registered without a selector, or the
500
+ * requested one is missing.
501
+ *
502
+ * The `client` string selects explicitly (`'fetch'` / `'axios'`); when it is unset a lone registered
503
+ * contract client plugin is picked up automatically.
504
+ */
505
+ const pluginFetchName = "plugin-fetch";
506
+ const pluginAxiosName = "plugin-axios";
507
+ const selectorToPlugin = {
508
+ fetch: pluginFetchName,
509
+ axios: pluginAxiosName
510
+ };
511
+ const contractPlugins = [pluginFetchName, pluginAxiosName];
512
+ /**
513
+ * Applies the `client` resolution rules. See the module comment for the strategy shape.
514
+ *
515
+ * @example
516
+ * ```ts
517
+ * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })
518
+ * // { kind: 'contract', pluginName: 'plugin-fetch' }
519
+ * ```
520
+ *
521
+ * @example
522
+ * ```ts
523
+ * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
524
+ * // { kind: 'error', message: 'No client plugin is registered…' }
525
+ * ```
526
+ */
527
+ function resolveClient(options) {
528
+ const { client, pluginNames } = options;
529
+ const has = (name) => pluginNames.includes(name);
530
+ if (client === "fetch" || client === "axios") {
531
+ const pluginName = selectorToPlugin[client];
532
+ if (!has(pluginName)) return {
533
+ kind: "error",
534
+ message: `\`client: '${client}'\` is set but \`@kubb/plugin-${client}\` is not registered in \`plugins\`. Add it, or drop \`client\` to use a different client plugin.`
535
+ };
536
+ return {
537
+ kind: "contract",
538
+ pluginName
539
+ };
540
+ }
541
+ const registered = contractPlugins.filter(has);
542
+ if (registered.length === 1) return {
543
+ kind: "contract",
544
+ pluginName: registered[0]
545
+ };
546
+ if (registered.length > 1) return {
547
+ kind: "error",
548
+ message: `Multiple client plugins are registered (${registered.map((name) => `\`@kubb/${name}\``).join(", ")}). Set \`client: 'fetch' | 'axios'\` to choose which client the hooks call, or register a single client plugin.`
549
+ };
550
+ return {
551
+ kind: "error",
552
+ message: "No client plugin is registered. Add `@kubb/plugin-axios` or `@kubb/plugin-fetch` to `plugins` so the generated code has an HTTP client to call."
553
+ };
554
+ }
555
+ //#endregion
556
+ //#region ../../internals/client/src/resolveClientOperation.ts
557
+ /**
558
+ * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up
559
+ * the registered contract client plugin's resolver and output. Works for any contract client plugin
560
+ * (plugin-fetch or plugin-axios). Returns `null` when no contract plugin is in play (the inline
561
+ * path). The plugin injects `.kubb/client.ts` at the global output root, the same path consumers
562
+ * read `RequestConfig` / `ResponseErrorConfig` from.
563
+ */
564
+ function resolveClientOperation(options) {
565
+ const { clientPlugin, driver, node, root, output } = options;
566
+ if (!clientPlugin) return null;
567
+ const resolver = driver.getResolver(clientPlugin.pluginName);
568
+ if (!resolver) return null;
569
+ const plugin = driver.getPlugin(clientPlugin.pluginName);
570
+ const file = resolver.resolveFile(operationFileEntry(node, node.operationId), {
571
+ root,
572
+ output: plugin?.options?.output ?? output,
573
+ group: plugin?.options?.group ?? void 0
574
+ });
575
+ return {
576
+ name: resolver.resolveName(node.operationId),
577
+ path: file.path,
578
+ clientPath: path.resolve(root, ".kubb/client.ts")
579
+ };
580
+ }
581
+ //#endregion
582
+ //#region ../../internals/tanstack-query/src/components/MutationKey.tsx
583
+ const declarationPrinter$7 = functionPrinter({ mode: "declaration" });
584
+ const mutationKeyTransformer = ({ node }) => {
585
+ if (!node.path) return [];
586
+ return [`{ url: '${Url.toPath(node.path)}' }`];
587
+ };
588
+ function MutationKey({ name, node, transformer }) {
589
+ const paramsNode = createFunctionParameters({ params: [] });
590
+ const paramsSignature = declarationPrinter$7.print(paramsNode) ?? "";
591
+ const keys = (transformer ?? mutationKeyTransformer)({
592
+ node,
593
+ casing: "camelcase"
594
+ });
595
+ return /* @__PURE__ */ jsx(File.Source, {
596
+ name,
597
+ isExportable: true,
598
+ isIndexable: true,
599
+ children: /* @__PURE__ */ jsx(Function.Arrow, {
600
+ name,
601
+ export: true,
602
+ params: paramsSignature,
603
+ singleLine: true,
604
+ children: `[${keys.join(", ")}] as const`
605
+ })
606
+ });
607
+ }
608
+ //#endregion
609
+ //#region ../../internals/tanstack-query/src/utils.ts
610
+ /**
611
+ * The grouped request options, ordered for both the destructured signature and the
612
+ * call passed to the underlying client.
613
+ */
614
+ const requestGroupOrder$1 = [
615
+ "path",
616
+ "query",
617
+ "body",
618
+ "headers"
619
+ ];
620
+ /**
621
+ * Builds the grouped `{ path, query, body, headers }` parameter that mirrors the client
622
+ * function signature. Only the groups the operation carries are emitted, typed from the
623
+ * operation's `RequestConfig`. `keys` narrows the emitted groups, used by the query key which
624
+ * never carries `headers`.
625
+ *
626
+ * By default the whole group is typed as the single `RequestConfig` reference. When
627
+ * `memberTypeWrapper` is set, each group is emitted as its own member typed from the matching
628
+ * `RequestConfig['<group>']` slice and wrapped, used by vue-query to apply
629
+ * `MaybeRefOrGetter` per group.
630
+ */
631
+ function buildGroupedRequestParam(node, options) {
632
+ const { resolver, keys = requestGroupOrder$1, memberTypeWrapper } = options;
633
+ const { groups, hasRequiredPath, hasRequiredQuery, hasRequiredHeader } = getRequestGroupOptionality(node);
634
+ const names = keys.filter((key) => groups[key]);
635
+ if (names.length === 0) return null;
636
+ const requiredByGroup = {
637
+ path: hasRequiredPath,
638
+ query: hasRequiredQuery,
639
+ body: groups.body,
640
+ headers: hasRequiredHeader
641
+ };
642
+ const isOptional = names.every((name) => !requiredByGroup[name]);
643
+ const requestConfigName = resolver.resolveRequestConfigName(node);
644
+ const omittedKeys = requestGroupOrder$1.filter((key) => !keys.includes(key));
645
+ const requestConfigType = omittedKeys.length > 0 ? `Omit<${requestConfigName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : requestConfigName;
646
+ if (memberTypeWrapper) {
647
+ const members = names.map((name) => ({
648
+ name,
649
+ type: memberTypeWrapper(`${requestConfigType}['${name}']`),
650
+ optional: !requiredByGroup[name]
651
+ }));
652
+ return createFunctionParameter({
653
+ name: createObjectBindingPattern({ elements: names.map((name) => ({ name })) }),
654
+ type: createTypeLiteral({ members }),
655
+ optional: false,
656
+ ...isOptional ? { default: "{}" } : {}
657
+ });
658
+ }
659
+ return createFunctionParameter({
660
+ name: createObjectBindingPattern({ elements: names.map((name) => ({ name })) }),
661
+ type: requestConfigType,
662
+ optional: false,
663
+ ...isOptional ? { default: "{}" } : {}
664
+ });
665
+ }
666
+ /**
667
+ * Builds the shared `({ path, query, body, headers }, config = {})` parameter list for a
668
+ * TanStack query-options function. The leading parameter mirrors the client signature, and the
669
+ * trailing `config` is a partial `RequestConfig` minus the grouped data-shape keys, which are passed
670
+ * explicitly. Framework plugins wrap the result when needed, for example vue-query applies `MaybeRefOrGetter`.
671
+ */
672
+ function buildQueryOptionsParams(node, options) {
673
+ const { resolver, memberTypeWrapper } = options;
674
+ return createFunctionParameters({ params: [buildGroupedRequestParam(node, {
675
+ resolver,
676
+ memberTypeWrapper
677
+ }), createFunctionParameter({
678
+ name: "config",
679
+ type: `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`,
680
+ default: "{}"
681
+ })].filter((param) => param !== null) });
682
+ }
683
+ /**
684
+ * Returns `'zod'` when response-direction parsing is enabled.
685
+ * The string shorthand `'zod'` also enables response parsing.
686
+ */
687
+ function resolveResponseParser(parser) {
688
+ if (!parser) return null;
689
+ if (parser === "zod") return "zod";
690
+ return parser.response ?? null;
691
+ }
692
+ /**
693
+ * Returns `'zod'` when request body parsing is enabled.
694
+ * The string shorthand `'zod'` also enables request body parsing (existing behavior).
695
+ */
696
+ function resolveRequestParser(parser) {
697
+ if (!parser) return null;
698
+ if (parser === "zod") return "zod";
699
+ return parser.request ?? null;
700
+ }
701
+ /**
702
+ * Returns `'zod'` when query-params parsing is enabled.
703
+ * Only the object form `{ request: 'zod' }` enables this. `parser: 'zod'` does not.
704
+ */
705
+ function resolveQueryParamsParser(parser) {
706
+ if (!parser || parser === "zod") return null;
707
+ return parser.request ?? null;
708
+ }
709
+ /**
710
+ * Collects the Zod schema import names for an operation based on the active parser directions.
711
+ *
712
+ * - `parser: 'zod'`: response and request body names (backward-compatible behavior).
713
+ * - `parser: { request: 'zod' }`: request body and query params names.
714
+ * - `parser: { response: 'zod' }`: response name only.
715
+ * - `parser: { request: 'zod', response: 'zod' }`: all three.
716
+ *
717
+ * Returns an empty array when no resolver is provided or `parser` is falsy.
718
+ */
719
+ function resolveZodSchemaNames(node, zodResolver, parser) {
720
+ if (!zodResolver || !parser) return [];
721
+ const { query: queryParams } = getOperationParameters(node, { paramsCasing: "original" });
722
+ return [
723
+ resolveResponseParser(parser) === "zod" ? zodResolver.resolveResponseName?.(node) : null,
724
+ resolveRequestParser(parser) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
725
+ resolveQueryParamsParser(parser) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null
726
+ ].filter((n) => Boolean(n));
727
+ }
728
+ functionPrinter({ mode: "declaration" });
729
+ const queryKeyTransformer = ({ node }) => {
730
+ if (!node.path) return [];
731
+ const hasPathParams = getOperationParameters(node).path.length > 0;
732
+ const hasQueryParams = getOperationParameters(node).query.length > 0;
733
+ const hasRequestBody = !!node.requestBody?.content?.[0]?.schema;
734
+ return [
735
+ hasPathParams ? `{ url: '${Url.toPath(node.path)}', params: path }` : `{ url: '${Url.toPath(node.path)}' }`,
736
+ hasQueryParams ? "...(query ? [query] : [])" : null,
737
+ hasRequestBody ? "...(body ? [body] : [])" : null
738
+ ].filter(Boolean);
739
+ };
740
+ //#endregion
741
+ //#region src/utils.ts
742
+ /**
743
+ * Wraps a type string in `MaybeRefOrGetter<…>` so a vue-query signature accepts refs or getters.
744
+ */
745
+ function maybeRefOrGetter(type) {
746
+ return `MaybeRefOrGetter<${type}>`;
747
+ }
748
+ const requestGroupOrder = [
749
+ "path",
750
+ "query",
751
+ "body",
752
+ "headers"
753
+ ];
754
+ /**
755
+ * Builds the call to a contract client `<op>` function inside a vue-query composable body. The
756
+ * function takes a single grouped options object, so `config` is spread first, then the operation's
757
+ * request groups are unwrapped with `toValue()`, then the abort `signal` for queries, with
758
+ * `throwOnError: true` pinned last so a caller's config can't flip the query's error semantics.
759
+ * Mutations omit the `signal`.
760
+ */
761
+ function buildVueClientCall(node, options) {
762
+ const { clientName, signal = false } = options;
763
+ const groups = getRequestGroups(node);
764
+ return `${clientName}({ ${[
765
+ "...config",
766
+ ...requestGroupOrder.filter((key) => groups[key]).map((name) => `${name}: toValue(${name})`),
767
+ signal ? "signal: config.signal ?? signal" : null,
768
+ "throwOnError: true"
769
+ ].filter((part) => part !== null).join(", ")} })`;
770
+ }
771
+ //#endregion
772
+ //#region src/components/QueryKey.tsx
773
+ const declarationPrinter$5 = functionPrinter({ mode: "declaration" });
774
+ function buildQueryKeyParamsNode(node, options) {
775
+ const groupedParam = buildGroupedRequestParam(node, {
776
+ resolver: options.resolver,
777
+ keys: [
778
+ "path",
779
+ "query",
780
+ "body"
781
+ ],
782
+ memberTypeWrapper: maybeRefOrGetter
783
+ });
784
+ return createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
785
+ }
786
+ function QueryKey({ name, node, tsResolver, typeName, transformer }) {
787
+ const paramsNode = buildQueryKeyParamsNode(node, { resolver: tsResolver });
788
+ const paramsSignature = declarationPrinter$5.print(paramsNode) ?? "";
789
+ const keys = (transformer ?? queryKeyTransformer)({
790
+ node,
791
+ casing: "camelcase"
792
+ });
793
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File.Source, {
794
+ name,
795
+ isExportable: true,
796
+ isIndexable: true,
797
+ children: /* @__PURE__ */ jsx(Function.Arrow, {
798
+ name,
799
+ export: true,
800
+ params: paramsSignature,
801
+ singleLine: true,
802
+ children: `[${keys.join(", ")}] as const`
803
+ })
804
+ }), /* @__PURE__ */ jsx(File.Source, {
805
+ name: typeName,
806
+ isExportable: true,
807
+ isIndexable: true,
808
+ isTypeOnly: true,
809
+ children: /* @__PURE__ */ jsx(Type, {
810
+ name: typeName,
811
+ export: true,
812
+ children: `ReturnType<typeof ${name}>`
813
+ })
814
+ })] });
815
+ }
816
+ //#endregion
817
+ //#region src/components/QueryOptions.tsx
818
+ const declarationPrinter$4 = functionPrinter({ mode: "declaration" });
819
+ const callPrinter$4 = functionPrinter({ mode: "call" });
820
+ function getQueryOptionsParams(node, options) {
821
+ return buildQueryOptionsParams(node, {
822
+ resolver: options.resolver,
823
+ memberTypeWrapper: maybeRefOrGetter
824
+ });
825
+ }
826
+ function QueryOptions({ name, clientName, node, tsResolver, queryKeyName }) {
827
+ const successNames = resolveSuccessNames(node, tsResolver);
828
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
829
+ const errorNames = resolveErrorNames(node, tsResolver);
830
+ const TData = responseName;
831
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
832
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { resolver: tsResolver });
833
+ const queryKeyParamsCall = callPrinter$4.print(queryKeyParamsNode) ?? "";
834
+ const paramsNode = getQueryOptionsParams(node, { resolver: tsResolver });
835
+ const paramsSignature = declarationPrinter$4.print(paramsNode) ?? "";
836
+ const queryFnBody = `const { data } = await ${buildVueClientCall(node, {
837
+ clientName,
838
+ signal: true
839
+ })}
840
+ return data`;
841
+ return /* @__PURE__ */ jsx(File.Source, {
842
+ name,
843
+ isExportable: true,
844
+ isIndexable: true,
845
+ children: /* @__PURE__ */ jsx(Function, {
846
+ name,
847
+ export: true,
848
+ params: paramsSignature,
849
+ children: `
850
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
851
+ return queryOptions<${TData}, ${TError}, ${TData}>({
852
+ queryKey,
853
+ queryFn: async ({ signal }) => {
854
+ ${queryFnBody}
855
+ },
856
+ })
857
+ `
858
+ })
859
+ });
860
+ }
861
+ //#endregion
862
+ //#region src/components/InfiniteQuery.tsx
863
+ const declarationPrinter$3 = functionPrinter({ mode: "declaration" });
864
+ const callPrinter$3 = functionPrinter({ mode: "call" });
865
+ function buildInfiniteQueryParamsNode(node, options) {
866
+ const { resolver } = options;
867
+ const successNames = resolveSuccessNames(node, resolver);
868
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.resolveResponseName(node);
869
+ const errorNames = resolveErrorNames(node, resolver);
870
+ const optionsParam = createFunctionParameter({
871
+ name: "options",
872
+ type: `{
873
+ query?: Partial<UseInfiniteQueryOptions<${[
874
+ responseName,
875
+ `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
876
+ "TQueryData",
877
+ "TQueryKey",
878
+ "TQueryData"
879
+ ].join(", ")}>> & { client?: QueryClient },
880
+ client?: ${buildClientOptionType()}
881
+ }`,
882
+ default: "{}"
883
+ });
884
+ return createFunctionParameters({ params: [buildGroupedRequestParam(node, {
885
+ resolver,
886
+ memberTypeWrapper: maybeRefOrGetter
887
+ }), optionsParam].filter((param) => param !== null) });
888
+ }
889
+ function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
890
+ const successNames = resolveSuccessNames(node, tsResolver);
891
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
892
+ const errorNames = resolveErrorNames(node, tsResolver);
893
+ const TData = responseName;
894
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
895
+ const returnType = `UseInfiniteQueryReturnType<${["TData", TError].join(", ")}> & { queryKey: TQueryKey }`;
896
+ const generics = [
897
+ `TData = InfiniteData<${TData}>`,
898
+ `TQueryData = ${TData}`,
899
+ `TQueryKey extends QueryKey = ${queryKeyTypeName}`
900
+ ];
901
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { resolver: tsResolver });
902
+ const queryKeyParamsCall = callPrinter$3.print(queryKeyParamsNode) ?? "";
903
+ const queryOptionsParamsNode = getQueryOptionsParams(node, { resolver: tsResolver });
904
+ const queryOptionsParamsCall = callPrinter$3.print(queryOptionsParamsNode) ?? "";
905
+ const paramsNode = buildInfiniteQueryParamsNode(node, { resolver: tsResolver });
906
+ const paramsSignature = declarationPrinter$3.print(paramsNode) ?? "";
907
+ return /* @__PURE__ */ jsx(File.Source, {
908
+ name,
909
+ isExportable: true,
910
+ isIndexable: true,
911
+ children: /* @__PURE__ */ jsx(Function, {
912
+ name,
913
+ export: true,
914
+ generics: generics.join(", "),
915
+ params: paramsSignature,
916
+ JSDoc: { comments: buildOperationComments(node) },
917
+ children: `
918
+ const { query: queryConfig = {}, client: config = {} } = options ?? {}
919
+ const { client: queryClient, ...resolvedOptions } = queryConfig
920
+ const queryKey = (resolvedOptions && 'queryKey' in resolvedOptions ? toValue(resolvedOptions.queryKey) : undefined) ?? ${queryKeyName}(${queryKeyParamsCall})
921
+
922
+ const queryResult = useInfiniteQuery({
923
+ ...${queryOptionsName}(${queryOptionsParamsCall}),
924
+ ...resolvedOptions,
925
+ queryKey
926
+ } as unknown as UseInfiniteQueryOptions<${TData}, ${TError}, ${TData}, TQueryKey, ${TData}>, toValue(queryClient)) as ${returnType}
927
+
928
+ queryResult.queryKey = queryKey as TQueryKey
929
+
930
+ return queryResult
931
+ `
932
+ })
933
+ });
934
+ }
935
+ //#endregion
936
+ //#region src/components/InfiniteQueryOptions.tsx
937
+ const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
938
+ const callPrinter$2 = functionPrinter({ mode: "call" });
939
+ function InfiniteQueryOptions({ name, clientName, initialPageParam, cursorParam, nextParam, previousParam, node, tsResolver, queryParam, queryKeyName }) {
940
+ const successNames = resolveSuccessNames(node, tsResolver);
941
+ const queryFnDataType = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
942
+ const errorNames = resolveErrorNames(node, tsResolver);
943
+ const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
944
+ const isInitialPageParamDefined = initialPageParam !== void 0 && initialPageParam !== null;
945
+ const fallbackPageParamType = typeof initialPageParam === "number" ? "number" : typeof initialPageParam === "string" ? initialPageParam.includes(" as ") ? (() => {
946
+ const parts = initialPageParam.split(" as ");
947
+ return parts[parts.length - 1] ?? "unknown";
948
+ })() : "string" : typeof initialPageParam === "boolean" ? "boolean" : "unknown";
949
+ const rawQueryParams = getOperationParameters(node, { paramsCasing: "original" }).query;
950
+ const queryParamsTypeName = rawQueryParams.length > 0 ? (() => {
951
+ const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]);
952
+ return groupName !== tsResolver.resolveParamName(node, rawQueryParams[0]) ? groupName : null;
953
+ })() : null;
954
+ const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null;
955
+ const pageParamType = queryParamType ? isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType : fallbackPageParamType;
956
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { resolver: tsResolver });
957
+ const queryKeyParamsCall = callPrinter$2.print(queryKeyParamsNode) ?? "";
958
+ const paramsNode = getQueryOptionsParams(node, { resolver: tsResolver });
959
+ const paramsSignature = declarationPrinter$2.print(paramsNode) ?? "";
960
+ const queryFnBody = `const { data } = await ${buildVueClientCall(node, {
961
+ clientName,
962
+ signal: true
963
+ })}
964
+ return data`;
965
+ const hasNewParams = nextParam != null || previousParam != null;
966
+ const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
967
+ if (hasNewParams) {
968
+ const nextAccessor = nextParam ? getNestedAccessor(nextParam, "lastPage") : null;
969
+ const prevAccessor = previousParam ? getNestedAccessor(previousParam, "firstPage") : null;
970
+ return [nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null, prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null];
971
+ }
972
+ if (cursorParam) return [`getNextPageParam: (lastPage) => lastPage['${cursorParam}']`, `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`];
973
+ return ["getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1", "getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1"];
974
+ })();
975
+ const queryOptionsArr = [
976
+ `initialPageParam: ${typeof initialPageParam === "string" ? JSON.stringify(initialPageParam) : initialPageParam}`,
977
+ getNextPageParamExpr,
978
+ getPreviousPageParamExpr
979
+ ].filter(Boolean);
980
+ const infiniteOverrideParams = queryParam && queryParamsTypeName ? `query = {
981
+ ...(query ?? {}),
982
+ ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
983
+ } as ${queryParamsTypeName}` : "";
984
+ if (infiniteOverrideParams) return /* @__PURE__ */ jsx(File.Source, {
985
+ name,
986
+ isExportable: true,
987
+ isIndexable: true,
988
+ children: /* @__PURE__ */ jsx(Function, {
989
+ name,
990
+ export: true,
991
+ params: paramsSignature,
992
+ children: `
993
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
994
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
995
+ queryKey,
996
+ queryFn: async ({ signal, pageParam }) => {
997
+ ${infiniteOverrideParams}
998
+ ${queryFnBody}
999
+ },
1000
+ ${queryOptionsArr.join(",\n ")}
1001
+ })
1002
+ `
1003
+ })
1004
+ });
1005
+ return /* @__PURE__ */ jsx(File.Source, {
1006
+ name,
1007
+ isExportable: true,
1008
+ isIndexable: true,
1009
+ children: /* @__PURE__ */ jsx(Function, {
1010
+ name,
1011
+ export: true,
1012
+ params: paramsSignature,
1013
+ children: `
1014
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
1015
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
1016
+ queryKey,
1017
+ queryFn: async ({ signal }) => {
1018
+ ${queryFnBody}
1019
+ },
1020
+ ${queryOptionsArr.join(",\n ")}
1021
+ })
1022
+ `
1023
+ })
1024
+ });
1025
+ }
1026
+ //#endregion
1027
+ //#region src/components/Mutation.tsx
1028
+ const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
1029
+ const callPrinter$1 = functionPrinter({ mode: "call" });
1030
+ function resolveMutationRequestType(node, resolver) {
1031
+ return buildGroupedRequestParam(node, { resolver }) ? resolver.resolveRequestConfigName(node) : "undefined";
1032
+ }
1033
+ function buildMutationParamsNode(node, options) {
1034
+ const { resolver } = options;
1035
+ const successNames = resolveSuccessNames(node, resolver);
1036
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.resolveResponseName(node);
1037
+ const errorNames = resolveErrorNames(node, resolver);
1038
+ return createFunctionParameters({ params: [createFunctionParameter({
1039
+ name: "options",
1040
+ type: `{
1041
+ mutation?: MutationObserverOptions<${[
1042
+ responseName,
1043
+ `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
1044
+ resolveMutationRequestType(node, resolver),
1045
+ "TContext"
1046
+ ].join(", ")}> & { client?: QueryClient },
1047
+ client?: ${buildRequestConfigType(node)},
1048
+ }`,
1049
+ default: "{}"
1050
+ })] });
1051
+ }
1052
+ function Mutation({ name, clientName, node, tsResolver, mutationKeyName }) {
1053
+ const successNames = resolveSuccessNames(node, tsResolver);
1054
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
1055
+ const errorNames = resolveErrorNames(node, tsResolver);
1056
+ const TData = responseName;
1057
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
1058
+ const groupedParam = buildGroupedRequestParam(node, { resolver: tsResolver });
1059
+ const hasMutationParams = groupedParam !== null;
1060
+ const groupedParamsNode = createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
1061
+ const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "";
1062
+ const mutationFnBody = `const { data } = await ${buildVueClientCall(node, {
1063
+ clientName,
1064
+ signal: false
1065
+ })}
1066
+ return data`;
1067
+ const generics = [
1068
+ TData,
1069
+ TError,
1070
+ resolveMutationRequestType(node, tsResolver),
1071
+ "TContext"
1072
+ ].join(", ");
1073
+ const mutationKeyParamsNode = createFunctionParameters({ params: [] });
1074
+ const mutationKeyParamsCall = callPrinter$1.print(mutationKeyParamsNode) ?? "";
1075
+ const paramsNode = buildMutationParamsNode(node, { resolver: tsResolver });
1076
+ const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
1077
+ return /* @__PURE__ */ jsx(File.Source, {
1078
+ name,
1079
+ isExportable: true,
1080
+ isIndexable: true,
1081
+ children: /* @__PURE__ */ jsx(Function, {
1082
+ name,
1083
+ export: true,
1084
+ params: paramsSignature,
1085
+ JSDoc: { comments: buildOperationComments(node) },
1086
+ generics: ["TContext"],
1087
+ children: `
1088
+ const { mutation = {}, client: config = {} } = options ?? {}
1089
+ const { client: queryClient, ...mutationOptions } = mutation;
1090
+ const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}(${mutationKeyParamsCall})
1091
+
1092
+ return useMutation<${generics}>({
1093
+ mutationFn: async(${hasMutationParams ? argBindingStr : ""}) => {
1094
+ ${mutationFnBody}
1095
+ },
1096
+ mutationKey,
1097
+ ...mutationOptions
1098
+ }, queryClient)
1099
+ `
1100
+ })
1101
+ });
1102
+ }
1103
+ //#endregion
1104
+ //#region src/components/Query.tsx
1105
+ const declarationPrinter = functionPrinter({ mode: "declaration" });
1106
+ const callPrinter = functionPrinter({ mode: "call" });
1107
+ function buildQueryParamsNode(node, options) {
1108
+ const { resolver } = options;
1109
+ const successNames = resolveSuccessNames(node, resolver);
1110
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.resolveResponseName(node);
1111
+ const errorNames = resolveErrorNames(node, resolver);
1112
+ const optionsParam = createFunctionParameter({
1113
+ name: "options",
1114
+ type: `{
1115
+ query?: Partial<UseQueryOptions<${[
1116
+ responseName,
1117
+ `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
1118
+ "TData",
1119
+ "TQueryData",
1120
+ "TQueryKey"
1121
+ ].join(", ")}>> & { client?: QueryClient },
1122
+ client?: ${buildClientOptionType()}
1123
+ }`,
1124
+ default: "{}"
1125
+ });
1126
+ return createFunctionParameters({ params: [buildGroupedRequestParam(node, {
1127
+ resolver,
1128
+ memberTypeWrapper: maybeRefOrGetter
1129
+ }), optionsParam].filter((param) => param !== null) });
1130
+ }
1131
+ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
1132
+ const successNames = resolveSuccessNames(node, tsResolver);
1133
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
1134
+ const errorNames = resolveErrorNames(node, tsResolver);
1135
+ const TData = responseName;
1136
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
1137
+ const returnType = `UseQueryReturnType<${["TData", TError].join(", ")}> & { queryKey: TQueryKey }`;
1138
+ const generics = [
1139
+ `TData = ${TData}`,
1140
+ `TQueryData = ${TData}`,
1141
+ `TQueryKey extends QueryKey = ${queryKeyTypeName}`
1142
+ ];
1143
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { resolver: tsResolver });
1144
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? "";
1145
+ const queryOptionsParamsNode = getQueryOptionsParams(node, { resolver: tsResolver });
1146
+ const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? "";
1147
+ const paramsNode = buildQueryParamsNode(node, { resolver: tsResolver });
1148
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
1149
+ return /* @__PURE__ */ jsx(File.Source, {
1150
+ name,
1151
+ isExportable: true,
1152
+ isIndexable: true,
1153
+ children: /* @__PURE__ */ jsx(Function, {
1154
+ name,
1155
+ export: true,
1156
+ generics: generics.join(", "),
1157
+ params: paramsSignature,
1158
+ JSDoc: { comments: buildOperationComments(node) },
1159
+ children: `
1160
+ const { query: queryConfig = {}, client: config = {} } = options ?? {}
1161
+ const { client: queryClient, ...resolvedOptions } = queryConfig
1162
+ const queryKey = (resolvedOptions && 'queryKey' in resolvedOptions ? toValue(resolvedOptions.queryKey) : undefined) ?? ${queryKeyName}(${queryKeyParamsCall})
1163
+
1164
+ const queryResult = useQuery({
1165
+ ...${queryOptionsName}(${queryOptionsParamsCall}),
1166
+ ...resolvedOptions,
1167
+ queryKey
1168
+ } as unknown as UseQueryOptions<${TData}, ${TError}, TData, ${TData}, TQueryKey>, toValue(queryClient)) as ${returnType}
1169
+
1170
+ queryResult.queryKey = queryKey as TQueryKey
1171
+
1172
+ return queryResult
1173
+ `
1174
+ })
1175
+ });
1176
+ }
1177
+ //#endregion
1178
+ //#region src/generators/infiniteQueryGenerator.tsx
1179
+ /**
1180
+ * Built-in generator for `useInfiniteQuery` composables. Enabled when
1181
+ * `pluginVueQuery({ infinite: { ... } })`. Emits one `useFooInfiniteQuery`
1182
+ * composable per query operation, wiring the configured cursor path into
1183
+ * TanStack Query's cursor-based pagination.
1184
+ */
1185
+ const infiniteQueryGenerator = defineGenerator({
1186
+ name: "vue-query-infinite",
1187
+ renderer: jsxRenderer,
1188
+ operation(node, ctx) {
1189
+ if (!ast.isHttpOperationNode(node)) return null;
1190
+ const { config, driver, resolver, root } = ctx;
1191
+ const { output, query, mutation, infinite, parser, client, group } = ctx.options;
1192
+ const pluginTs = driver.getPlugin(pluginTsName);
1193
+ if (!pluginTs) return null;
1194
+ const tsResolver = driver.getResolver(pluginTsName);
1195
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1196
+ const queryMethods = new Set(query ? query.methods : []);
1197
+ const isMutation = mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase());
1198
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1199
+ if (!isQuery || isMutation || !infiniteOptions) return null;
1200
+ const normalizeKey = (key) => key.replace(/\?$/, "");
1201
+ const queryParamKeys = getOperationParameters(node, { paramsCasing: "original" }).query.map((p) => p.name);
1202
+ const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false;
1203
+ const hasCursorParam = !infiniteOptions.cursorParam || true;
1204
+ if (!hasQueryParam || !hasCursorParam) return null;
1205
+ const importPath = query ? query.importPath : "@tanstack/vue-query";
1206
+ const contractOp = resolveClientOperation({
1207
+ clientPlugin: { pluginName: client.pluginName },
1208
+ driver,
1209
+ node,
1210
+ root,
1211
+ output
1212
+ });
1213
+ if (!contractOp) return null;
1214
+ const queryName = resolver.resolveInfiniteQueryName(node);
1215
+ const queryOptionsName = resolver.resolveInfiniteQueryOptionsName(node);
1216
+ const queryKeyName = resolver.resolveInfiniteQueryKeyName(node);
1217
+ const queryKeyTypeName = resolver.resolveInfiniteQueryKeyTypeName(node);
1218
+ const meta = {
1219
+ file: resolver.resolveFile(operationFileEntry(node, queryName), {
1220
+ root,
1221
+ output,
1222
+ group: group ?? void 0
1223
+ }),
1224
+ fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1225
+ root,
1226
+ output: pluginTs.options?.output ?? output,
1227
+ group: pluginTs.options?.group ?? void 0
1228
+ })
1229
+ };
1230
+ const rawQueryParams = getOperationParameters(node, { paramsCasing: "original" }).query;
1231
+ const queryParamsTypeName = rawQueryParams.length > 0 && tsResolver.resolveQueryParamsName(node, rawQueryParams[0]) !== tsResolver.resolveParamName(node, rawQueryParams[0]) ? tsResolver.resolveQueryParamsName(node, rawQueryParams[0]) : null;
1232
+ const importedTypeNames = [
1233
+ tsResolver.resolveRequestConfigName(node),
1234
+ queryParamsTypeName,
1235
+ ...resolveOperationTypeNames(node, tsResolver, {
1236
+ exclude: [queryKeyTypeName],
1237
+ order: "body-response-first",
1238
+ includeParams: false
1239
+ })
1240
+ ].filter((name) => Boolean(name));
1241
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
1242
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1243
+ const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1244
+ root,
1245
+ output: pluginZod?.options?.output ?? output,
1246
+ group: pluginZod?.options?.group ?? void 0
1247
+ }) : null;
1248
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1249
+ const calledClientName = contractOp.name;
1250
+ return /* @__PURE__ */ jsxs(File, {
1251
+ baseName: meta.file.baseName,
1252
+ path: meta.file.path,
1253
+ meta: meta.file.meta,
1254
+ banner: resolver.resolveBanner(ctx.meta, {
1255
+ output,
1256
+ config,
1257
+ file: {
1258
+ path: meta.file.path,
1259
+ baseName: meta.file.baseName
1260
+ }
1261
+ }),
1262
+ footer: resolver.resolveFooter(ctx.meta, {
1263
+ output,
1264
+ config,
1265
+ file: {
1266
+ path: meta.file.path,
1267
+ baseName: meta.file.baseName
1268
+ }
1269
+ }),
1270
+ children: [
1271
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1272
+ name: zodSchemaNames,
1273
+ root: meta.file.path,
1274
+ path: fileZod.path
1275
+ }),
1276
+ /* @__PURE__ */ jsx(File.Import, {
1277
+ name: [contractOp.name],
1278
+ root: meta.file.path,
1279
+ path: contractOp.path
1280
+ }),
1281
+ /* @__PURE__ */ jsx(File.Import, {
1282
+ name: ["RequestConfig", "ResponseErrorConfig"],
1283
+ root: meta.file.path,
1284
+ path: contractOp.clientPath,
1285
+ isTypeOnly: true
1286
+ }),
1287
+ /* @__PURE__ */ jsx(File.Import, {
1288
+ name: ["toValue"],
1289
+ path: "vue"
1290
+ }),
1291
+ /* @__PURE__ */ jsx(File.Import, {
1292
+ name: ["MaybeRefOrGetter"],
1293
+ path: "vue",
1294
+ isTypeOnly: true
1295
+ }),
1296
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1297
+ name: Array.from(new Set(importedTypeNames)),
1298
+ root: meta.file.path,
1299
+ path: meta.fileTs.path,
1300
+ isTypeOnly: true
1301
+ }),
1302
+ /* @__PURE__ */ jsx(QueryKey, {
1303
+ name: queryKeyName,
1304
+ typeName: queryKeyTypeName,
1305
+ node,
1306
+ tsResolver,
1307
+ transformer: ctx.options.queryKey
1308
+ }),
1309
+ /* @__PURE__ */ jsx(File.Import, {
1310
+ name: ["InfiniteData"],
1311
+ isTypeOnly: true,
1312
+ path: importPath
1313
+ }),
1314
+ /* @__PURE__ */ jsx(File.Import, {
1315
+ name: ["infiniteQueryOptions"],
1316
+ path: importPath
1317
+ }),
1318
+ /* @__PURE__ */ jsx(InfiniteQueryOptions, {
1319
+ name: queryOptionsName,
1320
+ clientName: calledClientName,
1321
+ queryKeyName,
1322
+ node,
1323
+ tsResolver,
1324
+ cursorParam: infiniteOptions.cursorParam,
1325
+ nextParam: infiniteOptions.nextParam,
1326
+ previousParam: infiniteOptions.previousParam,
1327
+ initialPageParam: infiniteOptions.initialPageParam,
1328
+ queryParam: infiniteOptions.queryParam
1329
+ }),
1330
+ /* @__PURE__ */ jsx(File.Import, {
1331
+ name: ["useInfiniteQuery"],
1332
+ path: importPath
1333
+ }),
1334
+ /* @__PURE__ */ jsx(File.Import, {
1335
+ name: [
1336
+ "QueryKey",
1337
+ "QueryClient",
1338
+ "UseInfiniteQueryOptions",
1339
+ "UseInfiniteQueryReturnType"
1340
+ ],
1341
+ path: importPath,
1342
+ isTypeOnly: true
1343
+ }),
1344
+ /* @__PURE__ */ jsx(InfiniteQuery, {
1345
+ name: queryName,
1346
+ queryOptionsName,
1347
+ queryKeyName,
1348
+ queryKeyTypeName,
1349
+ node,
1350
+ tsResolver,
1351
+ initialPageParam: infiniteOptions.initialPageParam,
1352
+ queryParam: infiniteOptions.queryParam
1353
+ })
1354
+ ]
1355
+ });
1356
+ }
1357
+ });
1358
+ //#endregion
1359
+ //#region src/generators/mutationGenerator.tsx
1360
+ /**
1361
+ * Built-in generator for `useMutation` composables. Emits one
1362
+ * `useFooMutation` composable per POST/PUT/DELETE operation (configurable
1363
+ * via `mutation.methods`) plus the matching `fooMutationKey` helper.
1364
+ */
1365
+ const mutationGenerator = defineGenerator({
1366
+ name: "vue-query-mutation",
1367
+ renderer: jsxRenderer,
1368
+ operation(node, ctx) {
1369
+ if (!ast.isHttpOperationNode(node)) return null;
1370
+ const { config, driver, resolver, root } = ctx;
1371
+ const { output, query, mutation, parser, client, group } = ctx.options;
1372
+ const pluginTs = driver.getPlugin(pluginTsName);
1373
+ if (!pluginTs) return null;
1374
+ const tsResolver = driver.getResolver(pluginTsName);
1375
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1376
+ const queryMethods = new Set(query ? query.methods : []);
1377
+ if (!(mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase()))) return null;
1378
+ const importPath = mutation ? mutation.importPath : "@tanstack/vue-query";
1379
+ const contractOp = resolveClientOperation({
1380
+ clientPlugin: { pluginName: client.pluginName },
1381
+ driver,
1382
+ node,
1383
+ root,
1384
+ output
1385
+ });
1386
+ if (!contractOp) return null;
1387
+ const mutationHookName = resolver.resolveMutationName(node);
1388
+ const mutationTypeName = resolver.resolveMutationTypeName(node);
1389
+ const mutationKeyName = resolver.resolveMutationKeyName(node);
1390
+ const meta = {
1391
+ file: resolver.resolveFile(operationFileEntry(node, mutationHookName), {
1392
+ root,
1393
+ output,
1394
+ group: group ?? void 0
1395
+ }),
1396
+ fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1397
+ root,
1398
+ output: pluginTs.options?.output ?? output,
1399
+ group: pluginTs.options?.group ?? void 0
1400
+ })
1401
+ };
1402
+ const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1403
+ order: "body-response-first",
1404
+ includeParams: false
1405
+ })].filter((name) => Boolean(name));
1406
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
1407
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1408
+ const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1409
+ root,
1410
+ output: pluginZod?.options?.output ?? output,
1411
+ group: pluginZod?.options?.group ?? void 0
1412
+ }) : null;
1413
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1414
+ const calledClientName = contractOp.name;
1415
+ const groups = getRequestGroups(node);
1416
+ const hasRequestGroups = groups.path || groups.query || groups.body || groups.headers;
1417
+ return /* @__PURE__ */ jsxs(File, {
1418
+ baseName: meta.file.baseName,
1419
+ path: meta.file.path,
1420
+ meta: meta.file.meta,
1421
+ banner: resolver.resolveBanner(ctx.meta, {
1422
+ output,
1423
+ config,
1424
+ file: {
1425
+ path: meta.file.path,
1426
+ baseName: meta.file.baseName
1427
+ }
1428
+ }),
1429
+ footer: resolver.resolveFooter(ctx.meta, {
1430
+ output,
1431
+ config,
1432
+ file: {
1433
+ path: meta.file.path,
1434
+ baseName: meta.file.baseName
1435
+ }
1436
+ }),
1437
+ children: [
1438
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1439
+ name: zodSchemaNames,
1440
+ root: meta.file.path,
1441
+ path: fileZod.path
1442
+ }),
1443
+ /* @__PURE__ */ jsx(File.Import, {
1444
+ name: [contractOp.name],
1445
+ root: meta.file.path,
1446
+ path: contractOp.path
1447
+ }),
1448
+ /* @__PURE__ */ jsx(File.Import, {
1449
+ name: ["RequestConfig", "ResponseErrorConfig"],
1450
+ root: meta.file.path,
1451
+ path: contractOp.clientPath,
1452
+ isTypeOnly: true
1453
+ }),
1454
+ hasRequestGroups && /* @__PURE__ */ jsx(File.Import, {
1455
+ name: ["toValue"],
1456
+ path: "vue"
1457
+ }),
1458
+ /* @__PURE__ */ jsx(File.Import, {
1459
+ name: ["MaybeRefOrGetter"],
1460
+ path: "vue",
1461
+ isTypeOnly: true
1462
+ }),
1463
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1464
+ name: Array.from(new Set(importedTypeNames)),
1465
+ root: meta.file.path,
1466
+ path: meta.fileTs.path,
1467
+ isTypeOnly: true
1468
+ }),
1469
+ /* @__PURE__ */ jsx(MutationKey, {
1470
+ name: mutationKeyName,
1471
+ node,
1472
+ transformer: ctx.options.mutationKey
1473
+ }),
1474
+ mutation && /* @__PURE__ */ jsxs(Fragment, { children: [
1475
+ /* @__PURE__ */ jsx(File.Import, {
1476
+ name: ["useMutation"],
1477
+ path: importPath
1478
+ }),
1479
+ /* @__PURE__ */ jsx(File.Import, {
1480
+ name: ["MutationObserverOptions", "QueryClient"],
1481
+ path: importPath,
1482
+ isTypeOnly: true
1483
+ }),
1484
+ /* @__PURE__ */ jsx(Mutation, {
1485
+ name: mutationHookName,
1486
+ clientName: calledClientName,
1487
+ typeName: mutationTypeName,
1488
+ node,
1489
+ tsResolver,
1490
+ mutationKeyName
1491
+ })
1492
+ ] })
1493
+ ]
1494
+ });
1495
+ }
1496
+ });
1497
+ //#endregion
1498
+ //#region src/generators/queryGenerator.tsx
1499
+ /**
1500
+ * Built-in generator for `useQuery` composables. Emits one `useFooQuery`
1501
+ * composable per GET operation (configurable via `query.methods`) plus the
1502
+ * matching `fooQueryKey` / `fooQueryOptions` helpers.
1503
+ */
1504
+ const queryGenerator = defineGenerator({
1505
+ name: "vue-query",
1506
+ renderer: jsxRenderer,
1507
+ operation(node, ctx) {
1508
+ if (!ast.isHttpOperationNode(node)) return null;
1509
+ const { config, driver, resolver, root } = ctx;
1510
+ const { output, query, mutation, parser, client, group } = ctx.options;
1511
+ const pluginTs = driver.getPlugin(pluginTsName);
1512
+ if (!pluginTs) return null;
1513
+ const tsResolver = driver.getResolver(pluginTsName);
1514
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1515
+ const queryMethods = new Set(query ? query.methods : []);
1516
+ const isMutation = mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase());
1517
+ if (!isQuery || isMutation) return null;
1518
+ const importPath = query ? query.importPath : "@tanstack/vue-query";
1519
+ const contractOp = resolveClientOperation({
1520
+ clientPlugin: { pluginName: client.pluginName },
1521
+ driver,
1522
+ node,
1523
+ root,
1524
+ output
1525
+ });
1526
+ if (!contractOp) return null;
1527
+ const queryName = resolver.resolveQueryName(node);
1528
+ const queryOptionsName = resolver.resolveQueryOptionsName(node);
1529
+ const queryKeyName = resolver.resolveQueryKeyName(node);
1530
+ const queryKeyTypeName = resolver.resolveQueryKeyTypeName(node);
1531
+ const meta = {
1532
+ file: resolver.resolveFile(operationFileEntry(node, queryName), {
1533
+ root,
1534
+ output,
1535
+ group: group ?? void 0
1536
+ }),
1537
+ fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1538
+ root,
1539
+ output: pluginTs.options?.output ?? output,
1540
+ group: pluginTs.options?.group ?? void 0
1541
+ })
1542
+ };
1543
+ const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1544
+ exclude: [queryKeyTypeName],
1545
+ order: "body-response-first",
1546
+ includeParams: false
1547
+ })].filter((name) => Boolean(name));
1548
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
1549
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1550
+ const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1551
+ root,
1552
+ output: pluginZod?.options?.output ?? output,
1553
+ group: pluginZod?.options?.group ?? void 0
1554
+ }) : null;
1555
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1556
+ const calledClientName = contractOp.name;
1557
+ return /* @__PURE__ */ jsxs(File, {
1558
+ baseName: meta.file.baseName,
1559
+ path: meta.file.path,
1560
+ meta: meta.file.meta,
1561
+ banner: resolver.resolveBanner(ctx.meta, {
1562
+ output,
1563
+ config,
1564
+ file: {
1565
+ path: meta.file.path,
1566
+ baseName: meta.file.baseName
1567
+ }
1568
+ }),
1569
+ footer: resolver.resolveFooter(ctx.meta, {
1570
+ output,
1571
+ config,
1572
+ file: {
1573
+ path: meta.file.path,
1574
+ baseName: meta.file.baseName
1575
+ }
1576
+ }),
1577
+ children: [
1578
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1579
+ name: zodSchemaNames,
1580
+ root: meta.file.path,
1581
+ path: fileZod.path
1582
+ }),
1583
+ /* @__PURE__ */ jsx(File.Import, {
1584
+ name: [contractOp.name],
1585
+ root: meta.file.path,
1586
+ path: contractOp.path
1587
+ }),
1588
+ /* @__PURE__ */ jsx(File.Import, {
1589
+ name: ["RequestConfig", "ResponseErrorConfig"],
1590
+ root: meta.file.path,
1591
+ path: contractOp.clientPath,
1592
+ isTypeOnly: true
1593
+ }),
1594
+ /* @__PURE__ */ jsx(File.Import, {
1595
+ name: ["toValue"],
1596
+ path: "vue"
1597
+ }),
1598
+ /* @__PURE__ */ jsx(File.Import, {
1599
+ name: ["MaybeRefOrGetter"],
1600
+ path: "vue",
1601
+ isTypeOnly: true
1602
+ }),
1603
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1604
+ name: Array.from(new Set(importedTypeNames)),
1605
+ root: meta.file.path,
1606
+ path: meta.fileTs.path,
1607
+ isTypeOnly: true
1608
+ }),
1609
+ /* @__PURE__ */ jsx(QueryKey, {
1610
+ name: queryKeyName,
1611
+ typeName: queryKeyTypeName,
1612
+ node,
1613
+ tsResolver,
1614
+ transformer: ctx.options.queryKey
1615
+ }),
1616
+ /* @__PURE__ */ jsx(File.Import, {
1617
+ name: ["queryOptions"],
1618
+ path: importPath
1619
+ }),
1620
+ /* @__PURE__ */ jsx(QueryOptions, {
1621
+ name: queryOptionsName,
1622
+ clientName: calledClientName,
1623
+ queryKeyName,
1624
+ node,
1625
+ tsResolver
1626
+ }),
1627
+ query && /* @__PURE__ */ jsxs(Fragment, { children: [
1628
+ /* @__PURE__ */ jsx(File.Import, {
1629
+ name: ["useQuery"],
1630
+ path: importPath
1631
+ }),
1632
+ /* @__PURE__ */ jsx(File.Import, {
1633
+ name: [
1634
+ "QueryKey",
1635
+ "QueryClient",
1636
+ "UseQueryOptions",
1637
+ "UseQueryReturnType"
1638
+ ],
1639
+ path: importPath,
1640
+ isTypeOnly: true
1641
+ }),
1642
+ /* @__PURE__ */ jsx(Query, {
1643
+ name: queryName,
1644
+ queryOptionsName,
1645
+ queryKeyName,
1646
+ queryKeyTypeName,
1647
+ node,
1648
+ tsResolver
1649
+ })
1650
+ ] })
1651
+ ]
1652
+ });
1653
+ }
1654
+ });
1655
+ //#endregion
68
1656
  //#region src/resolvers/resolverVueQuery.ts
69
1657
  function capitalize(name) {
70
1658
  return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
@@ -172,10 +1760,8 @@ const pluginVueQuery = definePlugin((options) => {
172
1760
  const { output = {
173
1761
  path: "hooks",
174
1762
  barrel: { type: "named" }
175
- }, group, exclude = [], include, override = [], parser = false, infinite = false, paramsType = "inline", pathParamsType = paramsType === "object" ? "object" : options.pathParamsType || "inline", mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, paramsCasing, client, resolver: userResolver, macros: userMacros, generators: userGenerators = [] } = options;
176
- const clientName = client?.client ?? "axios";
177
- const clientImportPath = client?.importPath ?? (!client?.bundle ? `@kubb/plugin-client/clients/${clientName}` : void 0);
178
- const selectedGenerators = options.generators ?? [
1763
+ }, group, exclude = [], include, override = [], parser = false, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, client, resolver: userResolver, macros: userMacros } = options;
1764
+ const selectedGenerators = [
179
1765
  queryGenerator,
180
1766
  infiniteQueryGenerator,
181
1767
  mutationGenerator
@@ -190,17 +1776,18 @@ const pluginVueQuery = definePlugin((options) => {
190
1776
  ...resolverVueQuery,
191
1777
  ...userResolver
192
1778
  } : resolverVueQuery;
1779
+ const resolvedClient = resolveClient({
1780
+ client,
1781
+ pluginNames: (ctx.config.plugins ?? []).map((p) => p.name).filter((name) => Boolean(name))
1782
+ });
1783
+ if (resolvedClient.kind === "error") throw new Error(resolvedClient.message);
1784
+ const resolvedClientDescriptor = {
1785
+ kind: "contract",
1786
+ pluginName: resolvedClient.pluginName
1787
+ };
193
1788
  ctx.setOptions({
194
1789
  output,
195
- client: {
196
- bundle: client?.bundle,
197
- baseURL: client?.baseURL,
198
- client: clientName,
199
- clientType: client?.clientType ?? "function",
200
- importPath: clientImportPath,
201
- dataReturnType: client?.dataReturnType ?? "data",
202
- paramsCasing
203
- },
1790
+ client: resolvedClientDescriptor,
204
1791
  queryKey,
205
1792
  query: query === false ? false : {
206
1793
  importPath: "@tanstack/vue-query",
@@ -227,9 +1814,6 @@ const pluginVueQuery = definePlugin((options) => {
227
1814
  ...infinite
228
1815
  } : false,
229
1816
  parser,
230
- paramsType,
231
- pathParamsType,
232
- paramsCasing,
233
1817
  group: groupConfig,
234
1818
  exclude,
235
1819
  include,
@@ -239,29 +1823,6 @@ const pluginVueQuery = definePlugin((options) => {
239
1823
  ctx.setResolver(resolver);
240
1824
  if (userMacros?.length) ctx.setMacros(userMacros);
241
1825
  for (const gen of selectedGenerators) ctx.addGenerator(gen);
242
- for (const gen of userGenerators) ctx.addGenerator(gen);
243
- const root = path.resolve(ctx.config.root, ctx.config.output.path);
244
- const hasClientPlugin = !!ctx.config.plugins?.some((p) => p.name === pluginClientName);
245
- if (client?.bundle && !hasClientPlugin && !clientImportPath) ctx.injectFile({
246
- baseName: "client.ts",
247
- path: path.resolve(root, ".kubb/client.ts"),
248
- sources: [ast.factory.createSource({
249
- name: "client",
250
- nodes: [ast.factory.createText(clientName === "fetch" ? source$1 : source)],
251
- isExportable: true,
252
- isIndexable: true
253
- })]
254
- });
255
- if (!hasClientPlugin) ctx.injectFile({
256
- baseName: "config.ts",
257
- path: path.resolve(root, ".kubb/config.ts"),
258
- sources: [ast.factory.createSource({
259
- name: "config",
260
- nodes: [ast.factory.createText(source$2)],
261
- isExportable: false,
262
- isIndexable: false
263
- })]
264
- });
265
1826
  } }
266
1827
  };
267
1828
  });