@kubb/plugin-vue-query 5.0.0-beta.99 → 5.0.1

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
@@ -23,257 +23,17 @@ var __copyProps = (to, from, except, desc) => {
23
23
  }
24
24
  return to;
25
25
  };
26
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
26
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
27
27
  value: mod,
28
28
  enumerable: true
29
29
  }) : target, mod));
30
30
  //#endregion
31
+ let kubb_kit = require("kubb/kit");
31
32
  let node_path = require("node:path");
32
33
  node_path = __toESM(node_path, 1);
33
- let kubb_kit = require("kubb/kit");
34
34
  let _kubb_plugin_ts = require("@kubb/plugin-ts");
35
35
  let kubb_jsx = require("kubb/jsx");
36
36
  let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
37
- //#region ../../internals/utils/src/casing.ts
38
- /**
39
- * Shared implementation for camelCase and PascalCase conversion.
40
- * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
41
- * and capitalizes each word according to `pascal`.
42
- *
43
- * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
44
- */
45
- function toCamelOrPascal(text, pascal) {
46
- 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) => {
47
- if (word.length > 1 && word === word.toUpperCase()) return word;
48
- return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
49
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
50
- }
51
- /**
52
- * Converts `text` to camelCase.
53
- *
54
- * @example Word boundaries
55
- * `camelCase('hello-world') // 'helloWorld'`
56
- *
57
- * @example With a prefix
58
- * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
59
- */
60
- function camelCase(text, { prefix = "", suffix = "" } = {}) {
61
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
62
- }
63
- /**
64
- * Uppercases only the first character of `text`, leaving the rest untouched.
65
- * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.
66
- *
67
- * @example
68
- * `capitalize('getPetById') // 'GetPetById'`
69
- */
70
- function capitalize(text) {
71
- return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
72
- }
73
- //#endregion
74
- //#region ../../internals/utils/src/reserved.ts
75
- /**
76
- * JavaScript and Java reserved words.
77
- * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
78
- */
79
- const reservedWords = /* @__PURE__ */ new Set([
80
- "abstract",
81
- "arguments",
82
- "boolean",
83
- "break",
84
- "byte",
85
- "case",
86
- "catch",
87
- "char",
88
- "class",
89
- "const",
90
- "continue",
91
- "debugger",
92
- "default",
93
- "delete",
94
- "do",
95
- "double",
96
- "else",
97
- "enum",
98
- "eval",
99
- "export",
100
- "extends",
101
- "false",
102
- "final",
103
- "finally",
104
- "float",
105
- "for",
106
- "function",
107
- "goto",
108
- "if",
109
- "implements",
110
- "import",
111
- "in",
112
- "instanceof",
113
- "int",
114
- "interface",
115
- "let",
116
- "long",
117
- "native",
118
- "new",
119
- "null",
120
- "package",
121
- "private",
122
- "protected",
123
- "public",
124
- "return",
125
- "short",
126
- "static",
127
- "super",
128
- "switch",
129
- "synchronized",
130
- "this",
131
- "throw",
132
- "throws",
133
- "transient",
134
- "true",
135
- "try",
136
- "typeof",
137
- "var",
138
- "void",
139
- "volatile",
140
- "while",
141
- "with",
142
- "yield",
143
- "Array",
144
- "Date",
145
- "hasOwnProperty",
146
- "Infinity",
147
- "isFinite",
148
- "isNaN",
149
- "isPrototypeOf",
150
- "length",
151
- "Math",
152
- "name",
153
- "NaN",
154
- "Number",
155
- "Object",
156
- "prototype",
157
- "String",
158
- "toString",
159
- "undefined",
160
- "valueOf"
161
- ]);
162
- /**
163
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
164
- *
165
- * @example
166
- * ```ts
167
- * isValidVarName('status') // true
168
- * isValidVarName('class') // false (reserved word)
169
- * isValidVarName('42foo') // false (starts with digit)
170
- * ```
171
- */
172
- function isValidVarName(name) {
173
- if (!name || reservedWords.has(name)) return false;
174
- return isIdentifier(name);
175
- }
176
- /**
177
- * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
178
- *
179
- * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
180
- * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
181
- * deciding whether an object key needs quoting.
182
- *
183
- * @example
184
- * ```ts
185
- * isIdentifier('name') // true
186
- * isIdentifier('x-total')// false
187
- * ```
188
- */
189
- function isIdentifier(name) {
190
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
191
- }
192
- //#endregion
193
- //#region ../../internals/utils/src/strings.ts
194
- /**
195
- * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
196
- * `accessor`. Returns `null` for an empty path.
197
- *
198
- * @example
199
- * ```ts
200
- * getNestedAccessor('pagination.next.id', 'lastPage')
201
- * // "lastPage?.['pagination']?.['next']?.['id']"
202
- * ```
203
- */
204
- function getNestedAccessor(param, accessor) {
205
- const parts = Array.isArray(param) ? param : param.split(".");
206
- if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
207
- return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
208
- }
209
- //#endregion
210
- //#region ../../internals/utils/src/url.ts
211
- /**
212
- * Keeps the OpenAPI parameter name as-is when it is already a valid JS identifier, and
213
- * camelCases it only enough to become one otherwise (for example a hyphenated path segment).
214
- */
215
- function transformParam(raw) {
216
- return isValidVarName(raw) ? raw : camelCase(raw);
217
- }
218
- /**
219
- * Helpers for OpenAPI/Swagger paths.
220
- */
221
- var Url = class Url {
222
- /**
223
- * Converts an OpenAPI/Swagger path to Express-style colon syntax.
224
- *
225
- * @example
226
- * Url.toPath('/pet/{petId}') // '/pet/:petId'
227
- */
228
- static toPath(path) {
229
- return path.replace(/\{([^}]+)\}/g, ":$1");
230
- }
231
- /**
232
- * Rewrites OpenAPI placeholder names while keeping the `{...}` braces, so the generated `url`
233
- * literal aligns with the grouped `path` request option that the runtime client interpolates by
234
- * key.
235
- *
236
- * @example
237
- * Url.toSafeTemplate('/user/{monetary-account-id}') // '/user/{monetaryAccountId}'
238
- */
239
- static toSafeTemplate(path) {
240
- return path.replace(/\{([^}]+)\}/g, (_, name) => `{${transformParam(name)}}`);
241
- }
242
- /**
243
- * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
244
- * `prefix` is prepended inside the literal, and `replacer` transforms each parameter name.
245
- *
246
- * @example
247
- * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
248
- *
249
- * @example
250
- * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
251
- */
252
- static toTemplateString(path, { prefix, replacer } = {}) {
253
- const result = path.split(/\{([^}]+)\}/).map((part, i) => {
254
- if (i % 2 === 0) return part;
255
- const param = transformParam(part);
256
- return `\${${replacer ? replacer(param) : param}}`;
257
- }).join("");
258
- return `\`${prefix ?? ""}${result}\``;
259
- }
260
- /**
261
- * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
262
- * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
263
- * names match the generated `path` type, and `prefix` is prepended inside the literal. Shared by
264
- * the client and cypress generators that pass a grouped `path` object.
265
- *
266
- * @example
267
- * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
268
- */
269
- static toGroupedTemplateString(path, { prefix } = {}) {
270
- return Url.toTemplateString(path, {
271
- prefix,
272
- replacer: (name) => `path.${name}`
273
- });
274
- }
275
- };
276
- //#endregion
277
37
  //#region ../../internals/shared/src/params.ts
