openapi-ts
openapi-ts copied to clipboard
Throw error on non-success response status
Discussed in https://github.com/orgs/hey-api/discussions/740
Originally posted by tillprochaska July 1, 2024 Hi there, thanks a lot for maintaining openapi-ts! I’m currently in the process of migrating from 0.32.0 to the latest version and am wondering whether it is possible to recreate some of the behavior of 0.32.0.
In particular, we used to have a global error handler that would catch instances of ApiError and render a generic error page depending on the status code:
import { ApiError } from "./api/generated";
function onError(error, response) {
if (error instanceof ApiError && error.status === 404) {
return renderNotFound();
}
return renderServerError();
}
In most cases, we have a 1:1 mapping from frontend routes to API requests, so not having to handle API errors explicitly was quite convenient. For example, I could just write a route handler like this:
import { client } from "./api";
import { Pet } from "./api/generated/models";
app.get("/pets/:id", async (request, response) => {
const data: Pet = await client.pets.getPet({ id: request.params.id });
return renderPetPage(data);
});
If the API returned a successful response, the page would be rendered. If the API returned an error response, an error page would be rendered depending on the status code, all without the need to explicit error handling in the route.
I have successfully updated our app to flat services and am now using the fetch client package. I’ve also set up a response interceptor to throw an error in case the API returns an error response:
import { client } from "@hey-api/client-fetch";
import { APIError } from "./api/custom";
client.interceptors.response.use((response) => {
if (response.status === 404) {
throw new APIError(response.status);
}
return response;
});
I have also adjusted my routes, but while my services now will never return an error response (because the interceptor would throw an error in that case), that is obviously not reflected in the return types:
import { getPet } from "./api/generated";
app.get("/pets/:id", async (request, response) => {
// ❌ This fails because data is `Pet | undefined`
const { data }: { data: Pet } = getPet({ path: { id: request.params.id } });
return renderPetPage(data);
});
Is there any way to adjust the response types of services to always assume a successful response? Or to make the client package throw an error in case the API returns an error?