30 lines
894 B
TypeScript
30 lines
894 B
TypeScript
export interface ApiFailure {
|
|
error: string;
|
|
code?: string;
|
|
issues?: Array<{ path: unknown; message: string }>;
|
|
}
|
|
|
|
export class ApiClientError extends Error {
|
|
constructor(public status: number, public code: string | undefined, message: string) {
|
|
super(message);
|
|
}
|
|
}
|
|
|
|
export async function apiFetch<T>(
|
|
input: string,
|
|
init: RequestInit = {},
|
|
): Promise<T> {
|
|
const headers = new Headers(init.headers);
|
|
if (init.body && !headers.has("content-type") && !(init.body instanceof FormData)) {
|
|
headers.set("content-type", "application/json");
|
|
}
|
|
const res = await fetch(input, { ...init, headers });
|
|
const text = await res.text();
|
|
const data = text ? (JSON.parse(text) as unknown) : undefined;
|
|
if (!res.ok) {
|
|
const fail = (data ?? { error: res.statusText }) as ApiFailure;
|
|
throw new ApiClientError(res.status, fail.code, fail.error);
|
|
}
|
|
return data as T;
|
|
}
|