@orval/query 8.9.1 → 8.11.0

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.mjs CHANGED
@@ -10,7 +10,10 @@ const normalizeQueryOptions = (queryOptions = {}, outputWorkspace) => {
10
10
  ...queryOptions.useInvalidate ? { useInvalidate: true } : {},
11
11
  ...queryOptions.useSetQueryData ? { useSetQueryData: true } : {},
12
12
  ...queryOptions.useGetQueryData ? { useGetQueryData: true } : {},
13
- ...queryOptions.useQuery ? { useQuery: true } : {},
13
+ ...queryOptions.useQuery === void 0 ? {} : { useQuery: queryOptions.useQuery },
14
+ ...queryOptions.useMutation === void 0 ? {} : { useMutation: queryOptions.useMutation },
15
+ ...queryOptions.useSuspenseQuery ? { useSuspenseQuery: true } : {},
16
+ ...queryOptions.useSuspenseInfiniteQuery ? { useSuspenseInfiniteQuery: true } : {},
14
17
  ...queryOptions.useInfinite ? { useInfinite: true } : {},
15
18
  ...queryOptions.useInfiniteQueryParam ? { useInfiniteQueryParam: queryOptions.useInfiniteQueryParam } : {},
16
19
  ...queryOptions.options ? { options: queryOptions.options } : {},
@@ -701,8 +704,11 @@ const VUE_QUERY_DEPENDENCIES = [{
701
704
  ],
702
705
  dependency: "vue"
703
706
  }];
