@kubb/plugin-vue-query 5.0.0-beta.103 → 5.0.0-beta.106

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
@@ -42,6 +42,26 @@ function operationFileEntry(node, name, extname = ".ts") {
42
42
  path: node.path
43
43
  };
44
44
  }
45
+ /**
46
+ * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the
47
+ * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the
48
+ * same dependency for the same operation in one pass (a query plugin's several hook generators, the
49
+ * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.
50
+ *
51
+ * @example Cache `plugin-ts`'s file for the current operation
52
+ * ```ts
53
+ * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })
54
+ * ```
55
+ */
56
+ function resolveDependencyOperationFile(options) {
57
+ const { cache, node, resolver, root, output, group } = options;
58
+ return cache.getOrSet(`${resolver.pluginName}:operationFile`, () => resolver.file({
59
+ ...operationFileEntry(node, node.operationId),
60
+ root,
61
+ output,
62
+ group: group ?? void 0
63
+ }));
64
+ }
45
65
  function getOperationLink(node, link) {
46
66
  if (!link) return null;
47
67
  if (typeof link === "function") return link(node) ?? null;
@@ -135,13 +155,24 @@ function buildOperationComments(node, options = {}) {
135
155
  if (!splitLines) return filteredComments;
136
156
  return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
137
157
  }
158
+ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
159
+ /**
160
+ * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
161
+ * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
162
+ * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
163
+ * same parameters once per plugin.
164
+ */
138
165
  function getOperationParameters(node) {
139
- return {
166
+ const cached = operationParameterGroupsByNode.get(node);
167
+ if (cached) return cached;
168
+ const groups = {
140
169
  path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
141
170
  query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
142
171
  header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
143
172
  cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
144
173
  };
174
+ operationParameterGroupsByNode.set(node, groups);
175
+ return groups;
145
176
  }
146
177
  function getStatusCodeNumber(statusCode) {
147
178
  const code = Number(statusCode);
@@ -369,14 +400,16 @@ function buildGroupedRequestParam(node, options) {
369
400
  */
370
401
  function buildQueryOptionsParams(node, options) {
371
402
  const { resolver, memberTypeWrapper } = options;
372
- return createFunctionParameters({ params: [buildGroupedRequestParam(node, {
403
+ const groupedParam = buildGroupedRequestParam(node, {
373
404
  resolver,
374
405
  memberTypeWrapper
375
- }), createFunctionParameter({
406
+ });
407
+ const configParam = createFunctionParameter({
376
408
  name: "config",
377
409
  type: `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`,
378
410
  default: "{}"
379
- })].filter((param) => param !== null) });
411
+ });
412
+ return createFunctionParameters({ params: [groupedParam, configParam].filter((param) => param !== null) });
380
413
  }
381
414
  /**
382
415
  * Builds the call to a client `<op>` function inside a query/mutation hook body. The function takes
@@ -759,23 +792,30 @@ function resolveContractClient(options) {
759
792
  * (plugin-fetch or plugin-axios). Returns `null` when no contract plugin is in play (the inline
760
793
  * path). The plugin injects `.kubb/client.ts` at the global output root, the same path consumers
761
794
  * read `RequestConfig` / `ResponseErrorConfig` from.
795
+ *
796
+ * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,
797
+ * so several dependents reading the same client plugin for one operation in a single pass
798
+ * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share
799
+ * one computed result instead of each re-deriving the name and path.
762
800
  */
763
801
  function resolveClientOperation(options) {
764
- const { clientPlugin, driver, node, root, output } = options;
802
+ const { clientPlugin, driver, node, root, output, cache } = options;
765
803
  if (!clientPlugin) return null;
766
- const resolver = driver.getResolver(clientPlugin.pluginName);
767
- const plugin = driver.getPlugin(clientPlugin.pluginName);
768
- const file = resolver.file({
769
- ...operationFileEntry(node, node.operationId),
770
- root,
771
- output: plugin?.options?.output ?? output,
772
- group: plugin?.options?.group ?? void 0
804
+ return cache.getOrSet(`${clientPlugin.pluginName}:clientOperation`, () => {
805
+ const resolver = driver.getResolver(clientPlugin.pluginName);
806
+ const plugin = driver.getPlugin(clientPlugin.pluginName);
807
+ const file = resolver.file({
808
+ ...operationFileEntry(node, node.operationId),
809
+ root,
810
+ output: plugin?.options?.output ?? output,
811
+ group: plugin?.options?.group ?? void 0
812
+ });
813
+ return {
814
+ name: resolver.name(node.operationId),
815
+ path: file.path,
816
+ clientPath: path.resolve(root, ".kubb/client.ts")
817
+ };
773
818
  });
774
- return {
775
- name: resolver.name(node.operationId),
776
- path: file.path,
777
- clientPath: path.resolve(root, ".kubb/client.ts")
778
- };
779
819
  }
780
820
  //#endregion
781
821
  //#region src/utils.ts
@@ -899,10 +939,11 @@ function buildInfiniteQueryParamsNode(node, options) {
899
939
  }`,
900
940
  default: "{}"
901
941
  });
902
- return createFunctionParameters({ params: [buildGroupedRequestParam(node, {
942
+ const groupedParam = buildGroupedRequestParam(node, {
903
943
  resolver,
904
944
  memberTypeWrapper: maybeRefOrGetter
905
- }), optionsParam].filter((param) => param !== null) });
945
+ });
946
+ return createFunctionParameters({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
906
947
  }
907
948
  function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
908
949
  const { TData, TError } = buildResponseTypes(node, tsResolver);
@@ -971,13 +1012,14 @@ function resolveMutationRequestType(node, resolver) {
971
1012
  function buildMutationParamsNode(node, options) {
972
1013
  const { resolver } = options;
973
1014
  const { TData, TError } = buildResponseTypes(node, resolver);
1015
+ const TRequest = resolveMutationRequestType(node, resolver);
974
1016
  return createFunctionParameters({ params: [createFunctionParameter({
975
1017
  name: "options",
976
1018
  type: `{
977
1019
  mutation?: MutationObserverOptions<${[
978
1020
  TData,
979
1021
  TError,
980
- resolveMutationRequestType(node, resolver),
1022
+ TRequest,
981
1023
  "TContext"
982
1024
  ].join(", ")}> & { client?: QueryClient },
983
1025
  client?: ${buildRequestConfigType(node)},
@@ -1051,10 +1093,11 @@ function buildQueryParamsNode(node, options) {
1051
1093
  }`,
1052
1094
  default: "{}"
1053
1095
  });
1054
- return createFunctionParameters({ params: [buildGroupedRequestParam(node, {
1096
+ const groupedParam = buildGroupedRequestParam(node, {
1055
1097
  resolver,
1056
1098
  memberTypeWrapper: maybeRefOrGetter
1057
- }), optionsParam].filter((param) => param !== null) });
1099
+ });
1100
+ return createFunctionParameters({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
1058
1101
  }
1059
1102
  function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver }) {
1060
1103
  const { TData, TError } = buildResponseTypes(node, tsResolver);
@@ -1131,7 +1174,8 @@ const infiniteQueryGenerator = defineGenerator({
1131
1174
  driver,
1132
1175
  node,
1133
1176
  root,
1134
- output
1177
+ output,
1178
+ cache: ctx.cache
1135
1179
  });
1136
1180
  if (!contractOp) return null;
1137
1181
  const queryName = resolver.infiniteQuery.name(node);
@@ -1145,11 +1189,13 @@ const infiniteQueryGenerator = defineGenerator({
1145
1189
  output,
1146
1190
  group: group ?? void 0
1147
1191
  }),
1148
- fileTs: tsResolver.file({
1149
- ...operationFileEntry(node, node.operationId),
1192
+ fileTs: resolveDependencyOperationFile({
1193
+ cache: ctx.cache,
1194
+ node,
1195
+ resolver: tsResolver,
1150
1196
  root,
1151
1197
  output: pluginTs.options?.output ?? output,
1152
- group: pluginTs.options?.group ?? void 0
1198
+ group: pluginTs.options?.group
1153
1199
  })
1154
1200
  };
1155
1201
  const { queryParamsTypeName } = resolvePageParamType(node, {
@@ -1298,7 +1344,8 @@ const mutationGenerator = defineGenerator({
1298
1344
  driver,
1299
1345
  node,
1300
1346
  root,
1301
- output
1347
+ output,
1348
+ cache: ctx.cache
1302
1349
  });
1303
1350
  if (!contractOp) return null;
1304
1351
  const mutationHookName = resolver.mutation.name(node);
@@ -1311,11 +1358,13 @@ const mutationGenerator = defineGenerator({
1311
1358
  output,
1312
1359
  group: group ?? void 0
1313
1360
  }),
1314
- fileTs: tsResolver.file({
1315
- ...operationFileEntry(node, node.operationId),
1361
+ fileTs: resolveDependencyOperationFile({
1362
+ cache: ctx.cache,
1363
+ node,
1364
+ resolver: tsResolver,
1316
1365
  root,
1317
1366
  output: pluginTs.options?.output ?? output,
1318
- group: pluginTs.options?.group ?? void 0
1367
+ group: pluginTs.options?.group
1319
1368
  })
1320
1369
  };
1321
1370
  const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
@@ -1428,7 +1477,8 @@ const queryGenerator = defineGenerator({
1428
1477
  driver,
1429
1478
  node,
1430
1479
  root,
1431
- output
1480
+ output,
1481
+ cache: ctx.cache
1432
1482
  });
1433
1483
  if (!contractOp) return null;
1434
1484
  const queryName = resolver.query.name(node);
@@ -1442,11 +1492,13 @@ const queryGenerator = defineGenerator({
1442
1492
  output,
1443
1493
  group: group ?? void 0
1444
1494
  }),
1445
- fileTs: tsResolver.file({
1446
- ...operationFileEntry(node, node.operationId),
1495
+ fileTs: resolveDependencyOperationFile({
1496
+ cache: ctx.cache,
1497
+ node,
1498
+ resolver: tsResolver,
1447
1499
  root,
1448
1500
  output: pluginTs.options?.output ?? output,
1449
- group: pluginTs.options?.group ?? void 0
1501
+ group: pluginTs.options?.group
1450
1502
  })
1451
1503
  };
1452
1504
  const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {