@kubb/plugin-swr 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,7 +1,7 @@
1
1
  import { t as __name } from "./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";
4
+ import path from "node:path";
5
5
  import { File, Function, Type, jsxRenderer } from "kubb/jsx";
6
6
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
7
7
  //#region ../../internals/utils/src/casing.ts
@@ -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,6 +131,22 @@ 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
@@ -311,13 +302,13 @@ function dedupeByCasedName(params) {
311
302
  //#region ../../internals/shared/src/operation.ts
312
303
  /**
313
304
  * Builds the `ResolverFileParams` every operation generator passes to
314
- * `resolver.resolveFile`: a file named `name`, tagged by the operation's first
305
+ * `resolver.file`: a file named `name`, tagged by the operation's first
315
306
  * tag (or `'default'`), at the operation's path. Centralizes the entry object
316
307
  * that was repeated at dozens of call sites across the client and query plugins.
317
308
  *
318
309
  * @example
319
310
  * ```ts
320
- * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })
311
+ * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
321
312
  * ```
322
313
  */
323
314
  function operationFileEntry(node, name, extname = ".ts") {
@@ -334,8 +325,11 @@ function getOperationLink(node, link) {
334
325
  if (link === "urlPath") return node.path ? `{@link ${Url.toPath(node.path)}}` : null;
335
326
  return node.path ? `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}` : null;
336
327
  }
337
- function getContentTypeInfo(node) {
338
- const contentTypes = node.requestBody?.content?.map((e) => e.contentType) ?? [];
328
+ /**
329
+ * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several
330
+ * are present and the union, default, and form-data flags the client uses to pick one.
331
+ */
332
+ function buildContentTypeInfo(contentTypes) {
339
333
  const isMultipleContentTypes = contentTypes.length > 1;
340
334
  return {
341
335
  contentTypes,
@@ -345,20 +339,15 @@ function getContentTypeInfo(node) {
345
339
  hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
346
340
  };
347
341
  }
342
+ function getContentTypeInfo(node) {
343
+ return buildContentTypeInfo(node.requestBody?.content?.map((e) => e.contentType) ?? []);
344
+ }
348
345
  /**
349
346
  * The request-body counterpart for the primary success response: the content types it documents and
350
347
  * whether several are present, so the client can let a caller pick which one to accept.
351
348
  */
352
349
  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
- };
350
+ return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? []);
362
351
  }
363
352
  function buildRequestConfigType(node) {
364
353
  const request = getContentTypeInfo(node);
@@ -455,10 +444,10 @@ function getPrimarySuccessResponse(node) {
455
444
  return getOperationSuccessResponses(node)[0] ?? null;
456
445
  }
457
446
  function resolveErrorNames(node, resolver) {
458
- return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
447
+ return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode));
459
448
  }
460
449
  function resolveStatusCodeNames(node, resolver) {
461
- return node.responses.map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
450
+ return node.responses.map((response) => resolver.response.status(node, response.statusCode));
462
451
  }
463
452
  const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