704
- const getSolidQueryImports = (prefix) => {
707
+ const getSolidQueryImports = (prefix, hasRenamedOptionsTypes) => {
705
708
  const capitalized = prefix === "use" ? "Use" : "Create";
709
+ const queryOptionsTypeName = hasRenamedOptionsTypes ? "QueryOptions" : "SolidQueryOptions";
710
+ const infiniteQueryOptionsTypeName = hasRenamedOptionsTypes ? "InfiniteQueryOptions" : "SolidInfiniteQueryOptions";
711
+ const mutationOptionsTypeName = hasRenamedOptionsTypes ? "MutationOptions" : "SolidMutationOptions";
706
712
  return [{
707
713
  exports: [
708
714
  {
@@ -719,10 +725,9 @@ const getSolidQueryImports = (prefix) => {
719
725
  },
720
726
  { name: `${capitalized}QueryOptions` },
721
727
  { name: `${capitalized}InfiniteQueryOptions` },
722
- { name: `${capitalized}MutationOptions` },
723
- { name: "SolidQueryOptions" },
724
- { name: "SolidInfiniteQueryOptions" },
725
- { name: "SolidMutationOptions" },
728
+ { name: queryOptionsTypeName },
729
+ { name: infiniteQueryOptionsTypeName },
730
+ { name: mutationOptionsTypeName },
726
731
  { name: "QueryFunction" },
727
732
  { name: "MutationFunction" },
728
733
  { name: `${capitalized}QueryResult` },
@@ -803,7 +808,7 @@ const getSolidQueryDependencies = (hasGlobalMutator, hasParamsSerializerOptions,
803
808
  return [
804
809
  ...!hasGlobalMutator && httpClient === OutputHttpClient.AXIOS ? AXIOS_DEPENDENCIES : [],
805
810
  ...hasParamsSerializerOptions ? PARAMS_SERIALIZER_DEPENDENCIES : [],
806
- ...getSolidQueryImports(isSolidQueryWithUsePrefix(packageJson) ? "use" : "create")
811
+ ...getSolidQueryImports(isSolidQueryWithUsePrefix(packageJson) ? "use" : "create", isSolidQueryWithRenamedOptionsTypes(packageJson))
807
812
  ];
808
813
  };
809
814
  const getAngularQueryDependencies = (hasGlobalMutator, hasParamsSerializerOptions, packageJson, httpClient) => {
@@ -861,6 +866,25 @@ const isSolidQueryWithUsePrefix = (packageJson) => {
861
866
  const withoutRc = version.split("-")[0];
862
867
  return compareVersions(withoutRc, "5.71.5");
863
868
  };
869
+ /**
870
+ * Solid Query renamed its plain options interfaces in v5.100.6, dropping the
871
+ * `Solid` prefix:
872
+ * - `SolidQueryOptions` → `QueryOptions`
873
+ * - `SolidInfiniteQueryOptions` → `InfiniteQueryOptions`
874
+ * - `SolidMutationOptions` → `MutationOptions`
875
+ *
876
+ * The Accessor wrappers `UseQueryOptions` / `UseInfiniteQueryOptions` /
877
+ * `UseMutationOptions` keep the same names but reference the renamed
878
+ * interfaces internally.
879
+ *
880
+ * https://github.com/TanStack/query/commit/<rename-commit>
881
+ */
882
+ const isSolidQueryWithRenamedOptionsTypes = (packageJson) => {
883
+ const version = getPackageByQueryClient(packageJson, "solid-query");
884
+ if (!version) return false;
885
+ const withoutRc = version.split("-")[0];
886
+ return compareVersions(withoutRc, "5.100.6");
887
+ };
864
888
  const getPackageByQueryClient = (packageJson, queryClient) => {
865
889
  switch (queryClient) {
866
890
  case "react-query": {
@@ -901,7 +925,7 @@ const generateQueryOptions = ({ params, options, type, adapter }) => {
901
925
  if (options) return `${queryConfig} ...queryOptions`;
902
926
  return "...queryOptions";
903
927
  }
904
- return `${adapter ? adapter.generateEnabledOption(params, options) : !isObject(options) || !Object.hasOwn(options, "enabled") ? `enabled: !!(${params.map(({ name }) => name).join(" && ")}),` : ""}${queryConfig} ...queryOptions`;
928
+ return `${adapter ? adapter.generateEnabledOption(params, options) : !isObject(options) || !Object.hasOwn(options, "enabled") ? `enabled: ${params.map(({ name }) => `${name} != null`).join(" && ")},` : ""}${queryConfig} ...queryOptions`;
905
929
  };
906
930
  const isSuspenseQuery = (type) => {
907
931
  return [QueryType.SUSPENSE_INFINITE, QueryType.SUSPENSE_QUERY].includes(type);
@@ -922,7 +946,7 @@ const getQueryOptionsDefinition = ({ operationName, mutator, definitions, type,
922
946
  const optionType = optionsTypeName ? `${optionsTypeName}<${funcReturnType}, TError, TData${hasQueryV5 && (type === QueryType.INFINITE || type === QueryType.SUSPENSE_INFINITE) && queryParam && queryParams ? `, QueryKey, ${queryParams.schema.name}['${queryParam}']` : ""}>` : `${prefix}${pascal(type)}Options<${funcReturnType}, TError, TData${hasQueryV5 && (type === QueryType.INFINITE || type === QueryType.SUSPENSE_INFINITE) && queryParam && queryParams ? hasQueryV5WithInfiniteQueryOptionsError ? `, QueryKey, ${queryParams.schema.name}['${queryParam}']` : `, ${funcReturnType}, QueryKey, ${queryParams.schema.name}['${queryParam}']` : ""}>`;
923
947
  return `${partialOptions ? "Partial<" : ""}${optionType}${partialOptions ? ">" : ""}${optionTypeInitialDataPostfix}`;
924
948
  }
925
- const mutationOptionsTypeName = isReturnType && adapter?.getOptionsReturnTypeName ? adapter.getOptionsReturnTypeName("mutation") : void 0;
949
+ const mutationOptionsTypeName = adapter?.getOptionsReturnTypeName ? adapter.getOptionsReturnTypeName("mutation") : void 0;
926
950
  return mutationOptionsTypeName ? `${mutationOptionsTypeName}<Awaited<ReturnType<${isMutatorHook ? `ReturnType<typeof use${pascal(operationName)}Hook>` : `typeof ${operationName}`}>>, TError,${definitions ? `{${definitions}}` : "void"}, TContext>` : `${prefix}MutationOptions<Awaited<ReturnType<${isMutatorHook ? `ReturnType<typeof use${pascal(operationName)}Hook>` : `typeof ${operationName}`}>>, TError,${definitions ? `{${definitions}}` : "void"}, TContext>`;
927
951
  };
928
952
  //#endregion
@@ -1107,7 +1131,7 @@ const createReactAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5
1107
1131
  });
1108
1132
  //#endregion
1109
1133
  //#region src/frameworks/solid.ts
1110
- const createSolidAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasQueryV5WithMutationContextOnSuccess, hasQueryV5WithRequiredContextOnSuccess, hasSolidQueryUsePrefix }) => ({
1134
+ const createSolidAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasQueryV5WithMutationContextOnSuccess, hasQueryV5WithRequiredContextOnSuccess, hasSolidQueryUsePrefix, hasSolidQueryRenamedOptionsTypes }) => ({
1111
1135
  outputClient: OutputClient.SOLID_QUERY,
1112
1136
  hookPrefix: hasSolidQueryUsePrefix ? "use" : "create",
1113
1137
  hasQueryV5,
@@ -1119,9 +1143,9 @@ const createSolidAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5
1119
1143
  return hasSolidQueryUsePrefix ? "Use" : "Create";
1120
1144
  },
1121
1145
  getOptionsReturnTypeName(type) {
1122
- if (type === "mutation") return "SolidMutationOptions";
1123
- if (type === "infiniteQuery") return "SolidInfiniteQueryOptions";
1124
- return "SolidQueryOptions";
1146
+ if (type === "mutation") return hasSolidQueryRenamedOptionsTypes ? "MutationOptions" : "SolidMutationOptions";
1147
+ if (type === "infiniteQuery") return hasSolidQueryRenamedOptionsTypes ? "InfiniteQueryOptions" : "SolidInfiniteQueryOptions";
1148
+ return hasSolidQueryRenamedOptionsTypes ? "QueryOptions" : "SolidQueryOptions";
1125
1149
  },
1126
1150
  getQueryKeyPrefix() {
1127
1151
  return "";
@@ -1328,7 +1352,8 @@ const createVueAdapter = ({ hasVueQueryV4, hasQueryV5, hasQueryV5WithDataTagErro
1328
1352
  return vueUnRefParams(props.filter((prop) => prop.type === GetterPropType.NAMED_PATH_PARAMS));
1329
1353
  },
1330
1354
  generateEnabledOption(params, options) {
1331
- if (!isObject(options) || !Object.hasOwn(options, "enabled")) return `enabled: computed(() => !!(${params.map(({ name }) => `unref(${name})`).join(" && ")})),`;
1355
+ if (params.length === 0) return "";
1356
+ if (!isObject(options) || !Object.hasOwn(options, "enabled")) return `enabled: computed(() => ${params.map(({ name }) => `unref(${name}) !== null && unref(${name}) !== undefined`).join(" && ")}),`;
1332
1357
  return "";
1333
1358
  },
1334
1359
  getQueryKeyPrefix() {
@@ -1378,7 +1403,8 @@ const withDefaults = (adapter) => ({
1378
1403
  return `\`${route}\``;
1379
1404
  },
1380
1405
  generateEnabledOption(params, options) {
1381
- if (!isObject(options) || !Object.hasOwn(options, "enabled")) return `enabled: !!(${params.map(({ name }) => name).join(" && ")}),`;
1406
+ if (params.length === 0) return "";
1407
+ if (!isObject(options) || !Object.hasOwn(options, "enabled")) return `enabled: ${params.map(({ name }) => `${name} !== null && ${name} !== undefined`).join(" && ")},`;
1382
1408
  return "";
1383
1409
  },
1384
1410
  getQueryPropertyForProp(prop, body) {
@@ -1412,7 +1438,8 @@ const withDefaults = (adapter) => ({
1412
1438
  queryParams,
1413
1439
  queryParam,
1414
1440
  isReturnType: false,
1415
- initialData
1441
+ initialData,
1442
+ adapter
1416
1443
  });
1417
1444
  if (!isRequestOptions) return `${type ? "queryOptions" : "mutationOptions"}${initialData === "defined" ? "" : "?"}: ${definition}`;
1418
1445
  const requestType = getQueryArgumentsRequestType(httpClient, mutator, useRuntimeFetcher);
@@ -1490,7 +1517,8 @@ const createFrameworkAdapter = ({ outputClient, packageJson, queryVersion }) =>
1490
1517
  hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError,
1491
1518
  hasQueryV5WithMutationContextOnSuccess: _hasQueryV5WithMutationContextOnSuccess,
1492
1519
  hasQueryV5WithRequiredContextOnSuccess: _hasQueryV5WithRequiredContextOnSuccess,
1493
- hasSolidQueryUsePrefix: isSolidQueryWithUsePrefix(packageJson)
1520
+ hasSolidQueryUsePrefix: isSolidQueryWithUsePrefix(packageJson),
1521
+ hasSolidQueryRenamedOptionsTypes: isSolidQueryWithRenamedOptionsTypes(packageJson)
1494
1522
  }));
1495
1523
  default: return withDefaults(createReactAdapter({
1496
1524
  hasQueryV5: _hasQueryV5,
@@ -1545,10 +1573,12 @@ const findOperationInfo = (spec, operationName) => {
1545
1573
  if (opId !== operationName && camel(opId) !== operationName) continue;
1546
1574
  if (!routePath.includes("{")) return {
1547
1575
  route: routePath,
1576
+ method,
1548
1577
  hasRequiredPathParams: false
1549
1578
  };
1550
1579
  return {
1551
1580
  route: routePath,
1581
+ method,
1552
1582
  hasRequiredPathParams: [...Array.isArray(pathItem.parameters) ? pathItem.parameters : [], ...Array.isArray(operation.parameters) ? operation.parameters : []].filter((p) => p.in === "path").some((p) => p.schema?.default === void 0 && p.default === void 0)
1553
1583
  };
1554
1584
  }
@@ -1597,7 +1627,7 @@ const generateParamArgs = (params) => {
1597
1627
  * Create a generateInvalidateCall function that has access to the OpenAPI spec
1598
1628
  * for intelligent route-based invalidation when params are not specified.
1599
1629
  */
1600
- const createGenerateInvalidateCall = (spec, shouldSplitQueryKey) => {
1630
+ const createGenerateInvalidateCall = (spec, shouldSplitQueryKey, useOperationIdAsQueryKey) => {
1601
1631
  return (target) => {
1602
1632
  const method = target.invalidateMode === "reset" ? "resetQueries" : "invalidateQueries";
1603
1633
  const queryKeyFn = camel(`get-${target.query}-query-key`);
@@ -1606,7 +1636,15 @@ const createGenerateInvalidateCall = (spec, shouldSplitQueryKey) => {
1606
1636
  if (info?.hasRequiredPathParams) {
1607
1637
  const prefix = getStaticRoutePrefix(info.route);
1608
1638
  if (prefix !== void 0) {
1609
- if (shouldSplitQueryKey) return ` queryClient.${method}({ queryKey: [${prefix.split("/").filter((s) => s !== "").map((s) => `'${s}'`).join(", ")}] });`;
1639
+ const verbPrefix = getQueryKeyVerbPrefix({
1640
+ verb: info.method,
1641
+ useOperationIdAsQueryKey
1642
+ });
1643
+ if (shouldSplitQueryKey) {
1644
+ const segments = prefix.split("/").filter((s) => s !== "").map((s) => `'${s}'`).join(", ");
1645
+ return ` queryClient.${method}({ queryKey: ${verbPrefix ? `['${verbPrefix}', ${segments}]` : `[${segments}]`} });`;
1646
+ }
1647
+ if (verbPrefix) return ` queryClient.${method}({ predicate: (query) => query.queryKey[0] === '${verbPrefix}' && typeof query.queryKey[1] === 'string' && query.queryKey[1].startsWith('${prefix}') });`;
1610
1648
  return ` queryClient.${method}({ predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith('${prefix}') });`;
1611
1649
  }
1612
1650
  }
@@ -1688,7 +1726,7 @@ ${hasInvalidation ? adapter.generateMutationOnSuccess({
1688
1726
  operationName,
1689
1727
  definitions,
1690
1728
  isRequestOptions,
1691
- generateInvalidateCall: createGenerateInvalidateCall(context.spec, !!query.shouldSplitQueryKey),
1729
+ generateInvalidateCall: createGenerateInvalidateCall(context.spec, !!query.shouldSplitQueryKey, !!query.useOperationIdAsQueryKey),
1692
1730
  uniqueInvalidates
1693
1731
  }) : ""}
1694
1732
 
@@ -1757,6 +1795,110 @@ const getMutationInvalidatesConflictWarning = ({ operationName, isMutation, isQu
1757
1795
  if (!mutationInvalidates.find((rule) => rule.onMutations.includes(operationName))) return void 0;
1758
1796
  return `mutationInvalidates rule references '${operationName}', but that operation is generated as a ${isQuery ? "Query hook" : "plain function (no hook)"}, not a Mutation. The invalidation will not fire. Either remove '${operationName}' from the rule's onMutations list, or configure '${operationName}' so that it is generated as a Mutation hook.`;
1759
1797
  };
1798
+ const escapeRegExpMetaChars = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
1799
+ /**
1800
+ * Wraps the body parameter's type in a property string with the mutator's
1801
+ * `BodyType<T>` envelope so that user-facing Query helpers (hook signature,
1802
+ * `getXxxQueryOptions`, `getXxxQueryKey`, prefetch / invalidate / set+get
1803
+ * QueryData) match the request function's signature, which is already
1804
+ * wrapped by `client.ts`. Without this, callers that pass a plain body to
1805
+ * a non-GET Query hook (possible after #2376 routes non-GET verbs to
1806
+ * Query hooks) would hit a type mismatch against the underlying request
1807
+ * function.
1808
+ *
1809
+ * The pattern handles three prop shapes that the various
1810
+ * `toObjectString(props, ...)` callers can emit:
1811
+ * - `name: T` — required body
1812
+ * - `name?: T` — optional body
1813
+ * - `name: undefined | T` — `definedInitialData` overload transform
1814
+ *
1815
+ * `body.definition` is fully regex-escaped so types containing metachars
1816
+ * (e.g. `Pet[]`, `Foo | Bar`, anonymous object types) are matched
1817
+ * verbatim rather than reinterpreted as regex syntax.
1818
+ *
1819
+ * No-op when the operation has no body or the mutator does not export a
1820
+ * `BodyType<T>` wrapper, so existing GET-only Query keys are unchanged.
1821
+ */
1822
+ const wrapPropsBodyWithMutatorBodyType = ({ propsString, body, mutator }) => {
1823
+ if (!mutator?.bodyTypeName || !body.definition) return propsString;
1824
+ const bodyDefinitionPattern = escapeRegExpMetaChars(body.definition);
1825
+ return propsString.replace(new RegExp(String.raw`(\w+\??:\s*(?:undefined\s*\|\s*)?)${bodyDefinitionPattern}`), `$1${mutator.bodyTypeName}<${body.definition}>`);
1826
+ };
1827
+ /**
1828
+ * Widens a parameter signature to be optional. Skips params that already
1829
+ * carry a default value (`= ...`), since those are syntactically optional
1830
+ * and adding `?` on top would be a TypeScript error.
1831
+ */
1832
+ const makeOptionalParam = (impl) => {
1833
+ if (impl.includes("=")) return impl;
1834
+ return impl.replace(/^(\w+):\s*/, "$1?: ");
1835
+ };
1836
+ /**
1837
+ * Widens a parameter type to also accept `undefined`. Already-optional
1838
+ * (`?:`) signatures are normalized to required-with-undefined, and params
1839
+ * with a default value pass through unchanged.
1840
+ */
1841
+ const allowUndefinedParam = (impl) => {
1842
+ if (impl.includes("=")) return impl;
1843
+ const optional = /^(\w+)\?:\s*(.+)$/.exec(impl);
1844
+ if (optional) return `${optional[1]}: ${optional[2]} | undefined`;
1845
+ return impl.replace(/^(\w+):\s*(.+)$/, "$1: $2 | undefined");
1846
+ };
1847
+ /**
1848
+ * Renders the `setXxxQueryData` helper as either a React hook (returns a
1849
+ * setter) or a plain function taking `queryClient`. Both shapes share the
1850
+ * same body and signature, so this collapses what would otherwise be two
1851
+ * near-identical template literals.
1852
+ */
1853
+ const renderSetQueryDataHelper = ({ doc, isReactQuery, fnName, propsSig, body }) => {
1854
+ const docPrefix = doc ?? "";
1855
+ if (isReactQuery) return `${docPrefix}export const ${fnName} = () => {
1856
+ const queryClient = useQueryClient();
1857
+ return (${propsSig}) => {
1858
+ ${body}
1859
+ };
1860
+ }\n`;
1861
+ return `${docPrefix}export const ${fnName} = (queryClient: QueryClient, ${propsSig}) => {
1862
+ ${body}
1863
+ }\n`;
1864
+ };
1865
+ /**
1866
+ * Renders the prop list shared by `getXxxQueryKey`, `setXxxQueryData` and
1867
+ * `getXxxQueryData` helpers: headers are dropped, path params stay required,
1868
+ * non-path params (query params, body) are passed through `widenNonPath`
1869
+ * (defaults to identity — pass `makeOptionalParam` or `allowUndefinedParam`
1870
+ * to relax the signature).
1871
+ *
1872
+ * Centralising this prevents the three call sites from drifting apart on
1873
+ * how they treat the same props.
1874
+ */
1875
+ const buildKeyShapedProps = ({ props, body, mutator, widenNonPath = (impl) => impl }) => wrapPropsBodyWithMutatorBodyType({
1876
+ propsString: toObjectString(props.filter((prop) => prop.type !== GetterPropType.HEADER).map((prop) => ({
1877
+ ...prop,
1878
+ implementation: prop.type === GetterPropType.PARAM || prop.type === GetterPropType.NAMED_PATH_PARAMS ? prop.implementation : widenNonPath(prop.implementation)
1879
+ })), "implementation"),
1880
+ body,
1881
+ mutator
1882
+ });
1883
+ /**
1884
+ * Computes a verb prefix segment for query keys when a non-GET operation is
1885
+ * routed to a Query hook. Without this prefix, two operations sharing a path
1886
+ * (e.g. `GET /pets` and `POST /pets`) would generate cache keys that both
1887
+ * begin with `'/pets'`, so TanStack Query would mix their cached data and
1888
+ * `invalidateQueries({ queryKey: ['/pets'] })` would match both.
1889
+ *
1890
+ * Skipped for GET (preserves existing keys) and when
1891
+ * `useOperationIdAsQueryKey` is enabled (operation IDs are already unique
1892
+ * across verb + path, so the prefix would be redundant).
1893
+ *
1894
+ * Returns the uppercased verb when a prefix should be inserted, or
1895
+ * `undefined` when no prefix is needed.
1896
+ */
1897
+ const getQueryKeyVerbPrefix = ({ verb, useOperationIdAsQueryKey }) => {
1898
+ if (useOperationIdAsQueryKey) return void 0;
1899
+ if (verb === Verbs.GET) return void 0;
1900
+ return verb.toUpperCase();
1901
+ };
1760
1902
  const getQueryFnArguments = ({ hasQueryParam, hasSignal, hasSignalParam = false }) => {
1761
1903
  if (!hasQueryParam && !hasSignal) return "";
1762
1904
  const signalDestructure = hasSignalParam ? "signal: querySignal" : "signal";
@@ -1787,20 +1929,32 @@ const generatePrefetch = ({ usePrefetch, type, useQuery, useInfinite, operationN
1787
1929
  return queryClient;
1788
1930
  }\n`;
1789
1931
  };
1790
- const generateQueryImplementation = ({ queryOption: { name, queryParam, options, type, queryKeyFnName }, operationName, queryProperties, queryKeyProperties, queryParams, params, props, mutator, queryOptionsMutator, queryKeyMutator, isRequestOptions, response, httpClient, isExactOptionalPropertyTypes, hasSignal, useRuntimeFetcher, route, doc, usePrefetch, useQuery, useInfinite, useInvalidate, useSetQueryData, useGetQueryData, adapter }) => {
1932
+ const generateQueryImplementation = ({ queryOption: { name, queryParam, options, type, queryKeyFnName }, operationName, queryProperties, queryKeyProperties, queryParams, params, props, body, mutator, queryOptionsMutator, queryKeyMutator, isRequestOptions, response, httpClient, isExactOptionalPropertyTypes, hasSignal, useRuntimeFetcher, route, doc, usePrefetch, useQuery, useInfinite, useInvalidate, useSetQueryData, useGetQueryData, adapter }) => {
1791
1933
  const { hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError } = adapter;
1792
1934
  const hasSignalParam = props.some((prop) => prop.name === "signal");
1793
- const queryPropDefinitions = toObjectString(props, "definition");
1794
- const definedInitialDataQueryPropsDefinitions = toObjectString(props.map((prop) => {
1795
- const regex = new RegExp(String.raw`^${prop.name}\s*\?:`);
1796
- if (!regex.test(prop.definition)) return prop;
1797
- const definitionWithUndefined = prop.definition.replace(regex, `${prop.name}: undefined | `);
1798
- return {
1799
- ...prop,
1800
- definition: definitionWithUndefined
1801
- };
1802
- }), "definition");
1803
- const queryProps = toObjectString(props, "implementation");
1935
+ const queryPropDefinitions = wrapPropsBodyWithMutatorBodyType({
1936
+ propsString: toObjectString(props, "definition"),
1937
+ body,
1938
+ mutator
1939
+ });
1940
+ const definedInitialDataQueryPropsDefinitions = wrapPropsBodyWithMutatorBodyType({
1941
+ propsString: toObjectString(props.map((prop) => {
1942
+ const regex = new RegExp(String.raw`^${prop.name}\s*\?:`);
1943
+ if (!regex.test(prop.definition)) return prop;
1944
+ const definitionWithUndefined = prop.definition.replace(regex, `${prop.name}: undefined | `);
1945
+ return {
1946
+ ...prop,
1947
+ definition: definitionWithUndefined
1948
+ };
1949
+ }), "definition"),
1950
+ body,
1951
+ mutator
1952
+ });
1953
+ const queryProps = wrapPropsBodyWithMutatorBodyType({
1954
+ propsString: toObjectString(props, "implementation"),
1955
+ body,
1956
+ mutator
1957
+ });
1804
1958
  const hasInfiniteQueryParam = queryParam && queryParams?.schema.name;
1805
1959
  const httpFunctionProps = queryParam ? adapter.getInfiniteQueryHttpProps(props, queryParam, !!mutator) : adapter.getHttpFunctionQueryProps(queryProperties, httpClient, !!mutator);
1806
1960
  const definedInitialDataReturnType = adapter.getQueryReturnType({
@@ -1955,18 +2109,28 @@ export function ${queryHookName}<TData = ${TData}, TError = ${errorType}>(\n ${q
1955
2109
  const isPrimaryQueryType = type === QueryType.QUERY || type === QueryType.INFINITE || type === QueryType.SUSPENSE_QUERY && !useQuery || type === QueryType.SUSPENSE_INFINITE && !useInfinite;
1956
2110
  const buildBaseQueryKeyExpr = () => queryKeyMutator ? `${queryKeyMutator.name}({ ${queryProperties} }${queryKeyMutator.hasSecondArg ? `, { url: \`${route}\` }` : ""})` : `${queryKeyFnName}(${queryKeyProperties})`;
1957
2111
  const applyQueryOptionsMutator = (baseExpr) => queryOptionsMutator && !queryOptionsMutator.isHook ? `${queryOptionsMutator.name}({ queryKey: ${baseExpr} }${queryOptionsMutator.hasSecondArg ? `, { ${queryProperties} }` : ""}${queryOptionsMutator.hasThirdArg ? `, { url: \`${route}\` }` : ""}).queryKey` : baseExpr;
2112
+ const hasHookMutator = !!queryOptionsMutator?.isHook;
2113
+ if (hasHookMutator && (useSetQueryData || useGetQueryData)) logWarning(`'${name}' has a hook-based queryOptions mutator, so the requested set/get-query-data helpers were skipped to avoid a cache-key mismatch with the query hook.`);
1958
2114
  const shouldGenerateInvalidate = useInvalidate && isPrimaryQueryType;
1959
2115
  const invalidateFnName = camel(`invalidate-${name}`);
1960
2116
  const invalidateQueryKeyExpr = applyQueryOptionsMutator(buildBaseQueryKeyExpr());
1961
- const shouldGenerateSetQueryData = useSetQueryData && isPrimaryQueryType;
2117
+ const shouldGenerateSetQueryData = useSetQueryData && isPrimaryQueryType && !hasHookMutator;
1962
2118
  const isReactQuery = adapter.outputClient === OutputClient.REACT_QUERY;
1963
2119
  const setQueryDataFnName = isReactQuery ? camel(`use-set-${name}-query-data`) : camel(`set-${name}-query-data`);
1964
- const setQueryDataKeyExpr = buildBaseQueryKeyExpr();
1965
- const setQueryDataProps = toObjectString(props.filter((prop) => prop.type !== GetterPropType.HEADER), "implementation").replaceAll("?:", ":");
1966
- const shouldGenerateGetQueryData = useGetQueryData && isPrimaryQueryType;
2120
+ const setQueryDataKeyExpr = applyQueryOptionsMutator(buildBaseQueryKeyExpr());
2121
+ const setQueryDataProps = buildKeyShapedProps({
2122
+ props,
2123
+ body,
2124
+ mutator,
2125
+ widenNonPath: allowUndefinedParam
2126
+ });
2127
+ const shouldGenerateGetQueryData = useGetQueryData && isPrimaryQueryType && !hasHookMutator;
1967
2128
  const getQueryDataFnName = isReactQuery ? camel(`use-get-${name}-query-data`) : camel(`get-${name}-query-data`);
1968
- const getQueryDataKeyExpr = setQueryDataKeyExpr;
1969
- const getQueryDataProps = setQueryDataProps;
2129
+ const getQueryDataProps = buildKeyShapedProps({
2130
+ props,
2131
+ body,
2132
+ mutator
2133
+ });
1970
2134
  const queryInit = adapter.generateQueryInit({
1971
2135
  queryOptionsFnName,
1972
2136
  queryProperties,
@@ -1993,7 +2157,11 @@ export type ${pascal(name)}QueryError = ${errorType}
1993
2157
 
1994
2158
  ${adapter.shouldGenerateOverrideTypes() ? overrideTypes : ""}
1995
2159
  ${doc}
1996
- export function ${queryHookName}<TData = ${TData}, TError = ${errorType}>(\n ${adapter.getHookPropsDefinitions(props)} ${queryArguments} ${optionalQueryClientArgument} \n ): ${returnType} {
2160
+ export function ${queryHookName}<TData = ${TData}, TError = ${errorType}>(\n ${wrapPropsBodyWithMutatorBodyType({
2161
+ propsString: adapter.getHookPropsDefinitions(props),
2162
+ body,
2163
+ mutator
2164
+ })} ${queryArguments} ${optionalQueryClientArgument} \n ): ${returnType} {
1997
2165
 
1998
2166
  ${queryInit}
1999
2167
 
@@ -2013,20 +2181,19 @@ ${shouldGenerateInvalidate ? `${doc}export const ${invalidateFnName} = async (\n
2013
2181
 
2014
2182
  return queryClient;
2015
2183
  }\n` : ""}
2016
- ${shouldGenerateSetQueryData ? isReactQuery ? `${doc}export const ${setQueryDataFnName} = () => {
2017
- const queryClient = useQueryClient();
2018
- return (${setQueryDataProps}updater: ${TData} | undefined | ((old: ${TData} | undefined) => ${TData} | undefined)) => {
2019
- queryClient.setQueryData(${setQueryDataKeyExpr}, updater);
2020
- };
2021
- }\n` : `${doc}export const ${setQueryDataFnName} = (queryClient: QueryClient, ${setQueryDataProps}updater: ${TData} | undefined | ((old: ${TData} | undefined) => ${TData} | undefined)) => {
2022
- queryClient.setQueryData(${setQueryDataKeyExpr}, updater);
2023
- }\n` : ""}
2184
+ ${shouldGenerateSetQueryData ? renderSetQueryDataHelper({
2185
+ doc,
2186
+ isReactQuery,
2187
+ fnName: setQueryDataFnName,
2188
+ propsSig: `${setQueryDataProps}updater: ${TData} | undefined | ((old: ${TData} | undefined) => ${TData} | undefined)`,
2189
+ body: `queryClient.setQueriesData<${TData}>({ queryKey: ${setQueryDataKeyExpr} }, updater);`
2190
+ }) : ""}
2024
2191
  ${shouldGenerateGetQueryData ? isReactQuery ? `${doc}export const ${getQueryDataFnName} = () => {
2025
2192
  const queryClient = useQueryClient();
2026
2193
  return (${getQueryDataProps}) =>
2027
- queryClient.getQueryData<${TData}>(${getQueryDataKeyExpr});
2194
+ queryClient.getQueryData<${TData}>(${setQueryDataKeyExpr});
2028
2195
  }\n` : `${doc}export const ${getQueryDataFnName} = (queryClient: QueryClient, ${getQueryDataProps}) =>
2029
- queryClient.getQueryData<${TData}>(${getQueryDataKeyExpr});\n` : ""}
2196
+ queryClient.getQueryData<${TData}>(${setQueryDataKeyExpr});\n` : ""}
2030
2197
  `;
2031
2198
  };
2032
2199
  const generateQueryHook = async (verbOptions, options, outputClient, adapter) => {
@@ -2045,20 +2212,14 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
2045
2212
  });
2046
2213
  let implementation = "";
2047
2214
  let mutators;
2048
- const hasOperationQueryOption = [
2049
- operationQueryOptions?.useQuery,
2050
- operationQueryOptions?.useSuspenseQuery,
2051
- operationQueryOptions?.useInfinite,
2052
- operationQueryOptions?.useSuspenseInfiniteQuery
2053
- ].some(Boolean);
2054
- let isQuery = Verbs.GET === verb && [
2055
- override.query.useQuery,
2056
- override.query.useSuspenseQuery,
2057
- override.query.useInfinite,
2058
- override.query.useSuspenseInfiniteQuery
2059
- ].some(Boolean) || hasOperationQueryOption;
2060
- let isMutation = override.query.useMutation && verb !== Verbs.GET;
2061
- if (operationQueryOptions?.useMutation !== void 0) isMutation = operationQueryOptions.useMutation;
2215
+ const effectiveUseQuery = operationQueryOptions?.useQuery ?? override.query.useQuery ?? verb === Verbs.GET;
2216
+ const effectiveUseMutation = operationQueryOptions?.useMutation ?? override.query.useMutation ?? verb !== Verbs.GET;
2217
+ const globalSuspenseOrInfiniteOnlyForGet = (flag) => flag === true && verb === Verbs.GET;
2218
+ const effectiveUseSuspenseQuery = operationQueryOptions?.useSuspenseQuery ?? globalSuspenseOrInfiniteOnlyForGet(override.query.useSuspenseQuery);
2219
+ const effectiveUseInfinite = operationQueryOptions?.useInfinite ?? globalSuspenseOrInfiniteOnlyForGet(override.query.useInfinite);
2220
+ const effectiveUseSuspenseInfiniteQuery = operationQueryOptions?.useSuspenseInfiniteQuery ?? globalSuspenseOrInfiniteOnlyForGet(override.query.useSuspenseInfiniteQuery);
2221
+ let isQuery = effectiveUseQuery || effectiveUseSuspenseQuery || effectiveUseInfinite || effectiveUseSuspenseInfiniteQuery;
2222
+ let isMutation = effectiveUseMutation;
2062
2223
  if (verb !== Verbs.GET && isQuery) isMutation = false;
2063
2224
  if (verb === Verbs.GET && isMutation) isQuery = false;
2064
2225
  const conflictWarning = getMutationInvalidatesConflictWarning({
@@ -2090,26 +2251,26 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
2090
2251
  return adapter.getQueryPropertyForProp(param, body);
2091
2252
  }).join(",");
2092
2253
  const queries = [
2093
- ...query.useInfinite || operationQueryOptions?.useInfinite ? [{
2254
+ ...effectiveUseInfinite ? [{
2094
2255
  name: camel(`${operationName}-infinite`),
2095
2256
  options: query.options,
2096
2257
  type: QueryType.INFINITE,
2097
2258
  queryParam: query.useInfiniteQueryParam,
2098
2259
  queryKeyFnName: camel(`get-${operationName}-infinite-query-key`)
2099
2260
  }] : [],
2100
- ...query.useQuery || operationQueryOptions?.useQuery ? [{
2261
+ ...effectiveUseQuery ? [{
2101
2262
  name: operationName,
2102
2263
  options: query.options,
2103
2264
  type: QueryType.QUERY,
2104
2265
  queryKeyFnName: camel(`get-${operationName}-query-key`)
2105
2266
  }] : [],
2106
- ...query.useSuspenseQuery || operationQueryOptions?.useSuspenseQuery ? [{
2267
+ ...effectiveUseSuspenseQuery ? [{
2107
2268
  name: camel(`${operationName}-suspense`),
2108
2269
  options: query.options,
2109
2270
  type: QueryType.SUSPENSE_QUERY,
2110
2271
  queryKeyFnName: camel(`get-${operationName}-query-key`)
2111
2272
  }] : [],
2112
- ...query.useSuspenseInfiniteQuery || operationQueryOptions?.useSuspenseInfiniteQuery ? [{
2273
+ ...effectiveUseSuspenseInfiniteQuery ? [{
2113
2274
  name: camel(`${operationName}-suspense-infinite`),
2114
2275
  options: query.options,
2115
2276
  type: QueryType.SUSPENSE_INFINITE,
@@ -2120,22 +2281,25 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
2120
2281
  const uniqueQueryOptionsByKeys = queries.filter((obj, index, self) => index === self.findIndex((t) => t.queryKeyFnName === obj.queryKeyFnName));
2121
2282
  let queryKeyFns = "";
2122
2283
  if (!queryKeyMutator) for (const queryOption of uniqueQueryOptionsByKeys) {
2123
- const makeOptionalParam = (impl) => {
2124
- if (impl.includes("=")) return impl;
2125
- return impl.replace(/^(\w+):\s*/, "$1?: ");
2126
- };
2127
- const queryKeyProps = toObjectString(props.filter((prop) => prop.type !== GetterPropType.HEADER).map((prop) => ({
2128
- ...prop,
2129
- implementation: prop.type === GetterPropType.PARAM || prop.type === GetterPropType.NAMED_PATH_PARAMS ? prop.implementation : makeOptionalParam(prop.implementation)
2130
- })), "implementation");
2284
+ const queryKeyProps = buildKeyShapedProps({
2285
+ props,
2286
+ body,
2287
+ mutator,
2288
+ widenNonPath: makeOptionalParam
2289
+ });
2131
2290
  const routeString = adapter.getQueryKeyRouteString(route, !!override.query.shouldSplitQueryKey);
2132
2291
  const queryKeyIdentifier = override.query.useOperationIdAsQueryKey ? `"${operationName}"` : routeString;
2133
2292
  const queryKeyParams = props.filter((p) => override.query.useOperationIdAsQueryKey ? true : p.type === GetterPropType.QUERY_PARAM).toSorted((a) => a.required ? -1 : 1).map((p) => `...(${p.name} ? [${p.name}] : [])`).join(", ");
2293
+ const verbPrefix = getQueryKeyVerbPrefix({
2294
+ verb,
2295
+ useOperationIdAsQueryKey: override.query.useOperationIdAsQueryKey
2296
+ });
2134
2297
  queryKeyFns += `
2135
2298
  ${override.query.shouldExportQueryKey ? "export " : ""}const ${queryOption.queryKeyFnName} = (${queryKeyProps}) => {
2136
2299
  return [
2137
2300
  ${[
2138
2301
  queryOption.type === QueryType.INFINITE || queryOption.type === QueryType.SUSPENSE_INFINITE ? `'infinite'` : "",
2302
+ verbPrefix ? `'${verbPrefix}'` : "",
2139
2303
  queryKeyIdentifier,
2140
2304
  queryKeyParams,
2141
2305
  body.implementation
@@ -2154,6 +2318,7 @@ ${queryKeyFns}`;
2154
2318
  queryKeyProperties,
2155
2319
  params,
2156
2320
  props,
2321
+ body,
2157
2322
  mutator,
2158
2323
  isRequestOptions,
2159
2324
  queryParams,
@@ -2167,8 +2332,8 @@ ${queryKeyFns}`;
2167
2332
  route,
2168
2333
  doc,
2169
2334
  usePrefetch: query.usePrefetch,
2170
- useQuery: query.useQuery,
2171
- useInfinite: query.useInfinite,
2335
+ useQuery: effectiveUseQuery,
2336
+ useInfinite: effectiveUseInfinite,
2172
2337
  useInvalidate: query.useInvalidate,
2173
2338
  useSetQueryData: operationQueryOptions?.useSetQueryData ?? query.useSetQueryData,
2174
2339
  useGetQueryData: operationQueryOptions?.useGetQueryData ?? query.useGetQueryData,