47 lines
1.1 KiB
TypeScript
47 lines
1.1 KiB
TypeScript
import { state } from "./state.js";
|
|
|
|
interface APIOptions {
|
|
method?: string;
|
|
body?: unknown;
|
|
}
|
|
|
|
export async function api<T>(path: string, options: APIOptions = {}): Promise<T> {
|
|
const headers: Record<string, string> = { Accept: "application/json" };
|
|
if (options.body !== undefined) {
|
|
headers["Content-Type"] = "application/json";
|
|
}
|
|
if (state.token) {
|
|
headers.Authorization = `Bearer ${state.token}`;
|
|
}
|
|
|
|
const res = await fetch(state.apiBase + path, {
|
|
method: options.method || "GET",
|
|
headers,
|
|
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
|
});
|
|
|
|
let data: unknown = {};
|
|
const text = await res.text();
|
|
if (text) {
|
|
try {
|
|
data = JSON.parse(text);
|
|
} catch {
|
|
data = { error: text };
|
|
}
|
|
}
|
|
if (!res.ok) {
|
|
throw new Error(apiErrorMessage(data, res.statusText));
|
|
}
|
|
return data as T;
|
|
}
|
|
|
|
function apiErrorMessage(data: unknown, fallback: string): string {
|
|
if (data && typeof data === "object" && "error" in data) {
|
|
const error = (data as { error?: unknown }).error;
|
|
if (typeof error === "string" && error) {
|
|
return error;
|
|
}
|
|
}
|
|
return fallback;
|
|
}
|