@kubb/plugin-react-query 5.5.0 → 5.5.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.js CHANGED
@@ -1,28 +1,10 @@
1
1
  import "./rolldown-runtime-C0LytTxp.js";
2
- import { Resolver, Url, addGenerator, ast, createResolver, defineExtension, defineGenerator, setMacros, setResolver, useConfig } from "kubb/kit";
2
+ import { Diagnostics, Resolver, Url, addGenerator, ast, createResolver, defineExtension, defineGenerator, setMacros, setResolver, useConfig } from "kubb/kit";
3
3
  import path from "node:path";
4
- import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, createTypeLiteral, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
5
4
  import { File, Function, Type, jsxRenderer } from "kubb/jsx";
5
+ import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, createTypeLiteral, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
6
6
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
7
7
  import fs from "node:fs";
8
- //#region ../../internals/shared/src/params.ts
9
- /**
10
- * Drops parameters that share the same name, keeping the first.
11
- *
12
- * A malformed spec can declare the same parameter name twice within one `in` location. Both would
13
- * resolve to the same output property, so emitting both would yield an object type with a duplicate
14
- * member, which TypeScript rejects. This is a defensive guard against that case, not a casing guard:
15
- * parameter names flow through unchanged, so no two distinct names ever collide here anymore.
16
- */
17
- function dedupeParams(params) {
18
- const seen = /* @__PURE__ */ new Set();
19
- return params.filter((param) => {
20
- if (seen.has(param.name)) return false;
21
- seen.add(param.name);
22
- return true;
23
- });
24
- }
25
- //#endregion
26
8
  //#region ../../internals/shared/src/operation.ts
27
9
  /**
28
10
  * Builds the `ResolverFileParams` every operation generator passes to
@@ -92,12 +74,12 @@ function getContentTypeInfo(node) {
92
74
  function getResponseContentTypeInfo(node) {
93
75
  return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? []);
94
76
  }
77
+ const requestConfigBaseType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
95
78
  function buildRequestConfigType(node) {
96
79
  const request = getContentTypeInfo(node);
97
80
  const response = getResponseContentTypeInfo(node);
98
- const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
99
81
  const members = [request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null, response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null].filter(Boolean);
100
- return members.length ? `${configType} & { contentType?: { ${members.join("; ")} } }` : configType;
82
+ return members.length ? `${requestConfigBaseType} & { contentType?: { ${members.join("; ")} } }` : requestConfigBaseType;
101
83
  }
102
84
  /**
103
85
  * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
@@ -106,7 +88,7 @@ function buildRequestConfigType(node) {
106
88
  * content type for.
107
89
  */
108
90
  function buildClientOptionType() {
109
- return `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
91
+ return requestConfigBaseType;
110
92
  }
111
93
  /**
112
94
  * Which of the grouped request options an operation carries.
@@ -166,11 +148,19 @@ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
166
148
  function getOperationParameters(node) {
167
149
  const cached = operationParameterGroupsByNode.get(node);
168
150
  if (cached) return cached;
151
+ const group = (location) => {
152
+ const seen = /* @__PURE__ */ new Set();
153
+ return node.parameters.filter((param) => {
154
+ if (param.in !== location || seen.has(param.name)) return false;
155
+ seen.add(param.name);
156
+ return true;
157
+ });
158
+ };
169
159
  const groups = {
170
- path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
171
- query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
172
- header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
173
- cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
160
+ path: group("path"),
161
+ query: group("query"),
162
+ header: group("header"),
163
+ cookie: group("cookie")
174
164
  };
175
165
  operationParameterGroupsByNode.set(node, groups);
176
166
  return groups;
@@ -330,7 +320,7 @@ var compatibility = {
330
320
  };
331
321
  //#endregion
332
322
  //#region package.json
333
- var version = "5.5.0";
323
+ var version = "5.5.1";
334
324
  //#endregion
335
325
  //#region ../../internals/client/src/resolveClient.ts
336
326
  /**
@@ -374,7 +364,7 @@ const contractPlugins = [
374
364
  * @example
375
365
  * ```ts
376
366
  * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
377
- * // { kind: 'error', message: 'No client plugin is registered…' }
367
+ * // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }
378
368
  * ```
379
369
  */
380
370
  function resolveClient(options) {
@@ -384,7 +374,9 @@ function resolveClient(options) {
384
374
  const pluginName = selectorToPlugin[client];
385
375
  if (!has(pluginName)) return {
386
376
  kind: "error",
387
- message: `\`client: '${client}'\` is set but \`@kubb/plugin-${client}\` is not registered in \`plugins\`. Add it, or drop \`client\` to use a different client plugin.`
377
+ code: Diagnostics.code.missingDependency,
378
+ message: `\`client: '${client}'\` is set but \`@kubb/plugin-${client}\` is not registered in \`plugins\`.`,
379
+ help: `Add \`@kubb/plugin-${client}\` to \`plugins\`, or drop \`client\` to use a different client plugin.`
388
380
  };
389
381
  return {
390
382
  kind: "contract",
@@ -393,7 +385,9 @@ function resolveClient(options) {
393
385
  }
394
386
  if (client !== void 0) return {
395
387
  kind: "error",
396
- message: `Option \`client\` is ${typeof client === "string" ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'. Drop \`client\` to use the registered client plugin.`
388
+ code: Diagnostics.code.invalidPluginOptions,
389
+ message: `Option \`client\` is ${typeof client === "string" ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,
390
+ help: "Set `client` to one of those values, or drop it to use the registered client plugin."
397
391
  };
398
392
  const registered = contractPlugins.filter(has);
399
393
  if (registered.length === 1) return {
@@ -402,25 +396,40 @@ function resolveClient(options) {
402
396
  };
403
397
  if (registered.length > 1) return {
404
398
  kind: "error",
405
- message: `Multiple client plugins are registered (${registered.map((name) => `\`@kubb/${name}\``).join(", ")}). Set \`client: 'fetch' | 'axios' | 'client'\` to choose which client the hooks call, or register a single client plugin.`
399
+ code: Diagnostics.code.invalidPluginOptions,
400
+ message: `Multiple client plugins are registered (${registered.map((name) => `\`@kubb/${name}\``).join(", ")}) and \`client\` is not set.`,
401
+ help: "Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin."
406
402
  };
407
403
  return {
408
404
  kind: "error",
409
- message: "No client plugin is registered. Add `@kubb/plugin-axios`, `@kubb/plugin-fetch`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call."
405
+ code: Diagnostics.code.missingDependency,
406
+ message: "No client plugin is registered.",
407
+ help: "Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call."
410
408
  };
411
409
  }
412
410
  /**
413
- * Resolves the contract client during a consumer plugin's setup hook. Extracts the plugin names
414
- * from the raw `plugins` config, applies {@link resolveClient}, and throws the diagnostic on a
415
- * misconfiguration so every consumer fails fast with the same message.
411
+ * Resolves the contract client during a consumer plugin's setup hook.
412
+ * It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.
413
+ * On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer
414
+ * fails fast with the same message.
416
415
  */
417
416
  function resolveContractClient(options) {
418
- const { client, plugins = [] } = options;
417
+ const { plugin, client, plugins = [] } = options;
419
418
  const resolved = resolveClient({
420
419
  client,
421
420
  pluginNames: plugins.map((plugin) => plugin.name).filter((name) => Boolean(name))
422
421
  });
423
- if (resolved.kind === "error") throw new Error(resolved.message);
422
+ if (resolved.kind === "error") {
423
+ const { code, message, help } = resolved;
424
+ throw new Diagnostics.Error({
425
+ code,
426
+ severity: "error",
427
+ message,
428
+ help,
429
+ location: { kind: "config" },
430
+ plugin
431
+ });
432
+ }
424
433
  return resolved;
425
434
  }
426
435
  //#endregion
@@ -484,12 +493,101 @@ function resolveClientOperation(options) {
484
493
  });
485
494
  }
486
495
  //#endregion
496
+ //#region ../../internals/tanstack-query/src/components/HookFile.tsx
497
+ /**
498
+ * Resolves what every TanStack hook file shares: its file, the `@kubb/plugin-ts` file and type names, banner and footer.
499
+ */
500
+ function resolveHookFile(node, ctx, options) {
501
+ const { name, output, group, contractOp, keyTypeName, extraTypeNames = [] } = options;
502
+ const { config, root, resolver } = ctx;
503
+ const pluginTs = ctx.requirePlugin(pluginTsName);
504
+ const tsResolver = ctx.driver.getResolver(pluginTsName);
505
+ const file = resolver.file({
506
+ ...operationFileEntry(node, name),
507
+ root,
508
+ output,
509
+ group: group ?? void 0
510
+ });
511
+ const fileTs = resolveDependencyOperationFile({
512
+ cache: ctx.cache,
513
+ node,
514
+ resolver: tsResolver,
515
+ root,
516
+ output: pluginTs.options?.output ?? output,
517
+ group: pluginTs.options?.group
518
+ });
519
+ const importedTypeNames = [
520
+ tsResolver.response.options(node),
521
+ ...extraTypeNames,
522
+ ...resolveOperationTypeNames(node, tsResolver, {
523
+ exclude: keyTypeName ? [keyTypeName] : void 0,
524
+ order: "body-response-first",
525
+ includeParams: false
526
+ })
527
+ ].filter((typeName) => Boolean(typeName));
528
+ const fileMeta = {
529
+ path: file.path,
530
+ baseName: file.baseName
531
+ };
532
+ return {
533
+ file,
534
+ fileTs,
535
+ tsResolver,
536
+ contractOp,
537
+ importedTypeNames,
538
+ banner: resolver.default.banner(ctx.meta, {
539
+ output,
540
+ config,
541
+ file: fileMeta
542
+ }),
543
+ footer: resolver.default.footer(ctx.meta, {
544
+ output,
545
+ config,
546
+ file: fileMeta
547
+ })
548
+ };
549
+ }
550
+ /**
551
+ * The `<File>` shell shared by the TanStack hook generators; renders `children` after the imports.
552
+ */
553
+ function HookFile({ hook, imports, children }) {
554
+ const { file, fileTs, contractOp, importedTypeNames, banner, footer } = hook;
555
+ return /* @__PURE__ */ jsxs(File, {
556
+ baseName: file.baseName,
557
+ path: file.path,
558
+ meta: file.meta,
559
+ banner,
560
+ footer,
561
+ children: [
562
+ /* @__PURE__ */ jsx(File.Import, {
563
+ name: [contractOp.name],
564
+ root: file.path,
565
+ path: contractOp.path
566
+ }),
567
+ /* @__PURE__ */ jsx(File.Import, {
568
+ name: ["RequestConfig", "ResponseErrorConfig"],
569
+ root: contractOp.clientPathIsFile ? file.path : void 0,
570
+ path: contractOp.clientPath,
571
+ isTypeOnly: true
572
+ }),
573
+ imports,
574
+ fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
575
+ name: Array.from(new Set(importedTypeNames)),
576
+ root: file.path,
577
+ path: fileTs.path,
578
+ isTypeOnly: true
579
+ }),
580
+ children
581
+ ]
582
+ });
583
+ }
584
+ //#endregion
487
585
  //#region ../../internals/tanstack-query/src/utils.ts
