Files
vod-system/frontend/src/utils/api/client.ts
Dylan De Faoite 9758bb296b
All checks were successful
CI / Maven unit tests (push) Successful in 14s
CI / Build and push images (push) Successful in 57s
CI / Deploy to server (push) Successful in 8s
fix(frontend): logout state not shown after JWT expires (#40)
Reviewed-on: #40
2026-09-06 23:26:07 +01:00

49 lines
1.5 KiB
TypeScript

import {config} from "../../config.ts";
const API_URL = config.apiUrl;
class AuthError extends Error {
constructor() { super("Not authenticated"); this.name = "AuthError"; }
}
let onUnauthorized: (() => void) | null = null;
export function registerUnauthorizedHandler(handler: () => void) {
onUnauthorized = handler;
}
/**
* Performs a request against the API, sending session cookies and funnelling
* expired/missing sessions through the registered unauthorized handler so the
* UI can drop back to a logged out state. Returns the raw response so callers
* that need something other than JSON (blobs, streams) can read it themselves.
*/
async function apiFetchRaw(url: string, options: RequestInit = {}): Promise<Response> {
const response = await fetch(url, {
...options,
credentials: 'include'
});
if (response.status == 401 || response.status == 403) {
onUnauthorized?.();
throw new AuthError();
}
if (!response.ok) {
const text = await response.text();
let message = text;
try { message = JSON.parse(text).message ?? text; } catch { /* not JSON, use raw text */ }
throw new Error(message || `Request failed: ${response.status}`);
}
return response;
}
async function apiFetch<T>(url: string, options: RequestInit = {}): Promise<T> {
const response = await apiFetchRaw(url, options);
const text = await response.text();
return text ? JSON.parse(text) : (undefined as T);
}
export { API_URL, AuthError, apiFetch, apiFetchRaw };