464
453
  function resolveOperationTypeNames(node, resolver, options = {}) {
@@ -475,11 +464,11 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
475
464
  const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
476
465
  const exclude = new Set(options.exclude ?? []);
477
466
  const paramNames = options.includeParams === false ? [] : [
478
- ...path.map((param) => resolver.resolvePathParamsName(node, param)),
479
- ...query.map((param) => resolver.resolveQueryParamsName(node, param)),
480
- ...header.map((param) => resolver.resolveHeaderParamsName(node, param))
467
+ ...path.map((param) => resolver.param.path(node, param)),
468
+ ...query.map((param) => resolver.param.query(node, param)),
469
+ ...header.map((param) => resolver.param.headers(node, param))
481
470
  ];
482
- const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)];
471
+ const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)];
483
472
  const result = (options.order === "body-response-first" ? [
484
473
  ...bodyAndResponseNames,
485
474
  ...paramNames,
@@ -603,15 +592,15 @@ function resolveClientOperation(options) {
603
592
  const { clientPlugin, driver, node, root, output } = options;
604
593
  if (!clientPlugin) return null;
605
594
  const resolver = driver.getResolver(clientPlugin.pluginName);
606
- if (!resolver) return null;
607
595
  const plugin = driver.getPlugin(clientPlugin.pluginName);
608
- const file = resolver.resolveFile(operationFileEntry(node, node.operationId), {
596
+ const file = resolver.file({
597
+ ...operationFileEntry(node, node.operationId),
609
598
  root,
610
599
  output: plugin?.options?.output ?? output,
611
600
  group: plugin?.options?.group ?? void 0
612
601
  });
613
602
  return {
614
- name: resolver.resolveName(node.operationId),
603
+ name: resolver.name(node.operationId),
615
604
  path: file.path,
616
605
  clientPath: path.resolve(root, ".kubb/client.ts")
617
606
  };
@@ -659,12 +648,12 @@ const requestGroupOrder = [
659
648
  /**
660
649
  * Builds the grouped `{ path, query, body, headers }` parameter that mirrors the client
661
650
  * function signature. Only the groups the operation carries are emitted, typed from the
662
- * operation's `RequestConfig`. `keys` narrows the emitted groups, used by the query key which
651
+ * operation's `Options`. `keys` narrows the emitted groups, used by the query key which
663
652
  * never carries `headers`.
664
653
  *
665
- * By default the whole group is typed as the single `RequestConfig` reference. When
654
+ * By default the whole group is typed as the single `Options` reference. When
666
655
  * `memberTypeWrapper` is set, each group is emitted as its own member typed from the matching
667
- * `RequestConfig['<group>']` slice and wrapped, used by vue-query to apply
656
+ * `Options['<group>']` slice and wrapped, used by vue-query to apply
668
657
  * `MaybeRefOrGetter` per group.
669
658
  */
670
659
  function buildGroupedRequestParam(node, options) {
@@ -679,13 +668,13 @@ function buildGroupedRequestParam(node, options) {
679
668
  headers: hasRequiredHeader
680
669
  };
681
670
  const isOptional = names.every((name) => !requiredByGroup[name]);
682
- const requestConfigName = resolver.resolveRequestConfigName(node);
671
+ const optionsName = resolver.response.options(node);
683
672
  const omittedKeys = requestGroupOrder.filter((key) => !keys.includes(key));
684
- const requestConfigType = omittedKeys.length > 0 ? `Omit<${requestConfigName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : requestConfigName;
673
+ const optionsType = omittedKeys.length > 0 ? `Omit<${optionsName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : optionsName;
685
674
  if (memberTypeWrapper) {
686
675
  const members = names.map((name) => ({
687
676
  name,
688
- type: memberTypeWrapper(`${requestConfigType}['${name}']`),
677
+ type: memberTypeWrapper(`${optionsType}['${name}']`),
689
678
  optional: !requiredByGroup[name]
690
679
  }));
691
680
  return createFunctionParameter({
@@ -697,7 +686,7 @@ function buildGroupedRequestParam(node, options) {
697
686
  }
698
687
  return createFunctionParameter({
699
688
  name: createObjectBindingPattern({ elements: names.map((name) => ({ name })) }),
700
- type: requestConfigType,
689
+ type: optionsType,
701
690
  optional: false,
702
691
  ...isOptional ? { default: "{}" } : {}
703
692
  });
@@ -743,7 +732,7 @@ function buildClientCall(node, options) {
743
732
  }
744
733
  /**
745
734
  * Build QueryKey params as the grouped `{ path, query, body }` object (NO headers, NO config),
746
- * typed from the operation's `RequestConfig` minus `url`. The query key transformer reads the
735
+ * typed from the operation's `Options` minus `url`. The query key transformer reads the
747
736
  * grouped `path`/`query`/`body` bindings.
748
737
  */
749
738
  function buildQueryKeyParams(node, options) {
@@ -805,7 +794,7 @@ const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
805
794
  const callPrinter$1 = functionPrinter({ mode: "call" });
806
795
  function buildMutationParamsNode(node, options) {
807
796
  const { mutationKeyTypeName, mutationArgTypeName, resolver } = options;
808
- const responseName = resolver.resolveResponseName(node);
797
+ const responseName = resolver.response.response(node);
809
798
  const errorNames = resolveErrorNames(node, resolver);
810
799
  return createFunctionParameters({ params: [createFunctionParameter({
811
800
  name: "options",
@@ -818,14 +807,14 @@ function buildMutationParamsNode(node, options) {
818
807
  })] });
819
808
  }
820
809
  function Mutation({ name, clientName, mutationKeyName, mutationKeyTypeName, mutationArgTypeName, node, tsResolver }) {
821
- const responseName = tsResolver.resolveResponseName(node);
810
+ const responseName = tsResolver.response.response(node);
822
811
  const errorNames = resolveErrorNames(node, tsResolver);
823
812
  const TData = responseName;
824
813
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`;
825
814
  const groupedParam = buildGroupedRequestParam(node, { resolver: tsResolver });
826
815
  const hasMutationParams = groupedParam !== null;
827
816
  const groupedParamsNode = createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
828
- const argTypeBody = hasMutationParams ? tsResolver.resolveRequestConfigName(node) : "";
817
+ const argTypeBody = hasMutationParams ? tsResolver.response.options(node) : "";
829
818
  const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "";
830
819
  const mutationFnBody = `const { data } = await ${buildClientCall(node, {
831
820
  clientName,
@@ -898,44 +887,12 @@ function MutationKey({ name, typeName, node, transformer }) {
898
887
  })] });
899
888
  }
900
889
  //#endregion
901
- //#region src/components/QueryOptions.tsx
902
- const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
903
- function getQueryOptionsParams(node, options) {
904
- return buildQueryOptionsParams(node, options);
905
- }
906
- function QueryOptions({ name, clientName, node, tsResolver }) {
907
- const paramsNode = getQueryOptionsParams(node, { resolver: tsResolver });
908
- const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
909
- const fetcherBody = `const { data } = await ${buildClientCall(node, {
910
- clientName,
911
- signal: false
912
- })}
913
- return data`;
914
- return /* @__PURE__ */ jsx(File.Source, {
915
- name,
916
- isExportable: true,
917
- isIndexable: true,
918
- children: /* @__PURE__ */ jsx(Function, {
919
- name,
920
- export: true,
921
- params: paramsSignature,
922
- children: `
923
- return {
924
- fetcher: async () => {
925
- ${fetcherBody}
926
- },
927
- }
928
- `
929
- })
930
- });
931
- }
932
- //#endregion
933
890
  //#region src/components/Query.tsx
934
- const declarationPrinter = functionPrinter({ mode: "declaration" });
891
+ const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
935
892
  const callPrinter = functionPrinter({ mode: "call" });
936
893
  function buildQueryParamsNode(node, options) {
937
894
  const { resolver } = options;
938
- const responseName = resolver.resolveResponseName(node);
895
+ const responseName = resolver.response.response(node);
939
896
  const errorNames = resolveErrorNames(node, resolver);
940
897
  const optionsParam = createFunctionParameter({
941
898
  name: "options",
@@ -950,7 +907,7 @@ function buildQueryParamsNode(node, options) {
950
907
  return createFunctionParameters({ params: [buildGroupedRequestParam(node, { resolver }), optionsParam].filter((param) => param !== null) });
951
908
  }
952
909
  function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
953
- const responseName = tsResolver.resolveResponseName(node);
910
+ const responseName = tsResolver.response.response(node);
954
911
  const errorNames = resolveErrorNames(node, tsResolver);
955
912
  const generics = [
956
913
  responseName,
@@ -959,10 +916,10 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
959
916
  ];
960
917
  const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
961
918
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? "";
962
- const queryOptionsParamsNode = getQueryOptionsParams(node, { resolver: tsResolver });
919
+ const queryOptionsParamsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
963
920
  const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? "";
964
921
  const paramsNode = buildQueryParamsNode(node, { resolver: tsResolver });
965
- const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
922
+ const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
966
923
  return /* @__PURE__ */ jsx(File.Source, {
967
924
  name,
968
925
  isExportable: true,
@@ -994,6 +951,35 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
994
951
  });
995
952
  }
996
953
  //#endregion
954
+ //#region src/components/QueryOptions.tsx
955
+ const declarationPrinter = functionPrinter({ mode: "declaration" });
956
+ function QueryOptions({ name, clientName, node, tsResolver }) {
957
+ const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
958
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
959
+ const fetcherBody = `const { data } = await ${buildClientCall(node, {
960
+ clientName,
961
+ signal: false
962
+ })}
963
+ return data`;
964
+ return /* @__PURE__ */ jsx(File.Source, {
965
+ name,
966
+ isExportable: true,
967
+ isIndexable: true,
968
+ children: /* @__PURE__ */ jsx(Function, {
969
+ name,
970
+ export: true,
971
+ params: paramsSignature,
972
+ children: `
973
+ return {
974
+ fetcher: async () => {
975
+ ${fetcherBody}
976
+ },
977
+ }
978
+ `
979
+ })
980
+ });
981
+ }
982
+ //#endregion
997
983
  //#region src/generators/mutationGenerator.tsx
998
984
  /**
999
985
  * Built-in generator for `useSWRMutation` hooks. Emits one `useFooMutation` hook
@@ -1022,33 +1008,31 @@ const mutationGenerator = defineGenerator({
1022
1008
  output
1023
1009
  });
1024
1010
  if (!contractOp) return null;
1025
- const mutationHookName = resolver.resolveMutationName(node);
1026
- const mutationKeyName = resolver.resolveMutationKeyName(node);
1027
- const mutationKeyTypeName = resolver.resolveMutationKeyTypeName(node);
1028
- const mutationArgTypeName = resolver.resolveMutationArgTypeName(node);
1011
+ const mutationHookName = resolver.mutation.name(node);
1012
+ const mutationKeyName = resolver.mutation.keyName(node);
1013
+ const mutationKeyTypeName = resolver.mutation.keyTypeName(node);
1014
+ const mutationArgTypeName = resolver.mutation.argTypeName(node);
1029
1015
  const meta = {
1030
- file: resolver.resolveFile({
1016
+ file: resolver.file({
1031
1017
  name: mutationHookName,
1032
1018
  extname: ".ts",
1033
1019
  tag: node.tags[0] ?? "default",
1034
- path: node.path
1035
- }, {
1020
+ path: node.path,
1036
1021
  root,
1037
1022
  output,
1038
1023
  group
1039
1024
  }),
1040
- fileTs: tsResolver.resolveFile({
1025
+ fileTs: tsResolver.file({
1041
1026
  name: node.operationId,
1042
1027
  extname: ".ts",
1043
1028
  tag: node.tags[0] ?? "default",
1044
- path: node.path
1045
- }, {
1029
+ path: node.path,
1046
1030
  root,
1047
1031
  output: pluginTs.options?.output ?? output,
1048
1032
  group: pluginTs.options?.group
1049
1033
  })
1050
1034
  };
1051
- const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1035
+ const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1052
1036
  order: "body-response-first",
1053
1037
  includeParams: false
1054
1038
  })].filter((name) => Boolean(name));
@@ -1057,7 +1041,7 @@ const mutationGenerator = defineGenerator({
1057
1041
  baseName: meta.file.baseName,
1058
1042
  path: meta.file.path,
1059
1043
  meta: meta.file.meta,
1060
- banner: resolver.resolveBanner(ctx.meta, {
1044
+ banner: resolver.default.banner(ctx.meta, {
1061
1045
  output,
1062
1046
  config,
1063
1047
  file: {
@@ -1065,7 +1049,7 @@ const mutationGenerator = defineGenerator({
1065
1049
  baseName: meta.file.baseName
1066
1050
  }
1067
1051
  }),
1068
- footer: resolver.resolveFooter(ctx.meta, {
1052
+ footer: resolver.default.footer(ctx.meta, {
1069
1053
  output,
1070
1054
  config,
1071
1055
  file: {
@@ -1133,14 +1117,11 @@ const queryGenerator = defineGenerator({
1133
1117
  operation(node, ctx) {
1134
1118
  if (!ast.isHttpOperationNode(node)) return null;
1135
1119
  const { config, driver, resolver, root } = ctx;
1136
- const { output, query, mutation, client, group } = ctx.options;
1120
+ const { output, query, client, group } = ctx.options;
1137
1121
  const pluginTs = driver.getPlugin(pluginTsName);
1138
1122
  if (!pluginTs) return null;
1139
1123
  const tsResolver = driver.getResolver(pluginTsName);
1140
- const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
1141
- const queryMethods = new Set(query ? query.methods : []);
1142
- const isMutation = mutation !== false && !isQuery && (mutation ? mutation.methods : []).some((method) => !queryMethods.has(method) && node.method.toLowerCase() === method.toLowerCase());
1143
- if (!isQuery || isMutation) return null;
1124
+ if (!(query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase()))) return null;
1144
1125
  const importPath = query ? query.importPath : "swr";
1145
1126
  const contractOp = resolveClientOperation({
1146
1127
  clientPlugin: { pluginName: client.pluginName },
@@ -1150,33 +1131,31 @@ const queryGenerator = defineGenerator({
1150
1131
  output
1151
1132
  });
1152
1133
  if (!contractOp) return null;
1153
- const queryName = resolver.resolveQueryName(node);
1154
- const queryOptionsName = resolver.resolveQueryOptionsName(node);
1155
- const queryKeyName = resolver.resolveQueryKeyName(node);
1156
- const queryKeyTypeName = resolver.resolveQueryKeyTypeName(node);
1134
+ const queryName = resolver.query.name(node);
1135
+ const queryOptionsName = resolver.query.optionsName(node);
1136
+ const queryKeyName = resolver.query.keyName(node);
1137
+ const queryKeyTypeName = resolver.query.keyTypeName(node);
1157
1138
  const meta = {
1158
- file: resolver.resolveFile({
1139
+ file: resolver.file({
1159
1140
  name: queryName,
1160
1141
  extname: ".ts",
1161
1142
  tag: node.tags[0] ?? "default",
1162
- path: node.path
1163
- }, {
1143
+ path: node.path,
1164
1144
  root,
1165
1145
  output,
1166
1146
  group
1167
1147
  }),
1168
- fileTs: tsResolver.resolveFile({
1148
+ fileTs: tsResolver.file({
1169
1149
  name: node.operationId,
1170
1150
  extname: ".ts",
1171
1151
  tag: node.tags[0] ?? "default",
1172
- path: node.path
1173
- }, {
1152
+ path: node.path,
1174
1153
  root,
1175
1154
  output: pluginTs.options?.output ?? output,
1176
1155
  group: pluginTs.options?.group
1177
1156
  })
1178
1157
  };
1179
- const importedTypeNames = [tsResolver.resolveRequestConfigName(node), ...resolveOperationTypeNames(node, tsResolver, {
1158
+ const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1180
1159
  exclude: [queryKeyTypeName],
1181
1160
  order: "body-response-first",
1182
1161
  includeParams: false
@@ -1186,7 +1165,7 @@ const queryGenerator = defineGenerator({
1186
1165
  baseName: meta.file.baseName,
1187
1166
  path: meta.file.path,
1188
1167
  meta: meta.file.meta,
1189
- banner: resolver.resolveBanner(ctx.meta, {
1168
+ banner: resolver.default.banner(ctx.meta, {
1190
1169
  output,
1191
1170
  config,
1192
1171
  file: {
@@ -1194,7 +1173,7 @@ const queryGenerator = defineGenerator({
1194
1173
  baseName: meta.file.baseName
1195
1174
  }
1196
1175
  }),
1197
- footer: resolver.resolveFooter(ctx.meta, {
1176
+ footer: resolver.default.footer(ctx.meta, {
1198
1177
  output,
1199
1178
  config,
1200
1179
  file: {
@@ -1262,53 +1241,55 @@ function capitalize(name) {
1262
1241
  return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
1263
1242
  }
1264
1243
  /**
1265
- * Naming convention resolver for the SWR plugin.
1244
+ * Default resolver used by `@kubb/plugin-swr`. Decides the names and file paths for every generated
1245
+ * SWR hook (`useFoo`, `useFooMutation`) and its companion helpers (`fooQueryKey`, `fooQueryOptions`,
1246
+ * `fooMutationKey`).
1266
1247
  *
1267
- * Provides default naming helpers using camelCase for functions and file paths.
1248
+ * Functions and files use the built-in camelCase casing; hooks get the `use` prefix.
1268
1249
  *
1269
- * @example
1270
- * `resolverSwr.default('list pets', 'function') // → 'listPets'`
1250
+ * @example Resolve hook and helper names
1251
+ * ```ts
1252
+ * import { resolverSwr } from '@kubb/plugin-swr'
1253
+ *
1254
+ * resolverSwr.query.name(operationNode) // 'useGetPetById'
1255
+ * resolverSwr.query.keyName(operationNode) // 'getPetByIdQueryKey'
1256
+ * resolverSwr.mutation.name(operationNode) // 'useUpdatePet'
1257
+ * ```
1271
1258
  */
1272
- const resolverSwr = defineResolver(() => ({
1273
- name: "default",
1259
+ const resolverSwr = createResolver({
1274
1260
  pluginName: "plugin-swr",
1275
- default(name, type) {
1276
- return type === "file" ? toFilePath(name) : camelCase(name);
1277
- },
1278
- resolveName(name) {
1279
- return this.default(name, "function");
1280
- },
1281
- resolvePathName(name, type) {
1282
- return this.default(name, type);
1283
- },
1284
- resolveQueryName(node) {
1285
- return `use${capitalize(this.resolveName(node.operationId))}`;
1286
- },
1287
- resolveMutationName(node) {
1288
- return `use${capitalize(this.resolveName(node.operationId))}`;
1289
- },
1290
- resolveQueryOptionsName(node) {
1291
- return `${this.resolveName(node.operationId)}QueryOptions`;
1292
- },
1293
- resolveQueryKeyName(node) {
1294
- return `${this.resolveName(node.operationId)}QueryKey`;
1295
- },
1296
- resolveMutationKeyName(node) {
1297
- return `${this.resolveName(node.operationId)}MutationKey`;
1298
- },
1299
- resolveQueryKeyTypeName(node) {
1300
- return `${capitalize(this.resolveName(node.operationId))}QueryKey`;
1301
- },
1302
- resolveMutationKeyTypeName(node) {
1303
- return `${capitalize(this.resolveName(node.operationId))}MutationKey`;
1304
- },
1305
- resolveMutationArgTypeName(node) {
1306
- return `${capitalize(this.resolveName(node.operationId))}MutationArg`;
1261
+ query: {
1262
+ name(node) {
1263
+ return `use${capitalize(this.name(node.operationId))}`;
1264
+ },
1265
+ optionsName(node) {
1266
+ return `${this.name(node.operationId)}QueryOptions`;
1267
+ },
1268
+ keyName(node) {
1269
+ return `${this.name(node.operationId)}QueryKey`;
1270
+ },
1271
+ keyTypeName(node) {
1272
+ return `${capitalize(this.name(node.operationId))}QueryKey`;
1273
+ },
1274
+ clientName(node) {
1275
+ return this.name(node.operationId);
1276
+ }
1307
1277
  },
1308
- resolveClientName(node) {
1309
- return this.resolveName(node.operationId);
1278
+ mutation: {
1279
+ name(node) {
1280
+ return `use${capitalize(this.name(node.operationId))}`;
1281
+ },
1282
+ keyName(node) {
1283
+ return `${this.name(node.operationId)}MutationKey`;
1284
+ },
1285
+ keyTypeName(node) {
1286
+ return `${capitalize(this.name(node.operationId))}MutationKey`;
1287
+ },
1288
+ argTypeName(node) {
1289
+ return `${capitalize(this.name(node.operationId))}MutationArg`;
1290
+ }
1310
1291
  }
1311
- }));
1292
+ });
1312
1293
  //#endregion
1313
1294
  //#region src/plugin.ts
1314
1295
  /**
@@ -1342,17 +1323,14 @@ const pluginSwr = definePlugin((options) => {
1342
1323
  path: "hooks",
1343
1324
  barrel: { type: "named" }
1344
1325
  }, group, exclude = [], include, override = [], mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, client, resolver: userResolver, macros: userMacros } = options;
1345
- const selectedGenerators = [queryGenerator, mutationGenerator].filter((generator) => Boolean(generator));
1326
+ const selectedGenerators = [queryGenerator, mutationGenerator];
1346
1327
  const groupConfig = createGroupConfig(group) ?? void 0;
1347
1328
  return {
1348
1329
  name: pluginSwrName,
1349
1330
  options,
1350
1331
  dependencies: [pluginTsName],
1351
1332
  hooks: { "kubb:plugin:setup"(ctx) {
1352
- const resolver = userResolver ? {
1353
- ...resolverSwr,
1354
- ...userResolver
1355
- } : resolverSwr;
1333
+ const resolver = userResolver ? Resolver.merge(resolverSwr, userResolver) : resolverSwr;
1356
1334
  const resolvedClient = resolveClient({
1357
1335
  client,
1358
1336
  pluginNames: (ctx.config.plugins ?? []).map((p) => p.name).filter((name) => Boolean(name))