@kubb/plugin-react-query 5.0.0-beta.10 → 5.0.0-beta.101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +22 -26
  2. package/dist/index.cjs +2288 -191
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.ts +494 -6
  5. package/dist/index.js +2258 -185
  6. package/dist/index.js.map +1 -1
  7. package/package.json +11 -34
  8. package/dist/components-Dow6tde8.js +0 -1459
  9. package/dist/components-Dow6tde8.js.map +0 -1
  10. package/dist/components-HwdCDefj.cjs +0 -1603
  11. package/dist/components-HwdCDefj.cjs.map +0 -1
  12. package/dist/components.cjs +0 -13
  13. package/dist/components.d.ts +0 -268
  14. package/dist/components.js +0 -2
  15. package/dist/generators-CcOmnTPa.cjs +0 -1454
  16. package/dist/generators-CcOmnTPa.cjs.map +0 -1
  17. package/dist/generators-yfZr_qfT.js +0 -1412
  18. package/dist/generators-yfZr_qfT.js.map +0 -1
  19. package/dist/generators.cjs +0 -9
  20. package/dist/generators.d.ts +0 -27
  21. package/dist/generators.js +0 -2
  22. package/dist/types-DG_OxOym.d.ts +0 -363
  23. package/extension.yaml +0 -911
  24. package/src/components/InfiniteQuery.tsx +0 -161
  25. package/src/components/InfiniteQueryOptions.tsx +0 -178
  26. package/src/components/Mutation.tsx +0 -121
  27. package/src/components/MutationKey.tsx +0 -1
  28. package/src/components/MutationOptions.tsx +0 -103
  29. package/src/components/Query.tsx +0 -118
  30. package/src/components/QueryKey.tsx +0 -1
  31. package/src/components/QueryOptions.tsx +0 -99
  32. package/src/components/SuspenseInfiniteQuery.tsx +0 -161
  33. package/src/components/SuspenseInfiniteQueryOptions.tsx +0 -178
  34. package/src/components/SuspenseQuery.tsx +0 -118
  35. package/src/components/index.ts +0 -11
  36. package/src/generators/customHookOptionsFileGenerator.tsx +0 -84
  37. package/src/generators/hookOptionsGenerator.tsx +0 -133
  38. package/src/generators/index.ts +0 -7
  39. package/src/generators/infiniteQueryGenerator.tsx +0 -194
  40. package/src/generators/mutationGenerator.tsx +0 -168
  41. package/src/generators/queryGenerator.tsx +0 -180
  42. package/src/generators/suspenseInfiniteQueryGenerator.tsx +0 -203
  43. package/src/generators/suspenseQueryGenerator.tsx +0 -181
  44. package/src/index.ts +0 -2
  45. package/src/plugin.ts +0 -186
  46. package/src/resolvers/resolverReactQuery.ts +0 -107
  47. package/src/types.ts +0 -328
  48. package/src/utils.ts +0 -10
  49. /package/dist/{chunk--u3MIqq1.js → rolldown-runtime-C0LytTxp.js} +0 -0
package/dist/index.cjs CHANGED
@@ -2,200 +2,2319 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_components = require("./components-HwdCDefj.cjs");
6
- const require_generators = require("./generators-CcOmnTPa.cjs");
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
+ key = keys[i];
15
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ //#endregion
27
+ let kubb_kit = require("kubb/kit");
7
28
  let node_path = require("node:path");
8
- node_path = require_components.__toESM(node_path, 1);
9
- let _kubb_core = require("@kubb/core");
10
- let _kubb_plugin_client = require("@kubb/plugin-client");
11
- let _kubb_plugin_client_templates_clients_axios_source = require("@kubb/plugin-client/templates/clients/axios.source");
12
- let _kubb_plugin_client_templates_clients_fetch_source = require("@kubb/plugin-client/templates/clients/fetch.source");
13
- let _kubb_plugin_client_templates_config_source = require("@kubb/plugin-client/templates/config.source");
29
+ node_path = __toESM(node_path, 1);
14
30
  let _kubb_plugin_ts = require("@kubb/plugin-ts");
