orval
orval copied to clipboard
Fetch: generator does not seem to support multiple response types
Description
If you use an openAPI schema with multiple responses like this:
"/api/user": {
"get": {
"operationId": "get_user",
"summary": "Get User",
"parameters": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/UserResponse" }
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ApiErrorResponse" }
}
}
}
The generated fetch will only have the 200 response type (in this example UserResponse). It does not seem to generate a union type for the method return type.
I tried to work around this using customFetch so I can union with the alternative response type: https://github.com/orval-labs/orval/blob/master/samples/next-app-with-fetch/custom-fetch.ts#L56
However, this wouldn't work as the result type <T> is generated by Orval.
Some maybe loosely related issues: #420, #935
I wonder if fetch needs generateEachHttpStatus similar to mock and zod https://github.com/orval-labs/orval/issues/1380
Hello @soartec-lab do you have any guidance on how to work on this issue? Currently it is hard to handle non-200 responses and errors in the generated code without this case.
@jamesleeht
There are no plans at the moment.
Does this mean that you want to include patterns other than 200 such as 404 in the data of responseType?
@soartec-lab pretty sure that's exactly what he means. I have similar case There is a piece from my OpenAPI docs
"/books/{id}": {
"get": {
"operationId": "BooksController_getBook",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"description": "Id",
"schema": {
"format": "uuid",
"example": "00000000-0000-0000-0000-000000000000",
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Book",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/BookResponse"
}
]
}
}
}
},
"400": {
"description": "Request failed",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/BookNotFoundError"
},
{
"$ref": "#/components/schemas/ValidationError"
}
]
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/UnknownError"
}
]
}
}
}
}
},
"summary": "Get book by id",
"tags": [
"books"
]
}
},
I expect to get any of these responses from fetch, but it generates only success 200 response
export const booksControllerGetBook = async (id: string, options?: RequestInit): Promise<BookResponse> => {
const res = await fetch(getBooksControllerGetBookUrl(id), { ...options, method: 'GET' });
const data = await res.json();
return data as BookResponse;
}
export interface BookResponse {
author: string;
description: string;
discountPrice: BookResponseDiscountPrice;
id: string;
imagePath: string;
name: string;
price: number;
}
It would be great to add possibility to generate types like this by some config flag and use them instead of BookResponse
export type BooksControllerGetBookResponse = BookResponse | BookNotFoundError | ValidationError | UnknownError;
// or
export type BooksControllerGetBookResponse = BookResponse | BooksControllerGetBook400 | UnknownError;
Thanks. well, I think that makes sense.