@kubb/plugin-swr 5.0.0-beta.64 → 5.0.0-beta.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,17 +2,66 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_components = require("./components-DxWGjLWg.cjs");
6
- const require_generators = require("./generators-CJ4ziuNk.cjs");
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __name = (target, value) => __defProp(target, "name", {
9
+ value,
10
+ configurable: true
11
+ });
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
18
+ key = keys[i];
19
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
20
+ get: ((k) => from[k]).bind(null, key),
21
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
22
+ });
23
+ }
24
+ return to;
25
+ };
26
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
27
+ value: mod,
28
+ enumerable: true
29
+ }) : target, mod));
30
+ //#endregion
7
31
  let node_path = require("node:path");
8
- node_path = require_components.__toESM(node_path, 1);
32
+ node_path = __toESM(node_path, 1);
9
33
  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");
14
34
  let _kubb_plugin_ts = require("@kubb/plugin-ts");
15
35
  let _kubb_plugin_zod = require("@kubb/plugin-zod");
36
+ let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
37
+ let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
38
+ //#region ../../internals/utils/src/casing.ts
39
+ /**
40
+ * Shared implementation for camelCase and PascalCase conversion.
41
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
42
+ * and capitalizes each word according to `pascal`.
43
+ *
44
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
45
+ */
46
+ function toCamelOrPascal(text, pascal) {
47
+ 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) => {
48
+ if (word.length > 1 && word === word.toUpperCase()) return word;
49
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
50
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
51
+ }
52
+ /**
53
+ * Converts `text` to camelCase.
54
+ *
55
+ * @example Word boundaries
56
+ * `camelCase('hello-world') // 'helloWorld'`
57
+ *
58
+ * @example With a prefix
59
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
60
+ */
61
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
62
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
63
+ }
64
+ //#endregion
16
65
  //#region ../../internals/utils/src/fs.ts
17
66
  /**
18
67
  * Builds a nested file path from a dotted name. Splits on dots that precede a letter
@@ -33,9 +82,389 @@ let _kubb_plugin_zod = require("@kubb/plugin-zod");
33
82
  * @example Suffix applied to the final segment only
34
83
  * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
35
84
  */
36
- function toFilePath(name, caseLast = require_components.camelCase) {
85
+ function toFilePath(name, caseLast = camelCase) {
37
86
  const parts = name.split(/\.(?=[a-zA-Z])/);
38
- return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : require_components.camelCase(part)).filter(Boolean).join("/");
87
+ return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
88
+ }
89
+ //#endregion
90
+ //#region ../../internals/utils/src/reserved.ts
91
+ /**
92
+ * JavaScript and Java reserved words.
93
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
94
+ */
95
+ const reservedWords = new Set([
96
+ "abstract",
97
+ "arguments",
98
+ "boolean",
99
+ "break",
100
+ "byte",
101
+ "case",
102
+ "catch",
103
+ "char",
104
+ "class",
105
+ "const",
106
+ "continue",
107
+ "debugger",
108
+ "default",
109
+ "delete",
110
+ "do",
111
+ "double",
112
+ "else",
113
+ "enum",
114
+ "eval",
115
+ "export",
116
+ "extends",
117
+ "false",
118
+ "final",
119
+ "finally",
120
+ "float",
121
+ "for",
122
+ "function",
123
+ "goto",
124
+ "if",
125
+ "implements",
126
+ "import",
127
+ "in",
128
+ "instanceof",
129
+ "int",
130
+ "interface",
131
+ "let",
132
+ "long",
133
+ "native",
134
+ "new",
135
+ "null",
136
+ "package",
137
+ "private",
138
+ "protected",
139
+ "public",
140
+ "return",
141
+ "short",
142
+ "static",
143
+ "super",
144
+ "switch",
145
+ "synchronized",
146
+ "this",
147
+ "throw",
148
+ "throws",
149
+ "transient",
150
+ "true",
151
+ "try",
152
+ "typeof",
153
+ "var",
154
+ "void",
155
+ "volatile",
156
+ "while",
157
+ "with",
158
+ "yield",
159
+ "Array",
160
+ "Date",
161
+ "hasOwnProperty",
162
+ "Infinity",
163
+ "isFinite",
164
+ "isNaN",
165
+ "isPrototypeOf",
166
+ "length",
167
+ "Math",
168
+ "name",
169
+ "NaN",
170
+ "Number",
171
+ "Object",
172
+ "prototype",
173
+ "String",
174
+ "toString",
175
+ "undefined",
176
+ "valueOf"
177
+ ]);
178
+ /**
179
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * isValidVarName('status') // true
184
+ * isValidVarName('class') // false (reserved word)
185
+ * isValidVarName('42foo') // false (starts with digit)
186
+ * ```
187
+ */
188
+ function isValidVarName(name) {
189
+ if (!name || reservedWords.has(name)) return false;
190
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
191
+ }
192
+ //#endregion
193
+ //#region ../../internals/utils/src/url.ts
194
+ function transformParam(raw, casing) {
195
+ const param = isValidVarName(raw) ? raw : camelCase(raw);
196
+ return casing === "camelcase" ? camelCase(param) : param;
197
+ }
198
+ function toParamsObject(path, { replacer, casing } = {}) {
199
+ const params = {};
200
+ for (const match of path.matchAll(/\{([^}]+)\}/g)) {
201
+ const param = transformParam(match[1], casing);
202
+ const key = replacer ? replacer(param) : param;
203
+ params[key] = key;
204
+ }
205
+ return Object.keys(params).length > 0 ? params : null;
206
+ }
207
+ /**
208
+ * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.
209
+ */
210
+ var Url = class Url {
211
+ /**
212
+ * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
213
+ *
214
+ * @example
215
+ * Url.canParse('https://petstore.swagger.io/v2') // true
216
+ * Url.canParse('/pet/{petId}') // false
217
+ */
218
+ static canParse(url, base) {
219
+ return URL.canParse(url, base);
220
+ }
221
+ /**
222
+ * Converts an OpenAPI/Swagger path to Express-style colon syntax.
223
+ *
224
+ * @example
225
+ * Url.toPath('/pet/{petId}') // '/pet/:petId'
226
+ */
227
+ static toPath(path) {
228
+ return path.replace(/\{([^}]+)\}/g, ":$1");
229
+ }
230
+ /**
231
+ * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
232
+ * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,
233
+ * and `casing` controls parameter identifier casing.
234
+ *
235
+ * @example
236
+ * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
237
+ *
238
+ * @example
239
+ * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
240
+ */
241
+ static toTemplateString(path, { prefix, replacer, casing } = {}) {
242
+ const result = path.split(/\{([^}]+)\}/).map((part, i) => {
243
+ if (i % 2 === 0) return part;
244
+ const param = transformParam(part, casing);
245
+ return `\${${replacer ? replacer(param) : param}}`;
246
+ }).join("");
247
+ return `\`${prefix ?? ""}${result}\``;
248
+ }
249
+ /**
250
+ * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
251
+ * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
252
+ * names are camelCased to match the generated `path` type, and `prefix` is prepended inside the
253
+ * literal. Shared by the client and cypress generators that pass a grouped `path` object.
254
+ *
255
+ * @example
256
+ * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
257
+ */
258
+ static toGroupedTemplateString(path, { prefix } = {}) {
259
+ return Url.toTemplateString(path, {
260
+ prefix,
261
+ casing: "camelcase",
262
+ replacer: (name) => `path.${name}`
263
+ });
264
+ }
265
+ /**
266
+ * Returns the path and its extracted params as a structured `URLObject`, or as a stringified
267
+ * expression when `stringify` is set.
268
+ *
269
+ * @example
270
+ * Url.toObject('/pet/{petId}')
271
+ * // { url: '/pet/:petId', params: { petId: 'petId' } }
272
+ */
273
+ static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
274
+ const object = {
275
+ url: type === "path" ? Url.toPath(path) : Url.toTemplateString(path, {
276
+ replacer,
277
+ casing
278
+ }),
279
+ params: toParamsObject(path, {
280
+ replacer,
281
+ casing
282
+ })
283
+ };
284
+ if (stringify) {
285
+ if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
286
+ if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
287
+ return `{ url: '${object.url}' }`;
288
+ }
289
+ return object;
290
+ }
291
+ };
292
+ //#endregion
293
+ //#region ../../internals/shared/src/params.ts
294
+ const caseParamsCache = /* @__PURE__ */ new WeakMap();
295
+ /**
296
+ * Applies camelCase to parameter names and returns a new array without mutating the input.
297
+ *
298
+ * Run it before handing parameters to schema builders so output property keys get the right casing
299
+ * while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
300
+ * original array is returned unchanged. Results are cached per input array.
301
+ */
302
+ function caseParams(params, casing) {
303
+ if (!casing) return params;
304
+ const cached = caseParamsCache.get(params);
305
+ if (cached) return cached;
306
+ const result = params.map((param) => ({
307
+ ...param,
308
+ name: camelCase(param.name)
309
+ }));
310
+ caseParamsCache.set(params, result);
311
+ return result;
312
+ }
313
+ //#endregion
314
+ //#region ../../internals/shared/src/operation.ts
315
+ /**
316
+ * Builds the `ResolverFileParams` every operation generator passes to
317
+ * `resolver.resolveFile`: a file named `name`, tagged by the operation's first
318
+ * tag (or `'default'`), at the operation's path. Centralizes the entry object
319
+ * that was repeated at dozens of call sites across the client and query plugins.
320
+ *
321
+ * @example
322
+ * ```ts
323
+ * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })
324
+ * ```
325
+ */
326
+ function operationFileEntry(node, name, extname = ".ts") {
327
+ return {
328
+ name,
329
+ extname,
330
+ tag: node.tags[0] ?? "default",
331
+ path: node.path
332
+ };
333
+ }
334
+ function getOperationLink(node, link) {
335
+ if (!link) return null;
336
+ if (typeof link === "function") return link(node) ?? null;
337
+ if (link === "urlPath") return node.path ? `{@link ${Url.toPath(node.path)}}` : null;
338
+ return node.path ? `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}` : null;
339
+ }
340
+ function getContentTypeInfo(node) {
341
+ const contentTypes = node.requestBody?.content?.map((e) => e.contentType) ?? [];
342
+ const isMultipleContentTypes = contentTypes.length > 1;
343
+ return {
344
+ contentTypes,
345
+ isMultipleContentTypes,
346
+ contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
347
+ defaultContentType: contentTypes[0] ?? "application/json",
348
+ hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
349
+ };
350
+ }
351
+ function buildRequestConfigType(node) {
352
+ const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node);
353
+ const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
354
+ const contentTypeProp = isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null;
355
+ return contentTypeProp ? `${configType} & { ${contentTypeProp} }` : configType;
356
+ }
357
+ /**
358
+ * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
359
+ * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a
360
+ * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a
361
+ * content type for.
362
+ */
363
+ function buildClientOptionType() {
364
+ return `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
365
+ }
366
+ /**
367
+ * Which of the grouped request options an operation carries.
368
+ */
369
+ function getRequestGroups(node) {
370
+ const { path, query, header } = getOperationParameters(node);
371
+ return {
372
+ path: path.length > 0,
373
+ query: query.length > 0,
374
+ body: Boolean(node.requestBody?.content?.[0]?.schema),
375
+ headers: header.length > 0
376
+ };
377
+ }
378
+ /**
379
+ * Resolves which grouped request options an operation carries together with whether each group
380
+ * holds a required member. The grouped parameter stays optional only when nothing inside it is
381
+ * required, matching the generated `RequestConfig` type.
382
+ */
383
+ function getRequestGroupOptionality(node) {
384
+ const groups = getRequestGroups(node);
385
+ const { path, query, header } = getOperationParameters(node);
386
+ const hasRequiredPath = path.some((param) => param.required);
387
+ const hasRequiredQuery = query.some((param) => param.required);
388
+ const hasRequiredHeader = header.some((param) => param.required);
389
+ return {
390
+ groups,
391
+ hasRequiredPath,
392
+ hasRequiredQuery,
393
+ hasRequiredHeader,
394
+ isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body
395
+ };
396
+ }
397
+ function buildOperationComments(node, options = {}) {
398
+ const { link = "pathTemplate", linkPosition = "afterDeprecated", splitLines = false } = options;
399
+ const linkComment = getOperationLink(node, link);
400
+ const filteredComments = (linkPosition === "beforeDeprecated" ? [
401
+ node.description && `@description ${node.description}`,
402
+ node.summary && `@summary ${node.summary}`,
403
+ linkComment,
404
+ node.deprecated && "@deprecated"
405
+ ] : [
406
+ node.description && `@description ${node.description}`,
407
+ node.summary && `@summary ${node.summary}`,
408
+ node.deprecated && "@deprecated",
409
+ linkComment
410
+ ]).filter((comment) => Boolean(comment));
411
+ if (!splitLines) return filteredComments;
412
+ return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
413
+ }
414
+ function getOperationParameters(node, options = {}) {
415
+ const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
416
+ return {
417
+ path: params.filter((param) => param.in === "path"),
418
+ query: params.filter((param) => param.in === "query"),
419
+ header: params.filter((param) => param.in === "header"),
420
+ cookie: params.filter((param) => param.in === "cookie")
421
+ };
422
+ }
423
+ function getStatusCodeNumber(statusCode) {
424
+ const code = Number(statusCode);
425
+ return Number.isNaN(code) ? null : code;
426
+ }
427
+ function isErrorStatusCode(statusCode) {
428
+ const code = getStatusCodeNumber(statusCode);
429
+ return code !== null && code >= 400;
430
+ }
431
+ function resolveErrorNames(node, resolver) {
432
+ return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
433
+ }
434
+ function resolveStatusCodeNames(node, resolver) {
435
+ return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
436
+ }
437
+ const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
438
+ function resolveOperationTypeNames(node, resolver, options = {}) {
439
+ const cacheKey = `${node.operationId}\0${options.paramsCasing ?? ""}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
440
+ let byResolver = typeNamesByResolver.get(resolver);
441
+ if (byResolver) {
442
+ const cached = byResolver.get(cacheKey);
443
+ if (cached) return cached;
444
+ } else {
445
+ byResolver = /* @__PURE__ */ new Map();
446
+ typeNamesByResolver.set(resolver, byResolver);
447
+ }
448
+ const { path, query, header } = getOperationParameters(node, { paramsCasing: options.paramsCasing });
449
+ const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
450
+ const exclude = new Set(options.exclude ?? []);
451
+ const paramNames = options.includeParams === false ? [] : [
452
+ ...path.map((param) => resolver.resolvePathParamsName(node, param)),
453
+ ...query.map((param) => resolver.resolveQueryParamsName(node, param)),
454
+ ...header.map((param) => resolver.resolveHeaderParamsName(node, param))
455
+ ];
456
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)];
457
+ const result = (options.order === "body-response-first" ? [
458
+ ...bodyAndResponseNames,
459
+ ...paramNames,
460
+ ...responseStatusNames
461
+ ] : [
462
+ ...paramNames,
463
+ ...bodyAndResponseNames,
464
+ ...responseStatusNames
465
+ ]).filter((name) => Boolean(name) && !exclude.has(name));
466
+ byResolver.set(cacheKey, result);
467
+ return result;
39
468
  }
40
469
  //#endregion
41
470
  //#region ../../internals/shared/src/group.ts
@@ -61,7 +490,7 @@ function createGroupConfig(group) {
61
490
  if (!group) return null;
62
491
  const defaultName = (ctx) => {
63
492
  if (group.type === "path") return `${ctx.group.split("/")[1]}`;
64
- return require_components.camelCase(ctx.group);
493
+ return camelCase(ctx.group);
65
494
  };
66
495
  return {
67
496
  ...group,
@@ -69,6 +498,826 @@ function createGroupConfig(group) {
69
498
  };
70
499
  }
71
500
  //#endregion
501
+ //#region ../../internals/client/src/builders/parser.ts
502
+ /**
503
+ * Returns `true` when any direction of the parser uses zod (used for dependency checks).
504
+ */
505
+ function isParserEnabled(parser) {
506
+ if (!parser) return false;
507
+ if (parser === "zod") return true;
508
+ return Boolean(parser.request || parser.response);
509
+ }
510
+ //#endregion
511
+ //#region ../../internals/client/src/resolveClient.ts
512
+ /**
513
+ * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
514
+ * operation, shared so the selection rules and diagnostics stay in one place.
515
+ *
516
+ * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered
517
+ * contract client plugin (plugin-fetch or plugin-axios) and never emits its own inline client:
518
+ *
519
+ * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
520
+ * imports and calls them.
521
+ * - `error` — no client plugin is registered, several are registered without a selector, or the
522
+ * requested one is missing.
523
+ *
524
+ * The `client` string selects explicitly (`'fetch'` / `'axios'`); when it is unset a lone registered
525
+ * contract client plugin is picked up automatically.
526
+ */
527
+ const pluginFetchName = "plugin-fetch";
528
+ const pluginAxiosName = "plugin-axios";
529
+ const selectorToPlugin = {
530
+ fetch: pluginFetchName,
531
+ axios: pluginAxiosName
532
+ };
533
+ const contractPlugins = [pluginFetchName, pluginAxiosName];
534
+ /**
535
+ * Applies the `client` resolution rules. See the module comment for the strategy shape.
536
+ *
537
+ * @example
538
+ * ```ts
539
+ * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })
540
+ * // { kind: 'contract', pluginName: 'plugin-fetch' }
541
+ * ```
542
+ *
543
+ * @example
544
+ * ```ts
545
+ * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
546
+ * // { kind: 'error', message: 'No client plugin is registered…' }
547
+ * ```
548
+ */
549
+ function resolveClient(options) {
550
+ const { client, pluginNames } = options;
551
+ const has = (name) => pluginNames.includes(name);
552
+ if (client === "fetch" || client === "axios") {
553
+ const pluginName = selectorToPlugin[client];
554
+ if (!has(pluginName)) return {
555
+ kind: "error",
556
+ 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.`
557
+ };
558
+ return {
559
+ kind: "contract",
560
+ pluginName
561
+ };
562
+ }
563
+ const registered = contractPlugins.filter(has);
564
+ if (registered.length === 1) return {
565
+ kind: "contract",
566
+ pluginName: registered[0]
567
+ };
568
+ if (registered.length > 1) return {
569
+ kind: "error",
570
+ 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.`
571
+ };
572
+ return {
573
+ kind: "error",
574
+ 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."
575
+ };
576
+ }
577
+ //#endregion
578
+ //#region ../../internals/client/src/resolveClientOperation.ts
579
+ /**
580
+ * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up
581
+ * the registered contract client plugin's resolver and output. Works for any contract client plugin
582
+ * (plugin-fetch or plugin-axios). Returns `null` when no contract plugin is in play (the inline
583
+ * path). The plugin injects `.kubb/client.ts` at the global output root, the same path consumers
584
+ * read `RequestConfig` / `ResponseErrorConfig` from.
585
+ */
586
+ function resolveClientOperation(options) {
587
+ const { clientPlugin, driver, node, root, output } = options;
588
+ if (!clientPlugin) return null;
589
+ const resolver = driver.getResolver(clientPlugin.pluginName);
590
+ if (!resolver) return null;
591
+ const plugin = driver.getPlugin(clientPlugin.pluginName);
592
+ const file = resolver.resolveFile(operationFileEntry(node, node.operationId), {
593
+ root,
594
+ output: plugin?.options?.output ?? output,
595
+ group: plugin?.options?.group ?? void 0
596
+ });
597
+ return {
598
+ name: resolver.resolveName(node.operationId),
599
+ path: file.path,
600
+ clientPath: node_path.default.resolve(root, ".kubb/client.ts")
601
+ };
602
+ }
603
+ //#endregion
604
+ //#region ../../internals/tanstack-query/src/components/MutationKey.tsx
605
+ const declarationPrinter$4 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
606
+ const mutationKeyTransformer = ({ node }) => {
607
+ if (!node.path) return [];
608
+ return [`{ url: '${Url.toPath(node.path)}' }`];
609
+ };
610
+ function MutationKey$1({ name, node, transformer }) {
611
+ const paramsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: [] });
612
+ const paramsSignature = declarationPrinter$4.print(paramsNode) ?? "";
613
+ const keys = (transformer ?? mutationKeyTransformer)({
614
+ node,
615
+ casing: "camelcase"
616
+ });
617
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
618
+ name,
619
+ isExportable: true,
620
+ isIndexable: true,
621
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function.Arrow, {
622
+ name,
623
+ export: true,
624
+ params: paramsSignature,
625
+ singleLine: true,
626
+ children: `[${keys.join(", ")}] as const`
627
+ })
628
+ });
629
+ }
630
+ __name(MutationKey$1, "MutationKey");
631
+ //#endregion
632
+ //#region ../../internals/tanstack-query/src/utils.ts
633
+ /**
634
+ * The grouped request options, ordered for both the destructured signature and the
635
+ * call passed to the underlying client.
636
+ */
637
+ const requestGroupOrder = [
638
+ "path",
639
+ "query",
640
+ "body",
641
+ "headers"
642
+ ];
643
+ /**
644
+ * Builds the grouped `{ path, query, body, headers }` parameter that mirrors the client
645
+ * function signature. Only the groups the operation carries are emitted, typed from the
646
+ * operation's `RequestConfig`. `keys` narrows the emitted groups, used by the query key which
647
+ * never carries `headers`.
648
+ *
649
+ * By default the whole group is typed as the single `RequestConfig` reference. When
650
+ * `memberTypeWrapper` is set, each group is emitted as its own member typed from the matching
651
+ * `RequestConfig['<group>']` slice and wrapped, used by vue-query to apply
652
+ * `MaybeRefOrGetter` per group.
653
+ */
654
+ function buildGroupedRequestParam(node, options) {
655
+ const { resolver, keys = requestGroupOrder, memberTypeWrapper } = options;
656
+ const { groups, hasRequiredPath, hasRequiredQuery, hasRequiredHeader } = getRequestGroupOptionality(node);
657
+ const names = keys.filter((key) => groups[key]);
658
+ if (names.length === 0) return null;
659
+ const requiredByGroup = {
660
+ path: hasRequiredPath,
661
+ query: hasRequiredQuery,
662
+ body: groups.body,
663
+ headers: hasRequiredHeader
664
+ };
665
+ const isOptional = names.every((name) => !requiredByGroup[name]);
666
+ const requestConfigName = resolver.resolveRequestConfigName(node);
667
+ const omittedKeys = requestGroupOrder.filter((key) => !keys.includes(key));
668
+ const requestConfigType = omittedKeys.length > 0 ? `Omit<${requestConfigName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : requestConfigName;
669
+ if (memberTypeWrapper) {
670
+ const members = names.map((name) => ({
671
+ name,
672
+ type: memberTypeWrapper(`${requestConfigType}['${name}']`),
673
+ optional: !requiredByGroup[name]
674
+ }));
675
+ return (0, _kubb_plugin_ts.createFunctionParameter)({
676
+ name: (0, _kubb_plugin_ts.createObjectBindingPattern)({ elements: names.map((name) => ({ name })) }),
677
+ type: (0, _kubb_plugin_ts.createTypeLiteral)({ members }),
678
+ optional: false,
679
+ ...isOptional ? { default: "{}" } : {}
680
+ });
681
+ }
682
+ return (0, _kubb_plugin_ts.createFunctionParameter)({
683
+ name: (0, _kubb_plugin_ts.createObjectBindingPattern)({ elements: names.map((name) => ({ name })) }),
684
+ type: requestConfigType,
685
+ optional: false,
686
+ ...isOptional ? { default: "{}" } : {}
687
+ });
688
+ }
689
+ /**
690
+ * Builds the shared `({ path, query, body, headers }, config = {})` parameter list for a
691
+ * TanStack query-options function. The leading parameter mirrors the client signature, and the
692
+ * trailing `config` is a partial `RequestConfig` minus the grouped data-shape keys, which are passed
693
+ * explicitly. Framework plugins wrap the result when needed, for example vue-query applies `MaybeRefOrGetter`.
694
+ */
695
+ function buildQueryOptionsParams(node, options) {
696
+ const { resolver, memberTypeWrapper } = options;
697
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
698
+ resolver,
699
+ memberTypeWrapper
700
+ }), (0, _kubb_plugin_ts.createFunctionParameter)({
701
+ name: "config",
702
+ type: `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`,
703
+ default: "{}"
704
+ })].filter((param) => param !== null) });
705
+ }
706
+ /**
707
+ * Builds the call to a client `<op>` function inside a query/mutation hook body. The function takes
708
+ * a single grouped options object, so the operation's request groups are passed as
709
+ * shorthand alongside the spread `config`, with `throwOnError: true` pinned last so a caller's config
710
+ * can't flip the query's error semantics. Queries thread the TanStack `signal`; mutations omit it.
711
+ *
712
+ * @example
713
+ * ```ts
714
+ * buildClientCall(node, { clientName: 'getPetById', signal: true })
715
+ * // getPetById({ path, ...config, signal: config.signal ?? signal, throwOnError: true })
716
+ * ```
717
+ */
718
+ function buildClientCall(node, options) {
719
+ const { clientName, signal = false } = options;
720
+ const { groups } = getRequestGroupOptionality(node);
721
+ return `${clientName}({ ${[
722
+ "...config",
723
+ ...requestGroupOrder.filter((key) => groups[key]),
724
+ signal ? "signal: config.signal ?? signal" : null,
725
+ "throwOnError: true"
726
+ ].filter((part) => part !== null).join(", ")} })`;
727
+ }
728
+ /**
729
+ * Returns `'zod'` when response-direction parsing is enabled.
730
+ * The string shorthand `'zod'` also enables response parsing.
731
+ */
732
+ function resolveResponseParser(parser) {
733
+ if (!parser) return null;
734
+ if (parser === "zod") return "zod";
735
+ return parser.response ?? null;
736
+ }
737
+ /**
738
+ * Returns `'zod'` when request body parsing is enabled.
739
+ * The string shorthand `'zod'` also enables request body parsing (existing behavior).
740
+ */
741
+ function resolveRequestParser(parser) {
742
+ if (!parser) return null;
743
+ if (parser === "zod") return "zod";
744
+ return parser.request ?? null;
745
+ }
746
+ /**
747
+ * Returns `'zod'` when query-params parsing is enabled.
748
+ * Only the object form `{ request: 'zod' }` enables this. `parser: 'zod'` does not.
749
+ */
750
+ function resolveQueryParamsParser(parser) {
751
+ if (!parser || parser === "zod") return null;
752
+ return parser.request ?? null;
753
+ }
754
+ /**
755
+ * Collects the Zod schema import names for an operation based on the active parser directions.
756
+ *
757
+ * - `parser: 'zod'`: response and request body names (backward-compatible behavior).
758
+ * - `parser: { request: 'zod' }`: request body and query params names.
759
+ * - `parser: { response: 'zod' }`: response name only.
760
+ * - `parser: { request: 'zod', response: 'zod' }`: all three.
761
+ *
762
+ * Returns an empty array when no resolver is provided or `parser` is falsy.
763
+ */
764
+ function resolveZodSchemaNames(node, zodResolver, parser) {
765
+ if (!zodResolver || !parser) return [];
766
+ const { query: queryParams } = getOperationParameters(node, { paramsCasing: "original" });
767
+ return [
768
+ resolveResponseParser(parser) === "zod" ? zodResolver.resolveResponseName?.(node) : null,
769
+ resolveRequestParser(parser) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
770
+ resolveQueryParamsParser(parser) === "zod" && queryParams.length > 0 ? zodResolver.resolveQueryParamsName?.(node, queryParams[0]) : null
771
+ ].filter((n) => Boolean(n));
772
+ }
773
+ /**
774
+ * Build QueryKey params as the grouped `{ path, query, body }` object (NO headers, NO config),
775
+ * typed from the operation's `RequestConfig` minus `url`. The query key transformer reads the
776
+ * grouped `path`/`query`/`body` bindings.
777
+ */
778
+ function buildQueryKeyParams(node, options) {
779
+ const { resolver } = options;
780
+ const groupedParam = buildGroupedRequestParam(node, {
781
+ resolver,
782
+ keys: [
783
+ "path",
784
+ "query",
785
+ "body"
786
+ ]
787
+ });
788
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedParam ? [groupedParam] : [] });
789
+ }
790
+ //#endregion
791
+ //#region ../../internals/tanstack-query/src/components/QueryKey.tsx
792
+ const declarationPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
793
+ const queryKeyTransformer = ({ node }) => {
794
+ if (!node.path) return [];
795
+ const hasPathParams = getOperationParameters(node).path.length > 0;
796
+ const hasQueryParams = getOperationParameters(node).query.length > 0;
797
+ const hasRequestBody = !!node.requestBody?.content?.[0]?.schema;
798
+ return [
799
+ hasPathParams ? `{ url: '${Url.toPath(node.path)}', params: path }` : `{ url: '${Url.toPath(node.path)}' }`,
800
+ hasQueryParams ? "...(query ? [query] : [])" : null,
801
+ hasRequestBody ? "...(body ? [body] : [])" : null
802
+ ].filter(Boolean);
803
+ };
804
+ function QueryKey({ name, node, tsResolver, typeName, transformer }) {
805
+ const paramsNode = buildQueryKeyParams(node, { resolver: tsResolver });
806
+ const paramsSignature = declarationPrinter$3.print(paramsNode) ?? "";
807
+ const keys = (transformer ?? queryKeyTransformer)({
808
+ node,
809
+ casing: "camelcase"
810
+ });
811
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
812
+ name,
813
+ isExportable: true,
814
+ isIndexable: true,
815
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function.Arrow, {
816
+ name,
817
+ export: true,
818
+ params: paramsSignature,
819
+ singleLine: true,
820
+ children: `[${keys.join(", ")}] as const`
821
+ })
822
+ }), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
823
+ name: typeName,
824
+ isTypeOnly: true,
825
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Type, {
826
+ name: typeName,
827
+ children: `ReturnType<typeof ${name}>`
828
+ })
829
+ })] });
830
+ }
831
+ //#endregion
832
+ //#region src/components/Mutation.tsx
833
+ const declarationPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
834
+ const callPrinter$1 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
835
+ function buildMutationParamsNode(node, options) {
836
+ const { mutationKeyTypeName, mutationArgTypeName, resolver } = options;
837
+ const responseName = resolver.resolveResponseName(node);
838
+ const errorNames = resolveErrorNames(node, resolver);
839
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
840
+ name: "options",
841
+ type: `{
842
+ mutation?: SWRMutationConfiguration<${responseName}, ${`ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`}, ${mutationKeyTypeName} | null, ${mutationArgTypeName}> & { throwOnError?: boolean },
843
+ client?: ${buildRequestConfigType(node)},
844
+ shouldFetch?: boolean,
845
+ }`,
846
+ default: "{}"
847
+ })] });
848
+ }
849
+ function Mutation({ name, clientName, mutationKeyName, mutationKeyTypeName, mutationArgTypeName, node, tsResolver }) {
850
+ const responseName = tsResolver.resolveResponseName(node);
851
+ const errorNames = resolveErrorNames(node, tsResolver);
852
+ const TData = responseName;
853
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
854
+ const groupedParam = buildGroupedRequestParam(node, { resolver: tsResolver });
855
+ const hasMutationParams = groupedParam !== null;
856
+ const groupedParamsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedParam ? [groupedParam] : [] });
857
+ const argTypeBody = hasMutationParams ? tsResolver.resolveRequestConfigName(node) : "";
858
+ const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "";
859
+ const mutationFnBody = `const { data } = await ${buildClientCall(node, {
860
+ clientName,
861
+ signal: false
862
+ })}
863
+ return data`;
864
+ const generics = [
865
+ TData,
866
+ TError,
867
+ `${mutationKeyTypeName} | null`,
868
+ mutationArgTypeName
869
+ ];
870
+ const paramsNode = buildMutationParamsNode(node, {
871
+ mutationKeyTypeName,
872
+ mutationArgTypeName,
873
+ resolver: tsResolver
874
+ });
875
+ const paramsSignature = declarationPrinter$2.print(paramsNode) ?? "";
876
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
877
+ name: mutationArgTypeName,
878
+ isExportable: true,
879
+ isIndexable: true,
880
+ isTypeOnly: true,
881
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Type, {
882
+ name: mutationArgTypeName,
883
+ export: true,
884
+ children: hasMutationParams ? argTypeBody : "never"
885
+ })
886
+ }), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
887
+ name,
888
+ isExportable: true,
889
+ isIndexable: true,
890
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function, {
891
+ name,
892
+ export: true,
893
+ params: paramsSignature,
894
+ JSDoc: { comments: buildOperationComments(node) },
895
+ children: `
896
+ const { mutation: mutationOptions, client: config = {}, shouldFetch = true } = options ?? {}
897
+ const mutationKey = ${mutationKeyName}()
898
+
899
+ return useSWRMutation<${generics.join(", ")}>(
900
+ shouldFetch ? mutationKey : null,
901
+ async (_url${hasMutationParams ? `, { arg: ${argBindingStr} }` : ""}) => {
902
+ ${mutationFnBody}
903
+ },
904
+ mutationOptions
905
+ )
906
+ `
907
+ })
908
+ })] });
909
+ }
910
+ //#endregion
911
+ //#region src/components/MutationKey.tsx
912
+ function MutationKey({ name, typeName, node, transformer }) {
913
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(MutationKey$1, {
914
+ name,
915
+ node,
916
+ transformer
917
+ }), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
918
+ name: typeName,
919
+ isExportable: true,
920
+ isIndexable: true,
921
+ isTypeOnly: true,
922
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Type, {
923
+ export: true,
924
+ name: typeName,
925
+ children: `ReturnType<typeof ${name}>`
926
+ })
927
+ })] });
928
+ }
929
+ //#endregion
930
+ //#region src/components/QueryOptions.tsx
931
+ const declarationPrinter$1 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
932
+ function getQueryOptionsParams(node, options) {
933
+ return buildQueryOptionsParams(node, options);
934
+ }
935
+ function QueryOptions({ name, clientName, node, tsResolver }) {
936
+ const paramsNode = getQueryOptionsParams(node, { resolver: tsResolver });
937
+ const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
938
+ const fetcherBody = `const { data } = await ${buildClientCall(node, {
939
+ clientName,
940
+ signal: false
941
+ })}
942
+ return data`;
943
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
944
+ name,
945
+ isExportable: true,
946
+ isIndexable: true,
947
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function, {
948
+ name,
949
+ export: true,
950
+ params: paramsSignature,
951
+ children: `
952
+ return {
953
+ fetcher: async () => {
954
+ ${fetcherBody}
955
+ },
956
+ }
957
+ `
958
+ })
959
+ });
960
+ }
961
+ //#endregion
962
+ //#region src/components/Query.tsx
963
+ const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
964
+ const callPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
965
+ function buildQueryParamsNode(node, options) {
966
+ const { resolver } = options;
967
+ const responseName = resolver.resolveResponseName(node);
968
+ const errorNames = resolveErrorNames(node, resolver);
969
+ const optionsParam = (0, _kubb_plugin_ts.createFunctionParameter)({
970
+ name: "options",
971
+ type: `{
972
+ query?: SWRConfiguration<${[responseName, `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`].join(", ")}>,
973
+ client?: ${buildClientOptionType()},
974
+ shouldFetch?: boolean,
975
+ immutable?: boolean
976
+ }`,
977
+ default: "{}"
978
+ });
979
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, { resolver }), optionsParam].filter((param) => param !== null) });
980
+ }
981
+ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
982
+ const responseName = tsResolver.resolveResponseName(node);
983
+ const errorNames = resolveErrorNames(node, tsResolver);
984
+ const generics = [
985
+ responseName,
986
+ `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`,
987
+ `${queryKeyTypeName} | null`
988
+ ];
989
+ const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
990
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? "";
991
+ const queryOptionsParamsNode = getQueryOptionsParams(node, { resolver: tsResolver });
992
+ const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? "";
993
+ const paramsNode = buildQueryParamsNode(node, { resolver: tsResolver });
994
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
995
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
996
+ name,
997
+ isExportable: true,
998
+ isIndexable: true,
999
+ children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function, {
1000
+ name,
1001
+ export: true,
1002
+ params: paramsSignature,
1003
+ JSDoc: { comments: buildOperationComments(node) },
1004
+ children: `
1005
+ const { query: queryOptions, client: config = {}, shouldFetch = true, immutable } = options ?? {}
1006
+
1007
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
1008
+
1009
+ return useSWR<${generics.join(", ")}>(
1010
+ shouldFetch ? queryKey : null,
1011
+ {
1012
+ ...${queryOptionsName}(${queryOptionsParamsCall}),
1013
+ ...(immutable ? {
1014
+ revalidateIfStale: false,
1015
+ revalidateOnFocus: false,
1016
+ revalidateOnReconnect: false
1017
+ } : { }),
1018
+ ...queryOptions,
1019
+ }
1020
+ )
1021
+ `
1022
+ })
1023
+ });
1024
+ }
1025
+ //#endregion
1026
+ //#region src/generators/mutationGenerator.tsx
1027
+ /**
1028
+ * Built-in generator for `useSWRMutation` hooks. Emits one `useFooMutation` hook
1029
+ * per POST/PUT/DELETE operation (configurable via `mutation.methods`) plus
1030
+ * the matching `fooMutationKey` helper.
1031
+ */
1032
+ const mutationGenerator = (0, _kubb_core.defineGenerator)({
1033
+ name: "swr-mutation",
1034
+ renderer: _kubb_renderer_jsx.jsxRenderer,
1035
+ operation(node, ctx) {
1036
+ if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1037
+ const { config, driver, resolver, root } = ctx;
1038
+ const { output, query, mutation, parser, client, group } = ctx.options;
1039
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1040
+ if (!pluginTs) return null;
1041
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1042
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1043
+ const queryMethods = new Set(query ? query.methods : []);
1044
+ if (!(mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase()))) return null;
1045
+ const importPath = mutation ? mutation.importPath : "swr/mutation";
1046
+ const contractOp = resolveClientOperation({
1047
+ clientPlugin: { pluginName: client.pluginName },
1048
+ driver,
1049
+ node,
1050
+ root,
1051
+ output
1052
+ });
1053
+ if (!contractOp) return null;
1054
+ const mutationHookName = resolver.resolveMutationName(node);
1055
+ const mutationKeyName = resolver.resolveMutationKeyName(node);
1056
+ const mutationKeyTypeName = resolver.resolveMutationKeyTypeName(node);
1057
+ const mutationArgTypeName = resolver.resolveMutationArgTypeName(node);
1058
+ const meta = {
1059
+ file: resolver.resolveFile({
1060
+ name: mutationHookName,
1061
+ extname: ".ts",
1062
+ tag: node.tags[0] ?? "default",
1063
+ path: node.path
1064
+ }, {
1065
+ root,
1066
+ output,
1067
+ group
1068
+ }),
1069
+ fileTs: tsResolver.resolveFile({
1070
+ name: node.operationId,
1071
+ extname: ".ts",
1072
+ tag: node.tags[0] ?? "default",
1073
+ path: node.path
1074
+ }, {
1075
+ root,
1076
+ output: pluginTs.options?.output ?? output,
1077
+ group: pluginTs.options?.group
1078
+ })
1079
+ };
1080
+ const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1081
+ order: "body-response-first",
1082
+ includeParams: false
1083
+ })].filter((name) => Boolean(name));
1084
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1085
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1086
+ const fileZod = zodResolver ? zodResolver.resolveFile({
1087
+ name: node.operationId,
1088
+ extname: ".ts",
1089
+ tag: node.tags[0] ?? "default",
1090
+ path: node.path
1091
+ }, {
1092
+ root,
1093
+ output: pluginZod?.options?.output ?? output,
1094
+ group: pluginZod?.options?.group
1095
+ }) : void 0;
1096
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1097
+ const calledClientName = contractOp.name;
1098
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1099
+ baseName: meta.file.baseName,
1100
+ path: meta.file.path,
1101
+ meta: meta.file.meta,
1102
+ banner: resolver.resolveBanner(ctx.meta, {
1103
+ output,
1104
+ config,
1105
+ file: {
1106
+ path: meta.file.path,
1107
+ baseName: meta.file.baseName
1108
+ }
1109
+ }),
1110
+ footer: resolver.resolveFooter(ctx.meta, {
1111
+ output,
1112
+ config,
1113
+ file: {
1114
+ path: meta.file.path,
1115
+ baseName: meta.file.baseName
1116
+ }
1117
+ }),
1118
+ children: [
1119
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1120
+ name: zodSchemaNames,
1121
+ root: meta.file.path,
1122
+ path: fileZod.path
1123
+ }),
1124
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1125
+ name: [contractOp.name],
1126
+ root: meta.file.path,
1127
+ path: contractOp.path
1128
+ }),
1129
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1130
+ name: ["RequestConfig", "ResponseErrorConfig"],
1131
+ root: meta.file.path,
1132
+ path: contractOp.clientPath,
1133
+ isTypeOnly: true
1134
+ }),
1135
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1136
+ name: Array.from(new Set(importedTypeNames)),
1137
+ root: meta.file.path,
1138
+ path: meta.fileTs.path,
1139
+ isTypeOnly: true
1140
+ }),
1141
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(MutationKey, {
1142
+ name: mutationKeyName,
1143
+ typeName: mutationKeyTypeName,
1144
+ node,
1145
+ transformer: ctx.options.mutationKey
1146
+ }),
1147
+ mutation && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1148
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1149
+ name: "useSWRMutation",
1150
+ path: importPath
1151
+ }),
1152
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1153
+ name: ["SWRMutationConfiguration"],
1154
+ path: importPath,
1155
+ isTypeOnly: true
1156
+ }),
1157
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(Mutation, {
1158
+ name: mutationHookName,
1159
+ clientName: calledClientName,
1160
+ mutationKeyName,
1161
+ mutationKeyTypeName,
1162
+ mutationArgTypeName,
1163
+ node,
1164
+ tsResolver
1165
+ })
1166
+ ] })
1167
+ ]
1168
+ });
1169
+ }
1170
+ });
1171
+ //#endregion
1172
+ //#region src/generators/queryGenerator.tsx
1173
+ const queryGenerator = (0, _kubb_core.defineGenerator)({
1174
+ name: "swr-query",
1175
+ renderer: _kubb_renderer_jsx.jsxRenderer,
1176
+ operation(node, ctx) {
1177
+ if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1178
+ const { config, driver, resolver, root } = ctx;
1179
+ const { output, query, mutation, parser, client, group } = ctx.options;
1180
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1181
+ if (!pluginTs) return null;
1182
+ const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1183
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1184
+ const queryMethods = new Set(query ? query.methods : []);
1185
+ const isMutation = mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase());
1186
+ if (!isQuery || isMutation) return null;
1187
+ const importPath = query ? query.importPath : "swr";
1188
+ const contractOp = resolveClientOperation({
1189
+ clientPlugin: { pluginName: client.pluginName },
1190
+ driver,
1191
+ node,
1192
+ root,
1193
+ output
1194
+ });
1195
+ if (!contractOp) return null;
1196
+ const queryName = resolver.resolveQueryName(node);
1197
+ const queryOptionsName = resolver.resolveQueryOptionsName(node);
1198
+ const queryKeyName = resolver.resolveQueryKeyName(node);
1199
+ const queryKeyTypeName = resolver.resolveQueryKeyTypeName(node);
1200
+ const meta = {
1201
+ file: resolver.resolveFile({
1202
+ name: queryName,
1203
+ extname: ".ts",
1204
+ tag: node.tags[0] ?? "default",
1205
+ path: node.path
1206
+ }, {
1207
+ root,
1208
+ output,
1209
+ group
1210
+ }),
1211
+ fileTs: tsResolver.resolveFile({
1212
+ name: node.operationId,
1213
+ extname: ".ts",
1214
+ tag: node.tags[0] ?? "default",
1215
+ path: node.path
1216
+ }, {
1217
+ root,
1218
+ output: pluginTs.options?.output ?? output,
1219
+ group: pluginTs.options?.group
1220
+ })
1221
+ };
1222
+ const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1223
+ exclude: [queryKeyTypeName],
1224
+ order: "body-response-first",
1225
+ includeParams: false
1226
+ })].filter((name) => Boolean(name));
1227
+ const pluginZod = isParserEnabled(parser) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1228
+ const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1229
+ const fileZod = zodResolver ? zodResolver.resolveFile({
1230
+ name: node.operationId,
1231
+ extname: ".ts",
1232
+ tag: node.tags[0] ?? "default",
1233
+ path: node.path
1234
+ }, {
1235
+ root,
1236
+ output: pluginZod?.options?.output ?? output,
1237
+ group: pluginZod?.options?.group
1238
+ }) : void 0;
1239
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1240
+ const calledClientName = contractOp.name;
1241
+ return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1242
+ baseName: meta.file.baseName,
1243
+ path: meta.file.path,
1244
+ meta: meta.file.meta,
1245
+ banner: resolver.resolveBanner(ctx.meta, {
1246
+ output,
1247
+ config,
1248
+ file: {
1249
+ path: meta.file.path,
1250
+ baseName: meta.file.baseName
1251
+ }
1252
+ }),
1253
+ footer: resolver.resolveFooter(ctx.meta, {
1254
+ output,
1255
+ config,
1256
+ file: {
1257
+ path: meta.file.path,
1258
+ baseName: meta.file.baseName
1259
+ }
1260
+ }),
1261
+ children: [
1262
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1263
+ name: zodSchemaNames,
1264
+ root: meta.file.path,
1265
+ path: fileZod.path
1266
+ }),
1267
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1268
+ name: [contractOp.name],
1269
+ root: meta.file.path,
1270
+ path: contractOp.path
1271
+ }),
1272
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1273
+ name: ["RequestConfig", "ResponseErrorConfig"],
1274
+ root: meta.file.path,
1275
+ path: contractOp.clientPath,
1276
+ isTypeOnly: true
1277
+ }),
1278
+ meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1279
+ name: Array.from(new Set(importedTypeNames)),
1280
+ root: meta.file.path,
1281
+ path: meta.fileTs.path,
1282
+ isTypeOnly: true
1283
+ }),
1284
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(QueryKey, {
1285
+ name: queryKeyName,
1286
+ typeName: queryKeyTypeName,
1287
+ node,
1288
+ tsResolver,
1289
+ transformer: ctx.options.queryKey
1290
+ }),
1291
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(QueryOptions, {
1292
+ name: queryOptionsName,
1293
+ clientName: calledClientName,
1294
+ node,
1295
+ tsResolver
1296
+ }),
1297
+ query && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1298
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1299
+ name: "useSWR",
1300
+ path: importPath
1301
+ }),
1302
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1303
+ name: ["SWRConfiguration"],
1304
+ path: importPath,
1305
+ isTypeOnly: true
1306
+ }),
1307
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(Query, {
1308
+ name: queryName,
1309
+ queryOptionsName,
1310
+ queryKeyName,
1311
+ queryKeyTypeName,
1312
+ node,
1313
+ tsResolver
1314
+ })
1315
+ ] })
1316
+ ]
1317
+ });
1318
+ }
1319
+ });
1320
+ //#endregion
72
1321
  //#region src/resolvers/resolverSwr.ts
73
1322
  function capitalize(name) {
74
1323
  return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
@@ -85,7 +1334,7 @@ const resolverSwr = (0, _kubb_core.defineResolver)(() => ({
85
1334
  name: "default",
86
1335
  pluginName: "plugin-swr",
87
1336
  default(name, type) {
88
- return type === "file" ? toFilePath(name) : require_components.camelCase(name);
1337
+ return type === "file" ? toFilePath(name) : camelCase(name);
89
1338
  },
90
1339
  resolveName(name) {
91
1340
  return this.default(name, "function");
@@ -128,31 +1377,30 @@ const pluginSwr = (0, _kubb_core.definePlugin)((options) => {
128
1377
  const { output = {
129
1378
  path: "hooks",
130
1379
  barrel: { type: "named" }
131
- }, group, exclude = [], include, override = [], parser = false, paramsType = "inline", pathParamsType = paramsType === "object" ? "object" : options.pathParamsType || "inline", mutation = {}, query = {}, mutationKey = require_components.mutationKeyTransformer, queryKey = require_components.queryKeyTransformer, paramsCasing, client, resolver: userResolver, macros: userMacros, generators: userGenerators = [] } = options;
132
- const clientName = client?.client ?? "axios";
133
- const clientImportPath = client?.importPath ?? (!client?.bundle ? `@kubb/plugin-client/clients/${clientName}` : void 0);
134
- const selectedGenerators = options.generators ?? [require_generators.queryGenerator, require_generators.mutationGenerator].filter((generator) => Boolean(generator));
1380
+ }, group, exclude = [], include, override = [], parser = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, client, resolver: userResolver, macros: userMacros } = options;
1381
+ const selectedGenerators = [queryGenerator, mutationGenerator].filter((generator) => Boolean(generator));
135
1382
  const groupConfig = createGroupConfig(group) ?? void 0;
136
1383
  return {
137
1384
  name: pluginSwrName,
138
1385
  options,
139
- dependencies: [_kubb_plugin_ts.pluginTsName, (0, _kubb_plugin_client.isParserEnabled)(parser) ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
1386
+ dependencies: [_kubb_plugin_ts.pluginTsName, isParserEnabled(parser) ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
140
1387
  hooks: { "kubb:plugin:setup"(ctx) {
141
1388
  const resolver = userResolver ? {
142
1389
  ...resolverSwr,
143
1390
  ...userResolver
144
1391
  } : resolverSwr;
1392
+ const resolvedClient = resolveClient({
1393
+ client,
1394
+ pluginNames: (ctx.config.plugins ?? []).map((p) => p.name).filter((name) => Boolean(name))
1395
+ });
1396
+ if (resolvedClient.kind === "error") throw new Error(resolvedClient.message);
1397
+ const resolvedClientDescriptor = {
1398
+ kind: "contract",
1399
+ pluginName: resolvedClient.pluginName
1400
+ };
145
1401
  ctx.setOptions({
146
1402
  output,
147
- client: {
148
- bundle: client?.bundle,
149
- baseURL: client?.baseURL,
150
- client: clientName,
151
- clientType: client?.clientType ?? "function",
152
- importPath: clientImportPath,
153
- dataReturnType: client?.dataReturnType ?? "data",
154
- paramsCasing
155
- },
1403
+ client: resolvedClientDescriptor,
156
1404
  queryKey,
157
1405
  query: query === false ? false : {
158
1406
  importPath: "swr",
@@ -171,9 +1419,6 @@ const pluginSwr = (0, _kubb_core.definePlugin)((options) => {
171
1419
  ...mutation
172
1420
  },
173
1421
  parser,
174
- paramsType,
175
- pathParamsType,
176
- paramsCasing,
177
1422
  group: groupConfig,
178
1423
  exclude,
179
1424
  include,
@@ -183,29 +1428,6 @@ const pluginSwr = (0, _kubb_core.definePlugin)((options) => {
183
1428
  ctx.setResolver(resolver);
184
1429
  if (userMacros?.length) ctx.setMacros(userMacros);
185
1430
  for (const gen of selectedGenerators) ctx.addGenerator(gen);
186
- for (const gen of userGenerators) ctx.addGenerator(gen);
187
- const root = node_path.default.resolve(ctx.config.root, ctx.config.output.path);
188
- const hasClientPlugin = !!ctx.config.plugins?.some((p) => p.name === _kubb_plugin_client.pluginClientName);
189
- if (client?.bundle && !hasClientPlugin && !clientImportPath) ctx.injectFile({
190
- baseName: "client.ts",
191
- path: node_path.default.resolve(root, ".kubb/client.ts"),
192
- sources: [_kubb_core.ast.factory.createSource({
193
- name: "client",
194
- nodes: [_kubb_core.ast.factory.createText(clientName === "fetch" ? _kubb_plugin_client_templates_clients_fetch_source.source : _kubb_plugin_client_templates_clients_axios_source.source)],
195
- isExportable: true,
196
- isIndexable: true
197
- })]
198
- });
199
- if (!hasClientPlugin) ctx.injectFile({
200
- baseName: "config.ts",
201
- path: node_path.default.resolve(root, ".kubb/config.ts"),
202
- sources: [_kubb_core.ast.factory.createSource({
203
- name: "config",
204
- nodes: [_kubb_core.ast.factory.createText(_kubb_plugin_client_templates_config_source.source)],
205
- isExportable: false,
206
- isIndexable: false
207
- })]
208
- });
209
1431
  } }
210
1432
  };
211
1433
  });