50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
const STORAGE_KEY = "jarvis_admin_key";
|
|
const UNAUTHORIZED_EVENT = "jarvis:unauthorized";
|
|
|
|
export class UnauthorizedError extends Error {}
|
|
|
|
function getApiBase(): string {
|
|
return import.meta.env.VITE_API_URL as string;
|
|
}
|
|
|
|
export function getStoredKey(): string | null {
|
|
return localStorage.getItem(STORAGE_KEY);
|
|
}
|
|
|
|
export function storeKey(key: string): void {
|
|
localStorage.setItem(STORAGE_KEY, key);
|
|
}
|
|
|
|
export function clearKey(): void {
|
|
localStorage.removeItem(STORAGE_KEY);
|
|
}
|
|
|
|
export function logout(): void {
|
|
clearKey();
|
|
window.dispatchEvent(new Event(UNAUTHORIZED_EVENT));
|
|
}
|
|
|
|
export function onUnauthorized(handler: () => void): () => void {
|
|
window.addEventListener(UNAUTHORIZED_EVENT, handler);
|
|
return () => window.removeEventListener(UNAUTHORIZED_EVENT, handler);
|
|
}
|
|
|
|
export async function apiFetch(
|
|
path: string,
|
|
options: RequestInit = {},
|
|
keyOverride?: string
|
|
): Promise<Response> {
|
|
const key = keyOverride ?? getStoredKey();
|
|
const headers = new Headers(options.headers);
|
|
if (key) {
|
|
headers.set("X-Admin-Key", key);
|
|
}
|
|
const response = await fetch(`${getApiBase()}${path}`, { ...options, headers });
|
|
if (response.status === 401) {
|
|
clearKey();
|
|
window.dispatchEvent(new Event(UNAUTHORIZED_EVENT));
|
|
throw new UnauthorizedError("Invalid or missing admin key");
|
|
}
|
|
return response;
|
|
}
|