15
- let _kubb_plugin_zod = require("@kubb/plugin-zod");
16
- //#region src/resolvers/resolverReactQuery.ts
17
- function capitalize(name) {
18
- return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
31
+ let kubb_jsx = require("kubb/jsx");
32
+ let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
33
+ let node_fs = require("node:fs");
34
+ node_fs = __toESM(node_fs, 1);
35
+ //#region ../../internals/shared/src/params.ts
36
+ /**
37
+ * Drops parameters that share the same name, keeping the first.
38
+ *
39
+ * A malformed spec can declare the same parameter name twice within one `in` location. Both would
40
+ * resolve to the same output property, so emitting both would yield an object type with a duplicate
41
+ * member, which TypeScript rejects. This is a defensive guard against that case, not a casing guard:
42
+ * parameter names flow through unchanged, so no two distinct names ever collide here anymore.
43
+ */
44
+ function dedupeParams(params) {
45
+ const seen = /* @__PURE__ */ new Set();
46
+ return params.filter((param) => {
47
+ if (seen.has(param.name)) return false;
48
+ seen.add(param.name);
49
+ return true;
50
+ });
51
+ }
52
+ //#endregion
53
+ //#region ../../internals/shared/src/operation.ts
54
+ /**
55
+ * Builds the `ResolverFileParams` every operation generator passes to
56
+ * `resolver.file`: a file named `name`, tagged by the operation's first
57
+ * tag (or `'default'`), at the operation's path. Centralizes the entry object
58
+ * that was repeated at dozens of call sites across the client and query plugins.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
63
+ * ```
64
+ */
65
+ function operationFileEntry(node, name, extname = ".ts") {
66
+ return {
67
+ name,
68
+ extname,
69
+ tag: node.tags[0] ?? "default",
70
+ path: node.path
71
+ };
72
+ }
73
+ function getOperationLink(node, link) {
74
+ if (!link) return null;
75
+ if (typeof link === "function") return link(node) ?? null;
76
+ return node.path ? `{@link ${kubb_kit.Url.toPath(node.path)}}` : null;
77
+ }
78
+ /**
79
+ * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several
80
+ * are present and the union, default, and form-data flags the client uses to pick one.
81
+ */
82
+ function buildContentTypeInfo(contentTypes) {
83
+ const isMultipleContentTypes = contentTypes.length > 1;
84
+ return {
85
+ contentTypes,
86
+ isMultipleContentTypes,
87
+ contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
88
+ defaultContentType: contentTypes[0] ?? "application/json",
89
+ hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
90
+ };
91
+ }
92
+ function getContentTypeInfo(node) {
93
+ return buildContentTypeInfo(node.requestBody?.content?.map((e) => e.contentType) ?? []);
94
+ }
95
+ /**
96
+ * The request-body counterpart for the primary success response: the content types it documents and
97
+ * whether several are present, so the client can let a caller pick which one to accept.
98
+ */
99
+ function getResponseContentTypeInfo(node) {
100
+ return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? []);
101
+ }
102
+ function buildRequestConfigType(node) {
103
+ const request = getContentTypeInfo(node);
104
+ const response = getResponseContentTypeInfo(node);
105
+ const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
106
+ const members = [request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null, response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null].filter(Boolean);
107
+ return members.length ? `${configType} & { contentType?: { ${members.join("; ")} } }` : configType;
108
+ }
109
+ /**
110
+ * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
111
+ * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a
112
+ * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a
113
+ * content type for.
114
+ */
115
+ function buildClientOptionType() {
116
+ return `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
117
+ }
118
+ /**
119
+ * Which of the grouped request options an operation carries.
120
+ */
121
+ function getRequestGroups(node) {
122
+ const { path, query, header } = getOperationParameters(node);
123
+ return {
124
+ path: path.length > 0,
125
+ query: query.length > 0,
126
+ body: Boolean(node.requestBody?.content?.[0]?.schema),
127
+ headers: header.length > 0
128
+ };
129
+ }
130
+ /**
131
+ * Resolves which grouped request options an operation carries together with whether each group
132
+ * holds a required member. The grouped parameter stays optional only when nothing inside it is
133
+ * required, matching the generated `RequestConfig` type.
134
+ */
135
+ function getRequestGroupOptionality(node) {
136
+ const groups = getRequestGroups(node);
137
+ const { path, query, header } = getOperationParameters(node);
138
+ const hasRequiredPath = path.some((param) => param.required);
139
+ const hasRequiredQuery = query.some((param) => param.required);
140
+ const hasRequiredHeader = header.some((param) => param.required);
141
+ return {
142
+ groups,
143
+ hasRequiredPath,
144
+ hasRequiredQuery,
145
+ hasRequiredHeader,
146
+ isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body
147
+ };
148
+ }
149
+ function buildOperationComments(node, options = {}) {
150
+ const { link = "pathTemplate", linkPosition = "afterDeprecated", splitLines = false } = options;
151
+ const linkComment = getOperationLink(node, link);
152
+ const filteredComments = (linkPosition === "beforeDeprecated" ? [
153
+ node.description && `@description ${node.description}`,
154
+ node.summary && `@summary ${node.summary}`,
155
+ linkComment,
156
+ node.deprecated && "@deprecated"
157
+ ] : [
158
+ node.description && `@description ${node.description}`,
159
+ node.summary && `@summary ${node.summary}`,
160
+ node.deprecated && "@deprecated",
161
+ linkComment
162
+ ]).filter((comment) => Boolean(comment));
163
+ if (!splitLines) return filteredComments;
164
+ return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
165
+ }
166
+ function getOperationParameters(node) {
167
+ return {
168
+ path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
169
+ query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
170
+ header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
171
+ cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
172
+ };
173
+ }
174
+ function getStatusCodeNumber(statusCode) {
175
+ const code = Number(statusCode);
176
+ return Number.isNaN(code) ? null : code;
177
+ }
178
+ function isSuccessStatusCode(statusCode) {
179
+ const code = getStatusCodeNumber(statusCode);
180
+ return code !== null && code >= 200 && code < 300;
181
+ }
182
+ function isErrorStatusCode(statusCode) {
183
+ const code = getStatusCodeNumber(statusCode);
184
+ return code !== null && code >= 400;
185
+ }
186
+ function getSuccessResponses(responses) {
187
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
188
+ }
189
+ function getOperationSuccessResponses(node) {
190
+ return getSuccessResponses(node.responses);
191
+ }
192
+ function getPrimarySuccessResponse(node) {
193
+ return getOperationSuccessResponses(node)[0] ?? null;
194
+ }
195
+ function resolveErrorNames(node, resolver) {
196
+ return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode));
197
+ }
198
+ function resolveSuccessNames(node, resolver) {
199
+ return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode));
200
+ }
201
+ function resolveStatusCodeNames(node, resolver) {
202
+ return node.responses.map((response) => resolver.response.status(node, response.statusCode));
203
+ }
204
+ const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
205
+ function resolveOperationTypeNames(node, resolver, options = {}) {
206
+ const cacheKey = `${node.operationId}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
207
+ let byResolver = typeNamesByResolver.get(resolver);
208
+ if (byResolver) {
209
+ const cached = byResolver.get(cacheKey);
210
+ if (cached) return cached;
211
+ } else {
212
+ byResolver = /* @__PURE__ */ new Map();
213
+ typeNamesByResolver.set(resolver, byResolver);
214
+ }
215
+ const { path, query, header } = getOperationParameters(node);
216
+ const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
217
+ const exclude = new Set(options.exclude ?? []);
218
+ const paramNames = options.includeParams === false ? [] : [
219
+ ...path.map((param) => resolver.param.path(node, param)),
220
+ ...query.map((param) => resolver.param.query(node, param)),
221
+ ...header.map((param) => resolver.param.headers(node, param))
222
+ ];
223
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)];
224
+ const result = (options.order === "body-response-first" ? [
225
+ ...bodyAndResponseNames,
226
+ ...paramNames,
227
+ ...responseStatusNames
228
+ ] : [
229
+ ...paramNames,
230
+ ...bodyAndResponseNames,
231
+ ...responseStatusNames
232
+ ]).filter((name) => Boolean(name) && !exclude.has(name));
233
+ byResolver.set(cacheKey, result);
234
+ return result;
235
+ }
236
+ //#endregion
237
+ //#region ../../internals/utils/src/casing.ts
238
+ /**
239
+ * Shared implementation for camelCase and PascalCase conversion.
240
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
241
+ * and capitalizes each word according to `pascal`.
242
+ *
243
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
244
+ */
245
+ function toCamelOrPascal(text, pascal) {
246
+ 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) => {
247
+ if (word.length > 1 && word === word.toUpperCase()) return word;
248
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
249
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
250
+ }
251
+ /**
252
+ * Converts `text` to camelCase.
253
+ *
254
+ * @example Word boundaries
255
+ * `camelCase('hello-world') // 'helloWorld'`
256
+ *
257
+ * @example With a prefix
258
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
259
+ */
260
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
261
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
262
+ }
263
+ /**
264
+ * Uppercases only the first character of `text`, leaving the rest untouched.
265
+ * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.
266
+ *
267
+ * @example
268
+ * `capitalize('getPetById') // 'GetPetById'`
269
+ */
270
+ function capitalize(text) {
271
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
272
+ }
273
+ //#endregion
274
+ //#region ../../internals/utils/src/strings.ts
275
+ /**
276
+ * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
277
+ * `accessor`. Returns `null` for an empty path.
278
+ *
279
+ * @example
280
+ * ```ts
281
+ * getNestedAccessor('pagination.next.id', 'lastPage')
282
+ * // "lastPage?.['pagination']?.['next']?.['id']"
283
+ * ```
284
+ */
285
+ function getNestedAccessor(param, accessor) {
286
+ const parts = Array.isArray(param) ? param : param.split(".");
287
+ if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
288
+ return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
289
+ }
290
+ //#endregion
291
+ //#region ../../internals/shared/src/group.ts
292
+ /**
293
+ * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
294
+ * shared default naming so every plugin groups output consistently:
295
+ *
296
+ * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
297
+ * - other groups use the camelCased group (`pet store` → `petStore`).
298
+ *
299
+ * A user-provided `group.name` always wins over the default namer, so callers stay in
300
+ * control of their output folders. Returns `null` when grouping is disabled, matching the
301
+ * per-plugin convention.
302
+ *
303
+ * @param group - The user-supplied group option, or `undefined` to disable grouping.
304
+ *
305
+ * @example
306
+ * ```ts
307
+ * createGroupConfig(group) // shared across every plugin
308
+ * ```
309
+ */
310
+ function createGroupConfig(group) {
311
+ if (!group) return null;
312
+ const defaultName = (ctx) => {
313
+ if (group.type === "path") return `${ctx.group.split("/")[1]}`;
314
+ return camelCase(ctx.group);
315
+ };
316
+ return {
317
+ ...group,
318
+ name: group.name ? group.name : defaultName
319
+ };
320
+ }
321
+ //#endregion
322
+ //#region ../../internals/client/src/resolveClient.ts
323
+ /**
324
+ * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
325
+ * operation, shared so the selection rules and diagnostics stay in one place.
326
+ *
327
+ * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered
328
+ * contract client plugin (plugin-fetch or plugin-axios) and never emits its own inline client:
329
+ *
330
+ * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
331
+ * imports and calls them.
332
+ * - `error` — no client plugin is registered, several are registered without a selector, or the
333
+ * requested one is missing.
334
+ *
335
+ * The `client` string selects explicitly (`'fetch'` / `'axios'`); when it is unset a lone registered
336
+ * contract client plugin is picked up automatically.
337
+ */
338
+ const pluginFetchName = "plugin-fetch";
339
+ const pluginAxiosName = "plugin-axios";
340
+ const selectorToPlugin = {
341
+ fetch: pluginFetchName,
342
+ axios: pluginAxiosName
343
+ };
344
+ const contractPlugins = [pluginFetchName, pluginAxiosName];
345
+ /**
346
+ * Applies the `client` resolution rules. See the module comment for the strategy shape.
347
+ *
348
+ * @example
349
+ * ```ts
350
+ * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })
351
+ * // { kind: 'contract', pluginName: 'plugin-fetch' }
352
+ * ```
353
+ *
354
+ * @example
355
+ * ```ts
356
+ * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
357
+ * // { kind: 'error', message: 'No client plugin is registered…' }
358
+ * ```
359
+ */
360
+ function resolveClient(options) {
361
+ const { client, pluginNames } = options;
362
+ const has = (name) => pluginNames.includes(name);
363
+ if (client === "fetch" || client === "axios") {
364
+ const pluginName = selectorToPlugin[client];
365
+ if (!has(pluginName)) return {
366
+ kind: "error",
367
+ 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.`
368
+ };
369
+ return {
370
+ kind: "contract",
371
+ pluginName
372
+ };
373
+ }
374
+ const registered = contractPlugins.filter(has);
375
+ if (registered.length === 1) return {
376
+ kind: "contract",
377
+ pluginName: registered[0]
378
+ };
379
+ if (registered.length > 1) return {
380
+ kind: "error",
381
+ 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.`
382
+ };
383
+ return {
384
+ kind: "error",
385
+ 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."
386
+ };
387
+ }
388
+ /**
389
+ * Resolves the contract client during a consumer plugin's setup hook. Extracts the plugin names
390
+ * from the raw `plugins` config, applies {@link resolveClient}, and throws the diagnostic on a
391
+ * misconfiguration so every consumer fails fast with the same message.
392
+ */
393
+ function resolveContractClient(options) {
394
+ const { client, plugins = [] } = options;
395
+ const resolved = resolveClient({
396
+ client,
397
+ pluginNames: plugins.map((plugin) => plugin.name).filter((name) => Boolean(name))
398
+ });
399
+ if (resolved.kind === "error") throw new Error(resolved.message);
400
+ return resolved;
401
+ }
402
+ //#endregion
403
+ //#region ../../internals/client/src/resolveClientOperation.ts
404
+ /**
405
+ * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up
406
+ * the registered contract client plugin's resolver and output. Works for any contract client plugin
407
+ * (plugin-fetch or plugin-axios). Returns `null` when no contract plugin is in play (the inline
408
+ * path). The plugin injects `.kubb/client.ts` at the global output root, the same path consumers
409
+ * read `RequestConfig` / `ResponseErrorConfig` from.
410
+ */
411
+ function resolveClientOperation(options) {
412
+ const { clientPlugin, driver, node, root, output } = options;
413
+ if (!clientPlugin) return null;
414
+ const resolver = driver.getResolver(clientPlugin.pluginName);
415
+ const plugin = driver.getPlugin(clientPlugin.pluginName);
416
+ const file = resolver.file({
417
+ ...operationFileEntry(node, node.operationId),
418
+ root,
419
+ output: plugin?.options?.output ?? output,
420
+ group: plugin?.options?.group ?? void 0
421
+ });
422
+ return {
423
+ name: resolver.name(node.operationId),
424
+ path: file.path,
425
+ clientPath: node_path.default.resolve(root, ".kubb/client.ts")
426
+ };
427
+ }
428
+ //#endregion
429
+ //#region ../../internals/tanstack-query/src/utils.ts
430
+ /**
431
+ * The grouped request options, ordered for both the destructured signature and the
432
+ * call passed to the underlying client.
433
+ */
434
+ const requestGroupOrder$1 = [
435
+ "path",
436
+ "query",
437
+ "body",
438
+ "headers"
439
+ ];
440
+ function maybeValueOrGetter(type) {
441
+ return `${type} | (() => ${type})`;
442
+ }
443
+ /**
444
+ * Builds the grouped `{ path, query, body, headers }` parameter that mirrors the client
445
+ * function signature. Only the groups the operation carries are emitted, typed from the
446
+ * operation's `Options`. `keys` narrows the emitted groups, used by the query key which
447
+ * never carries `headers`.
448
+ *
449
+ * By default the whole group is typed as the single `Options` reference. When
450
+ * `memberTypeWrapper` is set, each group is emitted as its own member typed from the matching
451
+ * `Options['<group>']` slice and wrapped, used by vue-query to apply
452
+ * `MaybeRefOrGetter` per group.
453
+ */
454
+ function buildGroupedRequestParam(node, options) {
455
+ const { resolver, keys = requestGroupOrder$1, memberTypeWrapper } = options;
456
+ const { groups, hasRequiredPath, hasRequiredQuery, hasRequiredHeader } = getRequestGroupOptionality(node);
457
+ const names = keys.filter((key) => groups[key]);
458
+ if (names.length === 0) return null;
459
+ const requiredByGroup = {
460
+ path: hasRequiredPath,
461
+ query: hasRequiredQuery,
462
+ body: groups.body,
463
+ headers: hasRequiredHeader
464
+ };
465
+ const isOptional = names.every((name) => !requiredByGroup[name]);
466
+ const optionsName = resolver.response.options(node);
467
+ const omittedKeys = requestGroupOrder$1.filter((key) => !keys.includes(key));
468
+ const optionsType = omittedKeys.length > 0 ? `Omit<${optionsName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : optionsName;
469
+ if (memberTypeWrapper) {
470
+ const members = names.map((name) => ({
471
+ name,
472
+ type: memberTypeWrapper(`${optionsType}['${name}']`),
473
+ optional: !requiredByGroup[name]
474
+ }));
475
+ return (0, _kubb_plugin_ts.createFunctionParameter)({
476
+ name: (0, _kubb_plugin_ts.createObjectBindingPattern)({ elements: names.map((name) => ({ name })) }),
477
+ type: (0, _kubb_plugin_ts.createTypeLiteral)({ members }),
478
+ optional: false,
479
+ ...isOptional ? { default: "{}" } : {}
480
+ });
481
+ }
482
+ return (0, _kubb_plugin_ts.createFunctionParameter)({
483
+ name: (0, _kubb_plugin_ts.createObjectBindingPattern)({ elements: names.map((name) => ({ name })) }),
484
+ type: optionsType,
485
+ optional: false,
486
+ ...isOptional ? { default: "{}" } : {}
487
+ });
488
+ }
489
+ /**
490
+ * Builds the shared `({ path, query, body, headers }, config = {})` parameter list for a
491
+ * TanStack query-options function. The leading parameter mirrors the client signature, and the
492
+ * trailing `config` is a partial `RequestConfig` minus the grouped data-shape keys, which are passed
493
+ * explicitly. Framework plugins wrap the result when needed, for example vue-query applies `MaybeRefOrGetter`.
494
+ */
495
+ function buildQueryOptionsParams(node, options) {
496
+ const { resolver, memberTypeWrapper } = options;
497
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
498
+ resolver,
499
+ memberTypeWrapper
500
+ }), (0, _kubb_plugin_ts.createFunctionParameter)({
501
+ name: "config",
502
+ type: `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`,
503
+ default: "{}"
504
+ })].filter((param) => param !== null) });
505
+ }
506
+ /**
507
+ * Builds the call to a client `<op>` function inside a query/mutation hook body. The function takes
508
+ * a single grouped options object, so the operation's request groups are passed as
509
+ * shorthand alongside the spread `config`, with `throwOnError: true` pinned last so a caller's config
510
+ * can't flip the query's error semantics. Queries thread the TanStack `signal`; mutations omit it.
511
+ *
512
+ * When `unwrapName` is set, each request group is passed as an explicit member unwrapped through it,
513
+ * used by vue-query to resolve refs and getters with `toValue(...)` at call time.
514
+ *
515
+ * @example
516
+ * ```ts
517
+ * buildClientCall(node, { clientName: 'getPetById', signal: true })
518
+ * // getPetById({ path, ...config, signal: config.signal ?? signal, throwOnError: true })
519
+ * ```
520
+ */
521
+ function buildClientCall(node, options) {
522
+ const { clientName, signal = false, unwrapName } = options;
523
+ const { groups } = getRequestGroupOptionality(node);
524
+ return `${clientName}({ ${[
525
+ "...config",
526
+ ...requestGroupOrder$1.filter((key) => groups[key]).map((name) => unwrapName ? `${name}: ${unwrapName(name)}` : name),
527
+ signal ? "signal: config.signal ?? signal" : null,
528
+ "throwOnError: true"
529
+ ].filter((part) => part !== null).join(", ")} })`;
530
+ }
531
+ /**
532
+ * Builds the `TData` / `TError` type expressions shared by every generated hook, joining the resolved
533
+ * success responses into `TData` and wrapping the error responses in `ResponseErrorConfig<...>`.
534
+ */
535
+ function buildResponseTypes(node, resolver) {
536
+ const successNames = resolveSuccessNames(node, resolver);
537
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.response.response(node);
538
+ const errorNames = resolveErrorNames(node, resolver);
539
+ return {
540
+ TData: responseName,
541
+ TError: `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`
542
+ };
543
+ }
544
+ function resolveFallbackPageParamType(initialPageParam) {
545
+ if (typeof initialPageParam === "number") return "number";
546
+ if (typeof initialPageParam === "boolean") return "boolean";
547
+ if (typeof initialPageParam !== "string") return "unknown";
548
+ if (!initialPageParam.includes(" as ")) return "string";
549
+ return initialPageParam.split(" as ").at(-1) ?? "unknown";
550
+ }
551
+ /**
552
+ * Resolves the `TPageParam` generic for the infinite-query hooks. Prefers the type read from the
553
+ * configured `queryParam` on the operation's query object, and falls back to the type inferred from
554
+ * `initialPageParam` when that parameter type is unavailable. Also returns the query params type name
555
+ * so callers can reuse it when rewriting the paginated request.
556
+ */
557
+ function resolvePageParamType(node, { resolver, initialPageParam, queryParam }) {
558
+ const firstQueryParam = getOperationParameters(node).query[0];
559
+ const groupName = firstQueryParam ? resolver.param.query(node, firstQueryParam) : null;
560
+ const queryParamsTypeName = groupName !== (firstQueryParam ? resolver.param.name(node, firstQueryParam) : null) ? groupName : null;
561
+ const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null;
562
+ if (!queryParamType) return {
563
+ queryParamsTypeName,
564
+ pageParamType: resolveFallbackPageParamType(initialPageParam)
565
+ };
566
+ return {
567
+ queryParamsTypeName,
568
+ pageParamType: initialPageParam !== void 0 && initialPageParam !== null ? `NonNullable<${queryParamType}>` : queryParamType
569
+ };
570
+ }
571
+ /**
572
+ * Applies the shared query defaults during plugin setup: `false` disables query generation, and an
573
+ * object merges over `methods: ['GET']` and the plugin's runtime `importPath`.
574
+ */
575
+ function resolveQueryConfig(query, options) {
576
+ if (query === false) return false;
577
+ return {
578
+ importPath: options.importPath,
579
+ methods: ["GET"],
580
+ ...query
581
+ };
582
+ }
583
+ /**
584
+ * Applies the shared mutation defaults during plugin setup: `false` disables mutation generation,
585
+ * and an object merges over `methods: ['POST', 'PUT', 'PATCH', 'DELETE']` and the plugin's runtime
586
+ * `importPath`.
587
+ */
588
+ function resolveMutationConfig(mutation, options) {
589
+ if (mutation === false) return false;
590
+ return {
591
+ importPath: options.importPath,
592
+ methods: [
593
+ "POST",
594
+ "PUT",
595
+ "PATCH",
596
+ "DELETE"
597
+ ],
598
+ ...mutation
599
+ };
600
+ }
601
+ /**
602
+ * Classifies an operation as a query or a mutation from the resolved `query` / `mutation` method lists.
603
+ * `query: false` still marks the operation as a query so the query-family generators keep matching it,
604
+ * and a method already claimed by `query` never counts as a mutation.
605
+ */
606
+ function classifyOperation(node, { query, mutation }) {
607
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
608
+ const queryMethods = new Set(query ? query.methods : []);
609
+ return {
610
+ isQuery,
611
+ isMutation: mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase())
612
+ };
613
+ }
614
+ /**
615
+ * Applies the shared infinite-query defaults during plugin setup: a falsy value disables infinite
616
+ * queries, and an object merges over `queryParam: 'id'` and `initialPageParam: 0` with the cursor
617
+ * paths cleared.
618
+ */
619
+ function resolveInfiniteConfig(infinite) {
620
+ if (!infinite) return false;
621
+ return {
622
+ queryParam: "id",
623
+ initialPageParam: 0,
624
+ cursorParam: null,
625
+ nextParam: null,
626
+ previousParam: null,
627
+ ...infinite
628
+ };
629
+ }
630
+ function matchesPattern(node, ov) {
631
+ const { type, pattern } = ov;
632
+ const matches = (value) => typeof pattern === "string" ? value === pattern : pattern.test(value);
633
+ if (type === "operationId") return matches(node.operationId);
634
+ if (type === "tag") return node.tags.some((t) => matches(t));
635
+ if (type === "path") return node.path !== void 0 && matches(node.path);
636
+ if (type === "method") return node.method !== void 0 && matches(node.method);
637
+ return false;
638
+ }
639
+ /**
640
+ * Resolves per-operation overrides (first matching override wins).
641
+ *
642
+ * @example
643
+ * ```ts
644
+ * const opts = resolveOperationOverrides(node, override)
645
+ * const queryOpts = 'query' in opts ? opts.query : defaultQuery
646
+ * ```
647
+ */
648
+ function resolveOperationOverrides(node, override) {
649
+ if (!override) return {};
650
+ return override.find((ov) => matchesPattern(node, ov))?.options ?? {};
651
+ }
652
+ /**
653
+ * Build QueryKey params as the grouped `{ path, query, body }` object (NO headers, NO config),
654
+ * typed from the operation's `Options` minus `url`. The query key transformer reads the
655
+ * grouped `path`/`query`/`body` bindings.
656
+ */
657
+ function buildQueryKeyParams(node, options) {
658
+ const { resolver } = options;
659
+ const groupedParam = buildGroupedRequestParam(node, {
660
+ resolver,
661
+ keys: [
662
+ "path",
663
+ "query",
664
+ "body"
665
+ ]
666
+ });
667
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedParam ? [groupedParam] : [] });
668
+ }
669
+ //#endregion
670
+ //#region ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
671
+ const declarationPrinter$7 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
672
+ const callPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
673
+ function InfiniteQueryOptions({ name, clientName, initialPageParam, cursorParam, nextParam, previousParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName }) {
674
+ const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver);
675
+ const { queryParamsTypeName, pageParamType } = resolvePageParamType(node, {
676
+ resolver: tsResolver,
677
+ initialPageParam,
678
+ queryParam
679
+ });
680
+ const groupedKeyParam = buildGroupedRequestParam(node, {
681
+ resolver: tsResolver,
682
+ keys: [
683
+ "path",
684
+ "query",
685
+ "body"
686
+ ],
687
+ memberTypeWrapper
688
+ });
689
+ const queryKeyParamsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedKeyParam ? [groupedKeyParam] : [] });
690
+ const queryKeyParamsCall = callPrinter$3.print(queryKeyParamsNode) ?? "";
691
+ const paramsNode = buildQueryOptionsParams(node, {
692
+ resolver: tsResolver,
693
+ memberTypeWrapper
694
+ });
695
+ const paramsSignature = declarationPrinter$7.print(paramsNode) ?? "";
696
+ const queryFnBody = `const { data } = await ${buildClientCall(node, {
697
+ clientName,
698
+ signal: true,
699
+ unwrapName
700
+ })}
701
+ return data`;
702
+ const hasNewParams = nextParam != null || previousParam != null;
703
+ const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
704
+ if (hasNewParams) {
705
+ const nextAccessor = nextParam ? getNestedAccessor(nextParam, "lastPage") : null;
706
+ const prevAccessor = previousParam ? getNestedAccessor(previousParam, "firstPage") : null;
707
+ return [nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null, prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null];
708
+ }
709
+ if (cursorParam) return [`getNextPageParam: (lastPage) => lastPage['${cursorParam}']`, `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`];
710
+ return ["getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1", "getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1"];
711
+ })();
712
+ const queryOptionsArr = [
713
+ `initialPageParam: ${typeof initialPageParam === "string" ? JSON.stringify(initialPageParam) : initialPageParam}`,
714
+ getNextPageParamExpr,
715
+ getPreviousPageParamExpr
716
+ ].filter(Boolean);
717
+ const infiniteOverrideParams = queryParam && queryParamsTypeName ? `query = {
718
+ ...(query ?? {}),
719
+ ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
720
+ } as ${queryParamsTypeName}` : "";
721
+ const queryFnArgs = infiniteOverrideParams ? "{ signal, pageParam }" : "{ signal }";
722
+ const queryFnStatements = infiniteOverrideParams ? `${infiniteOverrideParams}\n ${queryFnBody}` : queryFnBody;
723
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
724
+ name,
725
+ isExportable: true,
726
+ isIndexable: true,
727
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
728
+ name,
729
+ export: true,
730
+ params: paramsSignature,
731
+ children: `
732
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
733
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, ${queryKeyType}, ${pageParamType}>({
734
+ queryKey,
735
+ queryFn: async (${queryFnArgs}) => {
736
+ ${queryFnStatements}
737
+ },
738
+ ${queryOptionsArr.join(",\n ")}
739
+ })
740
+ `
741
+ })
742
+ });
743
+ }
744
+ //#endregion
745
+ //#region ../../internals/tanstack-query/src/components/MutationKey.tsx
746
+ const declarationPrinter$6 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
747
+ const mutationKeyTransformer = ({ node }) => {
748
+ if (!node.path) return [];
749
+ return [`{ url: '${kubb_kit.Url.toPath(node.path)}' }`];
750
+ };
751
+ function MutationKey({ name, node, transformer }) {
752
+ const paramsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: [] });
753
+ const paramsSignature = declarationPrinter$6.print(paramsNode) ?? "";
754
+ const keys = (transformer ?? mutationKeyTransformer)({
755
+ node,
756
+ casing: "camelcase"
757
+ });
758
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
759
+ name,
760
+ isExportable: true,
761
+ isIndexable: true,
762
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function.Arrow, {
763
+ name,
764
+ export: true,
765
+ params: paramsSignature,
766
+ singleLine: true,
767
+ children: `[${keys.join(", ")}] as const`
768
+ })
769
+ });
770
+ }
771
+ //#endregion
772
+ //#region ../../internals/tanstack-query/src/resolver.ts
773
+ /**
774
+ * Builds the shared query namespace for a variant. Spread the result into
775
+ * `createResolver` once per variant the plugin supports.
776
+ *
777
+ * @example
778
+ * ```ts
779
+ * createResolver<PluginReactQuery>({
780
+ * query: createQueryResolver(),
781
+ * suspenseQuery: createQueryResolver('Suspense'),
782
+ * })
783
+ * ```
784
+ */
785
+ function createQueryResolver(variant = "") {
786
+ return {
787
+ name(node) {
788
+ return `use${capitalize(this.name(node.operationId))}${variant}`;
789
+ },
790
+ optionsName(node) {
791
+ return `${this.name(node.operationId)}${variant}QueryOptions`;
792
+ },
793
+ keyName(node) {
794
+ return `${this.name(node.operationId)}${variant}QueryKey`;
795
+ },
796
+ keyTypeName(node) {
797
+ return `${capitalize(this.name(node.operationId))}${variant}QueryKey`;
798
+ },
799
+ clientName(node) {
800
+ return `${this.name(node.operationId)}${variant}`;
801
+ }
802
+ };
19
803
  }
20
804
  /**
21
- * Naming convention resolver for React Query plugin.
805
+ * Builds the shared mutation namespace. Spread the result into
806
+ * `createResolver` and add plugin-specific methods (`optionsName`,
807
+ * `typeName`, `argTypeName`) next to it.
22
808
  *
23
- * Provides default naming helpers using camelCase for functions and file paths.
809
+ * @example
810
+ * ```ts
811
+ * createResolver<PluginSwr>({ mutation: { ...createMutationResolver(), argTypeName(node) {...} } })
812
+ * ```
813
+ */
814
+ function createMutationResolver() {
815
+ return {
816
+ name(node) {
817
+ return `use${capitalize(this.name(node.operationId))}`;
818
+ },
819
+ keyName(node) {
820
+ return `${this.name(node.operationId)}MutationKey`;
821
+ }
822
+ };
823
+ }
824
+ //#endregion
825
+ //#region ../../internals/tanstack-query/src/components/QueryKey.tsx
826
+ const declarationPrinter$5 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
827
+ const queryKeyTransformer = ({ node }) => {
828
+ if (!node.path) return [];
829
+ const hasPathParams = getOperationParameters(node).path.length > 0;
830
+ const hasQueryParams = getOperationParameters(node).query.length > 0;
831
+ const hasRequestBody = !!node.requestBody?.content?.[0]?.schema;
832
+ return [
833
+ hasPathParams ? `{ url: '${kubb_kit.Url.toPath(node.path)}', params: path }` : `{ url: '${kubb_kit.Url.toPath(node.path)}' }`,
834
+ hasQueryParams ? "...(query ? [query] : [])" : null,
835
+ hasRequestBody ? "...(body ? [body] : [])" : null
836
+ ].filter(Boolean);
837
+ };
838
+ function QueryKey({ name, node, tsResolver, typeName, transformer }) {
839
+ const paramsNode = buildQueryKeyParams(node, { resolver: tsResolver });
840
+ const paramsSignature = declarationPrinter$5.print(paramsNode) ?? "";
841
+ const keys = (transformer ?? queryKeyTransformer)({
842
+ node,
843
+ casing: "camelcase"
844
+ });
845
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
846
+ name,
847
+ isExportable: true,
848
+ isIndexable: true,
849
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function.Arrow, {
850
+ name,
851
+ export: true,
852
+ params: paramsSignature,
853
+ singleLine: true,
854
+ children: `[${keys.join(", ")}] as const`
855
+ })
856
+ }), /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
857
+ name: typeName,
858
+ isTypeOnly: true,
859
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Type, {
860
+ name: typeName,
861
+ children: `ReturnType<typeof ${name}>`
862
+ })
863
+ })] });
864
+ }
865
+ //#endregion
866
+ //#region src/generators/customHookOptionsFileGenerator.tsx
867
+ /**
868
+ * Scaffolds the user-editable `useCustomHookOptions` file when
869
+ * `pluginReactQuery({ customOptions: { ... } })` is configured. The file is
870
+ * only created when it does not already exist, so user edits persist across
871
+ * regeneration.
872
+ */
873
+ const customHookOptionsFileGenerator = (0, kubb_kit.defineGenerator)({
874
+ name: "react-query-custom-hook-options-file",
875
+ renderer: kubb_jsx.jsxRenderer,
876
+ operations(nodes, ctx) {
877
+ const { resolver, root } = ctx;
878
+ const { output, customOptions, query, group } = ctx.options;
879
+ if (!customOptions) return null;
880
+ const { importPath, name } = customOptions;
881
+ const hookOptionsName = resolver.hook.optionsName();
882
+ const customHookOptionsName = resolver.hook.customOptionsName();
883
+ const reactQueryImportPath = query ? query.importPath : "@tanstack/react-query";
884
+ let hookFilePath;
885
+ const firstNode = nodes[0];
886
+ if (firstNode) {
887
+ const hookName = resolver.query.name(firstNode);
888
+ hookFilePath = resolver.file({
889
+ name: hookName,
890
+ extname: ".ts",
891
+ tag: firstNode.tags[0] ?? "default",
892
+ path: firstNode.path,
893
+ root,
894
+ output,
895
+ group: group ?? void 0
896
+ }).path;
897
+ } else hookFilePath = node_path.default.resolve(root, "index.ts");
898
+ const ensureExtension = (filePath, extname) => {
899
+ if (node_path.default.extname(filePath) === "") return filePath + extname;
900
+ return filePath;
901
+ };
902
+ const basePath = node_path.default.dirname(hookFilePath);
903
+ const actualFilePath = ensureExtension(importPath, ".ts");
904
+ const file = {
905
+ baseName: node_path.default.basename(actualFilePath),
906
+ name: node_path.default.basename(actualFilePath, node_path.default.extname(actualFilePath)),
907
+ path: node_path.default.resolve(basePath, actualFilePath)
908
+ };
909
+ if (node_fs.default.existsSync(file.path)) return null;
910
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
911
+ baseName: file.baseName,
912
+ path: file.path,
913
+ children: [
914
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
915
+ name: ["QueryClient"],
916
+ path: reactQueryImportPath,
917
+ isTypeOnly: true
918
+ }),
919
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
920
+ name: ["useQueryClient"],
921
+ path: reactQueryImportPath
922
+ }),
923
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
924
+ name: [hookOptionsName],
925
+ root: file.path,
926
+ path: node_path.default.resolve(root, "./index.ts")
927
+ }),
928
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File.Source, {
929
+ name: file.name,
930
+ isExportable: true,
931
+ isIndexable: true,
932
+ children: [/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
933
+ name: customHookOptionsName,
934
+ params: "{ queryClient }: { queryClient: QueryClient }",
935
+ returnType: `Partial<${hookOptionsName}>`,
936
+ children: `return {
937
+ // TODO: Define custom hook options here
938
+ // Example:
939
+ // useUpdatePetHook: {
940
+ // onSuccess: () => {
941
+ // void queryClient.invalidateQueries({ queryKey: ['pet'] })
942
+ // }
943
+ // }
944
+ }`
945
+ }), /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
946
+ name,
947
+ generics: `T extends keyof ${hookOptionsName}`,
948
+ params: "{ hookName, operationId }: { hookName: T, operationId: string }",
949
+ returnType: `${hookOptionsName}[T]`,
950
+ export: true,
951
+ children: `const queryClient = useQueryClient()
952
+ const customOptions = ${customHookOptionsName}({ queryClient })
953
+ return customOptions[hookName] ?? {}`
954
+ })]
955
+ })
956
+ ]
957
+ });
958
+ }
959
+ });
960
+ //#endregion
961
+ //#region src/utils.ts
962
+ const requestGroupOrder = [
963
+ "path",
964
+ "query",
965
+ "body",
966
+ "headers"
967
+ ];
968
+ /**
969
+ * Builds the object literal that resolves each request group to a concrete value, unwrapping a getter
970
+ * once before the value reaches the plain `queryKey`/`queryOptions` helpers. A getter must never reach a
971
+ * React Query key, which is hashed structurally. Returns `null` when the operation carries no request group.
24
972
  *
25
973
  * @example
26
- * `resolverReactQuery.default('list pets', 'function') // → 'listPets'`
974
+ * ```ts
975
+ * buildResolvedRequestParams(node) // { path: typeof path === 'function' ? path() : path }
976
+ * ```
27
977
  */
28
- const resolverReactQuery = (0, _kubb_core.defineResolver)(() => ({
29
- name: "default",
978
+ function buildResolvedRequestParams(node) {
979
+ const groups = getRequestGroups(node);
980
+ const names = requestGroupOrder.filter((key) => groups[key]);
981
+ if (names.length === 0) return null;
982
+ return `{ ${names.map((name) => `${name}: typeof ${name} === 'function' ? ${name}() : ${name}`).join(", ")} }`;
983
+ }
984
+ //#endregion
985
+ //#region src/generators/hookOptionsGenerator.tsx
986
+ /**
987
+ * Emits the `HookOptions` type used by `customOptions`. Enabled when
988
+ * `pluginReactQuery({ customOptions: { ... } })`. The generated type lists
989
+ * every hook keyed by name so user-supplied options stay in sync with the
990
+ * generated hooks at compile time.
991
+ */
992
+ const hookOptionsGenerator = (0, kubb_kit.defineGenerator)({
993
+ name: "react-query-hook-options",
994
+ renderer: kubb_jsx.jsxRenderer,
995
+ operations(nodes, ctx) {
996
+ const { resolver, config, root } = ctx;
997
+ const { output, customOptions, query, mutation, suspense, infinite, group, override, hooks } = ctx.options;
998
+ if (!customOptions || !hooks) return null;
999
+ const name = resolver.hook.optionsName();
1000
+ const resolvedFile = resolver.file({
1001
+ name,
1002
+ extname: ".ts",
1003
+ root,
1004
+ output,
1005
+ group: group ?? void 0
1006
+ });
1007
+ const hookOptionsFile = {
1008
+ ...resolvedFile,
1009
+ baseName: `${name}.ts`,
1010
+ path: resolvedFile.path.replace(/[^/\\]+\.ts$/, `${name}.ts`)
1011
+ };
1012
+ const imports = [];
1013
+ const hookOptions = {};
1014
+ for (const node of nodes) {
1015
+ if (!kubb_kit.ast.isHttpOperationNode(node)) continue;
1016
+ const opOverrides = resolveOperationOverrides(node, override);
1017
+ const nodeQuery = "query" in opOverrides ? opOverrides.query : query;
1018
+ const nodeMutation = "mutation" in opOverrides ? opOverrides.mutation : mutation;
1019
+ const nodeInfinite = "infinite" in opOverrides ? opOverrides.infinite : infinite;
1020
+ const nodeInfiniteOptions = nodeInfinite && typeof nodeInfinite === "object" ? nodeInfinite : null;
1021
+ const isQueryOp = nodeQuery === false ? !!query && query.methods.some((m) => node.method.toLowerCase() === m.toLowerCase()) : !!nodeQuery && nodeQuery.methods.some((m) => node.method.toLowerCase() === m.toLowerCase());
1022
+ const nodeQueryMethods = new Set(nodeQuery ? nodeQuery.methods : []);
1023
+ const isMutationOp = nodeMutation !== false && !isQueryOp && (nodeMutation ? nodeMutation.methods : []).some((m) => !nodeQueryMethods.has(m) && node.method.toLowerCase() === m.toLowerCase());
1024
+ const isSuspenseOp = !!suspense;
1025
+ const isInfiniteOp = !!nodeInfiniteOptions;
1026
+ if (isQueryOp) {
1027
+ const queryOptionsName = resolver.query.optionsName(node);
1028
+ const queryHookName = resolver.query.name(node);
1029
+ const queryHookFile = resolver.file({
1030
+ ...operationFileEntry(node, queryHookName),
1031
+ root,
1032
+ output,
1033
+ group: group ?? void 0
1034
+ });
1035
+ imports.push(/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1036
+ name: [queryOptionsName],
1037
+ root: hookOptionsFile.path,
1038
+ path: queryHookFile.path
1039
+ }));
1040
+ hookOptions[queryHookName] = `Partial<ReturnType<typeof ${queryOptionsName}>>`;
1041
+ if (isSuspenseOp) {
1042
+ const suspenseOptionsName = resolver.suspenseQuery.optionsName(node);
1043
+ const suspenseHookName = resolver.suspenseQuery.name(node);
1044
+ const suspenseHookFile = resolver.file({
1045
+ ...operationFileEntry(node, suspenseHookName),
1046
+ root,
1047
+ output,
1048
+ group: group ?? void 0
1049
+ });
1050
+ imports.push(/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1051
+ name: [suspenseOptionsName],
1052
+ root: hookOptionsFile.path,
1053
+ path: suspenseHookFile.path
1054
+ }));
1055
+ hookOptions[suspenseHookName] = `Partial<ReturnType<typeof ${suspenseOptionsName}>>`;
1056
+ }
1057
+ if (isInfiniteOp) {
1058
+ const normalizeKey = (key) => key.replace(/\?$/, "");
1059
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
1060
+ if (nodeInfiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === nodeInfiniteOptions.queryParam) : false) {
1061
+ const infiniteOptionsName = resolver.infiniteQuery.optionsName(node);
1062
+ const infiniteHookName = resolver.infiniteQuery.name(node);
1063
+ const infiniteHookFile = resolver.file({
1064
+ ...operationFileEntry(node, infiniteHookName),
1065
+ root,
1066
+ output,
1067
+ group: group ?? void 0
1068
+ });
1069
+ imports.push(/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1070
+ name: [infiniteOptionsName],
1071
+ root: hookOptionsFile.path,
1072
+ path: infiniteHookFile.path
1073
+ }));
1074
+ hookOptions[infiniteHookName] = `Partial<ReturnType<typeof ${infiniteOptionsName}>>`;
1075
+ if (isSuspenseOp) {
1076
+ const suspenseInfiniteOptionsName = resolver.suspenseInfiniteQuery.optionsName(node);
1077
+ const suspenseInfiniteHookName = resolver.suspenseInfiniteQuery.name(node);
1078
+ const suspenseInfiniteHookFile = resolver.file({
1079
+ ...operationFileEntry(node, suspenseInfiniteHookName),
1080
+ root,
1081
+ output,
1082
+ group: group ?? void 0
1083
+ });
1084
+ imports.push(/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1085
+ name: [suspenseInfiniteOptionsName],
1086
+ root: hookOptionsFile.path,
1087
+ path: suspenseInfiniteHookFile.path
1088
+ }));
1089
+ hookOptions[suspenseInfiniteHookName] = `Partial<ReturnType<typeof ${suspenseInfiniteOptionsName}>>`;
1090
+ }
1091
+ }
1092
+ }
1093
+ }
1094
+ if (isMutationOp) {
1095
+ const mutationOptionsName = resolver.mutation.optionsName(node);
1096
+ const mutationHookName = resolver.mutation.name(node);
1097
+ const mutationHookFile = resolver.file({
1098
+ ...operationFileEntry(node, mutationHookName),
1099
+ root,
1100
+ output,
1101
+ group: group ?? void 0
1102
+ });
1103
+ imports.push(/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1104
+ name: [mutationOptionsName],
1105
+ root: hookOptionsFile.path,
1106
+ path: mutationHookFile.path
1107
+ }));
1108
+ hookOptions[mutationHookName] = `Partial<ReturnType<typeof ${mutationOptionsName}>>`;
1109
+ }
1110
+ }
1111
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
1112
+ baseName: hookOptionsFile.baseName,
1113
+ path: hookOptionsFile.path,
1114
+ meta: hookOptionsFile.meta,
1115
+ banner: resolver.default.banner(ctx.meta, {
1116
+ output,
1117
+ config,
1118
+ file: {
1119
+ path: hookOptionsFile.path,
1120
+ baseName: hookOptionsFile.baseName
1121
+ }
1122
+ }),
1123
+ footer: resolver.default.footer(ctx.meta, {
1124
+ output,
1125
+ config,
1126
+ file: {
1127
+ path: hookOptionsFile.path,
1128
+ baseName: hookOptionsFile.baseName
1129
+ }
1130
+ }),
1131
+ children: [imports, /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
1132
+ name,
1133
+ isExportable: true,
1134
+ isIndexable: true,
1135
+ isTypeOnly: true,
1136
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Type, {
1137
+ export: true,
1138
+ name,
1139
+ children: `{ ${Object.keys(hookOptions).map((key) => `${JSON.stringify(key)}: ${hookOptions[key]}`).join(", ")} }`
1140
+ })
1141
+ })]
1142
+ });
1143
+ }
1144
+ });
1145
+ //#endregion
1146
+ //#region src/components/InfiniteQuery.tsx
1147
+ const declarationPrinter$4 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1148
+ function buildInfiniteQueryParamsNode(node, options) {
1149
+ const { resolver, pageParamGeneric, observerOptionsName } = options;
1150
+ const optionsParam = (0, _kubb_plugin_ts.createFunctionParameter)({
1151
+ name: "options",
1152
+ type: `{
1153
+ query?: Partial<${observerOptionsName}<TQueryFnData, TError, TData, TQueryKey, ${pageParamGeneric}>> & { client?: QueryClient },
1154
+ client?: ${buildClientOptionType()}
1155
+ }`,
1156
+ default: "{}"
1157
+ });
1158
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
1159
+ resolver,
1160
+ memberTypeWrapper: maybeValueOrGetter
1161
+ }), optionsParam].filter((param) => param !== null) });
1162
+ }
1163
+ function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, initialPageParam, queryParam, customOptions, suspense }) {
1164
+ const { TData: responseType, TError: errorType } = buildResponseTypes(node, tsResolver);
1165
+ const { pageParamType } = resolvePageParamType(node, {
1166
+ resolver: tsResolver,
1167
+ initialPageParam,
1168
+ queryParam
1169
+ });
1170
+ const hookName = suspense ? "useSuspenseInfiniteQuery" : "useInfiniteQuery";
1171
+ const observerOptionsName = suspense ? "UseSuspenseInfiniteQueryOptions" : "InfiniteQueryObserverOptions";
1172
+ const returnType = `${suspense ? "UseSuspenseInfiniteQueryResult" : "UseInfiniteQueryResult"}<TData, TError> & { queryKey: TQueryKey }`;
1173
+ const generics = [
1174
+ `TQueryFnData = ${responseType}`,
1175
+ `TError = ${errorType}`,
1176
+ "TData = InfiniteData<TQueryFnData>",
1177
+ `TQueryKey extends QueryKey = ${queryKeyTypeName}`,
1178
+ `TPageParam = ${pageParamType}`
1179
+ ];
1180
+ const resolvedParams = buildResolvedRequestParams(node);
1181
+ const queryKeyArgs = resolvedParams ? "resolvedParams" : "";
1182
+ const queryOptionsArgs = resolvedParams ? "resolvedParams, config" : "config";
1183
+ const paramsNode = buildInfiniteQueryParamsNode(node, {
1184
+ resolver: tsResolver,
1185
+ pageParamGeneric: "TPageParam",
1186
+ observerOptionsName
1187
+ });
1188
+ const paramsSignature = declarationPrinter$4.print(paramsNode) ?? "";
1189
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
1190
+ name,
1191
+ isExportable: true,
1192
+ isIndexable: true,
1193
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
1194
+ name,
1195
+ export: true,
1196
+ generics: generics.join(", "),
1197
+ params: paramsSignature,
1198
+ returnType: void 0,
1199
+ JSDoc: { comments: buildOperationComments(node) },
1200
+ children: `
1201
+ const { query: queryConfig = {}, client: config = {} } = options ?? {}
1202
+ const { client: queryClient, ...resolvedOptions } = queryConfig${resolvedParams ? `\n const resolvedParams = ${resolvedParams}` : ""}
1203
+ const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyArgs})${customOptions ? `\n const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ""}
1204
+
1205
+ const queryResult = ${hookName}({
1206
+ ...${queryOptionsName}(${queryOptionsArgs}),${customOptions ? "\n ...customOptions," : ""}
1207
+ ...resolvedOptions,
1208
+ queryKey,
1209
+ } as unknown as ${observerOptionsName}<TQueryFnData, TError, TData, TQueryKey, TPageParam>, queryClient) as ${returnType}
1210
+
1211
+ queryResult.queryKey = queryKey as TQueryKey
1212
+
1213
+ return queryResult
1214
+ `
1215
+ })
1216
+ });
1217
+ }
1218
+ //#endregion
1219
+ //#region src/components/MutationOptions.tsx
1220
+ const declarationPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1221
+ const callPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1222
+ function buildMutationConfigParamsNode(node) {
1223
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
1224
+ name: "config",
1225
+ type: buildRequestConfigType(node),
1226
+ default: "{}"
1227
+ })] });
1228
+ }
1229
+ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName }) {
1230
+ const { TData, TError } = buildResponseTypes(node, tsResolver);
1231
+ const configParamsNode = buildMutationConfigParamsNode(node);
1232
+ const paramsSignature = declarationPrinter$3.print(configParamsNode) ?? "";
1233
+ const groupedParam = buildGroupedRequestParam(node, { resolver: tsResolver });
1234
+ const hasMutationParams = groupedParam !== null;
1235
+ const groupedParamsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedParam ? [groupedParam] : [] });
1236
+ const TRequest = hasMutationParams ? tsResolver.response.options(node) : "undefined";
1237
+ const argBindingStr = hasMutationParams ? callPrinter$2.print(groupedParamsNode) ?? "" : "_";
1238
+ const mutationFnBody = `const { data } = await ${buildClientCall(node, {
1239
+ clientName,
1240
+ signal: false
1241
+ })}
1242
+ return data`;
1243
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
1244
+ name,
1245
+ isExportable: true,
1246
+ isIndexable: true,
1247
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
1248
+ name,
1249
+ export: true,
1250
+ params: paramsSignature,
1251
+ generics: ["TContext = unknown"],
1252
+ children: `
1253
+ const mutationKey = ${mutationKeyName}()
1254
+ return mutationOptions<${TData}, ${TError}, ${TRequest}, TContext>({
1255
+ mutationKey,
1256
+ mutationFn: async(${argBindingStr}) => {
1257
+ ${mutationFnBody}
1258
+ },
1259
+ })
1260
+ `
1261
+ })
1262
+ });
1263
+ }
1264
+ //#endregion
1265
+ //#region src/components/Mutation.tsx
1266
+ const declarationPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1267
+ const callPrinter$1 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1268
+ function resolveMutationRequestType(node, resolver) {
1269
+ return buildGroupedRequestParam(node, { resolver }) ? resolver.response.options(node) : "undefined";
1270
+ }
1271
+ function buildMutationParamsNode(node, options) {
1272
+ const { resolver } = options;
1273
+ const { TData, TError } = buildResponseTypes(node, resolver);
1274
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
1275
+ name: "options",
1276
+ type: `{
1277
+ mutation?: UseMutationOptions<${[
1278
+ TData,
1279
+ TError,
1280
+ resolveMutationRequestType(node, resolver),
1281
+ "TContext"
1282
+ ].join(", ")}> & { client?: QueryClient },
1283
+ client?: ${buildRequestConfigType(node)},
1284
+ }`,
1285
+ default: "{}"
1286
+ })] });
1287
+ }
1288
+ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName, customOptions }) {
1289
+ const { TData, TError } = buildResponseTypes(node, tsResolver);
1290
+ const generics = [
1291
+ TData,
1292
+ TError,
1293
+ resolveMutationRequestType(node, tsResolver),
1294
+ "TContext"
1295
+ ].join(", ");
1296
+ const returnType = `UseMutationResult<${generics}>`;
1297
+ const mutationOptionsConfigNode = buildMutationConfigParamsNode(node);
1298
+ const mutationOptionsParamsCall = callPrinter$1.print(mutationOptionsConfigNode) ?? "";
1299
+ const paramsNode = buildMutationParamsNode(node, { resolver: tsResolver });
1300
+ const paramsSignature = declarationPrinter$2.print(paramsNode) ?? "";
1301
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
1302
+ name,
1303
+ isExportable: true,
1304
+ isIndexable: true,
1305
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
1306
+ name,
1307
+ export: true,
1308
+ params: paramsSignature,
1309
+ JSDoc: { comments: buildOperationComments(node) },
1310
+ generics: ["TContext"],
1311
+ children: `
1312
+ const { mutation = {}, client: config = {} } = options ?? {}
1313
+ const { client: queryClient, ...mutationOptions } = mutation;
1314
+ const mutationKey = mutationOptions.mutationKey ?? ${mutationKeyName}()
1315
+
1316
+ const baseOptions = ${mutationOptionsName}(${mutationOptionsParamsCall}) as UseMutationOptions<${generics}>${customOptions ? `\n const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' }) as UseMutationOptions<${generics}>` : ""}
1317
+
1318
+ return useMutation<${generics}>({
1319
+ ...baseOptions,${customOptions ? "\n ...customOptions," : ""}
1320
+ mutationKey,
1321
+ ...mutationOptions,
1322
+ }, queryClient) as ${returnType}
1323
+ `
1324
+ })
1325
+ });
1326
+ }
1327
+ //#endregion
1328
+ //#region src/components/Query.tsx
1329
+ const declarationPrinter$1 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1330
+ function buildQueryParamsNode(node, options) {
1331
+ const { resolver, observerOptionsType } = options;
1332
+ const optionsParam = (0, _kubb_plugin_ts.createFunctionParameter)({
1333
+ name: "options",
1334
+ type: `{
1335
+ query?: Partial<${observerOptionsType}> & { client?: QueryClient },
1336
+ client?: ${buildClientOptionType()}
1337
+ }`,
1338
+ default: "{}"
1339
+ });
1340
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
1341
+ resolver,
1342
+ memberTypeWrapper: maybeValueOrGetter
1343
+ }), optionsParam].filter((param) => param !== null) });
1344
+ }
1345
+ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense }) {
1346
+ const { TData, TError } = buildResponseTypes(node, tsResolver);
1347
+ const hookName = suspense ? "useSuspenseQuery" : "useQuery";
1348
+ const observerOptionsName = suspense ? "UseSuspenseQueryOptions" : "QueryObserverOptions";
1349
+ const observerOptionsType = suspense ? `${observerOptionsName}<${[
1350
+ TData,
1351
+ TError,
1352
+ "TData",
1353
+ "TQueryKey"
1354
+ ].join(", ")}>` : `${observerOptionsName}<${[
1355
+ TData,
1356
+ TError,
1357
+ "TData",
1358
+ "TQueryData",
1359
+ "TQueryKey"
1360
+ ].join(", ")}>`;
1361
+ const returnType = `${suspense ? "UseSuspenseQueryResult" : "UseQueryResult"}<TData, ${TError}> & { queryKey: TQueryKey }`;
1362
+ const generics = suspense ? [`TData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`] : [
1363
+ `TData = ${TData}`,
1364
+ `TQueryData = ${TData}`,
1365
+ `TQueryKey extends QueryKey = ${queryKeyTypeName}`
1366
+ ];
1367
+ const resolvedParams = buildResolvedRequestParams(node);
1368
+ const queryKeyArgs = resolvedParams ? "resolvedParams" : "";
1369
+ const queryOptionsArgs = resolvedParams ? "resolvedParams, config" : "config";
1370
+ const paramsNode = buildQueryParamsNode(node, {
1371
+ resolver: tsResolver,
1372
+ observerOptionsType
1373
+ });
1374
+ const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
1375
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
1376
+ name,
1377
+ isExportable: true,
1378
+ isIndexable: true,
1379
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
1380
+ name,
1381
+ export: true,
1382
+ generics: generics.join(", "),
1383
+ params: paramsSignature,
1384
+ returnType: void 0,
1385
+ JSDoc: { comments: buildOperationComments(node) },
1386
+ children: `
1387
+ const { query: queryConfig = {}, client: config = {} } = options ?? {}
1388
+ const { client: queryClient, ...resolvedOptions } = queryConfig${resolvedParams ? `\n const resolvedParams = ${resolvedParams}` : ""}
1389
+ const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyArgs})${customOptions ? `\n const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ""}
1390
+
1391
+ const queryResult = ${hookName}({
1392
+ ...${queryOptionsName}(${queryOptionsArgs}),${customOptions ? "\n ...customOptions," : ""}
1393
+ ...resolvedOptions,
1394
+ queryKey,
1395
+ } as unknown as ${observerOptionsName}, queryClient) as ${returnType}
1396
+
1397
+ queryResult.queryKey = queryKey as TQueryKey
1398
+
1399
+ return queryResult
1400
+ `
1401
+ })
1402
+ });
1403
+ }
1404
+ //#endregion
1405
+ //#region src/components/QueryOptions.tsx
1406
+ const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
1407
+ const callPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
1408
+ function QueryOptions({ name, clientName, node, tsResolver, queryKeyName }) {
1409
+ const { TData, TError } = buildResponseTypes(node, tsResolver);
1410
+ const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
1411
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? "";
1412
+ const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
1413
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
1414
+ const queryFnBody = `const { data } = await ${buildClientCall(node, {
1415
+ clientName,
1416
+ signal: true
1417
+ })}
1418
+ return data`;
1419
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
1420
+ name,
1421
+ isExportable: true,
1422
+ isIndexable: true,
1423
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
1424
+ name,
1425
+ export: true,
1426
+ params: paramsSignature,
1427
+ children: `
1428
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
1429
+ return queryOptions<${TData}, ${TError}, ${TData}, typeof queryKey>({
1430
+ queryKey,
1431
+ queryFn: async ({ signal }) => {
1432
+ ${queryFnBody}
1433
+ },
1434
+ })
1435
+ `
1436
+ })
1437
+ });
1438
+ }
1439
+ //#endregion
1440
+ //#region src/generators/infiniteQueryGenerator.tsx
1441
+ /**
1442
+ * Built-in generator for `useInfiniteQuery` hooks. Enabled when
1443
+ * `pluginReactQuery({ infinite: { ... }, hooks: true })`. Emits one
1444
+ * `useFooInfiniteQuery` hook per query operation, wiring the configured
1445
+ * `nextParam` / `previousParam` paths into TanStack Query's cursor-based
1446
+ * pagination.
1447
+ */
1448
+ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1449
+ name: "react-infinite-query",
1450
+ renderer: kubb_jsx.jsxRenderer,
1451
+ operation(node, ctx) {
1452
+ if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
1453
+ const { config, driver, resolver, root } = ctx;
1454
+ const { output, query, mutation, infinite, client, group, customOptions, hooks } = ctx.options;
1455
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1456
+ if (!pluginTs) return null;
1457
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1458
+ const { isQuery, isMutation } = classifyOperation(node, {
1459
+ query,
1460
+ mutation
1461
+ });
1462
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1463
+ if (!isQuery || isMutation || !infiniteOptions || !hooks) return null;
1464
+ const normalizeKey = (key) => key.replace(/\?$/, "");
1465
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
1466
+ if (!(infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false)) return null;
1467
+ const importPath = query ? query.importPath : "@tanstack/react-query";
1468
+ const contractOp = resolveClientOperation({
1469
+ clientPlugin: { pluginName: client.pluginName },
1470
+ driver,
1471
+ node,
1472
+ root,
1473
+ output
1474
+ });
1475
+ if (!contractOp) return null;
1476
+ const queryName = resolver.infiniteQuery.name(node);
1477
+ const queryOptionsName = resolver.infiniteQuery.optionsName(node);
1478
+ const queryKeyName = resolver.infiniteQuery.keyName(node);
1479
+ const queryKeyTypeName = resolver.infiniteQuery.keyTypeName(node);
1480
+ const meta = {
1481
+ file: resolver.file({
1482
+ ...operationFileEntry(node, queryName),
1483
+ root,
1484
+ output,
1485
+ group: group ?? void 0
1486
+ }),
1487
+ fileTs: tsResolver.file({
1488
+ ...operationFileEntry(node, node.operationId),
1489
+ root,
1490
+ output: pluginTs.options?.output ?? output,
1491
+ group: pluginTs.options?.group ?? void 0
1492
+ })
1493
+ };
1494
+ const { queryParamsTypeName } = resolvePageParamType(node, {
1495
+ resolver: tsResolver,
1496
+ initialPageParam: infiniteOptions.initialPageParam,
1497
+ queryParam: infiniteOptions.queryParam
1498
+ });
1499
+ const importedTypeNames = [
1500
+ tsResolver.response.options(node),
1501
+ queryParamsTypeName,
1502
+ ...resolveOperationTypeNames(node, tsResolver, {
1503
+ exclude: [queryKeyTypeName],
1504
+ order: "body-response-first",
1505
+ includeParams: false
1506
+ })
1507
+ ].filter((name) => Boolean(name));
1508
+ const calledClientName = contractOp.name;
1509
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
1510
+ baseName: meta.file.baseName,
1511
+ path: meta.file.path,
1512
+ meta: meta.file.meta,
1513
+ banner: resolver.default.banner(ctx.meta, {
1514
+ output,
1515
+ config,
1516
+ file: {
1517
+ path: meta.file.path,
1518
+ baseName: meta.file.baseName
1519
+ }
1520
+ }),
1521
+ footer: resolver.default.footer(ctx.meta, {
1522
+ output,
1523
+ config,
1524
+ file: {
1525
+ path: meta.file.path,
1526
+ baseName: meta.file.baseName
1527
+ }
1528
+ }),
1529
+ children: [
1530
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1531
+ name: [contractOp.name],
1532
+ root: meta.file.path,
1533
+ path: contractOp.path
1534
+ }),
1535
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1536
+ name: ["RequestConfig", "ResponseErrorConfig"],
1537
+ root: meta.file.path,
1538
+ path: contractOp.clientPath,
1539
+ isTypeOnly: true
1540
+ }),
1541
+ customOptions && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1542
+ name: [customOptions.name],
1543
+ path: customOptions.importPath
1544
+ }),
1545
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1546
+ name: Array.from(new Set(importedTypeNames)),
1547
+ root: meta.file.path,
1548
+ path: meta.fileTs.path,
1549
+ isTypeOnly: true
1550
+ }),
1551
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(QueryKey, {
1552
+ name: queryKeyName,
1553
+ typeName: queryKeyTypeName,
1554
+ node,
1555
+ tsResolver,
1556
+ transformer: ctx.options.queryKey
1557
+ }),
1558
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1559
+ name: ["InfiniteData"],
1560
+ isTypeOnly: true,
1561
+ path: importPath
1562
+ }),
1563
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1564
+ name: ["infiniteQueryOptions"],
1565
+ path: importPath
1566
+ }),
1567
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQueryOptions, {
1568
+ name: queryOptionsName,
1569
+ clientName: calledClientName,
1570
+ queryKeyName,
1571
+ node,
1572
+ tsResolver,
1573
+ cursorParam: infiniteOptions.cursorParam,
1574
+ nextParam: infiniteOptions.nextParam,
1575
+ previousParam: infiniteOptions.previousParam,
1576
+ initialPageParam: infiniteOptions.initialPageParam,
1577
+ queryParam: infiniteOptions.queryParam
1578
+ }),
1579
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1580
+ name: ["useInfiniteQuery"],
1581
+ path: importPath
1582
+ }),
1583
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1584
+ name: [
1585
+ "QueryKey",
1586
+ "QueryClient",
1587
+ "InfiniteQueryObserverOptions",
1588
+ "UseInfiniteQueryResult"
1589
+ ],
1590
+ path: importPath,
1591
+ isTypeOnly: true
1592
+ }),
1593
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
1594
+ name: queryName,
1595
+ queryOptionsName,
1596
+ queryKeyName,
1597
+ queryKeyTypeName,
1598
+ node,
1599
+ tsResolver,
1600
+ initialPageParam: infiniteOptions.initialPageParam,
1601
+ queryParam: infiniteOptions.queryParam,
1602
+ customOptions
1603
+ })
1604
+ ]
1605
+ });
1606
+ }
1607
+ });
1608
+ //#endregion
1609
+ //#region src/generators/mutationGenerator.tsx
1610
+ /**
1611
+ * Built-in generator for `useMutation` hooks. Emits one `useFooMutation` hook
1612
+ * per POST/PUT/DELETE operation (configurable via `mutation.methods`) plus
1613
+ * the matching `fooMutationKey` / `fooMutationOptions` helpers.
1614
+ */
1615
+ const mutationGenerator = (0, kubb_kit.defineGenerator)({
1616
+ name: "react-query-mutation",
1617
+ renderer: kubb_jsx.jsxRenderer,
1618
+ operation(node, ctx) {
1619
+ if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
1620
+ const { config, driver, resolver, root } = ctx;
1621
+ const { output, query, mutation, client, group, customOptions, hooks } = ctx.options;
1622
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1623
+ if (!pluginTs) return null;
1624
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1625
+ const { isMutation } = classifyOperation(node, {
1626
+ query,
1627
+ mutation
1628
+ });
1629
+ if (!isMutation) return null;
1630
+ const importPath = mutation ? mutation.importPath : "@tanstack/react-query";
1631
+ const contractOp = resolveClientOperation({
1632
+ clientPlugin: { pluginName: client.pluginName },
1633
+ driver,
1634
+ node,
1635
+ root,
1636
+ output
1637
+ });
1638
+ if (!contractOp) return null;
1639
+ const mutationHookName = resolver.mutation.name(node);
1640
+ const mutationTypeName = resolver.mutation.typeName(node);
1641
+ const mutationOptionsName = resolver.mutation.optionsName(node);
1642
+ const mutationKeyName = resolver.mutation.keyName(node);
1643
+ const meta = {
1644
+ file: resolver.file({
1645
+ ...operationFileEntry(node, mutationHookName),
1646
+ root,
1647
+ output,
1648
+ group: group ?? void 0
1649
+ }),
1650
+ fileTs: tsResolver.file({
1651
+ ...operationFileEntry(node, node.operationId),
1652
+ root,
1653
+ output: pluginTs.options?.output ?? output,
1654
+ group: pluginTs.options?.group ?? void 0
1655
+ })
1656
+ };
1657
+ const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1658
+ order: "body-response-first",
1659
+ includeParams: false
1660
+ })].filter((name) => Boolean(name));
1661
+ const calledClientName = contractOp.name;
1662
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
1663
+ baseName: meta.file.baseName,
1664
+ path: meta.file.path,
1665
+ meta: meta.file.meta,
1666
+ banner: resolver.default.banner(ctx.meta, {
1667
+ output,
1668
+ config,
1669
+ file: {
1670
+ path: meta.file.path,
1671
+ baseName: meta.file.baseName
1672
+ }
1673
+ }),
1674
+ footer: resolver.default.footer(ctx.meta, {
1675
+ output,
1676
+ config,
1677
+ file: {
1678
+ path: meta.file.path,
1679
+ baseName: meta.file.baseName
1680
+ }
1681
+ }),
1682
+ children: [
1683
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1684
+ name: [contractOp.name],
1685
+ root: meta.file.path,
1686
+ path: contractOp.path
1687
+ }),
1688
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1689
+ name: ["RequestConfig", "ResponseErrorConfig"],
1690
+ root: meta.file.path,
1691
+ path: contractOp.clientPath,
1692
+ isTypeOnly: true
1693
+ }),
1694
+ customOptions && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1695
+ name: [customOptions.name],
1696
+ path: customOptions.importPath
1697
+ }),
1698
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1699
+ name: Array.from(new Set(importedTypeNames)),
1700
+ root: meta.file.path,
1701
+ path: meta.fileTs.path,
1702
+ isTypeOnly: true
1703
+ }),
1704
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(MutationKey, {
1705
+ name: mutationKeyName,
1706
+ node,
1707
+ transformer: ctx.options.mutationKey
1708
+ }),
1709
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1710
+ name: ["mutationOptions"],
1711
+ path: importPath
1712
+ }),
1713
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(MutationOptions, {
1714
+ name: mutationOptionsName,
1715
+ clientName: calledClientName,
1716
+ mutationKeyName,
1717
+ node,
1718
+ tsResolver
1719
+ }),
1720
+ mutation && hooks && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [
1721
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1722
+ name: ["useMutation"],
1723
+ path: importPath
1724
+ }),
1725
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1726
+ name: [
1727
+ "UseMutationOptions",
1728
+ "UseMutationResult",
1729
+ "QueryClient"
1730
+ ],
1731
+ path: importPath,
1732
+ isTypeOnly: true
1733
+ }),
1734
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Mutation, {
1735
+ name: mutationHookName,
1736
+ typeName: mutationTypeName,
1737
+ mutationOptionsName,
1738
+ mutationKeyName,
1739
+ node,
1740
+ tsResolver,
1741
+ customOptions
1742
+ })
1743
+ ] })
1744
+ ]
1745
+ });
1746
+ }
1747
+ });
1748
+ //#endregion
1749
+ //#region src/generators/queryGenerator.tsx
1750
+ /**
1751
+ * Built-in generator for `useQuery` hooks. Emits one `useFooQuery` hook per
1752
+ * GET operation (configurable via `query.methods`) plus the matching
1753
+ * `fooQueryKey` / `fooQueryOptions` helpers.
1754
+ */
1755
+ const queryGenerator = (0, kubb_kit.defineGenerator)({
1756
+ name: "react-query",
1757
+ renderer: kubb_jsx.jsxRenderer,
1758
+ operation(node, ctx) {
1759
+ if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
1760
+ const { config, driver, resolver, root } = ctx;
1761
+ const { output, query, mutation, client, group, customOptions, hooks } = ctx.options;
1762
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1763
+ if (!pluginTs) return null;
1764
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1765
+ const { isQuery, isMutation } = classifyOperation(node, {
1766
+ query,
1767
+ mutation
1768
+ });
1769
+ if (!isQuery || isMutation) return null;
1770
+ const importPath = query ? query.importPath : "@tanstack/react-query";
1771
+ const contractOp = resolveClientOperation({
1772
+ clientPlugin: { pluginName: client.pluginName },
1773
+ driver,
1774
+ node,
1775
+ root,
1776
+ output
1777
+ });
1778
+ if (!contractOp) return null;
1779
+ const queryName = resolver.query.name(node);
1780
+ const queryOptionsName = resolver.query.optionsName(node);
1781
+ const queryKeyName = resolver.query.keyName(node);
1782
+ const queryKeyTypeName = resolver.query.keyTypeName(node);
1783
+ const meta = {
1784
+ file: resolver.file({
1785
+ ...operationFileEntry(node, queryName),
1786
+ root,
1787
+ output,
1788
+ group: group ?? void 0
1789
+ }),
1790
+ fileTs: tsResolver.file({
1791
+ ...operationFileEntry(node, node.operationId),
1792
+ root,
1793
+ output: pluginTs.options?.output ?? output,
1794
+ group: pluginTs.options?.group ?? void 0
1795
+ })
1796
+ };
1797
+ const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1798
+ exclude: [queryKeyTypeName],
1799
+ order: "body-response-first",
1800
+ includeParams: false
1801
+ })].filter((name) => Boolean(name));
1802
+ const calledClientName = contractOp.name;
1803
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
1804
+ baseName: meta.file.baseName,
1805
+ path: meta.file.path,
1806
+ meta: meta.file.meta,
1807
+ banner: resolver.default.banner(ctx.meta, {
1808
+ output,
1809
+ config,
1810
+ file: {
1811
+ path: meta.file.path,
1812
+ baseName: meta.file.baseName
1813
+ }
1814
+ }),
1815
+ footer: resolver.default.footer(ctx.meta, {
1816
+ output,
1817
+ config,
1818
+ file: {
1819
+ path: meta.file.path,
1820
+ baseName: meta.file.baseName
1821
+ }
1822
+ }),
1823
+ children: [
1824
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1825
+ name: [contractOp.name],
1826
+ root: meta.file.path,
1827
+ path: contractOp.path
1828
+ }),
1829
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1830
+ name: ["RequestConfig", "ResponseErrorConfig"],
1831
+ root: meta.file.path,
1832
+ path: contractOp.clientPath,
1833
+ isTypeOnly: true
1834
+ }),
1835
+ customOptions && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1836
+ name: [customOptions.name],
1837
+ path: customOptions.importPath
1838
+ }),
1839
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1840
+ name: Array.from(new Set(importedTypeNames)),
1841
+ root: meta.file.path,
1842
+ path: meta.fileTs.path,
1843
+ isTypeOnly: true
1844
+ }),
1845
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(QueryKey, {
1846
+ name: queryKeyName,
1847
+ typeName: queryKeyTypeName,
1848
+ node,
1849
+ tsResolver,
1850
+ transformer: ctx.options.queryKey
1851
+ }),
1852
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1853
+ name: ["queryOptions"],
1854
+ path: importPath
1855
+ }),
1856
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(QueryOptions, {
1857
+ name: queryOptionsName,
1858
+ clientName: calledClientName,
1859
+ queryKeyName,
1860
+ node,
1861
+ tsResolver
1862
+ }),
1863
+ query && hooks && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [
1864
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1865
+ name: ["useQuery"],
1866
+ path: importPath
1867
+ }),
1868
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1869
+ name: [
1870
+ "QueryKey",
1871
+ "QueryClient",
1872
+ "QueryObserverOptions",
1873
+ "UseQueryResult"
1874
+ ],
1875
+ path: importPath,
1876
+ isTypeOnly: true
1877
+ }),
1878
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Query, {
1879
+ name: queryName,
1880
+ queryOptionsName,
1881
+ queryKeyName,
1882
+ queryKeyTypeName,
1883
+ node,
1884
+ tsResolver,
1885
+ customOptions
1886
+ })
1887
+ ] })
1888
+ ]
1889
+ });
1890
+ }
1891
+ });
1892
+ //#endregion
1893
+ //#region src/generators/suspenseInfiniteQueryGenerator.tsx
1894
+ /**
1895
+ * Built-in generator for `useSuspenseInfiniteQuery` hooks. Enabled when
1896
+ * `suspense`, `infinite`, and `hooks` are all configured. Combines suspense
1897
+ * semantics with cursor-based pagination. Handlers throw promises while
1898
+ * loading and pull additional pages on demand.
1899
+ */
1900
+ const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1901
+ name: "react-suspense-infinite-query",
1902
+ renderer: kubb_jsx.jsxRenderer,
1903
+ operation(node, ctx) {
1904
+ if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
1905
+ const { config, driver, resolver, root } = ctx;
1906
+ const { output, query, mutation, infinite, suspense, client, group, customOptions, hooks } = ctx.options;
1907
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1908
+ if (!pluginTs) return null;
1909
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1910
+ const { isQuery, isMutation } = classifyOperation(node, {
1911
+ query,
1912
+ mutation
1913
+ });
1914
+ const isSuspense = !!suspense;
1915
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1916
+ if (!isQuery || isMutation || !isSuspense || !infiniteOptions || !hooks) return null;
1917
+ const normalizeKey = (key) => key.replace(/\?$/, "");
1918
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
1919
+ if (!(infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false)) return null;
1920
+ const importPath = query ? query.importPath : "@tanstack/react-query";
1921
+ const contractOp = resolveClientOperation({
1922
+ clientPlugin: { pluginName: client.pluginName },
1923
+ driver,
1924
+ node,
1925
+ root,
1926
+ output
1927
+ });
1928
+ if (!contractOp) return null;
1929
+ const queryName = resolver.suspenseInfiniteQuery.name(node);
1930
+ const queryOptionsName = resolver.suspenseInfiniteQuery.optionsName(node);
1931
+ const queryKeyName = resolver.suspenseInfiniteQuery.keyName(node);
1932
+ const queryKeyTypeName = resolver.suspenseInfiniteQuery.keyTypeName(node);
1933
+ const meta = {
1934
+ file: resolver.file({
1935
+ ...operationFileEntry(node, queryName),
1936
+ root,
1937
+ output,
1938
+ group: group ?? void 0
1939
+ }),
1940
+ fileTs: tsResolver.file({
1941
+ ...operationFileEntry(node, node.operationId),
1942
+ root,
1943
+ output: pluginTs.options?.output ?? output,
1944
+ group: pluginTs.options?.group ?? void 0
1945
+ })
1946
+ };
1947
+ const rawQueryParams = getOperationParameters(node).query;
1948
+ const queryParamsTypeName = rawQueryParams.length > 0 && tsResolver.param.query(node, rawQueryParams[0]) !== tsResolver.param.name(node, rawQueryParams[0]) ? tsResolver.param.query(node, rawQueryParams[0]) : null;
1949
+ const importedTypeNames = [
1950
+ tsResolver.response.options(node),
1951
+ queryParamsTypeName,
1952
+ ...resolveOperationTypeNames(node, tsResolver, {
1953
+ order: "body-response-first",
1954
+ includeParams: false
1955
+ })
1956
+ ].filter((name) => Boolean(name));
1957
+ const calledClientName = contractOp.name;
1958
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
1959
+ baseName: meta.file.baseName,
1960
+ path: meta.file.path,
1961
+ meta: meta.file.meta,
1962
+ banner: resolver.default.banner(ctx.meta, {
1963
+ output,
1964
+ config,
1965
+ file: {
1966
+ path: meta.file.path,
1967
+ baseName: meta.file.baseName
1968
+ }
1969
+ }),
1970
+ footer: resolver.default.footer(ctx.meta, {
1971
+ output,
1972
+ config,
1973
+ file: {
1974
+ path: meta.file.path,
1975
+ baseName: meta.file.baseName
1976
+ }
1977
+ }),
1978
+ children: [
1979
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1980
+ name: [contractOp.name],
1981
+ root: meta.file.path,
1982
+ path: contractOp.path
1983
+ }),
1984
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1985
+ name: ["RequestConfig", "ResponseErrorConfig"],
1986
+ root: meta.file.path,
1987
+ path: contractOp.clientPath,
1988
+ isTypeOnly: true
1989
+ }),
1990
+ customOptions && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1991
+ name: [customOptions.name],
1992
+ path: customOptions.importPath
1993
+ }),
1994
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1995
+ name: Array.from(new Set(importedTypeNames)),
1996
+ root: meta.file.path,
1997
+ path: meta.fileTs.path,
1998
+ isTypeOnly: true
1999
+ }),
2000
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(QueryKey, {
2001
+ name: queryKeyName,
2002
+ typeName: queryKeyTypeName,
2003
+ node,
2004
+ tsResolver,
2005
+ transformer: ctx.options.queryKey
2006
+ }),
2007
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2008
+ name: ["InfiniteData"],
2009
+ isTypeOnly: true,
2010
+ path: importPath
2011
+ }),
2012
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2013
+ name: ["infiniteQueryOptions"],
2014
+ path: importPath
2015
+ }),
2016
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQueryOptions, {
2017
+ name: queryOptionsName,
2018
+ clientName: calledClientName,
2019
+ queryKeyName,
2020
+ node,
2021
+ tsResolver,
2022
+ cursorParam: infiniteOptions.cursorParam,
2023
+ nextParam: infiniteOptions.nextParam,
2024
+ previousParam: infiniteOptions.previousParam,
2025
+ initialPageParam: infiniteOptions.initialPageParam,
2026
+ queryParam: infiniteOptions.queryParam
2027
+ }),
2028
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2029
+ name: ["useSuspenseInfiniteQuery"],
2030
+ path: importPath
2031
+ }),
2032
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2033
+ name: [
2034
+ "QueryKey",
2035
+ "QueryClient",
2036
+ "UseSuspenseInfiniteQueryOptions",
2037
+ "UseSuspenseInfiniteQueryResult"
2038
+ ],
2039
+ path: importPath,
2040
+ isTypeOnly: true
2041
+ }),
2042
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
2043
+ name: queryName,
2044
+ queryOptionsName,
2045
+ queryKeyName,
2046
+ queryKeyTypeName,
2047
+ node,
2048
+ tsResolver,
2049
+ initialPageParam: infiniteOptions.initialPageParam,
2050
+ queryParam: infiniteOptions.queryParam,
2051
+ customOptions,
2052
+ suspense: true
2053
+ })
2054
+ ]
2055
+ });
2056
+ }
2057
+ });
2058
+ //#endregion
2059
+ //#region src/generators/suspenseQueryGenerator.tsx
2060
+ /**
2061
+ * Built-in generator for `useSuspenseQuery` hooks. Enabled when
2062
+ * `pluginReactQuery({ suspense: {}, hooks: true })`. Emits one
2063
+ * `useFooSuspenseQuery` hook per query operation. Suspense queries throw
2064
+ * promises while loading and require a `<Suspense>` boundary in the React
2065
+ * tree. TanStack Query v5+ only.
2066
+ */
2067
+ const suspenseQueryGenerator = (0, kubb_kit.defineGenerator)({
2068
+ name: "react-suspense-query",
2069
+ renderer: kubb_jsx.jsxRenderer,
2070
+ operation(node, ctx) {
2071
+ if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
2072
+ const { config, driver, resolver, root } = ctx;
2073
+ const { output, query, mutation, suspense, client, group, customOptions, hooks } = ctx.options;
2074
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
2075
+ if (!pluginTs) return null;
2076
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
2077
+ const { isQuery, isMutation } = classifyOperation(node, {
2078
+ query,
2079
+ mutation
2080
+ });
2081
+ if (!isQuery || isMutation || !!!suspense || !hooks) return null;
2082
+ const importPath = query ? query.importPath : "@tanstack/react-query";
2083
+ const contractOp = resolveClientOperation({
2084
+ clientPlugin: { pluginName: client.pluginName },
2085
+ driver,
2086
+ node,
2087
+ root,
2088
+ output
2089
+ });
2090
+ if (!contractOp) return null;
2091
+ const queryName = resolver.suspenseQuery.name(node);
2092
+ const queryOptionsName = resolver.suspenseQuery.optionsName(node);
2093
+ const queryKeyName = resolver.suspenseQuery.keyName(node);
2094
+ const queryKeyTypeName = resolver.suspenseQuery.keyTypeName(node);
2095
+ const meta = {
2096
+ file: resolver.file({
2097
+ ...operationFileEntry(node, queryName),
2098
+ root,
2099
+ output,
2100
+ group: group ?? void 0
2101
+ }),
2102
+ fileTs: tsResolver.file({
2103
+ ...operationFileEntry(node, node.operationId),
2104
+ root,
2105
+ output: pluginTs.options?.output ?? output,
2106
+ group: pluginTs.options?.group ?? void 0
2107
+ })
2108
+ };
2109
+ const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
2110
+ exclude: [queryKeyTypeName],
2111
+ order: "body-response-first",
2112
+ includeParams: false
2113
+ })].filter((name) => Boolean(name));
2114
+ const calledClientName = contractOp.name;
2115
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
2116
+ baseName: meta.file.baseName,
2117
+ path: meta.file.path,
2118
+ meta: meta.file.meta,
2119
+ banner: resolver.default.banner(ctx.meta, {
2120
+ output,
2121
+ config,
2122
+ file: {
2123
+ path: meta.file.path,
2124
+ baseName: meta.file.baseName
2125
+ }
2126
+ }),
2127
+ footer: resolver.default.footer(ctx.meta, {
2128
+ output,
2129
+ config,
2130
+ file: {
2131
+ path: meta.file.path,
2132
+ baseName: meta.file.baseName
2133
+ }
2134
+ }),
2135
+ children: [
2136
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2137
+ name: [contractOp.name],
2138
+ root: meta.file.path,
2139
+ path: contractOp.path
2140
+ }),
2141
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2142
+ name: ["RequestConfig", "ResponseErrorConfig"],
2143
+ root: meta.file.path,
2144
+ path: contractOp.clientPath,
2145
+ isTypeOnly: true
2146
+ }),
2147
+ customOptions && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2148
+ name: [customOptions.name],
2149
+ path: customOptions.importPath
2150
+ }),
2151
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2152
+ name: Array.from(new Set(importedTypeNames)),
2153
+ root: meta.file.path,
2154
+ path: meta.fileTs.path,
2155
+ isTypeOnly: true
2156
+ }),
2157
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(QueryKey, {
2158
+ name: queryKeyName,
2159
+ typeName: queryKeyTypeName,
2160
+ node,
2161
+ tsResolver,
2162
+ transformer: ctx.options.queryKey
2163
+ }),
2164
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2165
+ name: ["queryOptions"],
2166
+ path: importPath
2167
+ }),
2168
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(QueryOptions, {
2169
+ name: queryOptionsName,
2170
+ clientName: calledClientName,
2171
+ queryKeyName,
2172
+ node,
2173
+ tsResolver
2174
+ }),
2175
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2176
+ name: ["useSuspenseQuery"],
2177
+ path: importPath
2178
+ }),
2179
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
2180
+ name: [
2181
+ "QueryKey",
2182
+ "QueryClient",
2183
+ "UseSuspenseQueryOptions",
2184
+ "UseSuspenseQueryResult"
2185
+ ],
2186
+ path: importPath,
2187
+ isTypeOnly: true
2188
+ }),
2189
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Query, {
2190
+ name: queryName,
2191
+ queryOptionsName,
2192
+ queryKeyName,
2193
+ queryKeyTypeName,
2194
+ node,
2195
+ tsResolver,
2196
+ customOptions,
2197
+ suspense: true
2198
+ })
2199
+ ]
2200
+ });
2201
+ }
2202
+ });
2203
+ //#endregion
2204
+ //#region src/resolvers/resolverReactQuery.ts
2205
+ /**
2206
+ * Default resolver used by `@kubb/plugin-react-query`. Decides the names and
2207
+ * file paths for every generated TanStack Query hook (`useFoo`,
2208
+ * `useFooSuspense`, `useFooInfinite`, ...) and its companion helpers
2209
+ * (`fooQueryKey`, `fooQueryOptions`).
2210
+ *
2211
+ * Functions and files use the built-in camelCase casing; hooks get the `use`
2212
+ * prefix; suspense and infinite variants are suffixed with `Suspense`/`Infinite`.
2213
+ *
2214
+ * @example Resolve hook and helper names
2215
+ * ```ts
2216
+ * import { resolverReactQuery } from '@kubb/plugin-react-query'
2217
+ *
2218
+ * resolverReactQuery.query.name(operationNode) // 'useGetPetById'
2219
+ * resolverReactQuery.mutation.name(operationNode) // 'useUpdatePet'
2220
+ * resolverReactQuery.query.keyName(operationNode) // 'getPetByIdQueryKey'
2221
+ * resolverReactQuery.query.optionsName(operationNode) // 'getPetByIdQueryOptions'
2222
+ * ```
2223
+ */
2224
+ const resolverReactQuery = (0, kubb_kit.createResolver)({
30
2225
  pluginName: "plugin-react-query",
31
- default(name, type) {
32
- return require_components.camelCase(name, { isFile: type === "file" });
33
- },
34
- resolveName(name) {
35
- return this.default(name, "function");
36
- },
37
- resolvePathName(name, type) {
38
- return this.default(name, type);
39
- },
40
- resolveQueryName(node) {
41
- return `use${capitalize(this.resolveName(node.operationId))}`;
42
- },
43
- resolveSuspenseQueryName(node) {
44
- return `use${capitalize(this.resolveName(node.operationId))}Suspense`;
45
- },
46
- resolveInfiniteQueryName(node) {
47
- return `use${capitalize(this.resolveName(node.operationId))}Infinite`;
48
- },
49
- resolveSuspenseInfiniteQueryName(node) {
50
- return `use${capitalize(this.resolveName(node.operationId))}SuspenseInfinite`;
51
- },
52
- resolveMutationName(node) {
53
- return `use${capitalize(this.resolveName(node.operationId))}`;
54
- },
55
- resolveQueryOptionsName(node) {
56
- return `${this.resolveName(node.operationId)}QueryOptions`;
57
- },
58
- resolveSuspenseQueryOptionsName(node) {
59
- return `${this.resolveName(node.operationId)}SuspenseQueryOptions`;
60
- },
61
- resolveInfiniteQueryOptionsName(node) {
62
- return `${this.resolveName(node.operationId)}InfiniteQueryOptions`;
63
- },
64
- resolveSuspenseInfiniteQueryOptionsName(node) {
65
- return `${this.resolveName(node.operationId)}SuspenseInfiniteQueryOptions`;
66
- },
67
- resolveMutationOptionsName(node) {
68
- return `${this.resolveName(node.operationId)}MutationOptions`;
69
- },
70
- resolveQueryKeyName(node) {
71
- return `${this.resolveName(node.operationId)}QueryKey`;
72
- },
73
- resolveSuspenseQueryKeyName(node) {
74
- return `${this.resolveName(node.operationId)}SuspenseQueryKey`;
75
- },
76
- resolveInfiniteQueryKeyName(node) {
77
- return `${this.resolveName(node.operationId)}InfiniteQueryKey`;
78
- },
79
- resolveSuspenseInfiniteQueryKeyName(node) {
80
- return `${this.resolveName(node.operationId)}SuspenseInfiniteQueryKey`;
81
- },
82
- resolveMutationKeyName(node) {
83
- return `${this.resolveName(node.operationId)}MutationKey`;
84
- },
85
- resolveQueryKeyTypeName(node) {
86
- return `${capitalize(this.resolveName(node.operationId))}QueryKey`;
87
- },
88
- resolveSuspenseQueryKeyTypeName(node) {
89
- return `${capitalize(this.resolveName(node.operationId))}SuspenseQueryKey`;
90
- },
91
- resolveInfiniteQueryKeyTypeName(node) {
92
- return `${capitalize(this.resolveName(node.operationId))}InfiniteQueryKey`;
93
- },
94
- resolveSuspenseInfiniteQueryKeyTypeName(node) {
95
- return `${capitalize(this.resolveName(node.operationId))}SuspenseInfiniteQueryKey`;
96
- },
97
- resolveMutationTypeName(node) {
98
- return capitalize(this.resolveName(node.operationId));
99
- },
100
- resolveClientName(node) {
101
- return this.resolveName(node.operationId);
102
- },
103
- resolveSuspenseClientName(node) {
104
- return `${this.resolveName(node.operationId)}Suspense`;
105
- },
106
- resolveInfiniteClientName(node) {
107
- return `${this.resolveName(node.operationId)}Infinite`;
108
- },
109
- resolveSuspenseInfiniteClientName(node) {
110
- return `${this.resolveName(node.operationId)}SuspenseInfinite`;
111
- },
112
- resolveHookOptionsName() {
113
- return "HookOptions";
2226
+ query: createQueryResolver(),
2227
+ suspenseQuery: createQueryResolver("Suspense"),
2228
+ infiniteQuery: createQueryResolver("Infinite"),
2229
+ suspenseInfiniteQuery: createQueryResolver("SuspenseInfinite"),
2230
+ mutation: {
2231
+ ...createMutationResolver(),
2232
+ optionsName(node) {
2233
+ return `${this.name(node.operationId)}MutationOptions`;
2234
+ },
2235
+ typeName(node) {
2236
+ return capitalize(this.name(node.operationId));
2237
+ }
114
2238
  },
115
- resolveCustomHookOptionsName() {
116
- return "getCustomHookOptions";
2239
+ hook: {
2240
+ optionsName() {
2241
+ return "HookOptions";
2242
+ },
2243
+ customOptionsName() {
2244
+ return "getCustomHookOptions";
2245
+ }
117
2246
  }
118
- }));
2247
+ });
119
2248
  //#endregion
