@orval/query 8.16.0 → 8.18.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
@@ -1,4 +1,4 @@
1
- import { GetterPropType, OutputClient, OutputHttpClient, Verbs, camel, compareVersions, generateFormDataAndUrlEncodedFunction, generateMutator, generateMutatorConfig, generateMutatorRequestOptions, generateOptions, generateVerbImports, getAngularFilteredParamsCallExpression, getAngularFilteredParamsHelperBody, getRouteAsArray, getSuccessResponseType, isObject, isString, isSyntheticDefaultImportsAllow, jsDoc, kebab, logWarning, makeRouteSafe, mergeDeep, pascal, stringify, toObjectString } from "@orval/core";
1
+ import { GetterPropType, OutputClient, OutputHttpClient, Verbs, camel, compareVersions, generateFormDataAndUrlEncodedFunction, generateMutator, generateMutatorConfig, generateMutatorRequestOptions, generateOptions, generateVerbImports, getAngularFilteredParamsCallExpression, getAngularFilteredParamsHelperBody, getFullRoute, getRouteAsArray, getSuccessResponseType, isObject, isString, isSyntheticDefaultImportsAllow, jsDoc, kebab, logWarning, makeRouteSafe, 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";
@@ -680,11 +680,16 @@ const VUE_QUERY_DEPENDENCIES = [{
680
680
  name: "useMutation",
681
681
  values: true
682
682
  },
683
+ {
684
+ name: "useQueryClient",
685
+ values: true
686
+ },
683
687
  { name: "UseQueryOptions" },
684
688
  { name: "UseInfiniteQueryOptions" },
685
689
  { name: "UseMutationOptions" },
686
690
  { name: "QueryFunction" },
687
691
  { name: "MutationFunction" },
692
+ { name: "MutationFunctionContext" },
688
693
  { name: "QueryKey" },
689
694
  { name: "UseQueryReturnType" },
690
695
  { name: "UseInfiniteQueryReturnType" },
@@ -1122,7 +1127,7 @@ const createReactAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5
1122
1127
  >`;
1123
1128
  },
1124
1129
  getQueryReturnStatement({ queryResultVarName, queryOptionsVarName }) {
1125
- return `return { ...${queryResultVarName}, queryKey: ${queryOptionsVarName}.queryKey };`;
1130
+ return `return withQueryKey(${queryResultVarName}, ${queryOptionsVarName}.queryKey);`;
1126
1131
  },
1127
1132
  shouldGenerateOverrideTypes() {
1128
1133
  return hasQueryV5;
@@ -1371,17 +1376,39 @@ const createVueAdapter = ({ hasVueQueryV4, hasQueryV5, hasQueryV5WithDataTagErro
1371
1376
  getQueryKeyPrefix() {
1372
1377
  return hasVueQueryV4 ? "" : "queryOptions?.queryKey ?? ";
1373
1378
  },
1374
- generateMutationImplementation({ mutationOptionsFnName, isRequestOptions }) {
1375
- return `${mutationOptionsFnName}(${isRequestOptions ? "options" : "mutationOptions"})`;
1379
+ generateMutationImplementation({ mutationOptionsFnName, hasInvalidation, isRequestOptions }) {
1380
+ return `${mutationOptionsFnName}(${hasInvalidation ? `queryClient ?? backupQueryClient, ` : ""}${isRequestOptions ? "options" : "mutationOptions"})`;
1376
1381
  },
1377
1382
  supportsMutationInvalidation() {
1378
- return false;
1383
+ return hasQueryV5;
1379
1384
  },
1380
- generateMutationOnSuccess() {
1381
- return "";
1385
+ generateMutationOnSuccess({ operationName, definitions, isRequestOptions, generateInvalidateCall, uniqueInvalidates }) {
1386
+ const invalidateCalls = uniqueInvalidates.map((t) => generateInvalidateCall(t)).join("\n");
1387
+ if (hasQueryV5WithMutationContextOnSuccess) {
1388
+ if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
1389
+ if (!options?.skipInvalidation) {
1390
+ ${invalidateCalls}
1391
+ }
1392
+ unref(unref(typeof mutationOptions === 'function' ? mutationOptions() : mutationOptions)?.onSuccess)?.(data, variables, onMutateResult, context);
1393
+ };`;
1394
+ return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
1395
+ ${invalidateCalls}
1396
+ unref(unref(typeof mutationOptions === 'function' ? mutationOptions() : mutationOptions)?.onSuccess)?.(data, variables, onMutateResult, context);
1397
+ };`;
1398
+ }
1399
+ if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext${hasQueryV5WithRequiredContextOnSuccess ? "" : " | undefined"}) => {
1400
+ if (!options?.skipInvalidation) {
1401
+ ${invalidateCalls}
1402
+ }
1403
+ unref(unref(typeof mutationOptions === 'function' ? mutationOptions() : mutationOptions)?.onSuccess)?.(data, variables, context);
1404
+ };`;
1405
+ return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext${hasQueryV5WithRequiredContextOnSuccess ? "" : " | undefined"}) => {
1406
+ ${invalidateCalls}
1407
+ unref(unref(typeof mutationOptions === 'function' ? mutationOptions() : mutationOptions)?.onSuccess)?.(data, variables, context);
1408
+ };`;
1382
1409
  },
1383
- generateMutationHookBody({ operationPrefix, mutationImplementation, optionalQueryClientArgument }) {
1384
- return ` return ${operationPrefix}Mutation(${mutationImplementation}${optionalQueryClientArgument ? `, queryClient` : ""});`;
1410
+ generateMutationHookBody({ operationPrefix, mutationImplementation, hasInvalidation, optionalQueryClientArgument }) {
1411
+ return ` ${hasInvalidation ? `const backupQueryClient = useQueryClient();\n ` : ""}return ${operationPrefix}Mutation(${mutationImplementation}${optionalQueryClientArgument ? `, queryClient` : ""});`;
1385
1412
  },
1386
1413
  generateRequestFunction(verbOptions, options) {
1387
1414
  return options.context.output.httpClient === OutputHttpClient.AXIOS ? generateAxiosRequestFunction(verbOptions, options, true) : generateRequestFunction(verbOptions, options);
@@ -1661,10 +1688,18 @@ const generateParamArgs = (params) => {
1661
1688
  return Object.values(params).map((v) => generateParamArg(v)).join(", ");
1662
1689
  };
1663
1690
  /**
1691
+ * Build the code-literal form of a static route prefix for use inside a
1692
+ * `.startsWith(...)` predicate. A prefix derived from a runtime `baseUrl`
1693
+ * contains a `${...}` interpolation, so it must be emitted as a template
1694
+ * literal; otherwise a plain single-quoted string is enough and keeps the
1695
+ * output byte-identical to the no-baseUrl case.
1696
+ */
1697
+ const toPrefixLiteral = (prefix) => prefix.includes("${") ? `\`${prefix}\`` : `'${prefix}'`;
1698
+ /**
1664
1699
  * Create a generateInvalidateCall function that has access to the OpenAPI spec
1665
1700
  * for intelligent route-based invalidation when params are not specified.
1666
1701
  */