488
586
  /**
489
587
  * The grouped request options, ordered for both the destructured signature and the
490
588
  * call passed to the underlying client.
491
589
  */
492
- const requestGroupOrder$1 = [
590
+ const requestGroupOrder = [
493
591
  "path",
494
592
  "query",
495
593
  "body",
@@ -510,7 +608,7 @@ function maybeValueOrGetter(type) {
510
608
  * `MaybeRefOrGetter` per group.
511
609
  */
512
610
  function buildGroupedRequestParam(node, options) {
513
- const { resolver, keys = requestGroupOrder$1, memberTypeWrapper } = options;
611
+ const { resolver, keys = requestGroupOrder, memberTypeWrapper } = options;
514
612
  const { groups, hasRequiredPath, hasRequiredQuery, hasRequiredHeader } = getRequestGroupOptionality(node);
515
613
  const names = keys.filter((key) => groups[key]);
516
614
  if (names.length === 0) return null;
@@ -522,7 +620,7 @@ function buildGroupedRequestParam(node, options) {
522
620
  };
523
621
  const isOptional = names.every((name) => !requiredByGroup[name]);
524
622
  const optionsName = resolver.response.options(node);
525
- const omittedKeys = requestGroupOrder$1.filter((key) => !keys.includes(key));
623
+ const omittedKeys = requestGroupOrder.filter((key) => !keys.includes(key));
526
624
  const optionsType = omittedKeys.length > 0 ? `Omit<${optionsName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : optionsName;
527
625
  if (memberTypeWrapper) {
528
626
  const members = names.map((name) => ({
@@ -583,7 +681,7 @@ function buildClientCall(node, options) {
583
681
  const { groups } = getRequestGroupOptionality(node);
584
682
  return `${clientName}({ ${[
585
683
  "...config",
586
- ...requestGroupOrder$1.filter((key) => groups[key]).map((name) => unwrapName ? `${name}: ${unwrapName(name)}` : name),
684
+ ...requestGroupOrder.filter((key) => groups[key]).map((name) => unwrapName ? `${name}: ${unwrapName(name)}` : name),
587
685
  signal ? "signal: config.signal ?? signal" : null,
588
686
  "throwOnError: true"
589
687
  ].filter((part) => part !== null).join(", ")} })`;
@@ -793,16 +891,48 @@ function hasQueryKeyParams(node) {
793
891
  * grouped `path`/`query`/`body` bindings.
794
892
  */
795
893
  function buildQueryKeyParams(node, options) {
796
- const { resolver } = options;
894
+ const { resolver, memberTypeWrapper } = options;
797
895
  const groupedParam = buildGroupedRequestParam(node, {
798
896
  resolver,
799
- keys: queryKeyGroupOrder
897
+ keys: queryKeyGroupOrder,
898
+ memberTypeWrapper
800
899
  });
801
900
  return createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
802
901
  }
902
+ /**
903
+ * Builds the hook parameter list: the grouped request param (omitted when `withRequest` is `false`) then `options` typed as `optionsType`.
904
+ */
905
+ function buildHookParams(node, options) {
906
+ const { resolver, optionsType, memberTypeWrapper, withRequest = true } = options;
907
+ const optionsParam = createFunctionParameter({
908
+ name: "options",
909
+ type: optionsType,
910
+ default: "{}"
911
+ });
912
+ const groupedParam = withRequest ? buildGroupedRequestParam(node, {
913
+ resolver,
914
+ memberTypeWrapper
915
+ }) : null;
916
+ return createFunctionParameters({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
917
+ }
918
+ /**
919
+ * The `TRequest` type argument of a mutation hook: the options type when the operation takes a request, else `undefined`.
920
+ */
921
+ function resolveMutationRequestType(node, resolver) {
922
+ return buildGroupedRequestParam(node, { resolver }) ? resolver.response.options(node) : "undefined";
923
+ }
924
+ /**
925
+ * Builds the object literal that unwraps each request group's getter before it reaches `queryKey`/`queryOptions`; `null` without a request group.
926
+ */
927
+ function buildResolvedRequestParams(node) {
928
+ const groups = getRequestGroups(node);
929
+ const names = requestGroupOrder.filter((key) => groups[key]);
930
+ if (names.length === 0) return null;
931
+ return `{ ${names.map((name) => `${name}: typeof ${name} === 'function' ? ${name}() : ${name}`).join(", ")} }`;
932
+ }
803
933
  //#endregion
804
934
  //#region ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
805
- const declarationPrinter$7 = functionPrinter({ mode: "declaration" });
935
+ const declarationPrinter$6 = functionPrinter({ mode: "declaration" });
806
936
  const callPrinter$3 = functionPrinter({ mode: "call" });
807
937
  function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, returnType = "full" }) {
808
938
  const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver);
@@ -822,7 +952,7 @@ function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitI
822
952
  resolver: tsResolver,
823
953
  memberTypeWrapper
824
954
  });
825
- const paramsSignature = declarationPrinter$7.print(paramsNode) ?? "";
955
+ const paramsSignature = declarationPrinter$6.print(paramsNode) ?? "";
826
956
  const queryFnBody = buildCallResultBody(buildClientCall(node, {
827
957
  clientName,
828
958
  signal: true,
@@ -879,20 +1009,20 @@ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${que
879
1009
  }
880
1010
  //#endregion
881
1011
  //#region ../../internals/tanstack-query/src/components/MutationKey.tsx
882
- const declarationPrinter$6 = functionPrinter({ mode: "declaration" });
1012
+ const declarationPrinter$5 = functionPrinter({ mode: "declaration" });
883
1013
  const mutationKeyTransformer = ({ node }) => {
884
1014
  if (!node.path) return [];
885
1015
  return [`{ url: '${Url.toPath(node.path)}' }`];
886
1016
  };
887
- function MutationKey({ name, node, transformer }) {
1017
+ function MutationKey({ name, node, transformer, typeName }) {
888
1018
  const paramsNode = createFunctionParameters({ params: [] });
889
- const paramsSignature = declarationPrinter$6.print(paramsNode) ?? "";
1019
+ const paramsSignature = declarationPrinter$5.print(paramsNode) ?? "";
890
1020
  const keys = (transformer ?? mutationKeyTransformer)({
891
1021
  node,
892
1022
  casing: "camelcase",
893
1023
  variant: "mutation"
894
1024
  });
895
- return /* @__PURE__ */ jsx(File.Source, {
1025
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File.Source, {
896
1026
  name,
897
1027
  isExportable: true,
898
1028
  isIndexable: true,
@@ -903,7 +1033,17 @@ function MutationKey({ name, node, transformer }) {
903
1033
  singleLine: true,
904
1034
  children: `[${keys.join(", ")}] as const`
905
1035
  })
906
- });
1036
+ }), typeName && /* @__PURE__ */ jsx(File.Source, {
1037
+ name: typeName,
1038
+ isExportable: true,
1039
+ isIndexable: true,
1040
+ isTypeOnly: true,
1041
+ children: /* @__PURE__ */ jsx(Type, {
1042
+ export: true,
1043
+ name: typeName,
1044
+ children: `ReturnType<typeof ${name}>`
1045
+ })
1046
+ })] });
907
1047
  }
908
1048
  //#endregion
909
1049
  //#region ../../internals/tanstack-query/src/resolver.ts
@@ -960,7 +1100,7 @@ function createMutationResolver() {
960
1100
  }
961
1101
  //#endregion
962
1102
  //#region ../../internals/tanstack-query/src/components/QueryKey.tsx
963
- const declarationPrinter$5 = functionPrinter({ mode: "declaration" });
1103
+ const declarationPrinter$4 = functionPrinter({ mode: "declaration" });
964
1104
  const queryKeyTransformer = ({ node, variant }) => {
965
1105
  if (!node.path) return [];
966
1106
  const { path, query } = getOperationParameters(node);
@@ -973,9 +1113,12 @@ const queryKeyTransformer = ({ node, variant }) => {
973
1113
  if (node.requestBody?.content?.[0]?.schema) result.push("...(body !== undefined ? [body] : [])");
974
1114
  return result;
975
1115
  };
976
- function QueryKey({ name, node, tsResolver, typeName, transformer, variant = "query" }) {
977
- const paramsNode = buildQueryKeyParams(node, { resolver: tsResolver });
978
- const paramsSignature = declarationPrinter$5.print(paramsNode) ?? "";
1116
+ function QueryKey({ name, node, tsResolver, typeName, transformer, variant = "query", memberTypeWrapper, exportType }) {
1117
+ const paramsNode = buildQueryKeyParams(node, {
1118
+ resolver: tsResolver,
1119
+ memberTypeWrapper
1120
+ });
1121
+ const paramsSignature = declarationPrinter$4.print(paramsNode) ?? "";
979
1122
  const keys = (transformer ?? queryKeyTransformer)({
980
1123
  node,
981
1124
  casing: "camelcase",
@@ -994,9 +1137,12 @@ function QueryKey({ name, node, tsResolver, typeName, transformer, variant = "qu
994
1137
  })
995
1138
  }), /* @__PURE__ */ jsx(File.Source, {
996
1139
  name: typeName,
1140
+ isExportable: exportType,
1141
+ isIndexable: exportType,
997
1142
  isTypeOnly: true,
998
1143
  children: /* @__PURE__ */ jsx(Type, {
999
1144
  name: typeName,
1145
+ export: exportType,
1000
1146
  children: `ReturnType<typeof ${name}>`
1001
1147
  })
1002
1148
  })] });
@@ -1100,30 +1246,6 @@ const customHookOptionsFileGenerator = defineGenerator({
1100
1246
  }
1101
1247
  });
1102
1248
  //#endregion
1103
- //#region src/utils.ts
1104
- const requestGroupOrder = [
1105
- "path",
1106
- "query",
1107
- "body",
1108
- "headers"
1109
- ];
1110
- /**
1111
- * Builds the object literal that resolves each request group to a concrete value, unwrapping a getter
1112
- * once before the value reaches the plain `queryKey`/`queryOptions` helpers. A getter must never reach a
1113
- * React Query key, which is hashed structurally. Returns `null` when the operation carries no request group.
1114
- *
1115
- * @example
1116
- * ```ts
1117
- * buildResolvedRequestParams(node) // { path: typeof path === 'function' ? path() : path }
1118
- * ```
1119
- */
1120
- function buildResolvedRequestParams(node) {
1121
- const groups = getRequestGroups(node);
1122
- const names = requestGroupOrder.filter((key) => groups[key]);
1123
- if (names.length === 0) return null;
1124
- return `{ ${names.map((name) => `${name}: typeof ${name} === 'function' ? ${name}() : ${name}`).join(", ")} }`;
1125
- }
1126
- //#endregion
1127
1249
  //#region src/generators/hookOptionsGenerator.tsx
1128
1250
  /**
1129
1251
  * Emits the `HookOptions` type used by `customOptions`. Enabled when
@@ -1160,9 +1282,10 @@ const hookOptionsGenerator = defineGenerator({
1160
1282
  const nodeMutation = "mutation" in opOverrides ? opOverrides.mutation : mutation;
1161
1283
  const nodeInfinite = "infinite" in opOverrides ? opOverrides.infinite : infinite;
1162
1284
  const nodeInfiniteOptions = nodeInfinite && typeof nodeInfinite === "object" ? nodeInfinite : null;
1163
- const isQueryOp = nodeQuery === false ? !!query && query.methods.some((m) => node.method.toLowerCase() === m.toLowerCase()) : !!nodeQuery && nodeQuery.methods.some((m) => node.method.toLowerCase() === m.toLowerCase());
1164
- const nodeQueryMethods = new Set(nodeQuery ? nodeQuery.methods : []);
1165
- const isMutationOp = nodeMutation !== false && !isQueryOp && (nodeMutation ? nodeMutation.methods : []).some((m) => !nodeQueryMethods.has(m) && node.method.toLowerCase() === m.toLowerCase());
1285
+ const { isQuery: isQueryOp, isMutation: isMutationOp } = classifyOperation(node, {
1286
+ query: nodeQuery === false ? query : nodeQuery,
1287
+ mutation: nodeMutation
1288
+ });
1166
1289
  const isSuspenseOp = !!suspense;
1167
1290
  const isInfiniteOp = !!nodeInfiniteOptions;
1168
1291
  if (isQueryOp) {
@@ -1197,9 +1320,7 @@ const hookOptionsGenerator = defineGenerator({
1197
1320
  hookOptions[suspenseHookName] = `Partial<ReturnType<typeof ${suspenseOptionsName}>>`;
1198
1321
  }
1199
1322
  if (isInfiniteOp) {
1200
- const normalizeKey = (key) => key.replace(/\?$/, "");
1201
- const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
1202
- if (nodeInfiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === nodeInfiniteOptions.queryParam) : false) {
1323
+ if (matchesInfinite(node, nodeInfiniteOptions)) {
1203
1324
  const infiniteOptionsName = resolver.infiniteQuery.optionsName(node);
1204
1325
  const infiniteHookName = resolver.infiniteQuery.name(node);
1205
1326
  const infiniteHookFile = resolver.file({
@@ -1285,50 +1406,87 @@ const hookOptionsGenerator = defineGenerator({
1285
1406
  }
1286
1407
  });
1287
1408
  //#endregion
1288
- //#region src/components/InfiniteQuery.tsx
1289
- const declarationPrinter$4 = functionPrinter({ mode: "declaration" });
1290
- function buildInfiniteQueryParamsNode(node, options) {
1291
- const { resolver, pageParamGeneric, observerOptionsName } = options;
1292
- const optionsParam = createFunctionParameter({
1293
- name: "options",
1294
- type: `{
1295
- query?: Partial<${observerOptionsName}<TQueryFnData, TError, TData, TQueryKey, ${pageParamGeneric}>> & { client?: QueryClient },
1296
- client?: ${buildClientOptionType()}
1297
- }`,
1298
- default: "{}"
1299
- });
1300
- const groupedParam = buildGroupedRequestParam(node, {
1301
- resolver,
1302
- memberTypeWrapper: maybeValueOrGetter
1303
- });
1304
- return createFunctionParameters({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
1409
+ //#region src/components/Query.tsx
1410
+ const declarationPrinter$3 = functionPrinter({ mode: "declaration" });
1411
+ const OBSERVER_OPTIONS_NAMES = {
1412
+ infinite: {
1413
+ suspense: "UseSuspenseInfiniteQueryOptions",
1414
+ standard: "InfiniteQueryObserverOptions"
1415
+ },
1416
+ plain: {
1417
+ suspense: "UseSuspenseQueryOptions",
1418
+ standard: "QueryObserverOptions"
1419
+ }
1420
+ };
1421
+ function buildHookTypes({ node, tsResolver, infinite, suspense, TData, TError, queryKeyTypeName, observerOptionsName, resultTypeName }) {
1422
+ if (infinite) {
1423
+ const { pageParamType } = resolvePageParamType(node, {
1424
+ resolver: tsResolver,
1425
+ initialPageParam: infinite.initialPageParam,
1426
+ queryParam: infinite.queryParam
1427
+ });
1428
+ return {
1429
+ generics: [
1430
+ `TQueryFnData = ${TData}`,
1431
+ `TError = ${TError}`,
1432
+ "TData = InfiniteData<TQueryFnData>",
1433
+ `TQueryKey extends QueryKey = ${queryKeyTypeName}`,
1434
+ `TPageParam = ${pageParamType}`
1435
+ ],
1436
+ observerOptionsType: `${observerOptionsName}<TQueryFnData, TError, TData, TQueryKey, TPageParam>`,
1437
+ returnType: `${resultTypeName}<TData, TError> & { queryKey: TQueryKey }`
1438
+ };
1439
+ }
1440
+ return {
1441
+ generics: suspense ? [`TData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`] : [
1442
+ `TData = ${TData}`,
1443
+ `TQueryData = ${TData}`,
1444
+ `TQueryKey extends QueryKey = ${queryKeyTypeName}`
1445
+ ],
1446
+ observerOptionsType: `${observerOptionsName}<${(suspense ? [
1447
+ TData,
1448
+ TError,
1449
+ "TData",
1450
+ "TQueryKey"
1451
+ ] : [
1452
+ TData,
1453
+ TError,
1454
+ "TData",
1455
+ "TQueryData",
1456
+ "TQueryKey"
1457
+ ]).join(", ")}>`,
1458
+ returnType: `${resultTypeName}<TData, ${TError}> & { queryKey: TQueryKey }`
1459
+ };
1305
1460
  }
1306
- function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, initialPageParam, queryParam, customOptions, suspense }) {
1307
- const { TData: responseType, TError: errorType } = buildResponseTypes(node, tsResolver);
1308
- const { pageParamType } = resolvePageParamType(node, {
1309
- resolver: tsResolver,
1310
- initialPageParam,
1311
- queryParam
1461
+ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense, infinite }) {
1462
+ const { TData, TError } = buildResponseTypes(node, tsResolver);
1463
+ const prefix = suspense ? "UseSuspense" : "Use";
1464
+ const hookName = `${suspense ? "useSuspense" : "use"}${infinite ? "InfiniteQuery" : "Query"}`;
1465
+ const observerOptionsName = OBSERVER_OPTIONS_NAMES[infinite ? "infinite" : "plain"][suspense ? "suspense" : "standard"];
1466
+ const { generics, observerOptionsType, returnType } = buildHookTypes({
1467
+ node,
1468
+ tsResolver,
1469
+ infinite,
1470
+ suspense,
1471
+ TData,
1472
+ TError,
1473
+ queryKeyTypeName,
1474
+ observerOptionsName,
1475
+ resultTypeName: `${prefix}${infinite ? "Infinite" : ""}QueryResult`
1312
1476
  });
1313
- const hookName = suspense ? "useSuspenseInfiniteQuery" : "useInfiniteQuery";
1314
- const observerOptionsName = suspense ? "UseSuspenseInfiniteQueryOptions" : "InfiniteQueryObserverOptions";
1315
- const returnType = `${suspense ? "UseSuspenseInfiniteQueryResult" : "UseInfiniteQueryResult"}<TData, TError> & { queryKey: TQueryKey }`;
1316
- const generics = [
1317
- `TQueryFnData = ${responseType}`,
1318
- `TError = ${errorType}`,
1319
- "TData = InfiniteData<TQueryFnData>",
1320
- `TQueryKey extends QueryKey = ${queryKeyTypeName}`,
1321
- `TPageParam = ${pageParamType}`
1322
- ];
1477
+ const castType = infinite ? observerOptionsType : observerOptionsName;
1323
1478
  const resolvedParams = buildResolvedRequestParams(node);
1324
1479
  const queryKeyArgs = resolvedParams && hasQueryKeyParams(node) ? "resolvedParams" : "";
1325
1480
  const queryOptionsArgs = resolvedParams ? "resolvedParams, config" : "config";
1326
- const paramsNode = buildInfiniteQueryParamsNode(node, {
1481
+ const paramsNode = buildHookParams(node, {
1327
1482
  resolver: tsResolver,
1328
- pageParamGeneric: "TPageParam",
1329
- observerOptionsName
1483
+ memberTypeWrapper: maybeValueOrGetter,
1484
+ optionsType: `{
1485
+ query?: Partial<${observerOptionsType}> & { client?: QueryClient },
1486
+ client?: ${buildClientOptionType()}
1487
+ }`
1330
1488
  });
1331
- const paramsSignature = declarationPrinter$4.print(paramsNode) ?? "";
1489
+ const paramsSignature = declarationPrinter$3.print(paramsNode) ?? "";
1332
1490
  return /* @__PURE__ */ jsx(File.Source, {
1333
1491
  name,
1334
1492
  isExportable: true,
@@ -1349,7 +1507,7 @@ function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName,
1349
1507
  ...${queryOptionsName}(${queryOptionsArgs}),${customOptions ? "\n ...customOptions," : ""}
1350
1508
  ...resolvedOptions,
1351
1509
  queryKey,
1352
- } as unknown as ${observerOptionsName}<TQueryFnData, TError, TData, TQueryKey, TPageParam>, queryClient) as ${returnType}
1510
+ } as unknown as ${castType}, queryClient) as ${returnType}
1353
1511
 
1354
1512
  queryResult.queryKey = queryKey as TQueryKey
1355
1513
 
@@ -1359,9 +1517,216 @@ function InfiniteQuery({ name, queryKeyTypeName, queryOptionsName, queryKeyName,
1359
1517
  });
1360
1518
  }
1361
1519
  //#endregion
1362
- //#region src/components/MutationOptions.tsx
1363
- const declarationPrinter$3 = functionPrinter({ mode: "declaration" });
1520
+ //#region src/components/QueryOptions.tsx
1521
+ const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
1364
1522
  const callPrinter$2 = functionPrinter({ mode: "call" });
1523
+ function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, returnType = "full" }) {
1524
+ const { TData, TError } = buildResponseTypes(node, tsResolver);
1525
+ const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
1526
+ const queryKeyParamsCall = callPrinter$2.print(queryKeyParamsNode) ?? "";
1527
+ const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
1528
+ const paramsSignature = declarationPrinter$2.print(paramsNode) ?? "";
1529
+ const queryFnBody = buildCallResultBody(buildClientCall(node, {
1530
+ clientName,
1531
+ signal: true
1532
+ }), { returnType });
1533
+ return /* @__PURE__ */ jsx(File.Source, {
1534
+ name,
1535
+ isExportable: true,
1536
+ isIndexable: true,
1537
+ children: /* @__PURE__ */ jsx(Function, {
1538
+ name,
1539
+ export: true,
1540
+ params: paramsSignature,
1541
+ children: `
1542
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
1543
+ return queryOptions<${TData}, ${TError}, ${TData}, typeof queryKey>({
1544
+ queryKey,
1545
+ queryFn: async ({ signal }) => {
1546
+ ${queryFnBody}
1547
+ },
1548
+ })
1549
+ `
1550
+ })
1551
+ });
1552
+ }
1553
+ //#endregion
1554
+ //#region src/generators/createQueryGenerator.tsx
1555
+ const OBSERVER_IMPORTS = {
1556
+ query: ["QueryObserverOptions", "UseQueryResult"],
1557
+ suspenseQuery: ["UseSuspenseQueryOptions", "UseSuspenseQueryResult"],
1558
+ infiniteQuery: ["InfiniteQueryObserverOptions", "UseInfiniteQueryResult"],
1559
+ suspenseInfiniteQuery: ["UseSuspenseInfiniteQueryOptions", "UseSuspenseInfiniteQueryResult"]
1560
+ };
1561
+ /**
1562
+ * Builds the generator for one `useQuery` flavor. `variant` picks the resolver namespace
1563
+ * (`resolver.query`, `resolver.suspenseQuery`, ...), the TanStack hook, and the options it needs.
1564
+ */
1565
+ function createQueryGenerator({ name, variant }) {
1566
+ const suspense = variant === "suspenseQuery" || variant === "suspenseInfiniteQuery";
1567
+ const infinite = variant === "infiniteQuery" || variant === "suspenseInfiniteQuery";
1568
+ const hookImport = `use${suspense ? "Suspense" : ""}${infinite ? "InfiniteQuery" : "Query"}`;
1569
+ const observerImports = OBSERVER_IMPORTS[variant];
1570
+ return defineGenerator({
1571
+ name,
1572
+ renderer: jsxRenderer,
1573
+ match(node, ctx) {
1574
+ const operationNode = node;
1575
+ if (!ast.isHttpOperationNode(operationNode)) return false;
1576
+ const { query, mutation, infinite: infiniteConfig, suspense: suspenseConfig, hooks } = ctx.options;
1577
+ const { isQuery, isMutation } = classifyOperation(operationNode, {
1578
+ query,
1579
+ mutation
1580
+ });
1581
+ if (!isQuery || isMutation) return false;
1582
+ if (suspense && !suspenseConfig) return false;
1583
+ if (variant === "query") return true;
1584
+ if (!hooks) return false;
1585
+ if (!infinite) return true;
1586
+ const infiniteOptions = infiniteConfig && typeof infiniteConfig === "object" ? infiniteConfig : null;
1587
+ return !!infiniteOptions && matchesInfinite(operationNode, infiniteOptions);
1588
+ },
1589
+ operation(node, ctx) {
1590
+ if (!ast.isHttpOperationNode(node)) return null;
1591
+ const { driver, resolver, root } = ctx;
1592
+ const { output, query, infinite: infiniteConfig, client, group, customOptions, hooks } = ctx.options;
1593
+ const infiniteOptions = infinite && infiniteConfig && typeof infiniteConfig === "object" ? infiniteConfig : null;
1594
+ if (infinite && !infiniteOptions) return null;
1595
+ if (variant === "infiniteQuery" && infiniteOptions) {
1596
+ const pageParamsWarning = getDefaultPageParamsWarning(node, infiniteOptions);
1597
+ if (pageParamsWarning) ctx.warn(pageParamsWarning);
1598
+ }
1599
+ const contractOp = resolveClientOperation({
1600
+ clientPlugin: { pluginName: client.pluginName },
1601
+ driver,
1602
+ node,
1603
+ root,
1604
+ output,
1605
+ cache: ctx.cache
1606
+ });
1607
+ if (!contractOp) return null;
1608
+ const importPath = query ? query.importPath : "@tanstack/react-query";
1609
+ const variantResolver = resolver[variant];
1610
+ const queryName = variantResolver.name(node);
1611
+ const queryOptionsName = variantResolver.optionsName(node);
1612
+ const queryKeyName = variantResolver.keyName(node);
1613
+ const queryKeyTypeName = variantResolver.keyTypeName(node);
1614
+ const tsResolver = driver.getResolver(pluginTsName);
1615
+ const hook = resolveHookFile(node, ctx, {
1616
+ name: queryName,
1617
+ output,
1618
+ group,
1619
+ contractOp,
1620
+ keyTypeName: queryKeyTypeName,
1621
+ extraTypeNames: infiniteOptions ? [resolvePageParamType(node, {
1622
+ resolver: tsResolver,
1623
+ initialPageParam: infiniteOptions.initialPageParam,
1624
+ queryParam: infiniteOptions.queryParam
1625
+ }).queryParamsTypeName] : []
1626
+ });
1627
+ return /* @__PURE__ */ jsxs(HookFile, {
1628
+ hook,
1629
+ imports: customOptions && /* @__PURE__ */ jsx(File.Import, {
1630
+ name: [customOptions.name],
1631
+ path: customOptions.importPath
1632
+ }),
1633
+ children: [
1634
+ /* @__PURE__ */ jsx(QueryKey, {
1635
+ name: queryKeyName,
1636
+ typeName: queryKeyTypeName,
1637
+ node,
1638
+ tsResolver: hook.tsResolver,
1639
+ transformer: ctx.options.queryKey,
1640
+ variant
1641
+ }),
1642
+ infiniteOptions ? /* @__PURE__ */ jsxs(Fragment, { children: [
1643
+ /* @__PURE__ */ jsx(File.Import, {
1644
+ name: ["InfiniteData"],
1645
+ isTypeOnly: true,
1646
+ path: importPath
1647
+ }),
1648
+ /* @__PURE__ */ jsx(File.Import, {
1649
+ name: ["infiniteQueryOptions"],
1650
+ path: importPath
1651
+ }),
1652
+ /* @__PURE__ */ jsx(InfiniteQueryOptions, {
1653
+ name: queryOptionsName,
1654
+ clientName: contractOp.name,
1655
+ queryKeyName,
1656
+ node,
1657
+ tsResolver: hook.tsResolver,
1658
+ cursorParam: infiniteOptions.cursorParam,
1659
+ nextParam: infiniteOptions.nextParam,
1660
+ previousParam: infiniteOptions.previousParam,
1661
+ getNextPageParam: infiniteOptions.getNextPageParam,
1662
+ getPreviousPageParam: infiniteOptions.getPreviousPageParam,
1663
+ initialPageParam: infiniteOptions.initialPageParam,
1664
+ hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
1665
+ queryParam: infiniteOptions.queryParam,
1666
+ returnType: contractOp.returnType
1667
+ })
1668
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File.Import, {
1669
+ name: ["queryOptions"],
1670
+ path: importPath
1671
+ }), /* @__PURE__ */ jsx(QueryOptions, {
1672
+ name: queryOptionsName,
1673
+ clientName: contractOp.name,
1674
+ queryKeyName,
1675
+ node,
1676
+ tsResolver: hook.tsResolver,
1677
+ returnType: contractOp.returnType
1678
+ })] }),
1679
+ (variant !== "query" || query && hooks) && /* @__PURE__ */ jsxs(Fragment, { children: [
1680
+ /* @__PURE__ */ jsx(File.Import, {
1681
+ name: [hookImport],
1682
+ path: importPath
1683
+ }),
1684
+ /* @__PURE__ */ jsx(File.Import, {
1685
+ name: [
1686
+ "QueryKey",
1687
+ "QueryClient",
1688
+ ...observerImports
1689
+ ],
1690
+ path: importPath,
1691
+ isTypeOnly: true
1692
+ }),
1693
+ /* @__PURE__ */ jsx(Query, {
1694
+ name: queryName,
1695
+ queryOptionsName,
1696
+ queryKeyName,
1697
+ queryKeyTypeName,
1698
+ node,
1699
+ tsResolver: hook.tsResolver,
1700
+ customOptions,
1701
+ suspense,
1702
+ infinite: infiniteOptions ? {
1703
+ initialPageParam: infiniteOptions.initialPageParam,
1704
+ queryParam: infiniteOptions.queryParam
1705
+ } : void 0
1706
+ })
1707
+ ] })
1708
+ ]
1709
+ });
1710
+ }
1711
+ });
1712
+ }
1713
+ //#endregion
1714
+ //#region src/generators/infiniteQueryGenerator.tsx
1715
+ /**
1716
+ * Built-in generator for `useInfiniteQuery` hooks. Enabled when
1717
+ * `pluginReactQuery({ infinite: { ... }, hooks: true })`. Emits one
1718
+ * `useFooInfiniteQuery` hook per query operation, wiring the configured
1719
+ * `nextParam` / `previousParam` paths into TanStack Query's cursor-based
1720
+ * pagination.
1721
+ */
1722
+ const infiniteQueryGenerator = createQueryGenerator({
1723
+ name: "react-infinite-query",
1724
+ variant: "infiniteQuery"
1725
+ });
1726
+ //#endregion
1727
+ //#region src/components/MutationOptions.tsx
1728
+ const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
1729
+ const callPrinter$1 = functionPrinter({ mode: "call" });
1365
1730
  function buildMutationConfigParamsNode(node) {
1366
1731
  return createFunctionParameters({ params: [createFunctionParameter({
1367
1732
  name: "config",
@@ -1372,12 +1737,12 @@ function buildMutationConfigParamsNode(node) {
1372
1737
  function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName, returnType = "full" }) {
1373
1738
  const { TData, TError } = buildResponseTypes(node, tsResolver);
1374
1739
  const configParamsNode = buildMutationConfigParamsNode(node);
1375
- const paramsSignature = declarationPrinter$3.print(configParamsNode) ?? "";
1740
+ const paramsSignature = declarationPrinter$1.print(configParamsNode) ?? "";
1376
1741
  const groupedParam = buildGroupedRequestParam(node, { resolver: tsResolver });
1377
1742
  const hasMutationParams = groupedParam !== null;
1378
1743
  const groupedParamsNode = createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
1379
1744
  const TRequest = hasMutationParams ? tsResolver.response.options(node) : "undefined";
1380
- const argBindingStr = hasMutationParams ? callPrinter$2.print(groupedParamsNode) ?? "" : "_";
1745
+ const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "_";
1381
1746
  const mutationFnBody = buildCallResultBody(buildClientCall(node, {
1382
1747
  clientName,
1383
1748
  signal: false
@@ -1405,28 +1770,24 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
1405
1770
  }
1406
1771
  //#endregion
1407
1772
  //#region src/components/Mutation.tsx
1408
- const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
1409
- const callPrinter$1 = functionPrinter({ mode: "call" });
1410
- function resolveMutationRequestType(node, resolver) {
1411
- return buildGroupedRequestParam(node, { resolver }) ? resolver.response.options(node) : "undefined";
1412
- }
1773
+ const declarationPrinter = functionPrinter({ mode: "declaration" });
1774
+ const callPrinter = functionPrinter({ mode: "call" });
1413
1775
  function buildMutationParamsNode(node, options) {
1414
1776
  const { resolver } = options;
1415
1777
  const { TData, TError } = buildResponseTypes(node, resolver);
1416
- const generics = [
1417
- TData,
1418
- TError,
1419
- resolveMutationRequestType(node, resolver),
1420
- "TContext"
1421
- ].join(", ");
1422
- return createFunctionParameters({ params: [createFunctionParameter({
1423
- name: "options",
1424
- type: `{
1425
- mutation?: UseMutationOptions<${generics}> & { client?: QueryClient },
1778
+ return buildHookParams(node, {
1779
+ resolver,
1780
+ withRequest: false,
1781
+ optionsType: `{
1782
+ mutation?: UseMutationOptions<${[
1783
+ TData,
1784
+ TError,
1785
+ resolveMutationRequestType(node, resolver),
1786
+ "TContext"
1787
+ ].join(", ")}> & { client?: QueryClient },
1426
1788
  client?: ${buildRequestConfigType(node)},
1427
- }`,
1428
- default: "{}"
1429
- })] });
1789
+ }`
1790
+ });
1430
1791
  }
1431
1792
  function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName, customOptions }) {
1432
1793
  const { TData, TError } = buildResponseTypes(node, tsResolver);
@@ -1438,9 +1799,9 @@ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName
1438
1799
  ].join(", ");
1439
1800
  const returnType = `UseMutationResult<${generics}>`;
1440
1801
  const mutationOptionsConfigNode = buildMutationConfigParamsNode(node);
1441
- const mutationOptionsParamsCall = callPrinter$1.print(mutationOptionsConfigNode) ?? "";
1802
+ const mutationOptionsParamsCall = callPrinter.print(mutationOptionsConfigNode) ?? "";
1442
1803
  const paramsNode = buildMutationParamsNode(node, { resolver: tsResolver });
1443
- const paramsSignature = declarationPrinter$2.print(paramsNode) ?? "";
1804
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
1444
1805
  return /* @__PURE__ */ jsx(File.Source, {
1445
1806
  name,
1446
1807
  isExportable: true,
@@ -1468,301 +1829,6 @@ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName
1468
1829
  });
1469
1830
  }
1470
1831
  //#endregion
1471
- //#region src/components/Query.tsx
1472
- const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
1473
- function buildQueryParamsNode(node, options) {
1474
- const { resolver, observerOptionsType } = options;
1475
- const optionsParam = createFunctionParameter({
1476
- name: "options",
1477
- type: `{
1478
- query?: Partial<${observerOptionsType}> & { client?: QueryClient },
1479
- client?: ${buildClientOptionType()}
1480
- }`,
1481
- default: "{}"
1482
- });
1483
- const groupedParam = buildGroupedRequestParam(node, {
1484
- resolver,
1485
- memberTypeWrapper: maybeValueOrGetter
1486
- });
1487
- return createFunctionParameters({ params: [groupedParam, optionsParam].filter((param) => param !== null) });
1488
- }
1489
- function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense }) {
1490
- const { TData, TError } = buildResponseTypes(node, tsResolver);
1491
- const hookName = suspense ? "useSuspenseQuery" : "useQuery";
1492
- const observerOptionsName = suspense ? "UseSuspenseQueryOptions" : "QueryObserverOptions";
1493
- const observerOptionsType = suspense ? `${observerOptionsName}<${[
1494
- TData,
1495
- TError,
1496
- "TData",
1497
- "TQueryKey"
1498
- ].join(", ")}>` : `${observerOptionsName}<${[
1499
- TData,
1500
- TError,
1501
- "TData",
1502
- "TQueryData",
1503
- "TQueryKey"
1504
- ].join(", ")}>`;
1505
- const returnType = `${suspense ? "UseSuspenseQueryResult" : "UseQueryResult"}<TData, ${TError}> & { queryKey: TQueryKey }`;
1506
- const generics = suspense ? [`TData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`] : [
1507
- `TData = ${TData}`,
1508
- `TQueryData = ${TData}`,
1509
- `TQueryKey extends QueryKey = ${queryKeyTypeName}`
1510
- ];
1511
- const resolvedParams = buildResolvedRequestParams(node);
1512
- const queryKeyArgs = resolvedParams && hasQueryKeyParams(node) ? "resolvedParams" : "";
1513
- const queryOptionsArgs = resolvedParams ? "resolvedParams, config" : "config";
1514
- const paramsNode = buildQueryParamsNode(node, {
1515
- resolver: tsResolver,
1516
- observerOptionsType
1517
- });
1518
- const paramsSignature = declarationPrinter$1.print(paramsNode) ?? "";
1519
- return /* @__PURE__ */ jsx(File.Source, {
1520
- name,
1521
- isExportable: true,
1522
- isIndexable: true,
1523
- children: /* @__PURE__ */ jsx(Function, {
1524
- name,
1525
- export: true,
1526
- generics: generics.join(", "),
1527
- params: paramsSignature,
1528
- returnType: void 0,
1529
- JSDoc: { comments: buildOperationComments(node) },
1530
- children: `
1531
- const { query: queryConfig = {}, client: config = {} } = options ?? {}
1532
- const { client: queryClient, ...resolvedOptions } = queryConfig${resolvedParams ? `\n const resolvedParams = ${resolvedParams}` : ""}
1533
- const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyArgs})${customOptions ? `\n const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ""}
1534
-
1535
- const queryResult = ${hookName}({
1536
- ...${queryOptionsName}(${queryOptionsArgs}),${customOptions ? "\n ...customOptions," : ""}
1537
- ...resolvedOptions,
1538
- queryKey,
1539
- } as unknown as ${observerOptionsName}, queryClient) as ${returnType}
1540
-
1541
- queryResult.queryKey = queryKey as TQueryKey
1542
-
1543
- return queryResult
1544
- `
1545
- })
1546
- });
1547
- }
1548
- //#endregion
1549
- //#region src/components/QueryOptions.tsx
1550
- const declarationPrinter = functionPrinter({ mode: "declaration" });
1551
- const callPrinter = functionPrinter({ mode: "call" });
1552
- function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, returnType = "full" }) {
1553
- const { TData, TError } = buildResponseTypes(node, tsResolver);
1554
- const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
1555
- const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? "";
1556
- const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
1557
- const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
1558
- const queryFnBody = buildCallResultBody(buildClientCall(node, {
1559
- clientName,
1560
- signal: true
1561
- }), { returnType });
1562
- return /* @__PURE__ */ jsx(File.Source, {
1563
- name,
1564
- isExportable: true,
1565
- isIndexable: true,
1566
- children: /* @__PURE__ */ jsx(Function, {
1567
- name,
1568
- export: true,
1569
- params: paramsSignature,
1570
- children: `
1571
- const queryKey = ${queryKeyName}(${queryKeyParamsCall})
1572
- return queryOptions<${TData}, ${TError}, ${TData}, typeof queryKey>({
1573
- queryKey,
1574
- queryFn: async ({ signal }) => {
1575
- ${queryFnBody}
1576
- },
1577
- })
1578
- `
1579
- })
1580
- });
1581
- }
1582
- //#endregion
1583
- //#region src/generators/infiniteQueryGenerator.tsx
1584
- /**
1585
- * Built-in generator for `useInfiniteQuery` hooks. Enabled when
1586
- * `pluginReactQuery({ infinite: { ... }, hooks: true })`. Emits one
1587
- * `useFooInfiniteQuery` hook per query operation, wiring the configured
1588
- * `nextParam` / `previousParam` paths into TanStack Query's cursor-based
1589
- * pagination.
1590
- */
1591
- const infiniteQueryGenerator = defineGenerator({
1592
- name: "react-infinite-query",
1593
- renderer: jsxRenderer,
1594
- match(node, ctx) {
1595
- const operationNode = node;
1596
- if (!ast.isHttpOperationNode(operationNode)) return false;
1597
- const { query, mutation, infinite, hooks } = ctx.options;
1598
- const { isQuery, isMutation } = classifyOperation(operationNode, {
1599
- query,
1600
- mutation
1601
- });
1602
- const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1603
- if (!isQuery || isMutation || !infiniteOptions || !hooks) return false;
1604
- return matchesInfinite(operationNode, infiniteOptions);
1605
- },
1606
- operation(node, ctx) {
1607
- if (!ast.isHttpOperationNode(node)) return null;
1608
- const { config, driver, resolver, root } = ctx;
1609
- const { output, query, infinite, client, group, customOptions } = ctx.options;
1610
- const pluginTs = ctx.requirePlugin(pluginTsName);
1611
- const tsResolver = driver.getResolver(pluginTsName);
1612
- const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1613
- if (!infiniteOptions) return null;
1614
- const pageParamsWarning = getDefaultPageParamsWarning(node, infiniteOptions);
1615
- if (pageParamsWarning) ctx.warn(pageParamsWarning);
1616
- const importPath = query ? query.importPath : "@tanstack/react-query";
1617
- const contractOp = resolveClientOperation({
1618
- clientPlugin: { pluginName: client.pluginName },
1619
- driver,
1620
- node,
1621
- root,
1622
- output,
1623
- cache: ctx.cache
1624
- });
1625
- if (!contractOp) return null;
1626
- const queryName = resolver.infiniteQuery.name(node);
1627
- const queryOptionsName = resolver.infiniteQuery.optionsName(node);
1628
- const queryKeyName = resolver.infiniteQuery.keyName(node);
1629
- const queryKeyTypeName = resolver.infiniteQuery.keyTypeName(node);
1630
- const meta = {
1631
- file: resolver.file({
1632
- ...operationFileEntry(node, queryName),
1633
- root,
1634
- output,
1635
- group: group ?? void 0
1636
- }),
1637
- fileTs: resolveDependencyOperationFile({
1638
- cache: ctx.cache,
1639
- node,
1640
- resolver: tsResolver,
1641
- root,
1642
- output: pluginTs.options?.output ?? output,
1643
- group: pluginTs.options?.group
1644
- })
1645
- };
1646
- const { queryParamsTypeName } = resolvePageParamType(node, {
1647
- resolver: tsResolver,
1648
- initialPageParam: infiniteOptions.initialPageParam,
1649
- queryParam: infiniteOptions.queryParam
1650
- });
1651
- const importedTypeNames = [
1652
- tsResolver.response.options(node),
1653
- queryParamsTypeName,
1654
- ...resolveOperationTypeNames(node, tsResolver, {
1655
- exclude: [queryKeyTypeName],
1656
- order: "body-response-first",
1657
- includeParams: false
1658
- })
1659
- ].filter((name) => Boolean(name));
1660
- const calledClientName = contractOp.name;
1661
- return /* @__PURE__ */ jsxs(File, {
1662
- baseName: meta.file.baseName,
1663
- path: meta.file.path,
1664
- meta: meta.file.meta,
1665
- banner: resolver.default.banner(ctx.meta, {
1666
- output,
1667
- config,
1668
- file: {
1669
- path: meta.file.path,
1670
- baseName: meta.file.baseName
1671
- }
1672
- }),
1673
- footer: resolver.default.footer(ctx.meta, {
1674
- output,
1675
- config,
1676
- file: {
1677
- path: meta.file.path,
1678
- baseName: meta.file.baseName
1679
- }
1680
- }),
1681
- children: [
1682
- /* @__PURE__ */ jsx(File.Import, {
1683
- name: [contractOp.name],
1684
- root: meta.file.path,
1685
- path: contractOp.path
1686
- }),
1687
- /* @__PURE__ */ jsx(File.Import, {
1688
- name: ["RequestConfig", "ResponseErrorConfig"],
1689
- root: contractOp.clientPathIsFile ? meta.file.path : void 0,
1690
- path: contractOp.clientPath,
1691
- isTypeOnly: true
1692
- }),
1693
- customOptions && /* @__PURE__ */ jsx(File.Import, {
1694
- name: [customOptions.name],
1695
- path: customOptions.importPath
1696
- }),
1697
- meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1698
- name: Array.from(new Set(importedTypeNames)),
1699
- root: meta.file.path,
1700
- path: meta.fileTs.path,
1701
- isTypeOnly: true
1702
- }),
1703
- /* @__PURE__ */ jsx(QueryKey, {
1704
- name: queryKeyName,
1705
- typeName: queryKeyTypeName,
1706
- node,
1707
- tsResolver,
1708
- transformer: ctx.options.queryKey,
1709
- variant: "infiniteQuery"
1710
- }),
1711
- /* @__PURE__ */ jsx(File.Import, {
1712
- name: ["InfiniteData"],
1713
- isTypeOnly: true,
1714
- path: importPath
1715
- }),
1716
- /* @__PURE__ */ jsx(File.Import, {
1717
- name: ["infiniteQueryOptions"],
1718
- path: importPath
1719
- }),
1720
- /* @__PURE__ */ jsx(InfiniteQueryOptions, {
1721
- name: queryOptionsName,
1722
- clientName: calledClientName,
1723
- queryKeyName,
1724
- node,
1725
- tsResolver,
1726
- cursorParam: infiniteOptions.cursorParam,
1727
- nextParam: infiniteOptions.nextParam,
1728
- previousParam: infiniteOptions.previousParam,
1729
- getNextPageParam: infiniteOptions.getNextPageParam,
1730
- getPreviousPageParam: infiniteOptions.getPreviousPageParam,
1731
- initialPageParam: infiniteOptions.initialPageParam,
1732
- hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
1733
- queryParam: infiniteOptions.queryParam,
1734
- returnType: contractOp.returnType
1735
- }),
1736
- /* @__PURE__ */ jsx(File.Import, {
1737
- name: ["useInfiniteQuery"],
1738
- path: importPath
1739
- }),
1740
- /* @__PURE__ */ jsx(File.Import, {
1741
- name: [
1742
- "QueryKey",
1743
- "QueryClient",
1744
- "InfiniteQueryObserverOptions",
1745
- "UseInfiniteQueryResult"
1746
- ],
1747
- path: importPath,
1748
- isTypeOnly: true
1749
- }),
1750
- /* @__PURE__ */ jsx(InfiniteQuery, {
1751
- name: queryName,
1752
- queryOptionsName,
1753
- queryKeyName,
1754
- queryKeyTypeName,
1755
- node,
1756
- tsResolver,
1757
- initialPageParam: infiniteOptions.initialPageParam,
1758
- queryParam: infiniteOptions.queryParam,
1759
- customOptions
1760
- })
1761
- ]
1762
- });
1763
- }
1764
- });
1765
- //#endregion
1766
1832
  //#region src/generators/mutationGenerator.tsx