120
2249
  //#region src/plugin.ts
2250
+ /**
2251
+ * Canonical plugin name for `@kubb/plugin-react-query`. Used for driver lookups
2252
+ * and cross-plugin dependency references.
2253
+ */
121
2254
  const pluginReactQueryName = "plugin-react-query";
122
- const pluginReactQuery = (0, _kubb_core.definePlugin)((options) => {
2255
+ /**
2256
+ * Generates one TanStack Query hook per OpenAPI operation for React. Queries
2257
+ * become `useFoo`, with `useFooSuspense` and `useFooInfinite` variants.
2258
+ * Mutations become `useFoo`. Each hook is fully typed: query keys, input
2259
+ * variables, response data, and error shape all come from the spec.
2260
+ *
2261
+ * @example
2262
+ * ```ts
2263
+ * import { defineConfig } from 'kubb/config'
2264
+ * import { pluginTs } from '@kubb/plugin-ts'
2265
+ * import { pluginReactQuery } from '@kubb/plugin-react-query'
2266
+ *
2267
+ * export default defineConfig({
2268
+ * input: './petStore.yaml',
2269
+ * output: { path: './src/gen' },
2270
+ * plugins: [
2271
+ * pluginTs(),
2272
+ * pluginReactQuery({
2273
+ * output: { path: './hooks' },
2274
+ * suspense: {},
2275
+ * }),
2276
+ * ],
2277
+ * })
2278
+ * ```
2279
+ */
2280
+ const pluginReactQuery = (0, kubb_kit.definePlugin)((options) => {
123
2281
  const { output = {
124
2282
  path: "hooks",
125
- barrelType: "named"
126
- }, group, exclude = [], include, override = [], parser = "client", suspense = {}, infinite = false, paramsType = "inline", pathParamsType = paramsType === "object" ? "object" : options.pathParamsType || "inline", mutation = {}, query = {}, mutationKey = require_components.mutationKeyTransformer, queryKey = require_components.queryKeyTransformer, customOptions, paramsCasing, client, resolver: userResolver, transformer: userTransformer, generators: userGenerators = [] } = options;
127
- const clientName = client?.client ?? "axios";
128
- const clientImportPath = client?.importPath ?? (!client?.bundle ? `@kubb/plugin-client/clients/${clientName}` : void 0);
129
- const selectedGenerators = options.generators ?? [
130
- require_generators.queryGenerator,
131
- require_generators.suspenseQueryGenerator,
132
- require_generators.infiniteQueryGenerator,
133
- require_generators.suspenseInfiniteQueryGenerator,
134
- require_generators.mutationGenerator,
135
- require_generators.hookOptionsGenerator,
136
- require_generators.customHookOptionsFileGenerator
137
- ].filter((generator) => Boolean(generator));
138
- const groupConfig = group ? {
139
- ...group,
140
- name: group.name ? group.name : (ctx) => {
141
- if (group.type === "path") return `${ctx.group.split("/")[1]}`;
142
- return `${require_components.camelCase(ctx.group)}Controller`;
143
- }
144
- } : void 0;
2283
+ barrel: { type: "named" }
2284
+ }, group, exclude = [], include, override = [], suspense = false, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, customOptions, hooks = false, client, resolver: userResolver, macros: userMacros } = options;
2285
+ const selectedGenerators = [
2286
+ queryGenerator,
2287
+ suspenseQueryGenerator,
2288
+ infiniteQueryGenerator,
2289
+ suspenseInfiniteQueryGenerator,
2290
+ mutationGenerator,
2291
+ hookOptionsGenerator,
2292
+ customHookOptionsFileGenerator
2293
+ ];
2294
+ const groupConfig = createGroupConfig(group);
145
2295
  return {
146
2296
  name: pluginReactQueryName,
147
2297
  options,
148
- dependencies: [_kubb_plugin_ts.pluginTsName, parser === "zod" ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
2298
+ dependencies: [_kubb_plugin_ts.pluginTsName],
149
2299
  hooks: { "kubb:plugin:setup"(ctx) {
150
- const resolver = userResolver ? {
151
- ...resolverReactQuery,
152
- ...userResolver
153
- } : resolverReactQuery;
2300
+ const resolver = userResolver ? kubb_kit.Resolver.merge(resolverReactQuery, userResolver) : resolverReactQuery;
154
2301
  ctx.setOptions({
155
2302
  output,
156
- client: {
157
- bundle: client?.bundle,
158
- baseURL: client?.baseURL,
159
- client: clientName,
160
- clientType: client?.clientType ?? "function",
161
- importPath: clientImportPath,
162
- dataReturnType: client?.dataReturnType ?? "data",
163
- paramsCasing
164
- },
2303
+ client: resolveContractClient({
2304
+ client,
2305
+ plugins: ctx.config.plugins
2306
+ }),
165
2307
  queryKey,
166
- query: query === false ? false : {
167
- importPath: "@tanstack/react-query",
168
- methods: ["get"],
169
- ...query
170
- },
2308
+ query: resolveQueryConfig(query, { importPath: "@tanstack/react-query" }),
171
2309
  mutationKey,
172
- mutation: mutation === false ? false : {
173
- importPath: "@tanstack/react-query",
174
- methods: [
175
- "post",
176
- "put",
177
- "patch",
178
- "delete"
179
- ],
180
- ...mutation
181
- },
182
- infinite: infinite ? {
183
- queryParam: "id",
184
- initialPageParam: 0,
185
- cursorParam: void 0,
186
- nextParam: void 0,
187
- previousParam: void 0,
188
- ...infinite
189
- } : false,
2310
+ mutation: resolveMutationConfig(mutation, { importPath: "@tanstack/react-query" }),
2311
+ infinite: resolveInfiniteConfig(infinite),
190
2312
  suspense,
191
2313
  customOptions: customOptions ? {
192
2314
  name: "useCustomHookOptions",
193
2315
  ...customOptions
194
- } : void 0,
195
- parser,
196
- paramsType,
197
- pathParamsType,
198
- paramsCasing,
2316
+ } : null,
2317
+ hooks,
199
2318
  group: groupConfig,
200
2319
  exclude,
201
2320
  include,
@@ -203,31 +2322,8 @@ const pluginReactQuery = (0, _kubb_core.definePlugin)((options) => {
203
2322
  resolver
204
2323
  });
205
2324
  ctx.setResolver(resolver);
206
- if (userTransformer) ctx.setTransformer(userTransformer);
207
- for (const gen of selectedGenerators) ctx.addGenerator(gen);
208
- for (const gen of userGenerators) ctx.addGenerator(gen);
209
- const root = node_path.default.resolve(ctx.config.root, ctx.config.output.path);
210
- const hasClientPlugin = !!ctx.config.plugins?.some((p) => p.name === _kubb_plugin_client.pluginClientName);
211
- if (client?.bundle && !hasClientPlugin && !clientImportPath) ctx.injectFile({
212
- baseName: "fetch.ts",
213
- path: node_path.default.resolve(root, ".kubb/fetch.ts"),
214
- sources: [_kubb_core.ast.createSource({
215
- name: "fetch",
216
- nodes: [_kubb_core.ast.createText(clientName === "fetch" ? _kubb_plugin_client_templates_clients_fetch_source.source : _kubb_plugin_client_templates_clients_axios_source.source)],
217
- isExportable: true,
218
- isIndexable: true
219
- })]
220
- });
221
- if (!hasClientPlugin) ctx.injectFile({
222
- baseName: "config.ts",
223
- path: node_path.default.resolve(root, ".kubb/config.ts"),
224
- sources: [_kubb_core.ast.createSource({
225
- name: "config",
226
- nodes: [_kubb_core.ast.createText(_kubb_plugin_client_templates_config_source.source)],
227
- isExportable: false,
228
- isIndexable: false
229
- })]
230
- });
2325
+ if (userMacros?.length) ctx.setMacros(userMacros);
2326
+ ctx.addGenerator(...selectedGenerators);
231
2327
  } }
232
2328
  };
233
2329
  });
@@ -235,5 +2331,6 @@ const pluginReactQuery = (0, _kubb_core.definePlugin)((options) => {
235
2331
  exports.default = pluginReactQuery;
236
2332
  exports.pluginReactQuery = pluginReactQuery;
237
2333
  exports.pluginReactQueryName = pluginReactQueryName;
2334
+ exports.resolverReactQuery = resolverReactQuery;
238
2335
 
239
2336
  //# sourceMappingURL=index.cjs.map