@orval/query 8.3.0 → 8.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { GetterPropType, OutputClient, OutputHttpClient, TEMPLATE_TAG_REGEX, Verbs, camel, compareVersions, generateFormDataAndUrlEncodedFunction, generateMutator, generateMutatorConfig, generateMutatorRequestOptions, generateOptions, generateVerbImports, getRouteAsArray, isObject, isString, isSyntheticDefaultImportsAllow, jsDoc, mergeDeep, pascal, stringify, toObjectString, upath } 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, mergeDeep, pascal, stringify, toObjectString, upath } from "@orval/core";
2
2
  import { generateFetchHeader, generateRequestFunction } from "@orval/fetch";
3
3
  import chalk from "chalk";
4
4
  import { omitBy } from "remeda";
@@ -167,24 +167,29 @@ const generateAngularHttpRequestFunction = ({ headers, queryParams, operationNam
167
167
  const queryProps = toObjectString(props, "implementation").replace(/,\s*$/, "");
168
168
  const dataType = response.definition.success || "unknown";
169
169
  const hasQueryParams = queryParams?.schema.name;
170
- const urlConstruction = hasQueryParams ? `const httpParams = params ? new HttpParams({ fromObject: params as Record<string, string> }) : undefined;
170
+ const filteredParamsExpression = getAngularFilteredParamsCallExpression("params", queryParams?.requiredNullableKeys);
171
+ const urlConstruction = hasQueryParams ? `const httpParams = params ? new HttpParams({ fromObject: ${filteredParamsExpression} }) : undefined;
171
172
  const url = \`${route}\`;` : `const url = \`${route}\`;`;
172
173
  const httpOptions = [];
173
174
  if (hasQueryParams) httpOptions.push("params: httpParams");
174
175
  if (headers) httpOptions.push("headers: new HttpHeaders(headers)");
176
+ const successResponseType = getSuccessResponseType(response);
177
+ const responseTypeOption = successResponseType ? `'${successResponseType}'` : void 0;
178
+ if (responseTypeOption) httpOptions.push(`responseType: ${responseTypeOption}`);
175
179
  const optionsStr = httpOptions.length > 0 ? `, { ${httpOptions.join(", ")} }` : "";
176
180
  let httpCall;
181
+ const httpGeneric = responseTypeOption ? "" : `<${dataType}>`;
177
182
  const bodyArg = isFormData && body.formData ? "formData" : isFormUrlEncoded && body.formUrlEncoded ? "formUrlEncoded" : body.definition ? toObjectString([body], "implementation").replace(/,\s*$/, "") : "";
178
183
  switch (verb) {
179
184
  case "get":
180
185
  case "head":
181
- httpCall = `http.${verb}<${dataType}>(url${optionsStr})`;
186
+ httpCall = `http.${verb}${httpGeneric}(url${optionsStr})`;
182
187
  break;
183
188
  case "delete":
184
- httpCall = bodyArg ? `http.${verb}<${dataType}>(url, { ${httpOptions.length > 0 ? httpOptions.join(", ") + ", " : ""}body: ${bodyArg} })` : `http.${verb}<${dataType}>(url${optionsStr})`;
189
+ httpCall = bodyArg ? `http.${verb}${httpGeneric}(url, { ${httpOptions.length > 0 ? httpOptions.join(", ") + ", " : ""}body: ${bodyArg} })` : `http.${verb}${httpGeneric}(url${optionsStr})`;
185
190
  break;
186
191
  default:
187
- httpCall = `http.${verb}<${dataType}>(url, ${bodyArg || "undefined"}${optionsStr})`;
192
+ httpCall = `http.${verb}${httpGeneric}(url, ${bodyArg || "undefined"}${optionsStr})`;
188
193
  break;
189
194
  }
190
195
  const responseType = response.definition.success;
@@ -197,7 +202,7 @@ const generateAngularHttpRequestFunction = ({ headers, queryParams, operationNam
197
202
  ].includes(responseType);
198
203
  const hasSchema = response.imports.some((imp) => imp.name === responseType);
199
204
  const isZodOutput = isObject(context.output.schemas) && context.output.schemas.type === "zod";
200
- if (override.query.runtimeValidation && isZodOutput && !isPrimitiveType && hasSchema) httpCall = `${httpCall}.pipe(map(data => ${responseType}.parse(data)))`;
205
+ if (override.query.runtimeValidation && isZodOutput && !isPrimitiveType && hasSchema) httpCall = `${httpCall}.pipe(map(data => ${responseType === "Error" ? "ErrorSchema" : responseType}.parse(data)))`;
201
206
  const additionalParams = [queryProps, hasSignal ? "options?: { signal?: AbortSignal | null }" : ""].filter(Boolean).join(", ");
202
207
  return `${override.query.shouldExportHttpClient ? "export " : ""}const ${operationName} = (
203
208
  http: HttpClient${additionalParams ? `,\n ${additionalParams}` : ""}
@@ -395,7 +400,9 @@ const getMutationRequestArgs = (isRequestOptions, httpClient, mutator) => {
395
400
  return isRequestOptions ? mutator ? mutator.hasSecondArg ? "requestOptions" : "" : options : "";
396
401
  };
397
402
  const getQueryHeader = (params) => {
398
- return params.output.httpClient === OutputHttpClient.FETCH ? generateFetchHeader(params) : "";
403
+ if (params.output.httpClient === OutputHttpClient.FETCH) return generateFetchHeader(params);
404
+ if (params.output.httpClient === OutputHttpClient.ANGULAR) return Object.values(params.verbOptions).some((v) => v.queryParams) ? getAngularFilteredParamsHelperBody() : "";
405
+ return "";
399
406
  };
400
407
 
401
408
  //#endregion
@@ -565,6 +572,7 @@ const REACT_QUERY_DEPENDENCIES = [{
565
572
  { name: "UseMutationOptions" },
566
573
  { name: "QueryFunction" },
567
574
  { name: "MutationFunction" },
575
+ { name: "MutationFunctionContext" },
568
576
  { name: "UseQueryResult" },
569
577
  { name: "DefinedUseQueryResult" },
570
578
  { name: "UseSuspenseQueryResult" },
@@ -815,6 +823,18 @@ const isQueryV5WithDataTagError = (packageJson, queryClient) => {
815
823
  const withoutRc = version.split("-")[0];
816
824
  return compareVersions(withoutRc, "5.62.0");
817
825
  };
826
+ const isQueryV5WithRequiredContextOnSuccess = (packageJson, queryClient) => {
827
+ const version = getPackageByQueryClient(packageJson, queryClient);
828
+ if (!version) return false;
829
+ const withoutRc = version.split("-")[0];
830
+ return compareVersions(withoutRc, "5.14.1");
831
+ };
832
+ const isQueryV5WithMutationContextOnSuccess = (packageJson, queryClient) => {
833
+ const version = getPackageByQueryClient(packageJson, queryClient);
834
+ if (!version) return false;
835
+ const withoutRc = version.split("-")[0];
836
+ return compareVersions(withoutRc, "5.89.0");
837
+ };
818
838
  const isQueryV5WithInfiniteQueryOptionsError = (packageJson, queryClient) => {
819
839
  if (queryClient === "angular-query") return true;
820
840
  const version = getPackageByQueryClient(packageJson, queryClient);
@@ -830,11 +850,26 @@ const isSolidQueryWithUsePrefix = (packageJson) => {
830
850
  };
831
851
  const getPackageByQueryClient = (packageJson, queryClient) => {
832
852
  switch (queryClient) {
833
- case "react-query": return packageJson?.dependencies?.["@tanstack/react-query"] ?? packageJson?.devDependencies?.["@tanstack/react-query"] ?? packageJson?.peerDependencies?.["@tanstack/react-query"];
834
- case "svelte-query": return packageJson?.dependencies?.["@tanstack/svelte-query"] ?? packageJson?.devDependencies?.["@tanstack/svelte-query"] ?? packageJson?.peerDependencies?.["@tanstack/svelte-query"];
835
- case "vue-query": return packageJson?.dependencies?.["@tanstack/vue-query"] ?? packageJson?.devDependencies?.["@tanstack/vue-query"] ?? packageJson?.peerDependencies?.["@tanstack/vue-query"];
836
- case "angular-query": return packageJson?.dependencies?.["@tanstack/angular-query-experimental"] ?? packageJson?.devDependencies?.["@tanstack/angular-query-experimental"] ?? packageJson?.peerDependencies?.["@tanstack/angular-query-experimental"];
837
- case "solid-query": return packageJson?.dependencies?.["@tanstack/solid-query"] ?? packageJson?.devDependencies?.["@tanstack/solid-query"] ?? packageJson?.peerDependencies?.["@tanstack/solid-query"];
853
+ case "react-query": {
854
+ const pkgName = "@tanstack/react-query";
855
+ return packageJson?.resolvedVersions?.[pkgName] ?? packageJson?.dependencies?.[pkgName] ?? packageJson?.devDependencies?.[pkgName] ?? packageJson?.peerDependencies?.[pkgName];
856
+ }
857
+ case "svelte-query": {
858
+ const pkgName = "@tanstack/svelte-query";
859
+ return packageJson?.resolvedVersions?.[pkgName] ?? packageJson?.dependencies?.[pkgName] ?? packageJson?.devDependencies?.[pkgName] ?? packageJson?.peerDependencies?.[pkgName];
860
+ }
861
+ case "vue-query": {
862
+ const pkgName = "@tanstack/vue-query";
863
+ return packageJson?.resolvedVersions?.[pkgName] ?? packageJson?.dependencies?.[pkgName] ?? packageJson?.devDependencies?.[pkgName] ?? packageJson?.peerDependencies?.[pkgName];
864
+ }
865
+ case "angular-query": {
866
+ const pkgName = "@tanstack/angular-query-experimental";
867
+ return packageJson?.resolvedVersions?.[pkgName] ?? packageJson?.dependencies?.[pkgName] ?? packageJson?.devDependencies?.[pkgName] ?? packageJson?.peerDependencies?.[pkgName];
868
+ }
869
+ case "solid-query": {
870
+ const pkgName = "@tanstack/solid-query";
871
+ return packageJson?.resolvedVersions?.[pkgName] ?? packageJson?.dependencies?.[pkgName] ?? packageJson?.devDependencies?.[pkgName] ?? packageJson?.peerDependencies?.[pkgName];
872
+ }
838
873
  }
839
874
  };
840
875
 
@@ -879,7 +914,7 @@ const getQueryOptionsDefinition = ({ operationName, mutator, definitions, type,
879
914
 
880
915
  //#endregion
881
916
  //#region src/frameworks/angular.ts
882
- const createAngularAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError }) => {
917
+ const createAngularAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasQueryV5WithMutationContextOnSuccess, hasQueryV5WithRequiredContextOnSuccess }) => {
883
918
  const prefix = "Create";
884
919
  return {
885
920
  outputClient: OutputClient.ANGULAR_QUERY,
@@ -888,6 +923,8 @@ const createAngularAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQuery
888
923
  hasQueryV5,
889
924
  hasQueryV5WithDataTagError,
890
925
  hasQueryV5WithInfiniteQueryOptionsError,
926
+ hasQueryV5WithMutationContextOnSuccess,
927
+ hasQueryV5WithRequiredContextOnSuccess,
891
928
  getHookPropsDefinitions(props) {
892
929
  return toObjectString(props.map((prop) => {
893
930
  const getterType = prop.definition.replace(/^(\w+)(\??): (.+)$/, (_match, name, optional, type) => `${name}${optional}: ${type} | (() => ${type.replace(" | undefined", "")}${optional ? " | undefined" : ""})`);
@@ -981,19 +1018,6 @@ const createAngularAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQuery
981
1018
  supportsMutationInvalidation() {
982
1019
  return true;
983
1020
  },
984
- generateMutationOnSuccess({ operationName, definitions, isRequestOptions, generateInvalidateCall: generateInvalidateCall$1, uniqueInvalidates }) {
985
- const invalidateCalls = uniqueInvalidates.map((t) => generateInvalidateCall$1(t)).join("\n");
986
- if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
987
- if (!options?.skipInvalidation) {
988
- ${invalidateCalls}
989
- }
990
- mutationOptions?.onSuccess?.(data, variables, onMutateResult, context);
991
- };`;
992
- return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
993
- ${invalidateCalls}
994
- mutationOptions?.onSuccess?.(data, variables, onMutateResult, context);
995
- };`;
996
- },
997
1021
  generateMutationHookBody({ operationPrefix, mutationOptionsFnName, mutationOptionsVarName, isRequestOptions, mutator, hasInvalidation }) {
998
1022
  if (!mutator || mutator.hasSecondArg) return ` const http = inject(HttpClient);${hasInvalidation ? "\n const queryClient = inject(QueryClient);" : ""}
999
1023
  const ${mutationOptionsVarName} = ${mutationOptionsFnName}(http${hasInvalidation ? ", queryClient" : ""}${isRequestOptions ? ", options" : ", mutationOptions"});
@@ -1014,12 +1038,14 @@ ${invalidateCalls}
1014
1038
 
1015
1039
  //#endregion
1016
1040
  //#region src/frameworks/react.ts
1017
- const createReactAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError }) => ({
1041
+ const createReactAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasQueryV5WithMutationContextOnSuccess, hasQueryV5WithRequiredContextOnSuccess }) => ({
1018
1042
  outputClient: OutputClient.REACT_QUERY,
1019
1043
  hookPrefix: "use",
1020
1044
  hasQueryV5,
1021
1045
  hasQueryV5WithDataTagError,
1022
1046
  hasQueryV5WithInfiniteQueryOptionsError,
1047
+ hasQueryV5WithMutationContextOnSuccess,
1048
+ hasQueryV5WithRequiredContextOnSuccess,
1023
1049
  getQueryReturnType({ type, isInitialDataDefined }) {
1024
1050
  return ` ${isInitialDataDefined && !isSuspenseQuery(type) ? "Defined" : ""}Use${pascal(type)}Result<TData, TError> & { queryKey: ${hasQueryV5 ? `DataTag<QueryKey, TData${hasQueryV5WithDataTagError ? ", TError" : ""}>` : "QueryKey"} }`;
1025
1051
  },
@@ -1043,19 +1069,6 @@ const createReactAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5
1043
1069
  supportsMutationInvalidation() {
1044
1070
  return true;
1045
1071
  },
1046
- generateMutationOnSuccess({ operationName, definitions, isRequestOptions, generateInvalidateCall: generateInvalidateCall$1, uniqueInvalidates }) {
1047
- const invalidateCalls = uniqueInvalidates.map((t) => generateInvalidateCall$1(t)).join("\n");
1048
- if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext) => {
1049
- if (!options?.skipInvalidation) {
1050
- ${invalidateCalls}
1051
- }
1052
- mutationOptions?.onSuccess?.(data, variables, context);
1053
- };`;
1054
- return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext) => {
1055
- ${invalidateCalls}
1056
- mutationOptions?.onSuccess?.(data, variables, context);
1057
- };`;
1058
- },
1059
1072
  generateMutationHookBody({ operationPrefix, mutationImplementation, hasInvalidation, optionalQueryClientArgument }) {
1060
1073
  return ` ${hasInvalidation ? `const backupQueryClient = useQueryClient();\n ` : ""}return ${operationPrefix}Mutation(${mutationImplementation}${optionalQueryClientArgument ? `, queryClient` : ""});`;
1061
1074
  },
@@ -1066,12 +1079,14 @@ ${invalidateCalls}
1066
1079
 
1067
1080
  //#endregion
1068
1081
  //#region src/frameworks/solid.ts
1069
- const createSolidAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasSolidQueryUsePrefix }) => ({
1082
+ const createSolidAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasQueryV5WithMutationContextOnSuccess, hasQueryV5WithRequiredContextOnSuccess, hasSolidQueryUsePrefix }) => ({
1070
1083
  outputClient: OutputClient.SOLID_QUERY,
1071
1084
  hookPrefix: hasSolidQueryUsePrefix ? "use" : "create",
1072
1085
  hasQueryV5,
1073
1086
  hasQueryV5WithDataTagError,
1074
1087
  hasQueryV5WithInfiniteQueryOptionsError,
1088
+ hasQueryV5WithMutationContextOnSuccess,
1089
+ hasQueryV5WithRequiredContextOnSuccess,
1075
1090
  getQueryOptionsDefinitionPrefix() {
1076
1091
  return hasSolidQueryUsePrefix ? "Use" : "Create";
1077
1092
  },
@@ -1111,7 +1126,7 @@ const createSolidAdapter = ({ hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5
1111
1126
 
1112
1127
  //#endregion
1113
1128
  //#region src/frameworks/svelte.ts
1114
- const createSvelteAdapter = ({ hasSvelteQueryV4, hasSvelteQueryV6, hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError }) => {
1129
+ const createSvelteAdapter = ({ hasSvelteQueryV4, hasSvelteQueryV6, hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasQueryV5WithMutationContextOnSuccess, hasQueryV5WithRequiredContextOnSuccess }) => {
1115
1130
  const prefix = hasSvelteQueryV4 ? "Create" : "Use";
1116
1131
  return {
1117
1132
  outputClient: OutputClient.SVELTE_QUERY,
@@ -1119,6 +1134,8 @@ const createSvelteAdapter = ({ hasSvelteQueryV4, hasSvelteQueryV6, hasQueryV5, h
1119
1134
  hasQueryV5,
1120
1135
  hasQueryV5WithDataTagError,
1121
1136
  hasQueryV5WithInfiniteQueryOptionsError,
1137
+ hasQueryV5WithMutationContextOnSuccess,
1138
+ hasQueryV5WithRequiredContextOnSuccess,
1122
1139
  getHookPropsDefinitions(props) {
1123
1140
  if (hasSvelteQueryV6) return toObjectString(props.map((p) => ({
1124
1141
  ...p,
@@ -1194,31 +1211,6 @@ const createSvelteAdapter = ({ hasSvelteQueryV4, hasSvelteQueryV6, hasQueryV5, h
1194
1211
  supportsMutationInvalidation() {
1195
1212
  return true;
1196
1213
  },
1197
- generateMutationOnSuccess({ operationName, definitions, isRequestOptions, generateInvalidateCall: generateInvalidateCall$1, uniqueInvalidates }) {
1198
- const invalidateCalls = uniqueInvalidates.map((t) => generateInvalidateCall$1(t)).join("\n");
1199
- if (hasSvelteQueryV6) {
1200
- if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
1201
- if (!options?.skipInvalidation) {
1202
- ${invalidateCalls}
1203
- }
1204
- mutationOptions?.onSuccess?.(data, variables, onMutateResult, context);
1205
- };`;
1206
- return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
1207
- ${invalidateCalls}
1208
- mutationOptions?.onSuccess?.(data, variables, onMutateResult, context);
1209
- };`;
1210
- }
1211
- if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext | undefined) => {
1212
- if (!options?.skipInvalidation) {
1213
- ${invalidateCalls}
1214
- }
1215
- mutationOptions?.onSuccess?.(data, variables, context);
1216
- };`;
1217
- return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext | undefined) => {
1218
- ${invalidateCalls}
1219
- mutationOptions?.onSuccess?.(data, variables, context);
1220
- };`;
1221
- },
1222
1214
  generateMutationHookBody({ operationPrefix, mutationImplementation, hasInvalidation, optionalQueryClientArgument }) {
1223
1215
  if (hasSvelteQueryV6) return ` ${hasInvalidation ? `const backupQueryClient = useQueryClient(${optionalQueryClientArgument ? "queryClient?.()" : ""});\n ` : ""}return ${operationPrefix}Mutation(() => ({ ...${mutationImplementation} })${optionalQueryClientArgument ? `, queryClient` : ""});`;
1224
1216
  return ` ${hasInvalidation ? `const backupQueryClient = useQueryClient();\n ` : ""}return ${operationPrefix}Mutation(${mutationImplementation});`;
@@ -1235,12 +1227,14 @@ ${invalidateCalls}
1235
1227
 
1236
1228
  //#endregion
1237
1229
  //#region src/frameworks/vue.ts
1238
- const createVueAdapter = ({ hasVueQueryV4, hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError }) => ({
1230
+ const createVueAdapter = ({ hasVueQueryV4, hasQueryV5, hasQueryV5WithDataTagError, hasQueryV5WithInfiniteQueryOptionsError, hasQueryV5WithMutationContextOnSuccess, hasQueryV5WithRequiredContextOnSuccess }) => ({
1239
1231
  outputClient: OutputClient.VUE_QUERY,
1240
1232
  hookPrefix: "use",
1241
1233
  hasQueryV5,
1242
1234
  hasQueryV5WithDataTagError,
1243
1235
  hasQueryV5WithInfiniteQueryOptionsError,
1236
+ hasQueryV5WithMutationContextOnSuccess,
1237
+ hasQueryV5WithRequiredContextOnSuccess,
1244
1238
  transformProps(props) {
1245
1239
  return vueWrapTypeWithMaybeRef(props);
1246
1240
  },
@@ -1375,6 +1369,32 @@ const withDefaults = (adapter) => ({
1375
1369
  const optionsType = `{ ${type ? "query" : "mutation"}${isQueryRequired ? "" : "?"}:${definition}, ${!type && hasInvalidation ? "skipInvalidation?: boolean, " : ""}${requestType}}`;
1376
1370
  return `options${isQueryRequired ? "" : "?"}: ${optionsType}\n`;
1377
1371
  },
1372
+ generateMutationOnSuccess({ operationName, definitions, isRequestOptions, generateInvalidateCall: generateInvalidateCall$1, uniqueInvalidates }) {
1373
+ const invalidateCalls = uniqueInvalidates.map((t) => generateInvalidateCall$1(t)).join("\n");
1374
+ if (adapter.hasQueryV5WithMutationContextOnSuccess) {
1375
+ if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
1376
+ if (!options?.skipInvalidation) {
1377
+ ${invalidateCalls}
1378
+ }
1379
+ mutationOptions?.onSuccess?.(data, variables, onMutateResult, context);
1380
+ };`;
1381
+ return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, onMutateResult: TContext, context: MutationFunctionContext) => {
1382
+ ${invalidateCalls}
1383
+ mutationOptions?.onSuccess?.(data, variables, onMutateResult, context);
1384
+ };`;
1385
+ } else {
1386
+ if (isRequestOptions) return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext${adapter.hasQueryV5WithRequiredContextOnSuccess ? "" : " | undefined"}) => {
1387
+ if (!options?.skipInvalidation) {
1388
+ ${invalidateCalls}
1389
+ }
1390
+ mutationOptions?.onSuccess?.(data, variables, context);
1391
+ };`;
1392
+ return ` const onSuccess = (data: Awaited<ReturnType<typeof ${operationName}>>, variables: ${definitions ? `{${definitions}}` : "void"}, context: TContext${adapter.hasQueryV5WithRequiredContextOnSuccess ? "" : " | undefined"}) => {
1393
+ ${invalidateCalls}
1394
+ mutationOptions?.onSuccess?.(data, variables, context);
1395
+ };`;
1396
+ }
1397
+ },
1378
1398
  ...adapter
1379
1399
  });
1380
1400
  /**
@@ -1386,35 +1406,47 @@ const createFrameworkAdapter = ({ outputClient, packageJson, queryVersion }) =>
1386
1406
  const _hasQueryV5 = queryVersion === 5 || isQueryV5(packageJson, clientType);
1387
1407
  const _hasQueryV5WithDataTagError = queryVersion === 5 || isQueryV5WithDataTagError(packageJson, clientType);
1388
1408
  const _hasQueryV5WithInfiniteQueryOptionsError = queryVersion === 5 || isQueryV5WithInfiniteQueryOptionsError(packageJson, clientType);
1409
+ const _hasQueryV5WithMutationContextOnSuccess = isQueryV5WithMutationContextOnSuccess(packageJson, clientType);
1410
+ const _hasQueryV5WithRequiredContextOnSuccess = isQueryV5WithRequiredContextOnSuccess(packageJson, clientType);
1389
1411
  switch (outputClient) {
1390
1412
  case OutputClient.VUE_QUERY: return withDefaults(createVueAdapter({
1391
1413
  hasVueQueryV4: !isVueQueryV3(packageJson) || queryVersion === 4,
1392
1414
  hasQueryV5: _hasQueryV5,
1393
1415
  hasQueryV5WithDataTagError: _hasQueryV5WithDataTagError,
1394
- hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError
1416
+ hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError,
1417
+ hasQueryV5WithMutationContextOnSuccess: _hasQueryV5WithMutationContextOnSuccess,
1418
+ hasQueryV5WithRequiredContextOnSuccess: _hasQueryV5WithRequiredContextOnSuccess
1395
1419
  }));
1396
1420
  case OutputClient.SVELTE_QUERY: return withDefaults(createSvelteAdapter({
1397
1421
  hasSvelteQueryV4: !isSvelteQueryV3(packageJson) || queryVersion === 4,
1398
1422
  hasSvelteQueryV6: isSvelteQueryV6(packageJson),
1399
1423
  hasQueryV5: _hasQueryV5,
1400
1424
  hasQueryV5WithDataTagError: _hasQueryV5WithDataTagError,
1401
- hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError
1425
+ hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError,
1426
+ hasQueryV5WithMutationContextOnSuccess: _hasQueryV5WithMutationContextOnSuccess,
1427
+ hasQueryV5WithRequiredContextOnSuccess: _hasQueryV5WithRequiredContextOnSuccess
1402
1428
  }));
1403
1429
  case OutputClient.ANGULAR_QUERY: return withDefaults(createAngularAdapter({
1404
1430
  hasQueryV5: _hasQueryV5,
1405
1431
  hasQueryV5WithDataTagError: _hasQueryV5WithDataTagError,
1406
- hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError
1432
+ hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError,
1433
+ hasQueryV5WithMutationContextOnSuccess: _hasQueryV5WithMutationContextOnSuccess,
1434
+ hasQueryV5WithRequiredContextOnSuccess: _hasQueryV5WithRequiredContextOnSuccess
1407
1435
  }));
1408
1436
  case OutputClient.SOLID_QUERY: return withDefaults(createSolidAdapter({
1409
1437
  hasQueryV5: _hasQueryV5,
1410
1438
  hasQueryV5WithDataTagError: _hasQueryV5WithDataTagError,
1411
1439
  hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError,
1440
+ hasQueryV5WithMutationContextOnSuccess: _hasQueryV5WithMutationContextOnSuccess,
1441
+ hasQueryV5WithRequiredContextOnSuccess: _hasQueryV5WithRequiredContextOnSuccess,
1412
1442
  hasSolidQueryUsePrefix: isSolidQueryWithUsePrefix(packageJson)
1413
1443
  }));
1414
1444
  default: return withDefaults(createReactAdapter({
1415
1445
  hasQueryV5: _hasQueryV5,
1416
1446
  hasQueryV5WithDataTagError: _hasQueryV5WithDataTagError,
1417
- hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError
1447
+ hasQueryV5WithInfiniteQueryOptionsError: _hasQueryV5WithInfiniteQueryOptionsError,
1448
+ hasQueryV5WithMutationContextOnSuccess: _hasQueryV5WithMutationContextOnSuccess,
1449
+ hasQueryV5WithRequiredContextOnSuccess: _hasQueryV5WithRequiredContextOnSuccess
1418
1450
  }));
1419
1451
  }
1420
1452
  };
@@ -1431,7 +1463,8 @@ const normalizeTarget = (target) => isString(target) ? {
1431
1463
  const serializeTarget = (target) => JSON.stringify({
1432
1464
  query: target.query,
1433
1465
  params: target.params ?? [],
1434
- invalidateMode: target.invalidateMode
1466
+ invalidateMode: target.invalidateMode,
1467
+ file: target.file ?? ""
1435
1468
  });
1436
1469
  const generateVariableRef = (varName) => {
1437
1470
  const parts = varName.split(".");
@@ -1560,7 +1593,12 @@ ${mutationOptionsFn}
1560
1593
  ${mutationHookBody}
1561
1594
  }
1562
1595
  `,
1563
- mutators: mutationOptionsMutator ? [mutationOptionsMutator] : void 0
1596
+ mutators: mutationOptionsMutator ? [mutationOptionsMutator] : void 0,
1597
+ imports: hasInvalidation ? uniqueInvalidates.filter((i) => !!i.file).map((i) => ({
1598
+ name: camel(`get-${i.query}-query-key`),
1599
+ importPath: i.file,
1600
+ values: true
1601
+ })) : []
1564
1602
  };
1565
1603
  };
1566
1604
 
@@ -1812,7 +1850,6 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
1812
1850
  const isRequestOptions = override.requestOptions !== false;
1813
1851
  const operationQueryOptions = operations[operationId]?.query;
1814
1852
  const isExactOptionalPropertyTypes = !!context.output.tsconfig?.compilerOptions?.exactOptionalPropertyTypes;
1815
- const { hasQueryV5 } = adapter;
1816
1853
  const httpClient = context.output.httpClient;
1817
1854
  const doc = jsDoc({
1818
1855
  summary,
@@ -1886,8 +1923,8 @@ const generateQueryHook = async (verbOptions, options, outputClient, adapter) =>
1886
1923
  }] : []
1887
1924
  ];
1888
1925
  const uniqueQueryOptionsByKeys = queries.filter((obj, index, self) => index === self.findIndex((t) => t.queryKeyFnName === obj.queryKeyFnName));
1889
- implementation += `
1890
- ${queryKeyMutator ? "" : uniqueQueryOptionsByKeys.reduce((acc, queryOption) => {
1926
+ let queryKeyFns = "";
1927
+ if (!queryKeyMutator) for (const queryOption of uniqueQueryOptionsByKeys) {
1891
1928
  const makeOptionalParam = (impl) => {
1892
1929
  if (impl.includes("=")) return impl;
1893
1930
  return impl.replace(/^(\w+):\s*/, "$1?: ");
@@ -1899,7 +1936,7 @@ ${queryKeyMutator ? "" : uniqueQueryOptionsByKeys.reduce((acc, queryOption) => {
1899
1936
  const routeString = adapter.getQueryKeyRouteString(route, !!override.query.shouldSplitQueryKey);
1900
1937
  const queryKeyIdentifier = override.query.useOperationIdAsQueryKey ? `"${operationName}"` : routeString;
1901
1938
  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(", ");
1902
- return acc + `
1939
+ queryKeyFns += `
1903
1940
  ${override.query.shouldExportQueryKey ? "export " : ""}const ${queryOption.queryKeyFnName} = (${queryKeyProps}) => {
1904
1941
  return [
1905
1942
  ${[
@@ -1911,37 +1948,40 @@ ${override.query.shouldExportQueryKey ? "export " : ""}const ${queryOption.query
1911
1948
  ] as const;
1912
1949
  }
1913
1950
  `;
1914
- }, "")}`;
1951
+ }
1915
1952
  implementation += `
1916
- ${queries.reduce((acc, queryOption) => {
1917
- return acc + generateQueryImplementation({
1918
- queryOption,
1919
- operationName,
1920
- queryProperties,
1921
- queryKeyProperties,
1922
- params,
1923
- props,
1924
- mutator,
1925
- isRequestOptions,
1926
- queryParams,
1927
- response,
1928
- httpClient,
1929
- isExactOptionalPropertyTypes,
1930
- hasSignal: getHasSignal({ overrideQuerySignal: override.query.signal }),
1931
- queryOptionsMutator,
1932
- queryKeyMutator,
1933
- route,
1934
- doc,
1935
- usePrefetch: query.usePrefetch,
1936
- useQuery: query.useQuery,
1937
- useInfinite: query.useInfinite,
1938
- useInvalidate: query.useInvalidate,
1939
- adapter
1940
- });
1941
- }, "")}
1953
+ ${queryKeyFns}`;
1954
+ let queryImplementations = "";
1955
+ for (const queryOption of queries) queryImplementations += generateQueryImplementation({
1956
+ queryOption,
1957
+ operationName,
1958
+ queryProperties,
1959
+ queryKeyProperties,
1960
+ params,
1961
+ props,
1962
+ mutator,
1963
+ isRequestOptions,
1964
+ queryParams,
1965
+ response,
1966
+ httpClient,
1967
+ isExactOptionalPropertyTypes,
1968
+ hasSignal: getHasSignal({ overrideQuerySignal: override.query.signal }),
1969
+ queryOptionsMutator,
1970
+ queryKeyMutator,
1971
+ route,
1972
+ doc,
1973
+ usePrefetch: query.usePrefetch,
1974
+ useQuery: query.useQuery,
1975
+ useInfinite: query.useInfinite,
1976
+ useInvalidate: query.useInvalidate,
1977
+ adapter
1978
+ });
1979
+ implementation += `
1980
+ ${queryImplementations}
1942
1981
  `;
1943
1982
  mutators = queryOptionsMutator || queryKeyMutator ? [...queryOptionsMutator ? [queryOptionsMutator] : [], ...queryKeyMutator ? [queryKeyMutator] : []] : void 0;
1944
1983
  }
1984
+ let imports = [];
1945
1985
  if (isMutation) {
1946
1986
  const mutationResult = await generateMutationHook({
1947
1987
  verbOptions: {
@@ -1956,10 +1996,12 @@ ${override.query.shouldExportQueryKey ? "export " : ""}const ${queryOption.query
1956
1996
  });
1957
1997
  implementation += mutationResult.implementation;
1958
1998
  mutators = mutationResult.mutators ? [...mutators ?? [], ...mutationResult.mutators] : mutators;
1999
+ imports = mutationResult.imports;
1959
2000
  }
1960
2001
  return {
1961
2002
  implementation,
1962
- mutators
2003
+ mutators,
2004
+ imports
1963
2005
  };
1964
2006
  };
1965
2007
 
@@ -1973,17 +2015,36 @@ ${getQueryHeader(params)}
1973
2015
  `;
1974
2016
  };
1975
2017
  const generateQuery = async (verbOptions, options, outputClient) => {
2018
+ const isZodOutput = typeof options.context.output.schemas === "object" && options.context.output.schemas.type === "zod";
2019
+ const responseType = verbOptions.response.definition.success;
2020
+ const isPrimitiveResponse = [
2021
+ "string",
2022
+ "number",
2023
+ "boolean",
2024
+ "void",
2025
+ "unknown"
2026
+ ].includes(responseType);
2027
+ const normalizedVerbOptions = verbOptions.override.query.runtimeValidation && isZodOutput && !isPrimitiveResponse && verbOptions.response.imports.some((imp) => imp.name === responseType) ? {
2028
+ ...verbOptions,
2029
+ response: {
2030
+ ...verbOptions.response,
2031
+ imports: verbOptions.response.imports.map((imp) => imp.name === responseType ? {
2032
+ ...imp,
2033
+ values: true
2034
+ } : imp)
2035
+ }
2036
+ } : verbOptions;
1976
2037
  const adapter = createFrameworkAdapter({
1977
2038
  outputClient,
1978
2039
  packageJson: options.context.output.packageJson,
1979
- queryVersion: verbOptions.override.query.version
2040
+ queryVersion: normalizedVerbOptions.override.query.version
1980
2041
  });
1981
- const imports = generateVerbImports(verbOptions);
1982
- const functionImplementation = adapter.generateRequestFunction(verbOptions, options);
1983
- const { implementation: hookImplementation, mutators } = await generateQueryHook(verbOptions, options, outputClient, adapter);
2042
+ const imports = generateVerbImports(normalizedVerbOptions);
2043
+ const functionImplementation = adapter.generateRequestFunction(normalizedVerbOptions, options);
2044
+ const { implementation: hookImplementation, imports: hookImports, mutators } = await generateQueryHook(normalizedVerbOptions, options, outputClient, adapter);
1984
2045
  return {
1985
2046
  implementation: `${functionImplementation}\n\n${hookImplementation}`,
1986
- imports,
2047
+ imports: [...imports, ...hookImports],
1987
2048
  mutators
1988
2049
  };
1989
2050
  };