278
38
  /**
279
39
  * Drops parameters that share the same name, keeping the first.
@@ -312,11 +72,30 @@ function operationFileEntry(node, name, extname = ".ts") {
312
72
  path: node.path
313
73
  };
314
74
  }
75
+ /**
76
+ * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the
77
+ * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the
78
+ * same dependency for the same operation in one pass (a query plugin's several hook generators, the
79
+ * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.
80
+ *
81
+ * @example Cache `plugin-ts`'s file for the current operation
82
+ * ```ts
83
+ * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })
84
+ * ```
85
+ */
86
+ function resolveDependencyOperationFile(options) {
87
+ const { cache, node, resolver, root, output, group } = options;
88
+ return cache.ensureItem(`${resolver.pluginName}:operationFile`, () => resolver.file({
89
+ ...operationFileEntry(node, node.operationId),
90
+ root,
91
+ output,
92
+ group: group ?? void 0
93
+ }));
94
+ }
315
95
  function getOperationLink(node, link) {
316
96
  if (!link) return null;
317
97
  if (typeof link === "function") return link(node) ?? null;
318
- if (link === "urlPath") return node.path ? `{@link ${Url.toPath(node.path)}}` : null;
319
- return node.path ? `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}` : null;
98
+ return node.path ? `{@link ${kubb_kit.Url.toPath(node.path)}}` : null;
320
99
  }
