Skip to content

Commit

Permalink
feat(query): allow body type customisation through mutator for mutations
Browse files Browse the repository at this point in the history
  • Loading branch information
CPatchane committed Feb 14, 2022
1 parent 2b2de08 commit 638e2ee
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 9 deletions.
3 changes: 3 additions & 0 deletions docs/src/pages/guides/custom-axios.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ export const customInstance = <T>(config: AxiosRequestConfig): Promise<T> => {

// In some case with react-query and swr you want to be able to override the return error type so you can also do it here like this
export type ErrorType<Error> = AxiosError<Error>;
// In case you want to wrap the body type (optional)
// (if the custom instance is processing data before sending it, like changing the case for example)
export type BodyType<BodyData> = CamelCase<BodyType>
```
5 changes: 4 additions & 1 deletion docs/src/pages/guides/custom-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,7 @@ export default customInstance;

// In some case with react-query and swr you want to be able to override the return error type so you can also do it here like this
export type ErrorType<Error> = AxiosError<Error>;
```
// In case you want to wrap the body type (optional)
// (if the custom instance is processing data before sending it, like changing the case for example)
export type BodyType<BodyData> = CamelCase<BodyType>
```
5 changes: 5 additions & 0 deletions docs/src/pages/reference/configuration/output.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,9 @@ export const customInstance = <T>(config: AxiosRequestConfig): Promise<T> => {

// In some case with react-query and swr you want to be able to override the return error type so you can also do it here like this
export type ErrorType<Error> = AxiosError<Error>;
// In case you want to wrap the body type (optional)
// (if the custom instance is processing data before sending it, like changing the case for example)
export type BodyType<BodyData> = CamelCase<BodyType>
```
- If your file have some alias you will also need to define them in the mutator object.
Expand Down Expand Up @@ -400,6 +403,7 @@ export const customInstance = <T>(config: AxiosRequestConfig): Promise<T> => {
};

export type ErrorType<Error> = AxiosError<Error>;
export type BodyType<BodyData> = CamelCase<BodyType>
```
```js
Expand Down Expand Up @@ -475,6 +479,7 @@ export const useCustomInstance = <T>(): ((
export default useCustomInstance;

export type ErrorType<Error> = AxiosError<Error>;
export type BodyType<BodyData> = CamelCase<BodyType>
```
#### header
Expand Down
7 changes: 5 additions & 2 deletions src/core/generators/imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
GeneratorVerbOptions,
} from '../../types/generator';
import { camel } from '../../utils/case';
import { BODY_TYPE_NAME } from './mutator';

export const generateImports = ({
imports = [],
Expand Down Expand Up @@ -63,12 +64,14 @@ export const generateMutatorImports = (
const importDefault = mutator.default
? `${mutator.name}${
mutator.hasErrorType
? `, { ErrorType as ${mutator.errorTypeName} }`
? `, { ErrorType as ${mutator.errorTypeName}${
mutator.bodyTypeName ? `, ${BODY_TYPE_NAME} as ${mutator.bodyTypeName}` : ''
} }`
: ''
}`
: `{ ${mutator.name}${
mutator.hasErrorType ? `, ${mutator.errorTypeName}` : ''
} }`;
}${mutator.bodyTypeName ? `, ${mutator.bodyTypeName}` : ''} }`;

return `import ${importDefault} from '${oneMore ? '../' : ''}${
mutator.path
Expand Down
12 changes: 12 additions & 0 deletions src/core/generators/mutator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { getFileInfo, loadFile } from '../../utils/file';
import { createLogger } from '../../utils/messages/logs';
import { relativeSafe } from '../../utils/path';

export const BODY_TYPE_NAME = 'BodyType';

const getImport = (output: string, mutator: NormalizedMutator) => {
const outputFileInfo = getFileInfo(output);
const mutatorFileInfo = getFileInfo(mutator.path);
Expand Down Expand Up @@ -43,10 +45,18 @@ export const generateMutator = async ({
rawFile.includes('export type ErrorType') ||
rawFile.includes('export interface ErrorType');

const hasBodyType =
rawFile.includes(`export type ${BODY_TYPE_NAME}`) ||
rawFile.includes(`export interface ${BODY_TYPE_NAME}`);

const errorTypeName = !mutator.default
? 'ErrorType'
: `${pascal(name)}ErrorType`;

const bodyTypeName = !mutator.default
? BODY_TYPE_NAME
: `${pascal(name)}${BODY_TYPE_NAME}`;

const { file, cached } = await loadFile<Record<string, Function>>(
importPath,
{
Expand Down Expand Up @@ -81,6 +91,7 @@ export const generateMutator = async ({
mutatorFn,
hasErrorType,
errorTypeName,
...(hasBodyType ? { bodyTypeName } : {}),
};
} else {
const path = getImport(output, mutator);
Expand All @@ -100,6 +111,7 @@ export const generateMutator = async ({
mutatorFn: () => undefined,
hasErrorType,
errorTypeName,
...(hasBodyType ? { bodyTypeName } : {}),
};
}
};
24 changes: 18 additions & 6 deletions src/core/generators/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ const generateQueryRequestFunction = (
isFormUrlEncoded,
});

const propsImplementation = mutator?.bodyTypeName
? toObjectString(props, 'implementation').replace(
new RegExp(`(${verb}\\w*):\\s?(\\w*)`),
`$1: ${mutator.bodyTypeName}<$2>`,
)
: toObjectString(props, 'implementation');

const isMutatorHasSecondArg = mutator.mutatorFn.length > 1;
const requestOptions = isRequestOptions
? generateMutatorRequestOptions(
Expand All @@ -172,7 +179,7 @@ const generateQueryRequestFunction = (
response.definition.success || 'unknown'
}>();
return (\n ${toObjectString(props, 'implementation')}\n ${
return (\n ${propsImplementation}\n ${
isRequestOptions && isMutatorHasSecondArg
? `options?: SecondParameter<typeof ${mutator.name}>`
: ''
Expand All @@ -185,10 +192,7 @@ const generateQueryRequestFunction = (
`;
}

return `export const ${operationName} = (\n ${toObjectString(
props,
'implementation',
)}\n ${
return `export const ${operationName} = (\n ${propsImplementation}\n ${
isRequestOptions && isMutatorHasSecondArg
? `options?: SecondParameter<typeof ${mutator.name}>`
: ''
Expand Down Expand Up @@ -539,7 +543,11 @@ const generateQueryHook = (

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

Expand Down Expand Up @@ -569,6 +577,10 @@ const generateQueryHook = (
export type ${pascal(
operationName,
)}MutationResult = NonNullable<AsyncReturnType<${dataType}>>
export type ${pascal(operationName)}MutationBody = ${definitions.replace(
/^.*data:\s?([\w<>]*),?.*$/,
'$1',
)}
export type ${pascal(operationName)}MutationError = ${errorType}
export const ${camel(`use-${operationName}`)} = <TError = ${errorType},
Expand Down
1 change: 1 addition & 0 deletions src/types/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export type GeneratorMutator = {
mutatorFn: Function;
hasErrorType: boolean;
errorTypeName: string;
bodyTypeName?: string
};

export type ClientBuilder = (
Expand Down

0 comments on commit 638e2ee

Please sign in to comment.