1767
1833
  /**
1768
1834
  * Built-in generator for `useMutation` hooks. Emits one `useFooMutation` hook
@@ -1783,10 +1849,8 @@ const mutationGenerator = defineGenerator({
1783
1849
  },
1784
1850
  operation(node, ctx) {
1785
1851
  if (!ast.isHttpOperationNode(node)) return null;
1786
- const { config, driver, resolver, root } = ctx;
1852
+ const { driver, resolver, root } = ctx;
1787
1853
  const { output, mutation, client, group, customOptions, hooks } = ctx.options;
1788
- const pluginTs = ctx.requirePlugin(pluginTsName);
1789
- const tsResolver = driver.getResolver(pluginTsName);
1790
1854
  const importPath = mutation ? mutation.importPath : "@tanstack/react-query";
1791
1855
  const contractOp = resolveClientOperation({
1792
1856
  clientPlugin: { pluginName: client.pluginName },
@@ -1798,72 +1862,22 @@ const mutationGenerator = defineGenerator({
1798
1862
  });
1799
1863
  if (!contractOp) return null;
1800
1864
  const mutationHookName = resolver.mutation.name(node);
1801
- const mutationTypeName = resolver.mutation.typeName(node);
1802
1865
  const mutationOptionsName = resolver.mutation.optionsName(node);
1803
1866
  const mutationKeyName = resolver.mutation.keyName(node);
1804
- const meta = {
1805
- file: resolver.file({
1806
- ...operationFileEntry(node, mutationHookName),
1807
- root,
1808
- output,
1809
- group: group ?? void 0
1810
- }),
1811
- fileTs: resolveDependencyOperationFile({
1812
- cache: ctx.cache,
1813
- node,
1814
- resolver: tsResolver,
1815
- root,
1816
- output: pluginTs.options?.output ?? output,
1817
- group: pluginTs.options?.group
1818
- })
1819
- };
1820
- const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1821
- order: "body-response-first",
1822
- includeParams: false
1823
- })].filter((name) => Boolean(name));
1824
- const calledClientName = contractOp.name;
1825
- return /* @__PURE__ */ jsxs(File, {
1826
- baseName: meta.file.baseName,
1827
- path: meta.file.path,
1828
- meta: meta.file.meta,
1829
- banner: resolver.default.banner(ctx.meta, {
1830
- output,
1831
- config,
1832
- file: {
1833
- path: meta.file.path,
1834
- baseName: meta.file.baseName
1835
- }
1836
- }),
1837
- footer: resolver.default.footer(ctx.meta, {
1838
- output,
1839
- config,
1840
- file: {
1841
- path: meta.file.path,
1842
- baseName: meta.file.baseName
1843
- }
1867
+ const hook = resolveHookFile(node, ctx, {
1868
+ name: mutationHookName,
1869
+ output,
1870
+ group,
1871
+ contractOp
1872
+ });
1873
+ const { tsResolver } = hook;
1874
+ return /* @__PURE__ */ jsxs(HookFile, {
1875
+ hook,
1876
+ imports: customOptions && /* @__PURE__ */ jsx(File.Import, {
1877
+ name: [customOptions.name],
1878
+ path: customOptions.importPath
1844
1879
  }),
1845
1880
  children: [
1846
- /* @__PURE__ */ jsx(File.Import, {
1847
- name: [contractOp.name],
1848
- root: meta.file.path,
1849
- path: contractOp.path
1850
- }),
1851
- /* @__PURE__ */ jsx(File.Import, {
1852
- name: ["RequestConfig", "ResponseErrorConfig"],
1853
- root: contractOp.clientPathIsFile ? meta.file.path : void 0,
1854
- path: contractOp.clientPath,
1855
- isTypeOnly: true
1856
- }),
1857
- customOptions && /* @__PURE__ */ jsx(File.Import, {
1858
- name: [customOptions.name],
1859
- path: customOptions.importPath
1860
- }),
1861
- meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1862
- name: Array.from(new Set(importedTypeNames)),
1863
- root: meta.file.path,
1864
- path: meta.fileTs.path,
1865
- isTypeOnly: true
1866
- }),
1867
1881
  /* @__PURE__ */ jsx(MutationKey, {
1868
1882
  name: mutationKeyName,
1869
1883
  node,
@@ -1875,7 +1889,7 @@ const mutationGenerator = defineGenerator({
1875
1889
  }),
1876
1890
  /* @__PURE__ */ jsx(MutationOptions, {
1877
1891
  name: mutationOptionsName,
1878
- clientName: calledClientName,
1892
+ clientName: contractOp.name,
1879
1893
  mutationKeyName,
1880
1894
  node,
1881
1895
  tsResolver,
@@ -1897,7 +1911,6 @@ const mutationGenerator = defineGenerator({
1897
1911
  }),
1898
1912
  /* @__PURE__ */ jsx(Mutation, {
1899
1913
  name: mutationHookName,
1900
- typeName: mutationTypeName,
1901
1914
  mutationOptionsName,
1902
1915
  mutationKeyName,
1903
1916
  node,
@@ -1916,151 +1929,9 @@ const mutationGenerator = defineGenerator({
1916
1929
  * GET and QUERY operation (configurable via `query.methods`) plus the matching
1917
1930
  * `fooQueryKey` / `fooQueryOptions` helpers.
1918
1931
  */
1919
- const queryGenerator = defineGenerator({
1932
+ const queryGenerator = createQueryGenerator({
1920
1933
  name: "react-query",
1921
- renderer: jsxRenderer,
1922
- match(node, ctx) {
1923
- const operationNode = node;
1924
- if (!ast.isHttpOperationNode(operationNode)) return false;
1925
- const { query, mutation } = ctx.options;
1926
- const { isQuery, isMutation } = classifyOperation(operationNode, {
1927
- query,
1928
- mutation
1929
- });
1930
- return isQuery && !isMutation;
1931
- },
1932
- operation(node, ctx) {
1933
- if (!ast.isHttpOperationNode(node)) return null;
1934
- const { config, driver, resolver, root } = ctx;
1935
- const { output, query, client, group, customOptions, hooks } = ctx.options;
1936
- const pluginTs = ctx.requirePlugin(pluginTsName);
1937
- const tsResolver = driver.getResolver(pluginTsName);
1938
- const importPath = query ? query.importPath : "@tanstack/react-query";
1939
- const contractOp = resolveClientOperation({
1940
- clientPlugin: { pluginName: client.pluginName },
1941
- driver,
1942
- node,
1943
- root,
1944
- output,
1945
- cache: ctx.cache
1946
- });
1947
- if (!contractOp) return null;
1948
- const queryName = resolver.query.name(node);
1949
- const queryOptionsName = resolver.query.optionsName(node);
1950
- const queryKeyName = resolver.query.keyName(node);
1951
- const queryKeyTypeName = resolver.query.keyTypeName(node);
1952
- const meta = {
1953
- file: resolver.file({
1954
- ...operationFileEntry(node, queryName),
1955
- root,
1956
- output,
1957
- group: group ?? void 0
1958
- }),
1959
- fileTs: resolveDependencyOperationFile({
1960
- cache: ctx.cache,
1961
- node,
1962
- resolver: tsResolver,
1963
- root,
1964
- output: pluginTs.options?.output ?? output,
1965
- group: pluginTs.options?.group
1966
- })
1967
- };
1968
- const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
1969
- exclude: [queryKeyTypeName],
1970
- order: "body-response-first",
1971
- includeParams: false
1972
- })].filter((name) => Boolean(name));
1973
- const calledClientName = contractOp.name;
1974
- return /* @__PURE__ */ jsxs(File, {
1975
- baseName: meta.file.baseName,
1976
- path: meta.file.path,
1977
- meta: meta.file.meta,
1978
- banner: resolver.default.banner(ctx.meta, {
1979
- output,
1980
- config,
1981
- file: {
1982
- path: meta.file.path,
1983
- baseName: meta.file.baseName
1984
- }
1985
- }),
1986
- footer: resolver.default.footer(ctx.meta, {
1987
- output,
1988
- config,
1989
- file: {
1990
- path: meta.file.path,
1991
- baseName: meta.file.baseName
1992
- }
1993
- }),
1994
- children: [
1995
- /* @__PURE__ */ jsx(File.Import, {
1996
- name: [contractOp.name],
1997
- root: meta.file.path,
1998
- path: contractOp.path
1999
- }),
2000
- /* @__PURE__ */ jsx(File.Import, {
2001
- name: ["RequestConfig", "ResponseErrorConfig"],
2002
- root: contractOp.clientPathIsFile ? meta.file.path : void 0,
2003
- path: contractOp.clientPath,
2004
- isTypeOnly: true
2005
- }),
2006
- customOptions && /* @__PURE__ */ jsx(File.Import, {
2007
- name: [customOptions.name],
2008
- path: customOptions.importPath
2009
- }),
2010
- meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
2011
- name: Array.from(new Set(importedTypeNames)),
2012
- root: meta.file.path,
2013
- path: meta.fileTs.path,
2014
- isTypeOnly: true
2015
- }),
2016
- /* @__PURE__ */ jsx(QueryKey, {
2017
- name: queryKeyName,
2018
- typeName: queryKeyTypeName,
2019
- node,
2020
- tsResolver,
2021
- transformer: ctx.options.queryKey,
2022
- variant: "query"
2023
- }),
2024
- /* @__PURE__ */ jsx(File.Import, {
2025
- name: ["queryOptions"],
2026
- path: importPath
2027
- }),
2028
- /* @__PURE__ */ jsx(QueryOptions, {
2029
- name: queryOptionsName,
2030
- clientName: calledClientName,
2031
- queryKeyName,
2032
- node,
2033
- tsResolver,
2034
- returnType: contractOp.returnType
2035
- }),
2036
- query && hooks && /* @__PURE__ */ jsxs(Fragment, { children: [
2037
- /* @__PURE__ */ jsx(File.Import, {
2038
- name: ["useQuery"],
2039
- path: importPath
2040
- }),
2041
- /* @__PURE__ */ jsx(File.Import, {
2042
- name: [
2043
- "QueryKey",
2044
- "QueryClient",
2045
- "QueryObserverOptions",
2046
- "UseQueryResult"
2047
- ],
2048
- path: importPath,
2049
- isTypeOnly: true
2050
- }),
2051
- /* @__PURE__ */ jsx(Query, {
2052
- name: queryName,
2053
- queryOptionsName,
2054
- queryKeyName,
2055
- queryKeyTypeName,
2056
- node,
2057
- tsResolver,
2058
- customOptions
2059
- })
2060
- ] })
2061
- ]
2062
- });
2063
- }
1934
+ variant: "query"
2064
1935
  });
2065
1936
  //#endregion
2066
1937
  //#region src/generators/suspenseInfiniteQueryGenerator.tsx
@@ -2070,178 +1941,9 @@ const queryGenerator = defineGenerator({
2070
1941
  * semantics with cursor-based pagination. Handlers throw promises while
2071
1942
  * loading and pull additional pages on demand.
2072
1943
  */
2073
- const suspenseInfiniteQueryGenerator = defineGenerator({
1944
+ const suspenseInfiniteQueryGenerator = createQueryGenerator({
2074
1945
  name: "react-suspense-infinite-query",
2075
- renderer: jsxRenderer,
2076
- match(node, ctx) {
2077
- const operationNode = node;
2078
- if (!ast.isHttpOperationNode(operationNode)) return false;
2079
- const { query, mutation, infinite, suspense, hooks } = ctx.options;
2080
- const { isQuery, isMutation } = classifyOperation(operationNode, {
2081
- query,
2082
- mutation
2083
- });
2084
- const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
2085
- if (!isQuery || isMutation || !suspense || !infiniteOptions || !hooks) return false;
2086
- return matchesInfinite(operationNode, infiniteOptions);
2087
- },
2088
- operation(node, ctx) {
2089
- if (!ast.isHttpOperationNode(node)) return null;
2090
- const { config, driver, resolver, root } = ctx;
2091
- const { output, query, infinite, client, group, customOptions } = ctx.options;
2092
- const pluginTs = ctx.requirePlugin(pluginTsName);
2093
- const tsResolver = driver.getResolver(pluginTsName);
2094
- const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
2095
- if (!infiniteOptions) return null;
2096
- const importPath = query ? query.importPath : "@tanstack/react-query";
2097
- const contractOp = resolveClientOperation({
2098
- clientPlugin: { pluginName: client.pluginName },
2099
- driver,
2100
- node,
2101
- root,
2102
- output,
2103
- cache: ctx.cache
2104
- });
2105
- if (!contractOp) return null;
2106
- const queryName = resolver.suspenseInfiniteQuery.name(node);
2107
- const queryOptionsName = resolver.suspenseInfiniteQuery.optionsName(node);
2108
- const queryKeyName = resolver.suspenseInfiniteQuery.keyName(node);
2109
- const queryKeyTypeName = resolver.suspenseInfiniteQuery.keyTypeName(node);
2110
- const meta = {
2111
- file: resolver.file({
2112
- ...operationFileEntry(node, queryName),
2113
- root,
2114
- output,
2115
- group: group ?? void 0
2116
- }),
2117
- fileTs: resolveDependencyOperationFile({
2118
- cache: ctx.cache,
2119
- node,
2120
- resolver: tsResolver,
2121
- root,
2122
- output: pluginTs.options?.output ?? output,
2123
- group: pluginTs.options?.group
2124
- })
2125
- };
2126
- const { queryParamsTypeName } = resolvePageParamType(node, {
2127
- resolver: tsResolver,
2128
- initialPageParam: infiniteOptions.initialPageParam,
2129
- queryParam: infiniteOptions.queryParam
2130
- });
2131
- const importedTypeNames = [
2132
- tsResolver.response.options(node),
2133
- queryParamsTypeName,
2134
- ...resolveOperationTypeNames(node, tsResolver, {
2135
- exclude: [queryKeyTypeName],
2136
- order: "body-response-first",
2137
- includeParams: false
2138
- })
2139
- ].filter((name) => Boolean(name));
2140
- const calledClientName = contractOp.name;
2141
- return /* @__PURE__ */ jsxs(File, {
2142
- baseName: meta.file.baseName,
2143
- path: meta.file.path,
2144
- meta: meta.file.meta,
2145
- banner: resolver.default.banner(ctx.meta, {
2146
- output,
2147
- config,
2148
- file: {
2149
- path: meta.file.path,
2150
- baseName: meta.file.baseName
2151
- }
2152
- }),
2153
- footer: resolver.default.footer(ctx.meta, {
2154
- output,
2155
- config,
2156
- file: {
2157
- path: meta.file.path,
2158
- baseName: meta.file.baseName
2159
- }
2160
- }),
2161
- children: [
2162
- /* @__PURE__ */ jsx(File.Import, {
2163
- name: [contractOp.name],
2164
- root: meta.file.path,
2165
- path: contractOp.path
2166
- }),
2167
- /* @__PURE__ */ jsx(File.Import, {
2168
- name: ["RequestConfig", "ResponseErrorConfig"],
2169
- root: contractOp.clientPathIsFile ? meta.file.path : void 0,
2170
- path: contractOp.clientPath,
2171
- isTypeOnly: true
2172
- }),
2173
- customOptions && /* @__PURE__ */ jsx(File.Import, {
2174
- name: [customOptions.name],
2175
- path: customOptions.importPath
2176
- }),
2177
- meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
2178
- name: Array.from(new Set(importedTypeNames)),
2179
- root: meta.file.path,
2180
- path: meta.fileTs.path,
2181
- isTypeOnly: true
2182
- }),
2183
- /* @__PURE__ */ jsx(QueryKey, {
2184
- name: queryKeyName,
2185
- typeName: queryKeyTypeName,
2186
- node,
2187
- tsResolver,
2188
- transformer: ctx.options.queryKey,
2189
- variant: "suspenseInfiniteQuery"
2190
- }),
2191
- /* @__PURE__ */ jsx(File.Import, {
2192
- name: ["InfiniteData"],
2193
- isTypeOnly: true,
2194
- path: importPath
2195
- }),
2196
- /* @__PURE__ */ jsx(File.Import, {
2197
- name: ["infiniteQueryOptions"],
2198
- path: importPath
2199
- }),
2200
- /* @__PURE__ */ jsx(InfiniteQueryOptions, {
2201
- name: queryOptionsName,
2202
- clientName: calledClientName,
2203
- queryKeyName,
2204
- node,
2205
- tsResolver,
2206
- cursorParam: infiniteOptions.cursorParam,
2207
- nextParam: infiniteOptions.nextParam,
2208
- previousParam: infiniteOptions.previousParam,
2209
- getNextPageParam: infiniteOptions.getNextPageParam,
2210
- getPreviousPageParam: infiniteOptions.getPreviousPageParam,
2211
- initialPageParam: infiniteOptions.initialPageParam,
2212
- hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
2213
- queryParam: infiniteOptions.queryParam,
2214
- returnType: contractOp.returnType
2215
- }),
2216
- /* @__PURE__ */ jsx(File.Import, {
2217
- name: ["useSuspenseInfiniteQuery"],
2218
- path: importPath
2219
- }),
2220
- /* @__PURE__ */ jsx(File.Import, {
2221
- name: [
2222
- "QueryKey",
2223
- "QueryClient",
2224
- "UseSuspenseInfiniteQueryOptions",
2225
- "UseSuspenseInfiniteQueryResult"
2226
- ],
2227
- path: importPath,
2228
- isTypeOnly: true
2229
- }),
2230
- /* @__PURE__ */ jsx(InfiniteQuery, {
2231
- name: queryName,
2232
- queryOptionsName,
2233
- queryKeyName,
2234
- queryKeyTypeName,
2235
- node,
2236
- tsResolver,
2237
- initialPageParam: infiniteOptions.initialPageParam,
2238
- queryParam: infiniteOptions.queryParam,
2239
- customOptions,
2240
- suspense: true
2241
- })
2242
- ]
2243
- });
2244
- }
1946
+ variant: "suspenseInfiniteQuery"
2245
1947
  });
2246
1948
  //#endregion
2247
1949
  //#region src/generators/suspenseQueryGenerator.tsx
@@ -2252,150 +1954,9 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
2252
1954
  * promises while loading and require a `<Suspense>` boundary in the React
2253
1955
  * tree. TanStack Query v5+ only.
2254
1956
  */
2255
- const suspenseQueryGenerator = defineGenerator({
1957
+ const suspenseQueryGenerator = createQueryGenerator({
2256
1958
  name: "react-suspense-query",
2257
- renderer: jsxRenderer,
2258
- match(node, ctx) {
2259
- const operationNode = node;
2260
- if (!ast.isHttpOperationNode(operationNode)) return false;
2261
- const { query, mutation, suspense, hooks } = ctx.options;
2262
- const { isQuery, isMutation } = classifyOperation(operationNode, {
2263
- query,
2264
- mutation
2265
- });
2266
- return isQuery && !isMutation && !!suspense && hooks;
2267
- },
2268
- operation(node, ctx) {
2269
- if (!ast.isHttpOperationNode(node)) return null;
2270
- const { config, driver, resolver, root } = ctx;
2271
- const { output, query, client, group, customOptions } = ctx.options;
2272
- const pluginTs = ctx.requirePlugin(pluginTsName);
2273
- const tsResolver = driver.getResolver(pluginTsName);
2274
- const importPath = query ? query.importPath : "@tanstack/react-query";
2275
- const contractOp = resolveClientOperation({
2276
- clientPlugin: { pluginName: client.pluginName },
2277
- driver,
2278
- node,
2279
- root,
2280
- output,
2281
- cache: ctx.cache
2282
- });
2283
- if (!contractOp) return null;
2284
- const queryName = resolver.suspenseQuery.name(node);
2285
- const queryOptionsName = resolver.suspenseQuery.optionsName(node);
2286
- const queryKeyName = resolver.suspenseQuery.keyName(node);
2287
- const queryKeyTypeName = resolver.suspenseQuery.keyTypeName(node);
2288
- const meta = {
2289
- file: resolver.file({
2290
- ...operationFileEntry(node, queryName),
2291
- root,
2292
- output,
2293
- group: group ?? void 0
2294
- }),
2295
- fileTs: resolveDependencyOperationFile({
2296
- cache: ctx.cache,
2297
- node,
2298
- resolver: tsResolver,
2299
- root,
2300
- output: pluginTs.options?.output ?? output,
2301
- group: pluginTs.options?.group
2302
- })
2303
- };
2304
- const importedTypeNames = [tsResolver.response.options(node), ...resolveOperationTypeNames(node, tsResolver, {
2305
- exclude: [queryKeyTypeName],
2306
- order: "body-response-first",
2307
- includeParams: false
2308
- })].filter((name) => Boolean(name));
2309
- const calledClientName = contractOp.name;
2310
- return /* @__PURE__ */ jsxs(File, {
2311
- baseName: meta.file.baseName,
2312
- path: meta.file.path,
2313
- meta: meta.file.meta,
2314
- banner: resolver.default.banner(ctx.meta, {
2315
- output,
2316
- config,
2317
- file: {
2318
- path: meta.file.path,
2319
- baseName: meta.file.baseName
2320
- }
2321
- }),
2322
- footer: resolver.default.footer(ctx.meta, {
2323
- output,
2324
- config,
2325
- file: {
2326
- path: meta.file.path,
2327
- baseName: meta.file.baseName
2328
- }
2329
- }),
2330
- children: [
2331
- /* @__PURE__ */ jsx(File.Import, {
2332
- name: [contractOp.name],
2333
- root: meta.file.path,
2334
- path: contractOp.path
2335
- }),
2336
- /* @__PURE__ */ jsx(File.Import, {
2337
- name: ["RequestConfig", "ResponseErrorConfig"],
2338
- root: contractOp.clientPathIsFile ? meta.file.path : void 0,
2339
- path: contractOp.clientPath,
2340
- isTypeOnly: true
2341
- }),
2342
- customOptions && /* @__PURE__ */ jsx(File.Import, {
2343
- name: [customOptions.name],
2344
- path: customOptions.importPath
2345
- }),
2346
- meta.fileTs && importedTypeNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
2347
- name: Array.from(new Set(importedTypeNames)),
2348
- root: meta.file.path,
2349
- path: meta.fileTs.path,
2350
- isTypeOnly: true
2351
- }),
2352
- /* @__PURE__ */ jsx(QueryKey, {
2353
- name: queryKeyName,
2354
- typeName: queryKeyTypeName,
2355
- node,
2356
- tsResolver,
2357
- transformer: ctx.options.queryKey,
2358
- variant: "suspenseQuery"
2359
- }),
2360
- /* @__PURE__ */ jsx(File.Import, {
2361
- name: ["queryOptions"],
2362
- path: importPath
2363
- }),
2364
- /* @__PURE__ */ jsx(QueryOptions, {
2365
- name: queryOptionsName,
2366
- clientName: calledClientName,
2367
- queryKeyName,
2368
- node,
2369
- tsResolver,
2370
- returnType: contractOp.returnType
2371
- }),
2372
- /* @__PURE__ */ jsx(File.Import, {
2373
- name: ["useSuspenseQuery"],
2374
- path: importPath
2375
- }),
2376
- /* @__PURE__ */ jsx(File.Import, {
2377
- name: [
2378
- "QueryKey",
2379
- "QueryClient",
2380
- "UseSuspenseQueryOptions",
2381
- "UseSuspenseQueryResult"
2382
- ],
2383
- path: importPath,
2384
- isTypeOnly: true
2385
- }),
2386
- /* @__PURE__ */ jsx(Query, {
2387
- name: queryName,
2388
- queryOptionsName,
2389
- queryKeyName,
2390
- queryKeyTypeName,
2391
- node,
2392
- tsResolver,
2393
- customOptions,
2394
- suspense: true
2395
- })
2396
- ]
2397
- });
2398
- }
1959
+ variant: "suspenseQuery"
2399
1960
  });
2400
1961
  //#endregion
2401
1962
  //#region src/resolvers/resolverReactQuery.ts
@@ -2494,6 +2055,7 @@ const pluginReactQuery = defineExtension({
2494
2055
  return {
2495
2056
  output,
2496
2057
  client: resolveContractClient({
2058
+ plugin: pluginReactQueryName,
2497
2059
  client,
2498
2060
  plugins: useConfig().plugins
2499
2061
  }),