diff --git a/src/core/generators/angular.ts b/src/core/generators/angular.ts index 5125e7403..718ba5d76 100644 --- a/src/core/generators/angular.ts +++ b/src/core/generators/angular.ts @@ -117,7 +117,7 @@ const generateImplementation = ( formData, formUrlEncoded, }: GeneratorVerbOptions, - { route }: GeneratorOptions, + { route, context }: GeneratorOptions, ) => { const isRequestOptions = override?.requestOptions !== false; const isFormData = override?.formData !== false; @@ -140,6 +140,9 @@ const generateImplementation = ( ); if (mutator) { + const isExactOptionalPropertyTypes = + !!context.tsconfig?.compilerOptions?.exactOptionalPropertyTypes; + const mutatorConfig = generateMutatorConfig({ route, body, @@ -150,6 +153,7 @@ const generateImplementation = ( isFormUrlEncoded, hasSignal: false, isBodyVerb, + isExactOptionalPropertyTypes, }); const requestOptions = isRequestOptions diff --git a/src/core/generators/axios.ts b/src/core/generators/axios.ts index 543b1a17a..03b378de3 100644 --- a/src/core/generators/axios.ts +++ b/src/core/generators/axios.ts @@ -72,6 +72,9 @@ const generateAxiosImplementation = ( const isBodyVerb = VERBS_WITH_BODY.includes(verb); if (mutator) { + const isExactOptionalPropertyTypes = + !!context.tsconfig?.compilerOptions?.exactOptionalPropertyTypes; + const mutatorConfig = generateMutatorConfig({ route, body, @@ -82,6 +85,7 @@ const generateAxiosImplementation = ( isFormUrlEncoded, isBodyVerb, hasSignal: true, + isExactOptionalPropertyTypes, }); const requestOptions = isRequestOptions diff --git a/src/core/generators/options.ts b/src/core/generators/options.ts index f3bd3c6a5..c789a35c0 100644 --- a/src/core/generators/options.ts +++ b/src/core/generators/options.ts @@ -137,20 +137,20 @@ export const generateBodyMutatorConfig = ( export const generateQueryParamsAxiosConfig = ( response: GetterResponse, - queryParams?: GeneratorSchema, + queryParams?: GetterQueryParam, ) => { if (!queryParams && !response.isBlob) { return ''; } - let value = ','; + let value = ''; if (queryParams) { - value += '\n params,'; + value += ',\n params'; } if (response.isBlob) { - value += `\n responseType: 'blob',`; + value += `,\n responseType: 'blob'`; } return value; @@ -166,6 +166,7 @@ export const generateMutatorConfig = ({ isFormUrlEncoded, isBodyVerb, hasSignal, + isExactOptionalPropertyTypes, }: { route: string; body: GetterBody; @@ -176,6 +177,7 @@ export const generateMutatorConfig = ({ isFormUrlEncoded: boolean; isBodyVerb: boolean; hasSignal: boolean; + isExactOptionalPropertyTypes: boolean; }) => { const bodyOptions = isBodyVerb ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) @@ -183,16 +185,22 @@ export const generateMutatorConfig = ({ const queryParamsOptions = generateQueryParamsAxiosConfig( response, - queryParams?.schema, + queryParams, ); const headerOptions = body.contentType ? `,\n headers: {'Content-Type': '${body.contentType}'}` : ''; - return `{url: \`${route}\`, method: '${verb}'${ - !isBodyVerb && hasSignal ? ', signal' : '' - }${headerOptions}${bodyOptions}${queryParamsOptions}\n }`; + return `{url: \`${route}\`, method: '${verb}'${headerOptions}${bodyOptions}${queryParamsOptions}${ + !isBodyVerb && hasSignal + ? `, ${ + isExactOptionalPropertyTypes + ? '...(signal ? { signal }: {})' + : 'signal' + }` + : '' + }\n }`; }; export const generateMutatorRequestOptions = ( diff --git a/src/core/generators/query.ts b/src/core/generators/query.ts index 43fa20cd0..0a884d6c7 100644 --- a/src/core/generators/query.ts +++ b/src/core/generators/query.ts @@ -147,6 +147,8 @@ const generateQueryRequestFunction = ( const isSyntheticDefaultImportsAllowed = isSyntheticDefaultImportsAllow( context.tsconfig, ); + const isExactOptionalPropertyTypes = + !!context.tsconfig?.compilerOptions?.exactOptionalPropertyTypes; const isBodyVerb = VERBS_WITH_BODY.includes(verb); const bodyForm = generateFormDataAndUrlEncodedFunction({ @@ -168,6 +170,7 @@ const generateQueryRequestFunction = ( isFormUrlEncoded, isBodyVerb, hasSignal: true, + isExactOptionalPropertyTypes, }); const propsImplementation = @@ -364,6 +367,58 @@ const generateQueryReturnType = ({ } }; +const getQueryOptions = ({ + isRequestOptions, + mutator, + isExactOptionalPropertyTypes, +}: { + isRequestOptions: boolean; + mutator?: GeneratorMutator; + isExactOptionalPropertyTypes: boolean; +}) => { + if (!isRequestOptions) { + return ''; + } + + if (!mutator) { + return `{ ${ + isExactOptionalPropertyTypes ? '...(signal ? { signal } : {})' : 'signal' + }, ...axiosOptions }`; + } + + if (mutator.hasSecondArg) { + return 'requestOptions, signal'; + } + + return 'signal'; +}; + +const getHookOptions = ({ + isRequestOptions, + mutator, +}: { + isRequestOptions: boolean; + mutator?: GeneratorMutator; +}) => { + if (!isRequestOptions) { + return ''; + } + + let value = 'const {query: queryOptions'; + + if (!mutator) { + value += ', axios: axiosOptions'; + } + + if (mutator?.hasSecondArg) { + value += ', request: requestOptions'; + } + + value += '} = options ?? {}'; + + return value; +}; + const generateQueryImplementation = ({ queryOption: { name, queryParam, options, type }, operationName, @@ -376,6 +431,7 @@ const generateQueryImplementation = ({ isRequestOptions, response, outputClient, + isExactOptionalPropertyTypes, }: { queryOption: { name: string; @@ -393,6 +449,7 @@ const generateQueryImplementation = ({ response: GetterResponse; mutator?: GeneratorMutator; outputClient: OutputClient | OutputClientFunc; + isExactOptionalPropertyTypes: boolean; }) => { const httpFunctionProps = queryParam ? props @@ -423,6 +480,17 @@ const generateQueryImplementation = ({ ? `ReturnType` : `typeof ${operationName}`; + const queryOptions = getQueryOptions({ + isRequestOptions, + isExactOptionalPropertyTypes, + mutator, + }); + + const hookOptions = getHookOptions({ + isRequestOptions, + mutator, + }); + return ` export type ${pascal( name, @@ -441,17 +509,7 @@ export const ${camel( }, )}\n ): ${returnType} & { queryKey: QueryKey } => { - ${ - isRequestOptions - ? `const {query: queryOptions${ - !mutator - ? `, axios: axiosOptions` - : mutator.hasSecondArg - ? ', request: requestOptions' - : '' - }} = options ?? {}` - : '' - } + ${hookOptions} const queryKey = queryOptions?.queryKey ?? ${queryKeyFnName}(${properties}); @@ -469,15 +527,9 @@ export const ${camel( queryParam && props.some(({ type }) => type === 'queryParam') ? `{ signal, pageParam }` : '{ signal }' - }) => ${operationName}(${httpFunctionProps}${httpFunctionProps ? ', ' : ''}${ - isRequestOptions - ? !mutator - ? `{ signal, ...axiosOptions }` - : mutator.hasSecondArg - ? 'requestOptions, signal' - : 'signal' - : '' - }); + }) => ${operationName}(${httpFunctionProps}${ + httpFunctionProps ? ', ' : '' + }${queryOptions}); const query = ${camel(`use-${type}`)} { const query = override?.query; const isRequestOptions = override?.requestOptions !== false; const operationQueryOptions = operations[operationId]?.query; + const isExactOptionalPropertyTypes = + !!context.tsconfig?.compilerOptions?.exactOptionalPropertyTypes; if ( verb === Verbs.GET || @@ -570,6 +624,7 @@ const generateQueryHook = ( isRequestOptions, response, outputClient, + isExactOptionalPropertyTypes, }), '', )} diff --git a/src/core/generators/swr.ts b/src/core/generators/swr.ts index f7220a70c..519b5e44c 100644 --- a/src/core/generators/swr.ts +++ b/src/core/generators/swr.ts @@ -88,6 +88,9 @@ const generateSwrRequestFunction = ( }); if (mutator) { + const isExactOptionalPropertyTypes = + !!context.tsconfig?.compilerOptions?.exactOptionalPropertyTypes; + const mutatorConfig = generateMutatorConfig({ route, body, @@ -98,6 +101,7 @@ const generateSwrRequestFunction = ( isFormUrlEncoded, hasSignal: false, isBodyVerb, + isExactOptionalPropertyTypes, }); const requestOptions = isRequestOptions diff --git a/src/types/index.ts b/src/types/index.ts index e20b014b3..ead48b10a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -344,6 +344,7 @@ export interface Tsconfig { compilerOptions?: { esModuleInterop?: boolean; allowSyntheticDefaultImports?: boolean; + exactOptionalPropertyTypes?: boolean; paths?: Record; }; }