@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 +242 -77
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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 ? {
|
|
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:
|
|
723
|
-
{ name:
|
|
724
|
-
{ name:
|
|
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:
|
|
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 =
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
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 =
|
|
1966
|
-
|
|
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
|
|
1969
|
-
|
|
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 ${
|
|
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 ?
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
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}>(${
|
|
2194
|
+
queryClient.getQueryData<${TData}>(${setQueryDataKeyExpr});
|
|
2028
2195
|
}\n` : `${doc}export const ${getQueryDataFnName} = (queryClient: QueryClient, ${getQueryDataProps}) =>
|
|
2029
|
-
queryClient.getQueryData<${TData}>(${
|
|
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
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
let isQuery =
|
|
2055
|
-
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
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:
|
|
2171
|
-
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,
|