48 lines
1.1 KiB
TypeScript
48 lines
1.1 KiB
TypeScript
import { browser } from '$app/environment';
|
|
|
|
export const TOKEN_STORAGE_KEY = 'evobgp_api_token';
|
|
|
|
export type Problem = {
|
|
title?: string;
|
|
status?: number;
|
|
detail?: string;
|
|
};
|
|
|
|
function mergeHeaders(init?: RequestInit): Headers {
|
|
const h = new Headers(init?.headers);
|
|
if (!h.has('Accept')) {
|
|
h.set('Accept', 'application/json');
|
|
}
|
|
if (browser) {
|
|
const t = localStorage.getItem(TOKEN_STORAGE_KEY);
|
|
if (t && !h.has('Authorization')) {
|
|
h.set('Authorization', `Bearer ${t}`);
|
|
}
|
|
}
|
|
return h;
|
|
}
|
|
|
|
export async function apiFetch(path: string, init?: RequestInit): Promise<Response> {
|
|
if (!browser) {
|
|
throw new Error('API is only available in the browser');
|
|
}
|
|
return fetch(path, { ...init, headers: mergeHeaders(init) });
|
|
}
|
|
|
|
export async function apiJSON<T>(path: string, init?: RequestInit): Promise<T> {
|
|
const res = await apiFetch(path, init);
|
|
const text = await res.text();
|
|
if (!res.ok) {
|
|
let detail = text;
|
|
try {
|
|
const j = JSON.parse(text) as Problem;
|
|
if (j?.detail) detail = j.detail;
|
|
} catch {
|
|
/* plain text */
|
|
}
|
|
throw new Error(detail || `HTTP ${res.status}`);
|
|
}
|
|
if (!text) return undefined as T;
|
|
return JSON.parse(text) as T;
|
|
}
|