fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #1419 from hey-api/fix/axios-response-type

fix: infer responseType in SDKs for axios client

authored by

Lubos and committed by
GitHub
9ad666d6 2bf12331

+90 -2
+5
.changeset/fresh-feet-exist.md
··· 1 + --- 2 + '@hey-api/openapi-ts': patch 3 + --- 4 + 5 + fix: infer responseType in SDKs for axios client
+1 -1
packages/openapi-ts/src/ir/operation.ts
··· 61 61 62 62 type StatusGroup = '1XX' | '2XX' | '3XX' | '4XX' | '5XX' | 'default'; 63 63 64 - const statusCodeToGroup = ({ 64 + export const statusCodeToGroup = ({ 65 65 statusCode, 66 66 }: { 67 67 statusCode: string;
+74 -1
packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts
··· 5 5 import { clientApi, clientModulePath } from '../../../generate/client'; 6 6 import type { IRContext } from '../../../ir/context'; 7 7 import type { IROperationObject } from '../../../ir/ir'; 8 - import { hasOperationDataRequired } from '../../../ir/operation'; 8 + import { 9 + hasOperationDataRequired, 10 + statusCodeToGroup, 11 + } from '../../../ir/operation'; 9 12 import { escapeComment } from '../../../utils/escape'; 10 13 import { getServiceName } from '../../../utils/postprocess'; 11 14 import { irRef } from '../../../utils/ref'; ··· 74 77 75 78 const sdkId = 'sdk'; 76 79 80 + /** 81 + * Infers `responseType` value from provided response content type. This is 82 + * an adapted version of `getParseAs()` from the Fetch API client. 83 + * 84 + * From Axios documentation: 85 + * `responseType` indicates the type of data that the server will respond with 86 + * options are: 'arraybuffer', 'document', 'json', 'text', 'stream' 87 + * browser only: 'blob' 88 + */ 89 + export const getResponseType = ( 90 + contentType: string | null | undefined, 91 + ): 92 + | 'arraybuffer' 93 + | 'blob' 94 + | 'document' 95 + | 'json' 96 + | 'stream' 97 + | 'text' 98 + | undefined => { 99 + if (!contentType) { 100 + return; 101 + } 102 + 103 + const cleanContent = contentType.split(';')[0].trim(); 104 + 105 + if ( 106 + cleanContent.startsWith('application/json') || 107 + cleanContent.endsWith('+json') 108 + ) { 109 + return 'json'; 110 + } 111 + 112 + // Axios does not handle form data out of the box 113 + // if (cleanContent === 'multipart/form-data') { 114 + // return 'formData'; 115 + // } 116 + 117 + if ( 118 + ['application/', 'audio/', 'image/', 'video/'].some((type) => 119 + cleanContent.startsWith(type), 120 + ) 121 + ) { 122 + return 'blob'; 123 + } 124 + 125 + if (cleanContent.startsWith('text/')) { 126 + return 'text'; 127 + } 128 + }; 129 + 77 130 const operationStatements = ({ 78 131 context, 79 132 operation, ··· 171 224 }, 172 225 ], 173 226 }); 227 + } 228 + 229 + if (context.config.client.name === '@hey-api/client-axios') { 230 + // try to infer `responseType` option for Axios. We don't need this in 231 + // Fetch API client because it automatically detects the correct response 232 + // during runtime. 233 + for (const statusCode in operation.responses) { 234 + // this doesn't handle default status code for now 235 + if (statusCodeToGroup({ statusCode }) === '2XX') { 236 + const response = operation.responses[statusCode]; 237 + const responseType = getResponseType(response?.mediaType); 238 + // json is the default, skip it 239 + if (responseType && responseType !== 'json') { 240 + requestOptions.push({ 241 + key: 'responseType', 242 + value: responseType, 243 + }); 244 + } 245 + } 246 + } 174 247 } 175 248 176 249 // TODO: parser - set parseAs to skip inference if every response has the same
+1
packages/openapi-ts/test/__snapshots__/3.0.x/plugins/@tanstack/angular-query-experimental/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.0.x/plugins/@tanstack/react-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.0.x/plugins/@tanstack/solid-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.0.x/plugins/@tanstack/svelte-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.0.x/plugins/@tanstack/vue-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.1.x/plugins/@tanstack/angular-query-experimental/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.1.x/plugins/@tanstack/react-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.1.x/plugins/@tanstack/solid-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.1.x/plugins/@tanstack/svelte-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };
+1
packages/openapi-ts/test/__snapshots__/3.1.x/plugins/@tanstack/vue-query/axios/sdk.gen.ts
··· 304 304 export const fileResponse = <ThrowOnError extends boolean = false>(options: Options<FileResponseData, ThrowOnError>) => { 305 305 return (options?.client ?? client).get<FileResponseResponse, unknown, ThrowOnError>({ 306 306 ...options, 307 + responseType: 'blob', 307 308 url: '/api/v{api-version}/file/{id}' 308 309 }); 309 310 };