Skip to content

Commit

Permalink
feat(query): add useMutation options
Browse files Browse the repository at this point in the history
  • Loading branch information
anymaniax committed May 23, 2023
1 parent 5c1670c commit 2b2e2b7
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 88 deletions.
2 changes: 2 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ export type OverrideOutputContentType = {

export type NormalizedQueryOptions = {
useQuery?: boolean;
useMutation?: boolean;
useInfinite?: boolean;
useInfiniteQueryParam?: string;
options?: any;
Expand All @@ -300,6 +301,7 @@ export type NormalizedQueryOptions = {

export type QueryOptions = {
useQuery?: boolean;
useMutation?: boolean;
useInfinite?: boolean;
useInfiniteQueryParam?: string;
options?: any;
Expand Down
4 changes: 4 additions & 0 deletions packages/orval/src/utils/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export const normalizeOptions = async (
},
query: {
useQuery: true,
useMutation: true,
signal: true,
...normalizeQueryOptions(outputOptions.override?.query, workspace),
},
Expand Down Expand Up @@ -361,6 +362,9 @@ const normalizeQueryOptions = (
...(!isUndefined(queryOptions.useQuery)
? { useQuery: queryOptions.useQuery }
: {}),
...(!isUndefined(queryOptions.useMutation)
? { useMutation: queryOptions.useMutation }
: {}),
...(!isUndefined(queryOptions.useInfinite)
? { useInfinite: queryOptions.useInfinite }
: {}),
Expand Down
186 changes: 99 additions & 87 deletions packages/query/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -931,11 +931,16 @@ const generateQueryHook = async (

const doc = jsDoc({ summary, deprecated });

if (
verb === Verbs.GET ||
let implementation = '';
let mutators = undefined;

const isQuery =
(Verbs.GET === verb &&
(override.query.useQuery || override.query.useInfinite)) ||
operationQueryOptions?.useInfinite ||
operationQueryOptions?.useQuery
) {
operationQueryOptions?.useQuery;

if (isQuery) {
const queryKeyMutator = query.queryKey
? await generateMutator({
output,
Expand Down Expand Up @@ -1009,7 +1014,7 @@ const generateQueryHook = async (
queryParams ? ', ...(params ? [params]: [])' : ''
}${body.implementation ? `, ${body.implementation}` : ''}] as const;`;

const implementation = `${!queryKeyMutator ? queryKeyFn : ''}
implementation += `${!queryKeyMutator ? queryKeyFn : ''}
${queries.reduce(
Expand Down Expand Up @@ -1040,82 +1045,84 @@ const generateQueryHook = async (
)}
`;

return {
implementation,
mutators:
queryOptionsMutator || queryKeyMutator
? [
...(queryOptionsMutator ? [queryOptionsMutator] : []),
...(queryKeyMutator ? [queryKeyMutator] : []),
]
: undefined,
};
mutators =
queryOptionsMutator || queryKeyMutator
? [
...(queryOptionsMutator ? [queryOptionsMutator] : []),
...(queryKeyMutator ? [queryKeyMutator] : []),
]
: undefined;
}

const mutationOptionsMutator = query.mutationOptions
? await generateMutator({
output,
mutator: query.mutationOptions,
name: `${operationName}MutationOptions`,
workspace: context.workspace,
tsconfig: context.tsconfig,
})
: undefined;

const definitions = props
.map(({ definition, type }) =>
type === GetterPropType.BODY
? mutator?.bodyTypeName
? `data: ${mutator.bodyTypeName}<${body.definition}>`
: `data: ${body.definition}`
: definition,
)
.join(';');

const properties = props
.map(({ name, type }) => (type === GetterPropType.BODY ? 'data' : name))
.join(',');
const isMutation =
(verb !== Verbs.GET && override.query.useMutation) ||
operationQueryOptions?.useMutation;

let errorType = `AxiosError<${response.definition.errors || 'unknown'}>`;
if (isMutation) {
const mutationOptionsMutator = query.mutationOptions
? await generateMutator({
output,
mutator: query.mutationOptions,
name: `${operationName}MutationOptions`,
workspace: context.workspace,
tsconfig: context.tsconfig,
})
: undefined;

if (mutator) {
errorType = mutator.hasErrorType
? `${mutator.default ? pascal(operationName) : ''}ErrorType<${
response.definition.errors || 'unknown'
}>`
: response.definition.errors || 'unknown';
}
const definitions = props
.map(({ definition, type }) =>
type === GetterPropType.BODY
? mutator?.bodyTypeName
? `data: ${mutator.bodyTypeName}<${body.definition}>`
: `data: ${body.definition}`
: definition,
)
.join(';');

const dataType = mutator?.isHook
? `ReturnType<typeof use${pascal(operationName)}Hook>`
: `typeof ${operationName}`;
const properties = props
.map(({ name, type }) => (type === GetterPropType.BODY ? 'data' : name))
.join(',');

const mutationOptionFnReturnType = getQueryOptionsDefinition({
operationName,
definitions,
mutator,
hasSvelteQueryV4,
});
let errorType = `AxiosError<${response.definition.errors || 'unknown'}>`;

const mutationArguments = generateQueryArguments({
operationName,
definitions,
mutator,
isRequestOptions,
hasSvelteQueryV4,
});
if (mutator) {
errorType = mutator.hasErrorType
? `${mutator.default ? pascal(operationName) : ''}ErrorType<${
response.definition.errors || 'unknown'
}>`
: response.definition.errors || 'unknown';
}

const mutationOptionsFnName = camel(
mutationOptionsMutator || mutator?.isHook
? `use-${operationName}-mutationOptions`
: `get-${operationName}-mutationOptions`,
);
const dataType = mutator?.isHook
? `ReturnType<typeof use${pascal(operationName)}Hook>`
: `typeof ${operationName}`;

const mutationOptionsVarName = isRequestOptions
? 'mutationOptions'
: 'options';
const mutationOptionFnReturnType = getQueryOptionsDefinition({
operationName,
definitions,
mutator,
hasSvelteQueryV4,
});

const mutationOptionsFn = `export const ${mutationOptionsFnName} = <TError = ${errorType},
const mutationArguments = generateQueryArguments({
operationName,
definitions,
mutator,
isRequestOptions,
hasSvelteQueryV4,
});

const mutationOptionsFnName = camel(
mutationOptionsMutator || mutator?.isHook
? `use-${operationName}-mutationOptions`
: `get-${operationName}-mutationOptions`,
);

const mutationOptionsVarName = isRequestOptions
? 'mutationOptions'
: 'options';

const mutationOptionsFn = `export const ${mutationOptionsFnName} = <TError = ${errorType},
${!definitions ? `TVariables = void,` : ''}
TContext = unknown>(${mutationArguments}): ${mutationOptionFnReturnType} => {
${
Expand All @@ -1138,19 +1145,19 @@ const generateQueryHook = async (
const mutationFn: MutationFunction<Awaited<ReturnType<${dataType}>>, ${
definitions ? `{${definitions}}` : 'TVariables'
}> = (${properties ? 'props' : ''}) => {
definitions ? `{${definitions}}` : 'TVariables'
}> = (${properties ? 'props' : ''}) => {
${properties ? `const {${properties}} = props ?? {};` : ''}
return ${operationName}(${properties}${properties ? ',' : ''}${
isRequestOptions
? !mutator
? `axiosOptions`
: mutator?.hasSecondArg
? 'requestOptions'
isRequestOptions
? !mutator
? `axiosOptions`
: mutator?.hasSecondArg
? 'requestOptions'
: ''
: ''
: ''
})
})
}
${
Expand All @@ -1172,9 +1179,9 @@ const generateQueryHook = async (
: 'customOptions'
}}`;

const operationPrefix = hasSvelteQueryV4 ? 'create' : 'use';
const operationPrefix = hasSvelteQueryV4 ? 'create' : 'use';

const implementation = `
implementation += `
${mutationOptionsFn}
export type ${pascal(
Expand All @@ -1192,22 +1199,27 @@ ${mutationOptionsFn}
export type ${pascal(operationName)}MutationError = ${errorType}
${doc}export const ${camel(
`${operationPrefix}-${operationName}`,
)} = <TError = ${errorType},
`${operationPrefix}-${operationName}`,
)} = <TError = ${errorType},
${!definitions ? `TVariables = void,` : ''}
TContext = unknown>(${mutationArguments}) => {
const ${mutationOptionsVarName} = ${mutationOptionsFnName}(${
isRequestOptions ? 'options' : 'mutationOptions'
});
isRequestOptions ? 'options' : 'mutationOptions'
});
return ${operationPrefix}Mutation(${mutationOptionsVarName});
}
`;

mutators = mutationOptionsMutator
? [...(mutators ?? []), mutationOptionsMutator]
: mutators;
}

return {
implementation,
mutators: mutationOptionsMutator ? [mutationOptionsMutator] : undefined,
mutators,
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ export type ListPetsInfiniteQueryResult = NonNullable<
>;
export type ListPetsInfiniteQueryError = ErrorType<Error>;

/**
* @summary List all pets
*/
export const useListPetsInfinite = <
TData = Awaited<ReturnType<typeof listPets>>,
TError = ErrorType<Error>,
Expand Down Expand Up @@ -178,6 +181,9 @@ export type ListPetsQueryResult = NonNullable<
>;
export type ListPetsQueryError = ErrorType<Error>;

/**
* @summary List all pets
*/
export const useListPets = <
TData = Awaited<ReturnType<typeof listPets>>,
TError = ErrorType<Error>,
Expand Down Expand Up @@ -251,6 +257,9 @@ export type CreatePetsMutationResult = NonNullable<
export type CreatePetsMutationBody = CreatePetsBody;
export type CreatePetsMutationError = ErrorType<Error>;

/**
* @summary Create a pet
*/
export const useCreatePets = <
TError = ErrorType<Error>,
TContext = unknown,
Expand Down Expand Up @@ -315,6 +324,9 @@ export type UpdatePetsMutationResult = NonNullable<
export type UpdatePetsMutationBody = NonReadonly<Pet>;
export type UpdatePetsMutationError = ErrorType<Error>;

/**
* @summary Update a pet
*/
export const useUpdatePets = <
TError = ErrorType<Error>,
TContext = unknown,
Expand Down Expand Up @@ -384,6 +396,9 @@ export type ShowPetByIdInfiniteQueryResult = NonNullable<
>;
export type ShowPetByIdInfiniteQueryError = ErrorType<Error>;

/**
* @summary Info for a specific pet
*/
export const useShowPetByIdInfinite = <
TData = Awaited<ReturnType<typeof showPetById>>,
TError = ErrorType<Error>,
Expand Down Expand Up @@ -447,6 +462,9 @@ export type ShowPetByIdQueryResult = NonNullable<
>;
export type ShowPetByIdQueryError = ErrorType<Error>;

/**
* @summary Info for a specific pet
*/
export const useShowPetById = <
TData = Awaited<ReturnType<typeof showPetById>>,
TError = ErrorType<Error>,
Expand Down
2 changes: 1 addition & 1 deletion samples/react-query/basic/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "es6",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
Expand Down

0 comments on commit 2b2e2b7

Please sign in to comment.