@kubb/plugin-vue-query 5.0.0-beta.85 → 5.0.0-beta.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import "./rolldown-runtime-C0LytTxp.js";
2
- import path from "node:path";
3
- import { ast, defineGenerator, definePlugin, defineResolver } from "kubb/kit";
2
+ import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
4
3
  import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, createTypeLiteral, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
5
4
  import { File, Function, Type, jsxRenderer } from "kubb/jsx";
6
5
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
6
+ import path from "node:path";
7
7
  //#region ../../internals/utils/src/casing.ts
8
8
  /**
9
9
  * Shared implementation for camelCase and PascalCase conversion.
@@ -31,31 +31,6 @@ function camelCase(text, { prefix = "", suffix = "" } = {}) {
31
31
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
32
32
  }
33
33
  //#endregion
34
- //#region ../../internals/utils/src/fs.ts
35
- /**
36
- * Builds a nested file path from a dotted name. Splits on dots that precede a letter
37
- * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
38
- * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
39
- *
40
- * Empty segments are dropped before joining. They arise when the name starts with a dot
41
- * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
42
- * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
43
- * absolute path, letting generated files escape the configured output directory.
44
- *
45
- * @example Nested path from a dotted name
46
- * `toFilePath('pet.petId') // 'pet/petId'`
47
- *
48
- * @example PascalCase the final segment
49
- * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
50
- *
51
- * @example Suffix applied to the final segment only
52
- * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
53
- */
54
- function toFilePath(name, caseLast = camelCase) {
55
- const parts = name.split(/\.(?=[a-zA-Z])/);
56
- return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
57
- }
58
- //#endregion
59
34
  //#region ../../internals/utils/src/reserved.ts
