@orval/query 8.9.0 → 8.10.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 +164 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetterPropType, OutputClient, OutputHttpClient, TEMPLATE_TAG_REGEX, Verbs, camel, compareVersions, generateFormDataAndUrlEncodedFunction, generateMutator, generateMutatorConfig, generateMutatorRequestOptions, generateOptions, generateVerbImports, getAngularFilteredParamsCallExpression, getAngularFilteredParamsHelperBody, getRouteAsArray, getSuccessResponseType, isObject, isString, isSyntheticDefaultImportsAllow, jsDoc, kebab, mergeDeep, pascal, stringify, toObjectString } from "@orval/core";
|
|
1
|
+
import { GetterPropType, OutputClient, OutputHttpClient, TEMPLATE_TAG_REGEX, Verbs, camel, compareVersions, generateFormDataAndUrlEncodedFunction, generateMutator, generateMutatorConfig, generateMutatorRequestOptions, generateOptions, generateVerbImports, getAngularFilteredParamsCallExpression, getAngularFilteredParamsHelperBody, getRouteAsArray, getSuccessResponseType, isObject, isString, isSyntheticDefaultImportsAllow, jsDoc, kebab, logWarning, mergeDeep, pascal, stringify, toObjectString } from "@orval/core";
|
|
2
2
|
import { generateFetchHeader, generateRequestFunction } from "@orval/fetch";
|
|
3
3
|
import nodePath from "node:path";
|
|
4
4
|
import { styleText } from "node:util";
|
|
@@ -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 ? {
|
|
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 } : {},
|
|
@@ -901,7 +904,7 @@ const generateQueryOptions = ({ params, options, type, adapter }) => {
|
|
|
901
904
|
if (options) return `${queryConfig} ...queryOptions`;
|
|
902
905
|
return "...queryOptions";
|
|
903
906
|
}
|
|
904
|
-
return `${adapter ? adapter.generateEnabledOption(params, options) : !isObject(options) || !Object.hasOwn(options, "enabled") ? `enabled:
|
|
907
|
+
return `${adapter ? adapter.generateEnabledOption(params, options) : !isObject(options) || !Object.hasOwn(options, "enabled") ? `enabled: ${params.map(({ name }) => `${name} != null`).join(" && ")},` : ""}${queryConfig} ...queryOptions`;
|
|
905
908
|
};
|
|
906
909
|
const isSuspenseQuery = (type) => {
|
|
907
910
|
return [QueryType.SUSPENSE_INFINITE, QueryType.SUSPENSE_QUERY].includes(type);
|
|
@@ -1328,7 +1331,8 @@ const createVueAdapter = ({ hasVueQueryV4, hasQueryV5, hasQueryV5WithDataTagErro
|
|
|
1328
1331
|
return vueUnRefParams(props.filter((prop) => prop.type === GetterPropType.NAMED_PATH_PARAMS));
|
|
1329
1332
|
},
|
|
1330
1333
|
generateEnabledOption(params, options) {
|
|
1331
|
-
if (
|
|
1334
|
+
if (params.length === 0) return "";
|
|
1335
|
+
if (!isObject(options) || !Object.hasOwn(options, "enabled")) return `enabled: computed(() => ${params.map(({ name }) => `unref(${name}) !== null && unref(${name}) !== undefined`).join(" && ")}),`;
|
|
1332
1336
|
return "";
|
|
1333
1337
|
},
|
|
1334
1338
|
getQueryKeyPrefix() {
|
|
@@ -1378,7 +1382,8 @@ const withDefaults = (adapter) => ({
|
|
|
1378
1382
|
return `\`${route}\``;
|
|
1379
1383
|
},
|
|
1380
1384
|
generateEnabledOption(params, options) {
|
|
1381
|
-
if (
|
|
1385
|
+
if (params.length === 0) return "";
|
|
1386
|
+
if (!isObject(options) || !Object.hasOwn(options, "enabled")) return `enabled: ${params.map(({ name }) => `${name} !== null && ${name} !== undefined`).join(" && ")},`;
|
|
1382
1387
|
return "";
|
|
1383
1388
|
},
|
|
1384
1389
|
getQueryPropertyForProp(prop, body) {
|
|
@@ -1545,10 +1550,12 @@ const findOperationInfo = (spec, operationName) => {
|
|
|
1545
1550
|
if (opId !== operationName && camel(opId) !== operationName) continue;
|
|
1546
1551
|
if (!routePath.includes("{")) return {
|
|
1547
1552
|
route: routePath,
|
|
1553
|
+
method,
|
|
1548
1554
|
hasRequiredPathParams: false
|
|
1549
1555
|
};
|
|
1550
1556
|
return {
|
|
1551
1557
|
route: routePath,
|
|
1558
|
+
method,
|
|
1552
1559
|
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
1560
|
};
|
|
1554
1561
|
}
|
|
@@ -1597,7 +1604,7 @@ const generateParamArgs = (params) => {
|
|
|
1597
1604
|
* Create a generateInvalidateCall function that has access to the OpenAPI spec
|
|
1598
1605
|
* for intelligent route-based invalidation when params are not specified.
|
|
1599
1606
|
*/
|
|
1600
|
-
const createGenerateInvalidateCall = (spec, shouldSplitQueryKey) => {
|
|
1607
|
+
const createGenerateInvalidateCall = (spec, shouldSplitQueryKey, useOperationIdAsQueryKey) => {
|
|
1601
1608
|
return (target) => {
|
|
1602
1609
|
const method = target.invalidateMode === "reset" ? "resetQueries" : "invalidateQueries";
|
|
1603
1610
|
const queryKeyFn = camel(`get-${target.query}-query-key`);
|
|
@@ -1606,7 +1613,15 @@ const createGenerateInvalidateCall = (spec, shouldSplitQueryKey) => {
|
|
|
1606
1613
|
if (info?.hasRequiredPathParams) {
|
|
1607
1614
|
const prefix = getStaticRoutePrefix(info.route);
|
|
1608
1615
|
if (prefix !== void 0) {
|
|
1609
|
-
|
|
1616
|
+
const verbPrefix = getQueryKeyVerbPrefix({
|
|
1617
|
+
verb: info.method,
|
|
1618
|
+
useOperationIdAsQueryKey
|
|
1619
|
+
});
|
|
1620
|
+
if (shouldSplitQueryKey) {
|
|
1621
|
+
const segments = prefix.split("/").filter((s) => s !== "").map((s) => `'${s}'`).join(", ");
|
|
1622
|
+
return ` queryClient.${method}({ queryKey: ${verbPrefix ? `['${verbPrefix}', ${segments}]` : `[${segments}]`} });`;
|
|
1623
|
+
}
|
|
1624
|
+
if (verbPrefix) return ` queryClient.${method}({ predicate: (query) => query.queryKey[0] === '${verbPrefix}' && typeof query.queryKey[1] === 'string' && query.queryKey[1].startsWith('${prefix}') });`;
|
|
1610
1625
|
return ` queryClient.${method}({ predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith('${prefix}') });`;
|
|
1611
1626
|
}
|
|
1612
1627
|
}
|
|
@@ -1688,7 +1703,7 @@ ${hasInvalidation ? adapter.generateMutationOnSuccess({
|
|
|
1688
1703
|
operationName,
|
|
1689
1704
|
definitions,
|
|
1690
1705
|
isRequestOptions,
|
|
1691
|
-
generateInvalidateCall: createGenerateInvalidateCall(context.spec, !!query.shouldSplitQueryKey),
|
|
1706
|
+
generateInvalidateCall: createGenerateInvalidateCall(context.spec, !!query.shouldSplitQueryKey, !!query.useOperationIdAsQueryKey),
|
|
1692
1707
|
uniqueInvalidates
|
|
1693
1708
|
}) : ""}
|
|
1694
1709
|
|
|
@@ -1741,6 +1756,70 @@ ${mutationHookBody}
|
|
|
1741
1756
|
};
|
|
1742
1757
|
//#endregion
|
|
1743
1758
|
//#region src/query-generator.ts
|
|
1759
|
+
/**
|
|
1760
|
+
* Decide whether the current operation's configuration conflicts with a
|
|
1761
|
+
* `mutationInvalidates` rule. The rule wires its invalidation through the
|
|
1762
|
+
* Mutation hook's `onSuccess`, so referencing an operation that is not
|
|
1763
|
+
* generated as a Mutation (either forced into a Query via per-operation
|
|
1764
|
+
* `useQuery: true`, or suppressed entirely) makes the rule a silent no-op.
|
|
1765
|
+
*
|
|
1766
|
+
* Returns the warning message when the conflict applies, or `undefined`
|
|
1767
|
+
* when the configuration is consistent.
|
|
1768
|
+
*/
|
|
1769
|
+
const getMutationInvalidatesConflictWarning = ({ operationName, isMutation, isQuery, mutationInvalidates }) => {
|
|
1770
|
+
if (isMutation) return void 0;
|
|
1771
|
+
if (!mutationInvalidates?.length) return void 0;
|
|
1772
|
+
if (!mutationInvalidates.find((rule) => rule.onMutations.includes(operationName))) return void 0;
|
|
1773
|
+
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.`;
|
|
1774
|
+
};
|
|
1775
|
+
const escapeRegExpMetaChars = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
1776
|
+
/**
|
|
1777
|
+
* Wraps the body parameter's type in a property string with the mutator's
|
|
1778
|
+
* `BodyType<T>` envelope so that user-facing Query helpers (hook signature,
|
|
1779
|
+
* `getXxxQueryOptions`, `getXxxQueryKey`, prefetch / invalidate / set+get
|
|
1780
|
+
* QueryData) match the request function's signature, which is already
|
|
1781
|
+
* wrapped by `client.ts`. Without this, callers that pass a plain body to
|
|
1782
|
+
* a non-GET Query hook (possible after #2376 routes non-GET verbs to
|
|
1783
|
+
* Query hooks) would hit a type mismatch against the underlying request
|
|
1784
|
+
* function.
|
|
1785
|
+
*
|
|
1786
|
+
* The pattern handles three prop shapes that the various
|
|
1787
|
+
* `toObjectString(props, ...)` callers can emit:
|
|
1788
|
+
* - `name: T` — required body
|
|
1789
|
+
* - `name?: T` — optional body
|
|
1790
|
+
* - `name: undefined | T` — `definedInitialData` overload transform
|
|
1791
|
+
*
|
|
1792
|
+
* `body.definition` is fully regex-escaped so types containing metachars
|
|
1793
|
+
* (e.g. `Pet[]`, `Foo | Bar`, anonymous object types) are matched
|
|
1794
|
+
* verbatim rather than reinterpreted as regex syntax.
|
|
1795
|
+
*
|
|
1796
|
+
* No-op when the operation has no body or the mutator does not export a
|
|
1797
|
+
* `BodyType<T>` wrapper, so existing GET-only Query keys are unchanged.
|
|
1798
|
+
*/
|
|
1799
|
+
const wrapPropsBodyWithMutatorBodyType = ({ propsString, body, mutator }) => {
|
|
1800
|
+
if (!mutator?.bodyTypeName || !body.definition) return propsString;
|
|
1801
|
+
const bodyDefinitionPattern = escapeRegExpMetaChars(body.definition);
|
|
1802
|
+
return propsString.replace(new RegExp(String.raw`(\w+\??:\s*(?:undefined\s*\|\s*)?)${bodyDefinitionPattern}`), `$1${mutator.bodyTypeName}<${body.definition}>`);
|
|
1803
|
+
};
|
|
1804
|
+
/**
|
|
1805
|
+
* Computes a verb prefix segment for query keys when a non-GET operation is
|
|
1806
|
+
* routed to a Query hook. Without this prefix, two operations sharing a path
|
|
1807
|
+
* (e.g. `GET /pets` and `POST /pets`) would generate cache keys that both
|
|
1808
|
+
* begin with `'/pets'`, so TanStack Query would mix their cached data and
|
|
1809
|
+
* `invalidateQueries({ queryKey: ['/pets'] })` would match both.
|
|
1810
|
+
*
|
|
1811
|
+
* Skipped for GET (preserves existing keys) and when
|
|
1812
|
+
* `useOperationIdAsQueryKey` is enabled (operation IDs are already unique
|
|
1813
|
+
* across verb + path, so the prefix would be redundant).
|
|
1814
|
+
*
|
|
1815
|
+
* Returns the uppercased verb when a prefix should be inserted, or
|
|
1816
|
+
* `undefined` when no prefix is needed.
|
|
1817
|
+
*/
|
|
1818
|
+
const getQueryKeyVerbPrefix = ({ verb, useOperationIdAsQueryKey }) => {
|
|
1819
|
+
if (useOperationIdAsQueryKey) return void 0;
|
|
1820
|
+
if (verb === Verbs.GET) return void 0;
|
|
1821
|
+
return verb.toUpperCase();
|
|
1822
|
+
};
|
|
1744
1823
|
const getQueryFnArguments = ({ hasQueryParam, hasSignal, hasSignalParam = false }) => {
|
|
1745
1824
|
if (!hasQueryParam && !hasSignal) return "";
|
|
1746
1825
|
const signalDestructure = hasSignalParam ? "signal: querySignal" : "signal";
|
|
@@ -1771,20 +1850,32 @@ const generatePrefetch = ({ usePrefetch, type, useQuery, useInfinite, operationN
|
|
|
1771
1850
|
return queryClient;
|
|
1772
1851
|
}\n`;
|
|
1773
1852
|
};
|
|
1774
|
-
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 }) => {
|
|
1853
|
+
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 }) => {
|
|
1775
1854
|
const { hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError } = adapter;
|
|
1776
1855
|
const hasSignalParam = props.some((prop) => prop.name === "signal");
|
|
1777
|
-
const queryPropDefinitions =
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1856
|
+
const queryPropDefinitions = wrapPropsBodyWithMutatorBodyType({
|
|
1857
|
+
propsString: toObjectString(props, "definition"),
|
|
1858
|
+
body,
|
|
1859
|
+
mutator
|
|
1860
|
+
});
|
|
1861
|
+
const definedInitialDataQueryPropsDefinitions = wrapPropsBodyWithMutatorBodyType({
|
|
1862
|
+
propsString: toObjectString(props.map((prop) => {
|
|
1863
|
+
const regex = new RegExp(String.raw`^${prop.name}\s*\?:`);
|
|
1864
|
+
if (!regex.test(prop.definition)) return prop;
|
|
1865
|
+
const definitionWithUndefined = prop.definition.replace(regex, `${prop.name}: undefined | `);
|
|
1866
|
+
return {
|
|
1867
|
+
...prop,
|
|
1868
|
+
definition: definitionWithUndefined
|
|
1869
|
+
};
|
|
1870
|
+
}), "definition"),
|
|
1871
|
+
body,
|
|
1872
|
+
mutator
|
|
1873
|
+
});
|
|
1874
|
+
const queryProps = wrapPropsBodyWithMutatorBodyType({
|
|
1875
|
+
propsString: toObjectString(props, "implementation"),
|
|
1876
|
+
body,
|
|
1877
|
+
mutator
|
|
1878
|
+
});
|
|
1788
1879
|
const hasInfiniteQueryParam = queryParam && queryParams?.schema.name;
|
|
1789
1880
|
const httpFunctionProps = queryParam ? adapter.getInfiniteQueryHttpProps(props, queryParam, !!mutator) : adapter.getHttpFunctionQueryProps(queryProperties, httpClient, !!mutator);
|
|
1790
1881
|
const definedInitialDataReturnType = adapter.getQueryReturnType({
|
|
@@ -1937,13 +2028,20 @@ export function ${queryHookName}<TData = ${TData}, TError = ${errorType}>(\n ${q
|
|
|
1937
2028
|
};
|
|
1938
2029
|
const prefetch = adapter.generatePrefetch ? adapter.generatePrefetch(prefetchContext) : generatePrefetch(prefetchContext);
|
|
1939
2030
|
const isPrimaryQueryType = type === QueryType.QUERY || type === QueryType.INFINITE || type === QueryType.SUSPENSE_QUERY && !useQuery || type === QueryType.SUSPENSE_INFINITE && !useInfinite;
|
|
2031
|
+
const buildBaseQueryKeyExpr = () => queryKeyMutator ? `${queryKeyMutator.name}({ ${queryProperties} }${queryKeyMutator.hasSecondArg ? `, { url: \`${route}\` }` : ""})` : `${queryKeyFnName}(${queryKeyProperties})`;
|
|
2032
|
+
const applyQueryOptionsMutator = (baseExpr) => queryOptionsMutator && !queryOptionsMutator.isHook ? `${queryOptionsMutator.name}({ queryKey: ${baseExpr} }${queryOptionsMutator.hasSecondArg ? `, { ${queryProperties} }` : ""}${queryOptionsMutator.hasThirdArg ? `, { url: \`${route}\` }` : ""}).queryKey` : baseExpr;
|
|
1940
2033
|
const shouldGenerateInvalidate = useInvalidate && isPrimaryQueryType;
|
|
1941
2034
|
const invalidateFnName = camel(`invalidate-${name}`);
|
|
2035
|
+
const invalidateQueryKeyExpr = applyQueryOptionsMutator(buildBaseQueryKeyExpr());
|
|
1942
2036
|
const shouldGenerateSetQueryData = useSetQueryData && isPrimaryQueryType;
|
|
1943
2037
|
const isReactQuery = adapter.outputClient === OutputClient.REACT_QUERY;
|
|
1944
2038
|
const setQueryDataFnName = isReactQuery ? camel(`use-set-${name}-query-data`) : camel(`set-${name}-query-data`);
|
|
1945
|
-
const setQueryDataKeyExpr =
|
|
1946
|
-
const setQueryDataProps =
|
|
2039
|
+
const setQueryDataKeyExpr = buildBaseQueryKeyExpr();
|
|
2040
|
+
const setQueryDataProps = wrapPropsBodyWithMutatorBodyType({
|
|
2041
|
+
propsString: toObjectString(props.filter((prop) => prop.type !== GetterPropType.HEADER), "implementation").replaceAll("?:", ":"),
|
|
2042
|
+
body,
|
|
2043
|
+
mutator
|
|
2044
|
+
});
|
|
1947
2045
|
const shouldGenerateGetQueryData = useGetQueryData && isPrimaryQueryType;
|
|
1948
2046
|
const getQueryDataFnName = isReactQuery ? camel(`use-get-${name}-query-data`) : camel(`get-${name}-query-data`);
|
|
1949
2047
|
const getQueryDataKeyExpr = setQueryDataKeyExpr;
|
|
@@ -1974,7 +2072,11 @@ export type ${pascal(name)}QueryError = ${errorType}
|
|
|
1974
2072
|
|
|
1975
2073
|
${adapter.shouldGenerateOverrideTypes() ? overrideTypes : ""}
|
|
1976
2074
|
${doc}
|
|
1977
|
-
export function ${queryHookName}<TData = ${TData}, TError = ${errorType}>(\n ${
|
|
2075
|
+
export function ${queryHookName}<TData = ${TData}, TError = ${errorType}>(\n ${wrapPropsBodyWithMutatorBodyType({
|
|
2076
|
+
propsString: adapter.getHookPropsDefinitions(props),
|
|
2077
|
+
body,
|
|
2078
|
+
mutator
|
|
2079
|
+
})} ${queryArguments} ${optionalQueryClientArgument} \n ): ${returnType} {
|
|
1978
2080
|
|
|
1979
2081
|
${queryInit}
|
|
1980
2082
|
|
|
@@ -1990,7 +2092,7 @@ export function ${queryHookName}<TData = ${TData}, TError = ${errorType}>(\n ${a
|
|
|
1990
2092
|
${prefetch}
|
|
1991
2093
|
${shouldGenerateInvalidate ? `${doc}export const ${invalidateFnName} = async (\n queryClient: QueryClient, ${queryProps} options?: InvalidateOptions\n ): Promise<QueryClient> => {
|
|
1992
2094
|
|
|
1993
|
-
await queryClient.invalidateQueries({ queryKey: ${
|
|
2095
|
+
await queryClient.invalidateQueries({ queryKey: ${invalidateQueryKeyExpr} }, options);
|
|
1994
2096
|
|
|
1995
2097
|
return queryClient;
|
|
1996
2098
|
}\n` : ""}
|
|
@@ -2026,22 +2128,23 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
|
|
|
2026
2128
|
});
|
|
2027
2129
|
let implementation = "";
|
|
2028
2130
|
let mutators;
|
|
2029
|
-
const
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
let isQuery =
|
|
2036
|
-
|
|
2037
|
-
override.query.useSuspenseQuery,
|
|
2038
|
-
override.query.useInfinite,
|
|
2039
|
-
override.query.useSuspenseInfiniteQuery
|
|
2040
|
-
].some(Boolean) || hasOperationQueryOption;
|
|
2041
|
-
let isMutation = override.query.useMutation && verb !== Verbs.GET;
|
|
2042
|
-
if (operationQueryOptions?.useMutation !== void 0) isMutation = operationQueryOptions.useMutation;
|
|
2131
|
+
const effectiveUseQuery = operationQueryOptions?.useQuery ?? override.query.useQuery ?? verb === Verbs.GET;
|
|
2132
|
+
const effectiveUseMutation = operationQueryOptions?.useMutation ?? override.query.useMutation ?? verb !== Verbs.GET;
|
|
2133
|
+
const globalSuspenseOrInfiniteOnlyForGet = (flag) => flag === true && verb === Verbs.GET;
|
|
2134
|
+
const effectiveUseSuspenseQuery = operationQueryOptions?.useSuspenseQuery ?? globalSuspenseOrInfiniteOnlyForGet(override.query.useSuspenseQuery);
|
|
2135
|
+
const effectiveUseInfinite = operationQueryOptions?.useInfinite ?? globalSuspenseOrInfiniteOnlyForGet(override.query.useInfinite);
|
|
2136
|
+
const effectiveUseSuspenseInfiniteQuery = operationQueryOptions?.useSuspenseInfiniteQuery ?? globalSuspenseOrInfiniteOnlyForGet(override.query.useSuspenseInfiniteQuery);
|
|
2137
|
+
let isQuery = effectiveUseQuery || effectiveUseSuspenseQuery || effectiveUseInfinite || effectiveUseSuspenseInfiniteQuery;
|
|
2138
|
+
let isMutation = effectiveUseMutation && verb !== Verbs.GET;
|
|
2043
2139
|
if (verb !== Verbs.GET && isQuery) isMutation = false;
|
|
2044
2140
|
if (verb === Verbs.GET && isMutation) isQuery = false;
|
|
2141
|
+
const conflictWarning = getMutationInvalidatesConflictWarning({
|
|
2142
|
+
operationName,
|
|
2143
|
+
isMutation,
|
|
2144
|
+
isQuery,
|
|
2145
|
+
mutationInvalidates: override.query.mutationInvalidates
|
|
2146
|
+
});
|
|
2147
|
+
if (conflictWarning) logWarning(conflictWarning);
|
|
2045
2148
|
if (isQuery) {
|
|
2046
2149
|
const queryKeyMutator = query.queryKey ? await generateMutator({
|
|
2047
2150
|
output,
|
|
@@ -2064,26 +2167,26 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
|
|
|
2064
2167
|
return adapter.getQueryPropertyForProp(param, body);
|
|
2065
2168
|
}).join(",");
|
|
2066
2169
|
const queries = [
|
|
2067
|
-
...
|
|
2170
|
+
...effectiveUseInfinite ? [{
|
|
2068
2171
|
name: camel(`${operationName}-infinite`),
|
|
2069
2172
|
options: query.options,
|
|
2070
2173
|
type: QueryType.INFINITE,
|
|
2071
2174
|
queryParam: query.useInfiniteQueryParam,
|
|
2072
2175
|
queryKeyFnName: camel(`get-${operationName}-infinite-query-key`)
|
|
2073
2176
|
}] : [],
|
|
2074
|
-
...
|
|
2177
|
+
...effectiveUseQuery ? [{
|
|
2075
2178
|
name: operationName,
|
|
2076
2179
|
options: query.options,
|
|
2077
2180
|
type: QueryType.QUERY,
|
|
2078
2181
|
queryKeyFnName: camel(`get-${operationName}-query-key`)
|
|
2079
2182
|
}] : [],
|
|
2080
|
-
...
|
|
2183
|
+
...effectiveUseSuspenseQuery ? [{
|
|
2081
2184
|
name: camel(`${operationName}-suspense`),
|
|
2082
2185
|
options: query.options,
|
|
2083
2186
|
type: QueryType.SUSPENSE_QUERY,
|
|
2084
2187
|
queryKeyFnName: camel(`get-${operationName}-query-key`)
|
|
2085
2188
|
}] : [],
|
|
2086
|
-
...
|
|
2189
|
+
...effectiveUseSuspenseInfiniteQuery ? [{
|
|
2087
2190
|
name: camel(`${operationName}-suspense-infinite`),
|
|
2088
2191
|
options: query.options,
|
|
2089
2192
|
type: QueryType.SUSPENSE_INFINITE,
|
|
@@ -2098,18 +2201,27 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
|
|
|
2098
2201
|
if (impl.includes("=")) return impl;
|
|
2099
2202
|
return impl.replace(/^(\w+):\s*/, "$1?: ");
|
|
2100
2203
|
};
|
|
2101
|
-
const queryKeyProps =
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2204
|
+
const queryKeyProps = wrapPropsBodyWithMutatorBodyType({
|
|
2205
|
+
propsString: toObjectString(props.filter((prop) => prop.type !== GetterPropType.HEADER).map((prop) => ({
|
|
2206
|
+
...prop,
|
|
2207
|
+
implementation: prop.type === GetterPropType.PARAM || prop.type === GetterPropType.NAMED_PATH_PARAMS ? prop.implementation : makeOptionalParam(prop.implementation)
|
|
2208
|
+
})), "implementation"),
|
|
2209
|
+
body,
|
|
2210
|
+
mutator
|
|
2211
|
+
});
|
|
2105
2212
|
const routeString = adapter.getQueryKeyRouteString(route, !!override.query.shouldSplitQueryKey);
|
|
2106
2213
|
const queryKeyIdentifier = override.query.useOperationIdAsQueryKey ? `"${operationName}"` : routeString;
|
|
2107
2214
|
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(", ");
|
|
2215
|
+
const verbPrefix = getQueryKeyVerbPrefix({
|
|
2216
|
+
verb,
|
|
2217
|
+
useOperationIdAsQueryKey: override.query.useOperationIdAsQueryKey
|
|
2218
|
+
});
|
|
2108
2219
|
queryKeyFns += `
|
|
2109
2220
|
${override.query.shouldExportQueryKey ? "export " : ""}const ${queryOption.queryKeyFnName} = (${queryKeyProps}) => {
|
|
2110
2221
|
return [
|
|
2111
2222
|
${[
|
|
2112
2223
|
queryOption.type === QueryType.INFINITE || queryOption.type === QueryType.SUSPENSE_INFINITE ? `'infinite'` : "",
|
|
2224
|
+
verbPrefix ? `'${verbPrefix}'` : "",
|
|
2113
2225
|
queryKeyIdentifier,
|
|
2114
2226
|
queryKeyParams,
|
|
2115
2227
|
body.implementation
|
|
@@ -2128,6 +2240,7 @@ ${queryKeyFns}`;
|
|
|
2128
2240
|
queryKeyProperties,
|
|
2129
2241
|
params,
|
|
2130
2242
|
props,
|
|
2243
|
+
body,
|
|
2131
2244
|
mutator,
|
|
2132
2245
|
isRequestOptions,
|
|
2133
2246
|
queryParams,
|
|
@@ -2141,8 +2254,8 @@ ${queryKeyFns}`;
|
|
|
2141
2254
|
route,
|
|
2142
2255
|
doc,
|
|
2143
2256
|
usePrefetch: query.usePrefetch,
|
|
2144
|
-
useQuery:
|
|
2145
|
-
useInfinite:
|
|
2257
|
+
useQuery: effectiveUseQuery,
|
|
2258
|
+
useInfinite: effectiveUseInfinite,
|
|
2146
2259
|
useInvalidate: query.useInvalidate,
|
|
2147
2260
|
useSetQueryData: operationQueryOptions?.useSetQueryData ?? query.useSetQueryData,
|
|
2148
2261
|
useGetQueryData: operationQueryOptions?.useGetQueryData ?? query.useGetQueryData,
|
|
@@ -2213,10 +2326,12 @@ const generateQuery = async (verbOptions, options, outputClient) => {
|
|
|
2213
2326
|
const imports = generateVerbImports(normalizedVerbOptions);
|
|
2214
2327
|
const functionImplementation = adapter.generateRequestFunction(normalizedVerbOptions, options);
|
|
2215
2328
|
const { implementation: hookImplementation, imports: hookImports, mutators } = await generateQueryHook(normalizedVerbOptions, options, outputClient, adapter);
|
|
2329
|
+
const isFetchHttpClient = options.context.output.httpClient !== OutputHttpClient.AXIOS;
|
|
2216
2330
|
return {
|
|
2217
2331
|
implementation: `${functionImplementation}\n\n${hookImplementation}`,
|
|
2218
2332
|
imports: [...imports, ...hookImports],
|
|
2219
|
-
mutators
|
|
2333
|
+
mutators,
|
|
2334
|
+
...isFetchHttpClient && { docComment: "" }
|
|
2220
2335
|
};
|
|
2221
2336
|
};
|
|
2222
2337
|
const dependenciesBuilder = {
|