321
100
  /**
322
101
  * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several
@@ -406,16 +185,24 @@ function buildOperationComments(node, options = {}) {
406
185
  if (!splitLines) return filteredComments;
407
186
  return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
408
187
  }
188
+ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
189
+ /**
190
+ * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
191
+ * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
192
+ * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
193
+ * same parameters once per plugin.
194
+ */
409
195
  function getOperationParameters(node) {
410
- return {
411
- path: dedupeParams(node.parameters.filter((param) => param.in === "path").map((param) => isValidVarName(param.name) ? param : {
412
- ...param,
413
- name: camelCase(param.name)
414
- })),
196
+ const cached = operationParameterGroupsByNode.get(node);
197
+ if (cached) return cached;
198
+ const groups = {
199
+ path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
415
200
  query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
416
201
  header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
417
202
  cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
418
203
  };
204
+ operationParameterGroupsByNode.set(node, groups);
205
+ return groups;
419
206
  }
420
207
  function getStatusCodeNumber(statusCode) {
421
208
  const code = Number(statusCode);
@@ -480,6 +267,60 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
480
267
  return result;
481
268
  }
482
269
  //#endregion
270
+ //#region ../../internals/utils/src/casing.ts
271
+ /**
272
+ * Shared implementation for camelCase and PascalCase conversion.
273
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
274
+ * and capitalizes each word according to `pascal`.
275
+ *
276
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
277
+ */
278
+ function toCamelOrPascal(text, pascal) {
279
+ 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) => {
280
+ if (word.length > 1 && word === word.toUpperCase()) return word;
281
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
282
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
283
+ }
284
+ /**
285
+ * Converts `text` to camelCase.
286
+ *
287
+ * @example Word boundaries
288
+ * `camelCase('hello-world') // 'helloWorld'`
289
+ *
290
+ * @example With a prefix
291
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
292
+ */
293
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
294
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
295
+ }
296
+ /**
297
+ * Uppercases only the first character of `text`, leaving the rest untouched.
298
+ * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.
299
+ *
300
+ * @example
301
+ * `capitalize('getPetById') // 'GetPetById'`
302
+ */
303
+ function capitalize(text) {
304
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
305
+ }
306
+ //#endregion
307
+ //#region ../../internals/utils/src/strings.ts
308
+ /**
309
+ * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
310
+ * `accessor`. Returns `null` for an empty path.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * getNestedAccessor('pagination.next.id', 'lastPage')
315
+ * // "lastPage?.['pagination']?.['next']?.['id']"
316
+ * ```
317
+ */
318
+ function getNestedAccessor(param, accessor) {
319
+ const parts = Array.isArray(param) ? param : param.split(".");
320
+ if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
321
+ return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
322
+ }
323
+ //#endregion
483
324
  //#region ../../internals/shared/src/group.ts
484
325
  /**
485
326
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -589,14 +430,16 @@ function buildGroupedRequestParam(node, options) {
589
430
  */