60
35
  /**
61
36
  * JavaScript and Java reserved words.
@@ -156,9 +131,42 @@ const reservedWords = /* @__PURE__ */ new Set([
156
131
  */
157
132
  function isValidVarName(name) {
158
133
  if (!name || reservedWords.has(name)) return false;
134
+ return isIdentifier(name);
135
+ }
136
+ /**
137
+ * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
138
+ *
139
+ * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
140
+ * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
141
+ * deciding whether an object key needs quoting.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * isIdentifier('name') // true
146
+ * isIdentifier('x-total')// false
147
+ * ```
148
+ */
149
+ function isIdentifier(name) {
159
150
  return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
160
151
  }
161
152
  //#endregion
153
+ //#region ../../internals/utils/src/strings.ts
154
+ /**
155
+ * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
156
+ * `accessor`. Returns `null` for an empty path.
157
+ *
158
+ * @example
159
+ * ```ts
160
+ * getNestedAccessor('pagination.next.id', 'lastPage')
161
+ * // "lastPage?.['pagination']?.['next']?.['id']"
162
+ * ```
163
+ */
164
+ function getNestedAccessor(param, accessor) {
165
+ const parts = Array.isArray(param) ? param : param.split(".");
166
+ if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
167
+ return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
168
+ }
169
+ //#endregion
162
170
  //#region ../../internals/utils/src/url.ts
163
171
  function transformParam(raw, casing) {
164
172
  const param = isValidVarName(raw) ? raw : camelCase(raw);
@@ -311,13 +319,13 @@ function dedupeByCasedName(params) {
311
319
  //#region ../../internals/shared/src/operation.ts
312
320
  /**
313
321
  * Builds the `ResolverFileParams` every operation generator passes to
314
- * `resolver.resolveFile`: a file named `name`, tagged by the operation's first
322
+ * `resolver.file`: a file named `name`, tagged by the operation's first
315
323
  * tag (or `'default'`), at the operation's path. Centralizes the entry object
316
324
  * that was repeated at dozens of call sites across the client and query plugins.
317
325
  *
318
326
  * @example
319
327
  * ```ts
320
- * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })
328
+ * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
321
329
  * ```
322
330
  */
323
331
  function operationFileEntry(node, name, extname = ".ts") {
@@ -334,8 +342,11 @@ function getOperationLink(node, link) {
334
342
  if (link === "urlPath") return node.path ? `{@link ${Url.toPath(node.path)}}` : null;
335
343
  return node.path ? `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}` : null;
336
344
  }
337
- function getContentTypeInfo(node) {
338
- const contentTypes = node.requestBody?.content?.map((e) => e.contentType) ?? [];
345
+ /**
346
+ * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several
347
+ * are present and the union, default, and form-data flags the client uses to pick one.
348
+ */
349
+ function buildContentTypeInfo(contentTypes) {
339
350
  const isMultipleContentTypes = contentTypes.length > 1;
340
351
  return {
341
352
  contentTypes,
@@ -345,20 +356,15 @@ function getContentTypeInfo(node) {
345
356
  hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
346
357
  };
347
358
  }
359
+ function getContentTypeInfo(node) {
360
+ return buildContentTypeInfo(node.requestBody?.content?.map((e) => e.contentType) ?? []);
361
+ }
348
362
  /**
349
363
  * The request-body counterpart for the primary success response: the content types it documents and
350
364
  * whether several are present, so the client can let a caller pick which one to accept.
351
365
  */
352
366
  function getResponseContentTypeInfo(node) {
353
- const contentTypes = getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [];
354
- const isMultipleContentTypes = contentTypes.length > 1;
355
- return {
356
- contentTypes,
357
- isMultipleContentTypes,
358
- contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
359
- defaultContentType: contentTypes[0] ?? "application/json",
360
- hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
361
- };
367
+ return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? []);
362
368
  }
363
369
  function buildRequestConfigType(node) {
364
370
  const request = getContentTypeInfo(node);
@@ -455,13 +461,13 @@ function getPrimarySuccessResponse(node) {
455
461
  return getOperationSuccessResponses(node)[0] ?? null;
456
462
  }
457
463
  function resolveErrorNames(node, resolver) {
458
- return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
464
+ return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode));
459
465
  }
460
466
  function resolveSuccessNames(node, resolver) {
461
- return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
467
+ return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode));
462
468
  }
463
469
  function resolveStatusCodeNames(node, resolver) {
464
- return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
470
+ return node.responses.map((response) => resolver.response.status(node, response.statusCode));
465
471
  }
466
472
  const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
467
473
  function resolveOperationTypeNames(node, resolver, options = {}) {
@@ -478,11 +484,11 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
478
484
  const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
479
485
  const exclude = new Set(options.exclude ?? []);
480
486
  const paramNames = options.includeParams === false ? [] : [
481
- ...path.map((param) => resolver.resolvePathParamsName(node, param)),
482
- ...query.map((param) => resolver.resolveQueryParamsName(node, param)),
483
- ...header.map((param) => resolver.resolveHeaderParamsName(node, param))
487
+ ...path.map((param) => resolver.param.path(node, param)),
488
+ ...query.map((param) => resolver.param.query(node, param)),
489
+ ...header.map((param) => resolver.param.headers(node, param))
484
490
  ];
485
- const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)];
491
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)];
486
492
  const result = (options.order === "body-response-first" ? [
487
493
  ...bodyAndResponseNames,
488
494
  ...paramNames,
@@ -581,12 +587,12 @@ function maybeRefOrGetter(type) {
581
587
  /**
582
588
  * Builds the grouped `{ path, query, body, headers }` parameter that mirrors the client
583
589
  * function signature. Only the groups the operation carries are emitted, typed from the
584
- * operation's `RequestConfig`. `keys` narrows the emitted groups, used by the query key which
590
+ * operation's `Options`. `keys` narrows the emitted groups, used by the query key which
585
591
  * never carries `headers`.
586
592
  *
587
- * By default the whole group is typed as the single `RequestConfig` reference. When
593
+ * By default the whole group is typed as the single `Options` reference. When
588
594
  * `memberTypeWrapper` is set, each group is emitted as its own member typed from the matching
589
- * `RequestConfig['<group>']` slice and wrapped, used by vue-query to apply
595
+ * `Options['<group>']` slice and wrapped, used by vue-query to apply
590
596
  * `MaybeRefOrGetter` per group.
591
597
  */
592
598
  function buildGroupedRequestParam(node, options) {
@@ -601,13 +607,13 @@ function buildGroupedRequestParam(node, options) {
601
607
  headers: hasRequiredHeader
602
608
  };
603
609
  const isOptional = names.every((name) => !requiredByGroup[name]);
604
- const requestConfigName = resolver.resolveRequestConfigName(node);
610
+ const optionsName = resolver.response.options(node);
605
611
  const omittedKeys = requestGroupOrder$1.filter((key) => !keys.includes(key));
606
- const requestConfigType = omittedKeys.length > 0 ? `Omit<${requestConfigName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : requestConfigName;
612
+ const optionsType = omittedKeys.length > 0 ? `Omit<${optionsName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : optionsName;
607
613
  if (memberTypeWrapper) {
608
614
  const members = names.map((name) => ({
609
615
  name,
610
- type: memberTypeWrapper(`${requestConfigType}['${name}']`),
616
+ type: memberTypeWrapper(`${optionsType}['${name}']`),
611
617
  optional: !requiredByGroup[name]
612
618
  }));
613
619
  return createFunctionParameter({
@@ -619,7 +625,7 @@ function buildGroupedRequestParam(node, options) {
619
625
  }
620
626
  return createFunctionParameter({
621
627
  name: createObjectBindingPattern({ elements: names.map((name) => ({ name })) }),
622
- type: requestConfigType,
628
+ type: optionsType,
623
629
  optional: false,
624
630
  ...isOptional ? { default: "{}" } : {}
625
631
  });
@@ -733,15 +739,15 @@ function resolveClientOperation(options) {
733
739
  const { clientPlugin, driver, node, root, output } = options;
734
740
  if (!clientPlugin) return null;
735
741
  const resolver = driver.getResolver(clientPlugin.pluginName);
736
- if (!resolver) return null;
737
742
  const plugin = driver.getPlugin(clientPlugin.pluginName);
738
- const file = resolver.resolveFile(operationFileEntry(node, node.operationId), {
743
+ const file = resolver.file({
744
+ ...operationFileEntry(node, node.operationId),
739
745
  root,
740
746
  output: plugin?.options?.output ?? output,
741
747
  group: plugin?.options?.group ?? void 0
742
748
  });
743
749
  return {
744
- name: resolver.resolveName(node.operationId),
750
+ name: resolver.name(node.operationId),
745
751
  path: file.path,
746
752
  clientPath: path.resolve(root, ".kubb/client.ts")
747
753
  };
@@ -828,7 +834,7 @@ function getQueryOptionsParams(node, options) {
828
834
  }
829
835
  function QueryOptions({ name, clientName, node, tsResolver, queryKeyName }) {
830
836
  const successNames = resolveSuccessNames(node, tsResolver);
831
- const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
837
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.response.response(node);
832
838
  const errorNames = resolveErrorNames(node, tsResolver);
833
839
  const TData = responseName;
834
840
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
@@ -868,7 +874,7 @@ const callPrinter$3 = functionPrinter({ mode: "call" });
868
874
  function buildInfiniteQueryParamsNode(node, options) {
869
875
  const { resolver } = options;
870
876
  const successNames = resolveSuccessNames(node, resolver);
871
- const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.resolveResponseName(node);
877
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.response.response(node);
872
878
  const errorNames = resolveErrorNames(node, resolver);
873
879
  const optionsParam = createFunctionParameter({
874
880
  name: "options",
@@ -891,7 +897,7 @@ function buildInfiniteQueryParamsNode(node, options) {
891
897
  }
892
898
  function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
893
899
  const successNames = resolveSuccessNames(node, tsResolver);
894
- const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
900
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.response.response(node);
895
901
  const errorNames = resolveErrorNames(node, tsResolver);
896
902
  const TData = responseName;
897
903
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
@@ -941,7 +947,7 @@ const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
941
947
  const callPrinter$2 = functionPrinter({ mode: "call" });
942
948
  function InfiniteQueryOptions({ name, clientName, initialPageParam, cursorParam, nextParam, previousParam, node, tsResolver, queryParam, queryKeyName }) {
943
949
  const successNames = resolveSuccessNames(node, tsResolver);
944
- const queryFnDataType = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
950
+ const queryFnDataType = successNames.length > 0 ? successNames.join(" | ") : tsResolver.response.response(node);
945
951
  const errorNames = resolveErrorNames(node, tsResolver);
946
952
  const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
947
953
  const isInitialPageParamDefined = initialPageParam !== void 0 && initialPageParam !== null;
@@ -951,8 +957,8 @@ function InfiniteQueryOptions({ name, clientName, initialPageParam, cursorParam,
951
957
  })() : "string" : typeof initialPageParam === "boolean" ? "boolean" : "unknown";
952
958
  const rawQueryParams = getOperationParameters(node, { paramsCasing: "original" }).query;
953
959
  const queryParamsTypeName = rawQueryParams.length > 0 ? (() => {
954
- const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]);
955
- return groupName !== tsResolver.resolveParamName(node, rawQueryParams[0]) ? groupName : null;
960
+ const groupName = tsResolver.param.query(node, rawQueryParams[0]);
961
+ return groupName !== tsResolver.param.name(node, rawQueryParams[0]) ? groupName : null;
956
962
  })() : null;
957
963
  const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null;
958
964
  const pageParamType = queryParamType ? isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType : fallbackPageParamType;
@@ -968,8 +974,8 @@ function InfiniteQueryOptions({ name, clientName, initialPageParam, cursorParam,
968
974
  const hasNewParams = nextParam != null || previousParam != null;
969
975
  const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
970
976
  if (hasNewParams) {
971
- const nextAccessor = nextParam ? ast.getNestedAccessor(nextParam, "lastPage") : null;
972
- const prevAccessor = previousParam ? ast.getNestedAccessor(previousParam, "firstPage") : null;
977
+ const nextAccessor = nextParam ? getNestedAccessor(nextParam, "lastPage") : null;
978
+ const prevAccessor = previousParam ? getNestedAccessor(previousParam, "firstPage") : null;
973
979
  return [nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null, prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null];
974
980
  }
975
981
  if (cursorParam) return [`getNextPageParam: (lastPage) => lastPage['${cursorParam}']`, `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`];
@@ -1031,12 +1037,12 @@ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${que
1031
1037
  const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
1032
1038
  const callPrinter$1 = functionPrinter({ mode: "call" });
1033
1039
  function resolveMutationRequestType(node, resolver) {
1034
- return buildGroupedRequestParam(node, { resolver }) ? resolver.resolveRequestConfigName(node) : "undefined";
1040
+ return buildGroupedRequestParam(node, { resolver }) ? resolver.response.options(node) : "undefined";
1035
1041
  }
1036
1042
  function buildMutationParamsNode(node, options) {
1037
1043
  const { resolver } = options;
1038
1044
  const successNames = resolveSuccessNames(node, resolver);
1039
- const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.resolveResponseName(node);
1045
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.response.response(node);
1040
1046
  const errorNames = resolveErrorNames(node, resolver);
1041
1047
  return createFunctionParameters({ params: [createFunctionParameter({
1042
1048
  name: "options",
@@ -1054,7 +1060,7 @@ function buildMutationParamsNode(node, options) {
1054
1060
  }
1055
1061
  function Mutation({ name, clientName, node, tsResolver, mutationKeyName }) {
1056
1062
  const successNames = resolveSuccessNames(node, tsResolver);
1057
- const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
1063
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.response.response(node);
1058
1064
  const errorNames = resolveErrorNames(node, tsResolver);
1059
1065
  const TData = responseName;
1060
1066
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
@@ -1073,8 +1079,6 @@ function Mutation({ name, clientName, node, tsResolver, mutationKeyName }) {
1073
1079
  resolveMutationRequestType(node, tsResolver),
1074
1080
  "TContext"
1075
1081
  ].join(", ");
1076
- const mutationKeyParamsNode = createFunctionParameters({ params: [] });
1077
- const mutationKeyParamsCall = callPrinter$1.print(mutationKeyParamsNode) ?? "";
1078
1082
  const paramsNode = buildMutationParamsNode(node, { resolver: tsResolver });
1079
1083
  const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
1080
1084
  return /* @__PURE__ */ jsx(File.Source, {
@@ -1090,10 +1094,10 @@ function Mutation({ name, clientName, node, tsResolver, mutationKeyName }) {
1090
1094
  children: `
1091
1095
  const { mutation = {}, client: config = {} } = options ?? {}
1092
1096
  const { client: queryClient, ...mutationOptions } = mutation;
1093
- const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}(${mutationKeyParamsCall})
1097
+ const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}()
1094
1098
 
1095
1099
  return useMutation<${generics}>({
1096
- mutationFn: async(${hasMutationParams ? argBindingStr : ""}) => {
1100
+ mutationFn: async(${argBindingStr}) => {
1097
1101
  ${mutationFnBody}
1098
1102
  },
1099
1103
  mutationKey,
@@ -1110,7 +1114,7 @@ const callPrinter = functionPrinter({ mode: "call" });
1110
1114
  function buildQueryParamsNode(node, options) {
1111
1115
  const { resolver } = options;
1112
1116
  const successNames = resolveSuccessNames(node, resolver);
1113
- const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.resolveResponseName(node);
1117
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : resolver.response.response(node);
1114
1118
  const errorNames = resolveErrorNames(node, resolver);
1115
1119
  const optionsParam = createFunctionParameter({
1116
1120
  name: "options",
@@ -1133,7 +1137,7 @@ function buildQueryParamsNode(node, options) {
1133
1137
  }
1134
1138
  function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
1135
1139
  const successNames = resolveSuccessNames(node, tsResolver);
1136
- const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.resolveResponseName(node);
1140
+ const responseName = successNames.length > 0 ? successNames.join(" | ") : tsResolver.response.response(node);
1137
1141
  const errorNames = resolveErrorNames(node, tsResolver);
1138
1142
  const TData = responseName;
1139
1143
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
@@ -1202,9 +1206,7 @@ const infiniteQueryGenerator = defineGenerator({
1202
1206
  if (!isQuery || isMutation || !infiniteOptions) return null;
1203
1207
  const normalizeKey = (key) => key.replace(/\?$/, "");
1204
1208
  const queryParamKeys = getOperationParameters(node, { paramsCasing: "original" }).query.map((p) => p.name);
1205
- const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false;
1206
- const hasCursorParam = !infiniteOptions.cursorParam || true;
1207
- if (!hasQueryParam || !hasCursorParam) return null;
1209
+ if (!(infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false)) return null;
1208
1210
  const importPath = query ? query.importPath : "@tanstack/vue-query";
1209
1211
  const contractOp = resolveClientOperation({
1210
1212
  clientPlugin: { pluginName: client.pluginName },
@@ -1214,26 +1216,28 @@ const infiniteQueryGenerator = defineGenerator({
1214
1216
  output
1215
1217
  });
1216
1218
  if (!contractOp) return null;
1217
- const queryName = resolver.resolveInfiniteQueryName(node);
1218
- const queryOptionsName = resolver.resolveInfiniteQueryOptionsName(node);
1219
- const queryKeyName = resolver.resolveInfiniteQueryKeyName(node);
1220
- const queryKeyTypeName = resolver.resolveInfiniteQueryKeyTypeName(node);
1219
+ const queryName = resolver.infiniteQuery.name(node);
1220
+ const queryOptionsName = resolver.infiniteQuery.optionsName(node);
1221
+ const queryKeyName = resolver.infiniteQuery.keyName(node);
1222
+ const queryKeyTypeName = resolver.infiniteQuery.keyTypeName(node);
1221
1223
  const meta = {
1222
- file: resolver.resolveFile(operationFileEntry(node, queryName), {
1224
+ file: resolver.file({
1225
+ ...operationFileEntry(node, queryName),
1223
1226
  root,
1224
1227
  output,
1225
1228
  group: group ?? void 0
1226
1229
  }),
1227
- fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1230
+ fileTs: tsResolver.file({
1231
+ ...operationFileEntry(node, node.operationId),
1228
1232
  root,
1229
1233
  output: pluginTs.options?.output ?? output,
1230
1234
  group: pluginTs.options?.group ?? void 0
1231
1235
  })
1232
1236
  };
1233
1237
  const rawQueryParams = getOperationParameters(node, { paramsCasing: "original" }).query;
1234
- const queryParamsTypeName = rawQueryParams.length > 0 && tsResolver.resolveQueryParamsName(node, rawQueryParams[0]) !== tsResolver.resolveParamName(node, rawQueryParams[0]) ? tsResolver.resolveQueryParamsName(node, rawQueryParams[0]) : null;
1238
+ const queryParamsTypeName = rawQueryParams.length > 0 && tsResolver.param.query(node, rawQueryParams[0]) !== tsResolver.param.name(node, rawQueryParams[0]) ? tsResolver.param.query(node, rawQueryParams[0]) : null;
1235
1239
  const importedTypeNames = [
1236
- tsResolver.resolveRequestConfigName(node),
1240
+ tsResolver.response.options(node),
1237
1241
  queryParamsTypeName,
1238
1242
  ...resolveOperationTypeNames(node, tsResolver, {
1239
1243
  exclude: [queryKeyTypeName],
@@ -1246,7 +1250,7 @@ const infiniteQueryGenerator = defineGenerator({
1246
1250
  baseName: meta.file.baseName,
1247
1251
  path: meta.file.path,
1248
1252
  meta: meta.file.meta,
1249
- banner: resolver.resolveBanner(ctx.meta, {
1253
+ banner: resolver.default.banner(ctx.meta, {
1250
1254
  output,
1251
1255
  config,
1252
1256
  file: {
@@ -1254,7 +1258,7 @@ const infiniteQueryGenerator = defineGenerator({
1254
1258
  baseName: meta.file.baseName
1255
1259
  }
1256
1260
  }),
1257
- footer: resolver.resolveFooter(ctx.meta, {
1261
+ footer: resolver.default.footer(ctx.meta, {
1258
1262
  output,
1259
1263
  config,
1260
1264
  file: {
@@ -1376,22 +1380,24 @@ const mutationGenerator = defineGenerator({
1376
1380
  output
1377
1381
  });
1378
1382
  if (!contractOp) return null;
1379
- const mutationHookName = resolver.resolveMutationName(node);
1380
- const mutationTypeName = resolver.resolveMutationTypeName(node);
1381
- const mutationKeyName = resolver.resolveMutationKeyName(node);
1383
+ const mutationHookName = resolver.mutation.name(node);
1384
+ const mutationTypeName = resolver.mutation.typeName(node);
1385
+ const mutationKeyName = resolver.mutation.keyName(node);
1382
1386
  const meta = {
1383
- file: resolver.resolveFile(operationFileEntry(node, mutationHookName), {
1387
+ file: resolver.file({
1388
+ ...operationFileEntry(node, mutationHookName),
1384
1389
  root,
1385
1390
  output,
1386
1391
  group: group ?? void 0
1387
1392
  }),
1388
- fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1393
+ fileTs: tsResolver.file({
1394
+ ...operationFileEntry(node, node.operationId),
1389
1395
  root,
1390
1396
  output: pluginTs.options?.output ?? output,
1391
1397
  group: pluginTs.options?.group ?? void 0
1392
1398
  })
1393
1399
  };
1394
- const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1400
+ const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1395
1401
  order: "body-response-first",
1396
1402
  includeParams: false
1397
1403
  })].filter((name) => Boolean(name));
@@ -1402,7 +1408,7 @@ const mutationGenerator = defineGenerator({
1402
1408
  baseName: meta.file.baseName,
1403
1409
  path: meta.file.path,
1404
1410
  meta: meta.file.meta,
1405
- banner: resolver.resolveBanner(ctx.meta, {
1411
+ banner: resolver.default.banner(ctx.meta, {
1406
1412
  output,
1407
1413
  config,
1408
1414
  file: {
@@ -1410,7 +1416,7 @@ const mutationGenerator = defineGenerator({
1410
1416
  baseName: meta.file.baseName
1411
1417
  }
1412
1418
  }),
1413
- footer: resolver.resolveFooter(ctx.meta, {
1419
+ footer: resolver.default.footer(ctx.meta, {
1414
1420
  output,
1415
1421
  config,
1416
1422
  file: {
@@ -1503,23 +1509,25 @@ const queryGenerator = defineGenerator({
1503
1509
  output
1504
1510
  });
1505
1511
  if (!contractOp) return null;
1506
- const queryName = resolver.resolveQueryName(node);
1507
- const queryOptionsName = resolver.resolveQueryOptionsName(node);
1508
- const queryKeyName = resolver.resolveQueryKeyName(node);
1509
- const queryKeyTypeName = resolver.resolveQueryKeyTypeName(node);
1512
+ const queryName = resolver.query.name(node);
1513
+ const queryOptionsName = resolver.query.optionsName(node);
1514
+ const queryKeyName = resolver.query.keyName(node);
1515
+ const queryKeyTypeName = resolver.query.keyTypeName(node);
1510
1516
  const meta = {
1511
- file: resolver.resolveFile(operationFileEntry(node, queryName), {
1517
+ file: resolver.file({
1518
+ ...operationFileEntry(node, queryName),
1512
1519
  root,
1513
1520
  output,
1514
1521
  group: group ?? void 0
1515
1522
  }),
1516
- fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
1523
+ fileTs: tsResolver.file({
1524
+ ...operationFileEntry(node, node.operationId),
1517
1525
  root,
1518
1526
  output: pluginTs.options?.output ?? output,
1519
1527
  group: pluginTs.options?.group ?? void 0
1520
1528
  })
1521
1529
  };
1522
- const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1530
+ const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1523
1531
  exclude: [queryKeyTypeName],
1524
1532
  order: "body-response-first",
1525
1533
  includeParams: false
@@ -1529,7 +1537,7 @@ const queryGenerator = defineGenerator({
1529
1537
  baseName: meta.file.baseName,
1530
1538
  path: meta.file.path,
1531
1539
  meta: meta.file.meta,
1532
- banner: resolver.resolveBanner(ctx.meta, {
1540
+ banner: resolver.default.banner(ctx.meta, {
1533
1541
  output,
1534
1542
  config,
1535
1543
  file: {
@@ -1537,7 +1545,7 @@ const queryGenerator = defineGenerator({
1537
1545
  baseName: meta.file.baseName
1538
1546
  }
1539
1547
  }),
1540
- footer: resolver.resolveFooter(ctx.meta, {
1548
+ footer: resolver.default.footer(ctx.meta, {
1541
1549
  output,
1542
1550
  config,
1543
1551
  file: {
@@ -1628,69 +1636,67 @@ function capitalize(name) {
1628
1636
  * file paths for every generated TanStack Query composable (`useFoo`,
1629
1637
  * `useFooInfinite`) and its companion helpers.
1630
1638
  *
1631
- * Functions and files use camelCase; composables get the `use` prefix.
1639
+ * The `default` helpers are supplied by `createResolver`. Functions and files use camelCase;
1640
+ * composables get the `use` prefix. Operation-specific naming is grouped under the `query`,
1641
+ * `infiniteQuery`, and `mutation` namespaces.
1632
1642
  *
1633
1643
  * @example Resolve composable and helper names
1634
1644
  * ```ts
1635
1645
  * import { resolverVueQuery } from '@kubb/plugin-vue-query'
1636
1646
  *
1637
- * resolverVueQuery.resolveQueryName(operationNode) // 'useGetPetById'
1638
- * resolverVueQuery.resolveQueryKeyName(operationNode) // 'getPetByIdQueryKey'
1639
- * resolverVueQuery.resolveQueryOptionsName(operationNode) // 'getPetByIdQueryOptions'
1647
+ * resolverVueQuery.query.name(operationNode) // 'useGetPetById'
1648
+ * resolverVueQuery.query.keyName(operationNode) // 'getPetByIdQueryKey'
1649
+ * resolverVueQuery.query.optionsName(operationNode) // 'getPetByIdQueryOptions'
1640
1650
  * ```
1641
1651
  */
1642
- const resolverVueQuery = defineResolver(() => ({
1643
- name: "default",
1652
+ const resolverVueQuery = createResolver({
1644
1653
  pluginName: "plugin-vue-query",
1645
- default(name, type) {
1646
- return type === "file" ? toFilePath(name) : camelCase(name);
1647
- },
1648
- resolveName(name) {
1649
- return this.default(name, "function");
1650
- },
1651
- resolvePathName(name, type) {
1652
- return this.default(name, type);
1653
- },
1654
- resolveQueryName(node) {
1655
- return `use${capitalize(this.resolveName(node.operationId))}`;
1656
- },
1657
- resolveInfiniteQueryName(node) {
1658
- return `use${capitalize(this.resolveName(node.operationId))}Infinite`;
1659
- },
1660
- resolveMutationName(node) {
1661
- return `use${capitalize(this.resolveName(node.operationId))}`;
1662
- },
1663
- resolveQueryOptionsName(node) {
1664
- return `${this.resolveName(node.operationId)}QueryOptions`;
1665
- },
1666
- resolveInfiniteQueryOptionsName(node) {
1667
- return `${this.resolveName(node.operationId)}InfiniteQueryOptions`;
1668
- },
1669
- resolveQueryKeyName(node) {
1670
- return `${this.resolveName(node.operationId)}QueryKey`;
1671
- },
1672
- resolveInfiniteQueryKeyName(node) {
1673
- return `${this.resolveName(node.operationId)}InfiniteQueryKey`;
1674
- },
1675
- resolveMutationKeyName(node) {
1676
- return `${this.resolveName(node.operationId)}MutationKey`;
1677
- },
1678
- resolveQueryKeyTypeName(node) {
1679
- return `${capitalize(this.resolveName(node.operationId))}QueryKey`;
1680
- },
1681
- resolveInfiniteQueryKeyTypeName(node) {
1682
- return `${capitalize(this.resolveName(node.operationId))}InfiniteQueryKey`;
1683
- },
1684
- resolveMutationTypeName(node) {
1685
- return capitalize(this.resolveName(node.operationId));
1654
+ query: {
1655
+ name(node) {
1656
+ return `use${capitalize(this.name(node.operationId))}`;
1657
+ },
1658
+ keyName(node) {
1659
+ return `${this.name(node.operationId)}QueryKey`;
1660
+ },
1661
+ keyTypeName(node) {
1662
+ return `${capitalize(this.name(node.operationId))}QueryKey`;
1663
+ },
1664
+ optionsName(node) {
1665
+ return `${this.name(node.operationId)}QueryOptions`;
1666
+ },
1667
+ clientName(node) {
1668
+ return this.name(node.operationId);
1669
+ }
1686
1670
  },
1687
- resolveClientName(node) {
1688
- return this.resolveName(node.operationId);
1671
+ infiniteQuery: {
1672
+ name(node) {
1673
+ return `use${capitalize(this.name(node.operationId))}Infinite`;
1674
+ },
1675
+ keyName(node) {
1676
+ return `${this.name(node.operationId)}InfiniteQueryKey`;
1677
+ },
1678
+ keyTypeName(node) {
1679
+ return `${capitalize(this.name(node.operationId))}InfiniteQueryKey`;
1680
+ },
1681
+ optionsName(node) {
1682
+ return `${this.name(node.operationId)}InfiniteQueryOptions`;
1683
+ },
1684
+ clientName(node) {
1685
+ return `${this.name(node.operationId)}Infinite`;
1686
+ }
1689
1687
  },
1690
- resolveInfiniteClientName(node) {
1691
- return `${this.resolveName(node.operationId)}Infinite`;
1688
+ mutation: {
1689
+ name(node) {
1690
+ return `use${capitalize(this.name(node.operationId))}`;
1691
+ },
1692
+ keyName(node) {
1693
+ return `${this.name(node.operationId)}MutationKey`;
1694
+ },
1695
+ typeName(node) {
1696
+ return capitalize(this.name(node.operationId));
1697
+ }
1692
1698
  }
1693
- }));
1699
+ });
1694
1700
  //#endregion
1695
1701
  //#region src/plugin.ts
1696
1702
  /**
@@ -1731,17 +1737,14 @@ const pluginVueQuery = definePlugin((options) => {
1731
1737
  queryGenerator,
1732
1738
  infiniteQueryGenerator,
1733
1739
  mutationGenerator
1734
- ].filter((generator) => Boolean(generator));
1740
+ ];
1735
1741
  const groupConfig = createGroupConfig(group);
1736
1742
  return {
1737
1743
  name: pluginVueQueryName,
1738
1744
  options,
1739
1745
  dependencies: [pluginTsName],
1740
1746
  hooks: { "kubb:plugin:setup"(ctx) {
1741
- const resolver = userResolver ? {
1742
- ...resolverVueQuery,
1743
- ...userResolver
1744
- } : resolverVueQuery;
1747
+ const resolver = userResolver ? Resolver.merge(resolverVueQuery, userResolver) : resolverVueQuery;
1745
1748
  const resolvedClient = resolveClient({
1746
1749
  client,
1747
1750
  pluginNames: (ctx.config.plugins ?? []).map((p) => p.name).filter((name) => Boolean(name))