With hey-api
hey-api generates typed clients from OpenAPI specs. It supports both fetch and axios backends — use the adapter to normalize either.
Setup with @hey-api/client-fetch
Section titled “Setup with @hey-api/client-fetch”import { createExpectStatus, adapters } from "expect-status";
export const expectStatus = createExpectStatus({ adapter: adapters.openapiClient, fallbackMessage: "Request failed.", defaults: { 401: "Please sign in.", "5xx": "Service unavailable.", },});Both
client-fetchandclient-axiosreturn{ data, error, response }. The built-inadapters.openapiClientpreset handles both.
Basic usage
Section titled “Basic usage”import { expectStatus } from "@/lib/expect-status";import { getUser, createOrg } from "@/api/sdk";
const user = await expectStatus(200, getUser({ path: { id: "1" } }));
const org = await expectStatus(201, createOrg({ body: { name: "Acme" } }));With flat dispatch
Section titled “With flat dispatch”const org = await expectStatus(201, createOrg({ body: { name: "Acme" } }), { 409: ({ message }) => ({ error: message }), 422: "Please check your input.", "5xx": "Service unavailable.",});With TanStack Query
Section titled “With TanStack Query”function useUser(id: string) { return useQuery({ queryKey: ["user", id], queryFn: () => expectStatus(200, getUser({ path: { id } })), });}
function useCreateOrg() { return useMutation({ mutationFn: (data: { name: string }) => expectStatus(201, createOrg({ body: data }), { 409: "Organisation already exists.", }), });}SafeResult
Section titled “SafeResult”const result = await expectStatus(200, getUser({ path: { id } }), { throws: false,});
if (result.ok) { renderUser(result.data);} else { showError(result.error.message);}hey-api config reference
Section titled “hey-api config reference”Minimal @hey-api/openapi-ts config:
import { defineConfig } from "@hey-api/openapi-ts";
export default defineConfig({ client: "@hey-api/client-fetch", input: "./openapi.yaml", output: { path: "./src/api/sdk", },});Alternative: manual wrapping
Section titled “Alternative: manual wrapping”import { expectStatus } from "expect-status";import { getUser } from "@/api/sdk";
const { data, error, response } = await getUser({ path: { id: "1" } });
const user = await expectStatus(200, { status: response.status, body: data ?? error,});See also
Section titled “See also”- hey-api documentation
- With openapi-fetch — similar adapter pattern
- With TanStack Query — query and mutation patterns