1667
- const createGenerateInvalidateCall = (spec, shouldSplitQueryKey, useOperationIdAsQueryKey) => {
1702
+ const createGenerateInvalidateCall = (spec, shouldSplitQueryKey, useOperationIdAsQueryKey, baseUrl, servers) => {
1668
1703
  return (target) => {
1669
1704
  const method = target.invalidateMode === "reset" ? "resetQueries" : "invalidateQueries";
1670
1705
  const queryKeyFn = camel(`get-${target.query}-query-key`);
@@ -1673,16 +1708,18 @@ const createGenerateInvalidateCall = (spec, shouldSplitQueryKey, useOperationIdA
1673
1708
  if (info?.hasRequiredPathParams) {
1674
1709
  const prefix = getStaticRoutePrefix(info.route);
1675
1710
  if (prefix !== void 0) {
1711
+ const prefixWithBase = getFullRoute(prefix, servers, baseUrl);
1676
1712
  const verbPrefix = getQueryKeyVerbPrefix({
1677
1713
  verb: info.method,
1678
1714
  useOperationIdAsQueryKey
1679
1715
  });
1680
1716
  if (shouldSplitQueryKey) {
1681
- const segments = prefix.split("/").filter((s) => s !== "").map((s) => `'${s}'`).join(", ");
1717
+ const segments = getRouteAsArray(prefixWithBase);
1682
1718
  return ` queryClient.${method}({ queryKey: ${verbPrefix ? `['${verbPrefix}', ${segments}]` : `[${segments}]`} });`;
1683
1719
  }
1684
- if (verbPrefix) return ` queryClient.${method}({ predicate: (query) => query.queryKey[0] === '${verbPrefix}' && typeof query.queryKey[1] === 'string' && query.queryKey[1].startsWith('${prefix}') });`;
1685
- return ` queryClient.${method}({ predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith('${prefix}') });`;
1720
+ const prefixLiteral = toPrefixLiteral(prefixWithBase);
1721
+ if (verbPrefix) return ` queryClient.${method}({ predicate: (query) => query.queryKey[0] === '${verbPrefix}' && typeof query.queryKey[1] === 'string' && query.queryKey[1].startsWith(${prefixLiteral}) });`;
1722
+ return ` queryClient.${method}({ predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith(${prefixLiteral}) });`;
1686
1723
  }
1687
1724
  }
1688
1725
  return ` queryClient.${method}({ queryKey: ${queryKeyFn}() });`;
@@ -1763,7 +1800,7 @@ ${hasInvalidation ? adapter.generateMutationOnSuccess({
1763
1800
  operationName,
1764
1801
  definitions,
1765
1802
  isRequestOptions,
1766
- generateInvalidateCall: createGenerateInvalidateCall(context.spec, !!query.shouldSplitQueryKey, !!query.useOperationIdAsQueryKey),
1803
+ generateInvalidateCall: createGenerateInvalidateCall(context.spec, !!query.shouldSplitQueryKey, !!query.useOperationIdAsQueryKey, context.output.baseUrl, context.spec.servers),
1767
1804
  uniqueInvalidates
1768
1805
  }) : ""}
1769
1806
 
@@ -2414,12 +2451,27 @@ ${queryKeyFns}`;
2414
2451
  };
2415
2452
  //#endregion
2416
2453
  //#region src/index.ts
2454
+ const WITH_QUERY_KEY_HELPER = `const withQueryKey = <T extends object, K>(query: T, queryKey: K): T & { queryKey: K } => {
2455
+ const result = { queryKey } as T & { queryKey: K };
2456
+ for (const key of Object.keys(query)) {
2457
+ // The explicit queryKey always wins, matching the previous
2458
+ // \`{ ...query, queryKey }\` spread where it was set last.
2459
+ if (key === 'queryKey') continue;
2460
+ Object.defineProperty(result, key, {
2461
+ enumerable: true,
2462
+ configurable: true,
2463
+ get: () => (query as Record<string, unknown>)[key],
2464
+ });
2465
+ }
2466
+ return result;
2467
+ };`;
2417
2468
  const generateQueryHeader = (params) => {
2469
+ const needsWithQueryKey = params.clientImplementation.includes("withQueryKey(");
2418
2470
  return `${params.hasAwaitedType ? "" : `type AwaitedInput<T> = PromiseLike<T> | T;\n
2419
2471
  type Awaited<O> = O extends AwaitedInput<infer T> ? T : never;\n\n`}
2420
2472
  ${params.isRequestOptions && params.isMutator ? `type SecondParameter<T extends (...args: never) => unknown> = Parameters<T>[1];\n\n` : ""}
2421
2473
  ${getQueryHeader(params)}
2422
- `;
2474
+ ${needsWithQueryKey ? `${WITH_QUERY_KEY_HELPER}\n\n` : ""}`;
2423
2475
  };
2424
2476
  const generateQuery = async (verbOptions, options, outputClient) => {
2425
2477
  const isZodOutput = typeof options.context.output.schemas === "object" && options.context.output.schemas.type === "zod";