@kubb/plugin-react-query 5.2.0-canary.20261008T111956 → 5.2.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.d.ts CHANGED
@@ -13,8 +13,8 @@ import "@kubb/plugin-zod";
13
13
  *
14
14
  * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
15
15
  * imports and calls them.
16
- * - `error` — no client plugin is registered, several are registered without a selector, or the
17
- * requested one is missing.
16
+ * - `error` — no client plugin is registered, several are registered without a selector, the
17
+ * requested one is missing, or `client` is not a known selector.
18
18
  *
19
19
  * The `client` string selects explicitly (`'fetch'` / `'axios'`); when it is unset a lone registered
20
20
  * contract client plugin is picked up automatically.
@@ -36,9 +36,19 @@ type ResolvedContractClient = {
36
36
  //#endregion
37
37
  //#region ../../internals/tanstack-query/src/types.d.ts
38
38
  type ParamsCasing = 'camelcase' | undefined;
39
+ /**
40
+ * The hook a key is built for. Plain and suspense queries can share a key, but an infinite query
41
+ * caches `InfiniteData` and must never share one with a plain query.
42
+ */
43
+ type KeyVariant = 'query' | 'suspenseQuery' | 'infiniteQuery' | 'suspenseInfiniteQuery' | 'mutation';
44
+ /**
45
+ * Builds query or mutation key segments for an operation node.
46
+ * Receives `variant` indicating which hook or composable the key is built for.
47
+ */
39
48
  type Transformer = (props: {
40
49
  node: ast.OperationNode;
41
50
  casing: ParamsCasing;
51
+ variant: KeyVariant;
42
52
  }) => Array<unknown>;
43
53
  /**
44
54
  * Configures the query side of a TanStack-family plugin: which HTTP methods produce query
@@ -287,7 +297,8 @@ type ResolverReactQuery = Resolver & {
287
297
  };
288
298
  type Suspense = object;
289
299
  /**
290
- * Builds the `queryKey` used by each generated query hook.
300
+ * Builds the `queryKey` used by each generated query hook. `variant` tells which hook the key is for,
301
+ * so infinite keys can stay apart from plain ones.
291
302
  *
292
303
  * @note String values are inlined verbatim into generated code. Wrap literal
293
304
  * strings in `JSON.stringify(...)`.
@@ -388,11 +399,12 @@ type Options = OutputOptions & {
388
399
  */
389
400
  resolver?: ResolverPatch<ResolverReactQuery>;
390
401
  /**
391
- * Set to `false` to skip generating `use*` hook functions. `queryOptions`,
392
- * `mutationOptions`, `queryKey`, and `mutationKey` helpers are still emitted.
393
- * The resulting output uses only `@tanstack/react-query` factory imports
394
- * (`queryOptions`, `infiniteQueryOptions`, `mutationOptions`) that are
395
- * adapter-portable across React, Vue, Solid, and Svelte.
402
+ * Set to `true` to also generate `use*` hook functions. By default only the
403
+ * `queryOptions`, `mutationOptions`, `queryKey`, and `mutationKey` helpers are
404
+ * emitted, using `@tanstack/react-query` factory imports (`queryOptions`,
405
+ * `infiniteQueryOptions`, `mutationOptions`) that are adapter-portable across
406
+ * React, Vue, Solid, and Svelte. Infinite, suspense, and `customOptions` output
407
+ * needs `hooks: true` too.
396
408
  *
397
409
  * @default false
398
410
  */
package/dist/index.js CHANGED
@@ -333,8 +333,8 @@ function createGroupConfig(group) {
333
333
  *
334
334
  * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
335
335
  * imports and calls them.
336
- * - `error` — no client plugin is registered, several are registered without a selector, or the
337
- * requested one is missing.
336
+ * - `error` — no client plugin is registered, several are registered without a selector, the
337
+ * requested one is missing, or `client` is not a known selector.
338
338
  *
339
339
  * The `client` string selects explicitly (`'fetch'` / `'axios'`); when it is unset a lone registered
340
340
  * contract client plugin is picked up automatically.
@@ -375,6 +375,10 @@ function resolveClient(options) {
375
375
  pluginName
376
376
  };
377
377
  }
378
+ if (client !== void 0) return {
379
+ kind: "error",
380
+ message: `Option \`client\` is ${typeof client === "string" ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios'. Drop \`client\` to use the registered client plugin.`
381
+ };
378
382
  const registered = contractPlugins.filter(has);
379
383
  if (registered.length === 1) return {
380
384
  kind: "contract",
@@ -807,7 +811,8 @@ function MutationKey({ name, node, transformer }) {
807
811
  const paramsSignature = declarationPrinter$6.print(paramsNode) ?? "";
808
812
  const keys = (transformer ?? mutationKeyTransformer)({
809
813
  node,
810
- casing: "camelcase"
814
+ casing: "camelcase",
815
+ variant: "mutation"
811
816
  });
812
817
  return /* @__PURE__ */ jsx(File.Source, {
813
818
  name,
@@ -878,23 +883,25 @@ function createMutationResolver() {
878
883
  //#endregion
879
884
  //#region ../../internals/tanstack-query/src/components/QueryKey.tsx
880
885
  const declarationPrinter$5 = functionPrinter({ mode: "declaration" });
881
- const queryKeyTransformer = ({ node }) => {
886
+ const queryKeyTransformer = ({ node, variant }) => {
882
887
  if (!node.path) return [];
883
- const hasPathParams = getOperationParameters(node).path.length > 0;
884
- const hasQueryParams = getOperationParameters(node).query.length > 0;
885
- const hasRequestBody = !!node.requestBody?.content?.[0]?.schema;
886
- return [
887
- hasPathParams ? `{ url: '${Url.toPath(node.path)}', params: path }` : `{ url: '${Url.toPath(node.path)}' }`,
888
- hasQueryParams ? "...(query ? [query] : [])" : null,
889
- hasRequestBody ? "...(body ? [body] : [])" : null
890
- ].filter(Boolean);
888
+ const { path, query } = getOperationParameters(node);
889
+ const isInfinite = variant === "infiniteQuery" || variant === "suspenseInfiniteQuery";
890
+ const urlFields = [`url: '${Url.toPath(node.path)}'`];
891
+ if (path.length > 0) urlFields.push("params: path");
892
+ if (isInfinite) urlFields.push("infinite: true");
893
+ const result = [`{ ${urlFields.join(", ")} }`];
894
+ if (query.length > 0) result.push("...(query ? [query] : [])");
895
+ if (node.requestBody?.content?.[0]?.schema) result.push("...(body ? [body] : [])");
896
+ return result;
891
897
  };
892
- function QueryKey({ name, node, tsResolver, typeName, transformer }) {
898
+ function QueryKey({ name, node, tsResolver, typeName, transformer, variant = "query" }) {
893
899
  const paramsNode = buildQueryKeyParams(node, { resolver: tsResolver });
894
900
  const paramsSignature = declarationPrinter$5.print(paramsNode) ?? "";
895
901
  const keys = (transformer ?? queryKeyTransformer)({
896
902
  node,
897
- casing: "camelcase"
903
+ casing: "camelcase",
904
+ variant
898
905
  });
899
906
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File.Source, {
900
907
  name,
@@ -1519,8 +1526,7 @@ const infiniteQueryGenerator = defineGenerator({
1519
1526
  if (!ast.isHttpOperationNode(node)) return null;
1520
1527
  const { config, driver, resolver, root } = ctx;
1521
1528
  const { output, query, infinite, client, group, customOptions } = ctx.options;
1522
- const pluginTs = driver.getPlugin(pluginTsName);
1523
- if (!pluginTs) return null;
1529
+ const pluginTs = ctx.requirePlugin(pluginTsName);
1524
1530
  const tsResolver = driver.getResolver(pluginTsName);
1525
1531
  const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1526
1532
  if (!infiniteOptions) return null;
@@ -1616,7 +1622,8 @@ const infiniteQueryGenerator = defineGenerator({
1616
1622
  typeName: queryKeyTypeName,
1617
1623
  node,
1618
1624
  tsResolver,
1619
- transformer: ctx.options.queryKey
1625
+ transformer: ctx.options.queryKey,
1626
+ variant: "infiniteQuery"
1620
1627
  }),
1621
1628
  /* @__PURE__ */ jsx(File.Import, {
1622
1629
  name: ["InfiniteData"],
@@ -1692,8 +1699,7 @@ const mutationGenerator = defineGenerator({
1692
1699
  if (!ast.isHttpOperationNode(node)) return null;
1693
1700
  const { config, driver, resolver, root } = ctx;
1694
1701
  const { output, mutation, client, group, customOptions, hooks } = ctx.options;
1695
- const pluginTs = driver.getPlugin(pluginTsName);
1696
- if (!pluginTs) return null;
1702
+ const pluginTs = ctx.requirePlugin(pluginTsName);
1697
1703
  const tsResolver = driver.getResolver(pluginTsName);
1698
1704
  const importPath = mutation ? mutation.importPath : "@tanstack/react-query";
1699
1705
  const contractOp = resolveClientOperation({
@@ -1841,8 +1847,7 @@ const queryGenerator = defineGenerator({
1841
1847
  if (!ast.isHttpOperationNode(node)) return null;
1842
1848
  const { config, driver, resolver, root } = ctx;
1843
1849
  const { output, query, client, group, customOptions, hooks } = ctx.options;
1844
- const pluginTs = driver.getPlugin(pluginTsName);
1845
- if (!pluginTs) return null;
1850
+ const pluginTs = ctx.requirePlugin(pluginTsName);
1846
1851
  const tsResolver = driver.getResolver(pluginTsName);
1847
1852
  const importPath = query ? query.importPath : "@tanstack/react-query";
1848
1853
  const contractOp = resolveClientOperation({
@@ -1927,7 +1932,8 @@ const queryGenerator = defineGenerator({
1927
1932
  typeName: queryKeyTypeName,
1928
1933
  node,
1929
1934
  tsResolver,
1930
- transformer: ctx.options.queryKey
1935
+ transformer: ctx.options.queryKey,
1936
+ variant: "query"
1931
1937
  }),
1932
1938
  /* @__PURE__ */ jsx(File.Import, {
1933
1939
  name: ["queryOptions"],
@@ -1998,8 +2004,7 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1998
2004
  if (!ast.isHttpOperationNode(node)) return null;
1999
2005
  const { config, driver, resolver, root } = ctx;
2000
2006
  const { output, query, infinite, client, group, customOptions } = ctx.options;
2001
- const pluginTs = driver.getPlugin(pluginTsName);
2002
- if (!pluginTs) return null;
2007
+ const pluginTs = ctx.requirePlugin(pluginTsName);
2003
2008
  const tsResolver = driver.getResolver(pluginTsName);
2004
2009
  const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
2005
2010
  if (!infiniteOptions) return null;
@@ -2091,7 +2096,8 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
2091
2096
  typeName: queryKeyTypeName,
2092
2097
  node,
2093
2098
  tsResolver,
2094
- transformer: ctx.options.queryKey
2099
+ transformer: ctx.options.queryKey,
2100
+ variant: "suspenseInfiniteQuery"
2095
2101
  }),
2096
2102
  /* @__PURE__ */ jsx(File.Import, {
2097
2103
  name: ["InfiniteData"],
@@ -2171,8 +2177,7 @@ const suspenseQueryGenerator = defineGenerator({
2171
2177
  if (!ast.isHttpOperationNode(node)) return null;
2172
2178
  const { config, driver, resolver, root } = ctx;
2173
2179
  const { output, query, client, group, customOptions } = ctx.options;
2174
- const pluginTs = driver.getPlugin(pluginTsName);
2175
- if (!pluginTs) return null;
2180
+ const pluginTs = ctx.requirePlugin(pluginTsName);
2176
2181
  const tsResolver = driver.getResolver(pluginTsName);
2177
2182
  const importPath = query ? query.importPath : "@tanstack/react-query";
2178
2183
  const contractOp = resolveClientOperation({
@@ -2257,7 +2262,8 @@ const suspenseQueryGenerator = defineGenerator({
2257
2262
  typeName: queryKeyTypeName,
2258
2263
  node,
2259
2264
  tsResolver,
2260
- transformer: ctx.options.queryKey
2265
+ transformer: ctx.options.queryKey,
2266
+ variant: "suspenseQuery"
2261
2267
  }),
2262
2268
  /* @__PURE__ */ jsx(File.Import, {
2263
2269
  name: ["queryOptions"],
@@ -2396,6 +2402,7 @@ const pluginReactQuery = definePlugin((options) => {
2396
2402
  options,
2397
2403
  dependencies: [pluginTsName],
2398
2404
  hooks: { "kubb:plugin:setup"(ctx) {
2405
+ ctx.requirePlugin(pluginTsName);
2399
2406
  const resolver = userResolver ? Resolver.merge(resolverReactQuery, userResolver) : resolverReactQuery;
2400
2407
  ctx.setOptions({
2401
2408
  output,