Generated client does not return successful status codes
In some APIs I returns multiple status codes to distinguish between an object being created, updated, or no action being taken because the current value is already as requested by the client.
Currently I make axios requests on these APIs and check the status code to disambiguate the response type, rather than having a discriminated union of response types.
The generated client services do not expose the response status for successful requests , and the client services do now allow customization to pass a success predicate function to determine if a request was successful or not to try and cheat and use the error code in the thrown ApiError.
const isSuccess = (status: number): boolean => {
return status >= 200 && status < 300;
};
I'd prefer a pattern where services return an object similar to an Axios Response which contains isOk, status, headers, etc.
Another idea would be that if there are multiple successful status codes, openapi-typescript-codegen could generate its own discriminated union for the response where you can check response.status for the real type.
If an API returns a string for 200, and a number for 204, the generated method could return <{status: 200, data: string} | {status: 204, data: number}> rather than <string | number> as it does now.
I am exploring this utility as an option for our company repo, and I arrived here curious about the same. I am currently using the default generated http client, and noticed that the request generates an opinionated API response of ApiResult.
export type ApiResult = {
readonly url: string;
readonly ok: boolean;
readonly status: number;
readonly statusText: string;
readonly body: any;
};
The client then resolves only the body of ApiResult.
const result: ApiResult = {
url,
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: responseHeader ?? responseBody,
};
catchErrorCodes(options, result);
resolve(result.body);
It is unfortunate that the return is only the response body; returning the ApiResult it self would be infinitely more useful. It may be best to return the underlying Response versus an opinionated abstraction of ApiResult as It would highly increase the usability of this utility, vs vending opinionated abstractions that either intentionally, or unintentionally, create limitations.
Interestingly enough, the Angular handlebar template does return the ApiResult. A good first step in this area might be consistency between all of the client templates.
map(response => {
const responseBody = getResponseBody(response);
const responseHeader = getResponseHeader(response, options.responseHeader);
return {
url,
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: responseHeader ?? responseBody,
} as ApiResult;
}),
Agreed on consistency @Marshal27. Do you use Angular?
@rcbevans @Marshal27 you can get a fully typed result object in @nicolas-chaulet/openapi-typescript-codegen like this
const result = await MyService.operationMethod({
_result: 'raw'
})
console.log(result.body)
console.log(result.ok)
console.log(result.status)
console.log(result.statusText)
console.log(result.url)
I had to update the API a bit as the non-breaking generics change was in fact breaking when working with other libraries. To get the above behaviour
openapi --serviceResponse generics
to always return full result object
openapi --serviceResponse response
or the default/old behaviour can be optionally explicitly stated as
openapi --serviceResponse body
@rcbevans @Marshal27 are you able to share more about how you use this package? Particularly how you handle the existing response data