590
431
  function buildQueryOptionsParams(node, options) {
591
432
  const { resolver, memberTypeWrapper } = options;
592
- return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
433
+ const groupedParam = buildGroupedRequestParam(node, {
593
434
  resolver,
594
435
  memberTypeWrapper
595
- }), (0, _kubb_plugin_ts.createFunctionParameter)({
436
+ });
437
+ const configParam = (0, _kubb_plugin_ts.createFunctionParameter)({
596
438
  name: "config",
597
439
  type: `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`,
598
440
  default: "{}"
599
- })].filter((param) => param !== null) });
441
+ });
442
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [groupedParam, configParam].filter((param) => param !== null) });
600
443
  }
601
444
  /**
602
445
  * Builds the call to a client `<op>` function inside a query/mutation hook body. The function takes
@@ -694,6 +537,19 @@ function resolveMutationConfig(mutation, options) {
694
537
  };
695
538
  }
696
539
  /**
540
+ * Classifies an operation as a query or a mutation from the resolved `query` / `mutation` method lists.
541
+ * `query: false` still marks the operation as a query so the query-family generators keep matching it,
542
+ * and a method already claimed by `query` never counts as a mutation.
543
+ */
544
+ function classifyOperation(node, { query, mutation }) {
545
+ const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
546
+ const queryMethods = new Set(query ? query.methods : []);
547
+ return {
548
+ isQuery,
549
+ isMutation: mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase())
550
+ };
551
+ }
552
+ /**
697
553
  * Applies the shared infinite-query defaults during plugin setup: a falsy value disables infinite
698
554
  * queries, and an object merges over `queryParam: 'id'` and `initialPageParam: 0` with the cursor
699
555
  * paths cleared.
@@ -709,6 +565,16 @@ function resolveInfiniteConfig(infinite) {
709
565
  ...infinite
710
566
  };
711
567
  }
568
+ /**
569
+ * The request groups a query key is built from, matching `buildQueryKeyParams`. Headers are
570
+ * deliberately absent: they do not identify a cache entry, so the key factory takes no parameter
571
+ * for an operation that only carries headers.
572
+ */
573
+ const queryKeyGroupOrder = [
574
+ "path",
575
+ "query",
576
+ "body"
577
+ ];
712
578
  //#endregion
713
579
  //#region ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
714
580
  const declarationPrinter$7 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
@@ -722,11 +588,7 @@ function InfiniteQueryOptions$1({ name, clientName, initialPageParam, cursorPara
722
588
  });
723
589
  const groupedKeyParam = buildGroupedRequestParam(node, {
724
590
  resolver: tsResolver,
725
- keys: [
726
- "path",
727
- "query",
728
- "body"
729
- ],
591
+ keys: queryKeyGroupOrder,
730
592
  memberTypeWrapper
731
593
  });
732
594
  const queryKeyParamsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedKeyParam ? [groupedKeyParam] : [] });
@@ -736,12 +598,11 @@ function InfiniteQueryOptions$1({ name, clientName, initialPageParam, cursorPara
736
598
  memberTypeWrapper
737
599
  });
738
600
  const paramsSignature = declarationPrinter$7.print(paramsNode) ?? "";
739
- const queryFnBody = `const { data } = await ${buildClientCall(node, {
601
+ const queryFnBody = `return ${buildClientCall(node, {
740
602
  clientName,
741
603
  signal: true,
742
604
  unwrapName
743
- })}
744
- return data`;
605
+ })}.unwrap()`;
745
606
  const hasNewParams = nextParam != null || previousParam != null;
746
607
  const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
747
608
  if (hasNewParams) {
@@ -790,7 +651,7 @@ __name(InfiniteQueryOptions$1, "InfiniteQueryOptions");
790
651
  const declarationPrinter$6 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
791
652
  const mutationKeyTransformer = ({ node }) => {
792
653
  if (!node.path) return [];
793
- return [`{ url: '${Url.toPath(node.path)}' }`];
654
+ return [`{ url: '${kubb_kit.Url.toPath(node.path)}' }`];
794
655
  };
795
656
  function MutationKey({ name, node, transformer }) {
796
657
  const paramsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: [] });
@@ -872,7 +733,7 @@ const queryKeyTransformer = ({ node }) => {
872
733
  const hasQueryParams = getOperationParameters(node).query.length > 0;
873
734
  const hasRequestBody = !!node.requestBody?.content?.[0]?.schema;
874
735
  return [
875
- hasPathParams ? `{ url: '${Url.toPath(node.path)}', params: path }` : `{ url: '${Url.toPath(node.path)}' }`,
736
+ hasPathParams ? `{ url: '${kubb_kit.Url.toPath(node.path)}', params: path }` : `{ url: '${kubb_kit.Url.toPath(node.path)}' }`,
876
737
  hasQueryParams ? "...(query ? [query] : [])" : null,
877
738
  hasRequestBody ? "...(body ? [body] : [])" : null
878
739
  ].filter(Boolean);
@@ -966,23 +827,30 @@ function resolveContractClient(options) {
966
827
  * (plugin-fetch or plugin-axios). Returns `null` when no contract plugin is in play (the inline
967
828
  * path). The plugin injects `.kubb/client.ts` at the global output root, the same path consumers
968
829
  * read `RequestConfig` / `ResponseErrorConfig` from.
830
+ *
831
+ * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,
832
+ * so several dependents reading the same client plugin for one operation in a single pass
833
+ * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share
834
+ * one computed result instead of each re-deriving the name and path.
969
835
  */
970
836
  function resolveClientOperation(options) {
971
- const { clientPlugin, driver, node, root, output } = options;
837
+ const { clientPlugin, driver, node, root, output, cache } = options;
972
838
  if (!clientPlugin) return null;
973
- const resolver = driver.getResolver(clientPlugin.pluginName);
974
- const plugin = driver.getPlugin(clientPlugin.pluginName);
975
- const file = resolver.file({
976
- ...operationFileEntry(node, node.operationId),
977
- root,
978
- output: plugin?.options?.output ?? output,
979
- group: plugin?.options?.group ?? void 0
839
+ return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {
840
+ const resolver = driver.getResolver(clientPlugin.pluginName);
841
+ const plugin = driver.getPlugin(clientPlugin.pluginName);
842
+ const file = resolver.file({
843
+ ...operationFileEntry(node, node.operationId),
844
+ root,
845
+ output: plugin?.options?.output ?? output,
846
+ group: plugin?.options?.group ?? void 0
847
+ });
848
+ return {
849
+ name: resolver.name(node.operationId),
850
+ path: file.path,
851
+ clientPath: node_path.default.resolve(root, ".kubb/client.ts")
852
+ };
980
853
  });
981
- return {
982
- name: resolver.name(node.operationId),
983
- path: file.path,
984
- clientPath: node_path.default.resolve(root, ".kubb/client.ts")
985
- };
986
854
  }
987
855
  //#endregion
988
856
  //#region src/utils.ts
@@ -1005,11 +873,7 @@ const declarationPrinter$4 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "decla
1005
873
  function buildQueryKeyParamsNode(node, options) {
1006
874
  const groupedParam = buildGroupedRequestParam(node, {
1007
875
  resolver: options.resolver,
1008
- keys: [
1009
- "path",
1010
- "query",
1011
- "body"
1012
- ],
876
+ keys: queryKeyGroupOrder,
1013
877
  memberTypeWrapper: maybeRefOrGetter
1014
878
  });
1015
879
  return (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedParam ? [groupedParam] : [] });
@@ -1060,11 +924,10 @@ function QueryOptions({ name, clientName, node, tsResolver, queryKeyName }) {
1060
924
  const queryKeyParamsCall = callPrinter$3.print(queryKeyParamsNode) ?? "";
1061
925
  const paramsNode = getQueryOptionsParams(node, { resolver: tsResolver });
1062
926
  const paramsSignature = declarationPrinter$3.print(paramsNode) ?? "";
1063
- const queryFnBody = `const { data } = await ${buildVueClientCall(node, {
927
+ const queryFnBody = `return ${buildVueClientCall(node, {
1064
928
  clientName,
1065
929
  signal: true
1066
- })}
1067
- return data`;
930
+ })}.unwrap()`;
1068
931
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
1069
932
  name,
1070
933
  isExportable: true,
@@ -1106,10 +969,11 @@ function buildInfiniteQueryParamsNode(node, options) {
1106
969
  }`,
1107
970
  default: "{}"
1108
971
  });
1109
- return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
972
+ const groupedParam = buildGroupedRequestParam(node, {
1110
973
  resolver,
1111
974
  memberTypeWrapper: maybeRefOrGetter
1112
- }), optionsParam].filter((param) => param !== null) });
975
+ });
976
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
1113
977
  }
1114
978
  function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
1115
979
  const { TData, TError } = buildResponseTypes(node, tsResolver);
@@ -1178,13 +1042,14 @@ function resolveMutationRequestType(node, resolver) {
1178
1042
  function buildMutationParamsNode(node, options) {
1179
1043
  const { resolver } = options;
1180
1044
  const { TData, TError } = buildResponseTypes(node, resolver);
1045
+ const TRequest = resolveMutationRequestType(node, resolver);
1181
1046
  return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
1182
1047
  name: "options",
1183
1048
  type: `{
1184
1049
  mutation?: MutationObserverOptions<${[
1185
1050
  TData,
1186
1051
  TError,
1187
- resolveMutationRequestType(node, resolver),
1052
+ TRequest,
1188
1053
  "TContext"
1189
1054
  ].join(", ")}> & { client?: QueryClient },
1190
1055
  client?: ${buildRequestConfigType(node)},
@@ -1198,11 +1063,10 @@ function Mutation({ name, clientName, node, tsResolver, mutationKeyName }) {
1198
1063
  const hasMutationParams = groupedParam !== null;
1199
1064
  const groupedParamsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedParam ? [groupedParam] : [] });
1200
1065
  const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "";
1201
- const mutationFnBody = `const { data } = await ${buildVueClientCall(node, {
1066
+ const mutationFnBody = `return ${buildVueClientCall(node, {
1202
1067
  clientName,
1203
1068
  signal: false
1204
- })}
1205
- return data`;
1069
+ })}.unwrap()`;
1206
1070
  const generics = [
1207
1071
  TData,
1208
1072
  TError,
@@ -1258,10 +1122,11 @@ function buildQueryParamsNode(node, options) {
1258
1122
  }`,
1259
1123
  default: "{}"
1260
1124
  });
1261
- return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [buildGroupedRequestParam(node, {
1125
+ const groupedParam = buildGroupedRequestParam(node, {
1262
1126
  resolver,
1263
1127
  memberTypeWrapper: maybeRefOrGetter
1264
- }), optionsParam].filter((param) => param !== null) });
1128
+ });
1129
+ return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
1265
1130
  }
1266
1131
  function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
1267
1132
  const { TData, TError } = buildResponseTypes(node, tsResolver);
@@ -1309,9 +1174,9 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
1309
1174
  //#region src/generators/infiniteQueryGenerator.tsx
1310
1175
  /**
1311
1176
  * Built-in generator for `useInfiniteQuery` composables. Enabled when
1312
- * `pluginVueQuery({ infinite: { ... } })`. Emits one `useFooInfiniteQuery`
1313
- * composable per query operation, wiring the configured cursor path into
1314
- * TanStack Query's cursor-based pagination.
1177
+ * `pluginVueQuery({ infinite: { ... }, hooks: true })`. Emits one
1178
+ * `useFooInfiniteQuery` composable per query operation, wiring the
1179
+ * configured cursor path into TanStack Query's cursor-based pagination.
1315
1180
  */
1316
1181
  const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1317
1182
  name: "vue-query-infinite",
@@ -1323,11 +1188,12 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1323
1188
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1324
1189
  if (!pluginTs) return null;
1325
1190
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1326
- const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1327
- const queryMethods = new Set(query ? query.methods : []);
1328
- const isMutation = mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase());
1191
+ const { isQuery, isMutation } = classifyOperation(node, {
1192
+ query,
1193
+ mutation
1194
+ });
1329
1195
  const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1330
- if (!isQuery || isMutation || !infiniteOptions) return null;
1196
+ if (!isQuery || isMutation || !infiniteOptions || !hooks) return null;
1331
1197
  const normalizeKey = (key) => key.replace(/\?$/, "");
1332
1198
  const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
1333
1199
  if (!(infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false)) return null;
@@ -1337,7 +1203,8 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1337
1203
  driver,
1338
1204
  node,
1339
1205
  root,
1340
- output
1206
+ output,
1207
+ cache: ctx.cache
1341
1208
  });
1342
1209
  if (!contractOp) return null;
1343
1210
  const queryName = resolver.infiniteQuery.name(node);
@@ -1351,15 +1218,20 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1351
1218
  output,
1352
1219
  group: group ?? void 0
1353
1220
  }),
1354
- fileTs: tsResolver.file({
1355
- ...operationFileEntry(node, node.operationId),
1221
+ fileTs: resolveDependencyOperationFile({
1222
+ cache: ctx.cache,
1223
+ node,
1224
+ resolver: tsResolver,
1356
1225
  root,
1357
1226
  output: pluginTs.options?.output ?? output,
1358
- group: pluginTs.options?.group ?? void 0
1227
+ group: pluginTs.options?.group
1359
1228
  })
1360
1229
  };
1361
- const rawQueryParams = getOperationParameters(node).query;
1362
- const queryParamsTypeName = rawQueryParams.length > 0 && tsResolver.param.query(node, rawQueryParams[0]) !== tsResolver.param.name(node, rawQueryParams[0]) ? tsResolver.param.query(node, rawQueryParams[0]) : null;
1230
+ const { queryParamsTypeName } = resolvePageParamType(node, {
1231
+ resolver: tsResolver,
1232
+ initialPageParam: infiniteOptions.initialPageParam,
1233
+ queryParam: infiniteOptions.queryParam
1234
+ });
1363
1235
  const importedTypeNames = [
1364
1236
  tsResolver.response.options(node),
1365
1237
  queryParamsTypeName,
@@ -1445,32 +1317,30 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
1445
1317
  initialPageParam: infiniteOptions.initialPageParam,
1446
1318
  queryParam: infiniteOptions.queryParam
1447
1319
  }),
1448
- hooks && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [
1449
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1450
- name: ["useInfiniteQuery"],
1451
- path: importPath
1452
- }),
1453
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1454
- name: [
1455
- "QueryKey",
1456
- "QueryClient",
1457
- "UseInfiniteQueryOptions",
1458
- "UseInfiniteQueryReturnType"
1459
- ],
1460
- path: importPath,
1461
- isTypeOnly: true
1462
- }),
1463
- /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
1464
- name: queryName,
1465
- queryOptionsName,
1466
- queryKeyName,
1467
- queryKeyTypeName,
1468
- node,
1469
- tsResolver,
1470
- initialPageParam: infiniteOptions.initialPageParam,
1471
- queryParam: infiniteOptions.queryParam
1472
- })
1473
- ] })
1320
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1321
+ name: ["useInfiniteQuery"],
1322
+ path: importPath
1323
+ }),
1324
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1325
+ name: [
1326
+ "QueryKey",
1327
+ "QueryClient",
1328
+ "UseInfiniteQueryOptions",
1329
+ "UseInfiniteQueryReturnType"
1330
+ ],
1331
+ path: importPath,
1332
+ isTypeOnly: true
1333
+ }),
1334
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(InfiniteQuery, {
1335
+ name: queryName,
1336
+ queryOptionsName,
1337
+ queryKeyName,
1338
+ queryKeyTypeName,
1339
+ node,
1340
+ tsResolver,
1341
+ initialPageParam: infiniteOptions.initialPageParam,
1342
+ queryParam: infiniteOptions.queryParam
1343
+ })
1474
1344
  ]
1475
1345
  });
1476
1346
  }
@@ -1492,16 +1362,19 @@ const mutationGenerator = (0, kubb_kit.defineGenerator)({
1492
1362
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1493
1363
  if (!pluginTs) return null;
1494
1364
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1495
- const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1496
- const queryMethods = new Set(query ? query.methods : []);
1497
- if (!(mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase()))) return null;
1365
+ const { isMutation } = classifyOperation(node, {
1366
+ query,
1367
+ mutation
1368
+ });
1369
+ if (!isMutation) return null;
1498
1370
  const importPath = mutation ? mutation.importPath : "@tanstack/vue-query";
1499
1371
  const contractOp = resolveClientOperation({
1500
1372
  clientPlugin: { pluginName: client.pluginName },
1501
1373
  driver,
1502
1374
  node,
1503
1375
  root,
1504
- output
1376
+ output,
1377
+ cache: ctx.cache
1505
1378
  });
1506
1379
  if (!contractOp) return null;
1507
1380
  const mutationHookName = resolver.mutation.name(node);
@@ -1514,11 +1387,13 @@ const mutationGenerator = (0, kubb_kit.defineGenerator)({
1514
1387
  output,
1515
1388
  group: group ?? void 0
1516
1389
  }),
1517
- fileTs: tsResolver.file({
1518
- ...operationFileEntry(node, node.operationId),
1390
+ fileTs: resolveDependencyOperationFile({
1391
+ cache: ctx.cache,
1392
+ node,
1393
+ resolver: tsResolver,
1519
1394
  root,
1520
1395
  output: pluginTs.options?.output ?? output,
1521
- group: pluginTs.options?.group ?? void 0
1396
+ group: pluginTs.options?.group
1522
1397
  })
1523
1398
  };
1524
1399
  const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
@@ -1620,9 +1495,10 @@ const queryGenerator = (0, kubb_kit.defineGenerator)({
1620
1495
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1621
1496
  if (!pluginTs) return null;
1622
1497
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
1623
- const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1624
- const queryMethods = new Set(query ? query.methods : []);
1625
- const isMutation = mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase());
1498
+ const { isQuery, isMutation } = classifyOperation(node, {
1499
+ query,
1500
+ mutation
1501
+ });
1626
1502
  if (!isQuery || isMutation) return null;
1627
1503
  const importPath = query ? query.importPath : "@tanstack/vue-query";
1628
1504
  const contractOp = resolveClientOperation({
@@ -1630,7 +1506,8 @@ const queryGenerator = (0, kubb_kit.defineGenerator)({
1630
1506
  driver,
1631
1507
  node,
1632
1508
  root,
1633
- output
1509
+ output,
1510
+ cache: ctx.cache
1634
1511
  });
1635
1512
  if (!contractOp) return null;
1636
1513
  const queryName = resolver.query.name(node);
@@ -1644,11 +1521,13 @@ const queryGenerator = (0, kubb_kit.defineGenerator)({
1644
1521
  output,
1645
1522
  group: group ?? void 0
1646
1523
  }),
1647
- fileTs: tsResolver.file({
1648
- ...operationFileEntry(node, node.operationId),
1524
+ fileTs: resolveDependencyOperationFile({
1525
+ cache: ctx.cache,
1526
+ node,
1527
+ resolver: tsResolver,
1649
1528
  root,
1650
1529
  output: pluginTs.options?.output ?? output,
1651
- group: pluginTs.options?.group ?? void 0
1530
+ group: pluginTs.options?.group
1652
1531
  })
1653
1532
  };
1654
1533
  const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {