39 lines
1005 B
TypeScript
39 lines
1005 B
TypeScript
const BASE_URL = "/api";
|
|
|
|
export async function apiClient<T>(
|
|
endpoint: string,
|
|
options?: RequestInit,
|
|
): Promise<T> {
|
|
// Get token from global window object (set by Keycloak client)
|
|
const token =
|
|
typeof window !== "undefined" ? (window as any).__KEYCLOAK_TOKEN__ : null;
|
|
|
|
const headers: Record<string, string> = {
|
|
"Content-Type": "application/json",
|
|
...((options?.headers as Record<string, string>) || {}),
|
|
};
|
|
|
|
// Add Authorization header if token exists
|
|
if (token) {
|
|
headers["Authorization"] = `Bearer ${token}`;
|
|
}
|
|
|
|
const res = await fetch(`${BASE_URL}${endpoint}`, {
|
|
...options,
|
|
headers,
|
|
});
|
|
|
|
if (!res.ok) {
|
|
// Handle 401 - token expired
|
|
if (res.status === 401) {
|
|
// Trigger token refresh by dispatching event
|
|
if (typeof window !== "undefined") {
|
|
window.dispatchEvent(new CustomEvent("token-expired"));
|
|
}
|
|
}
|
|
throw new Error(`API error: ${res.status} ${res.statusText}`);
|
|
}
|
|
|
|
return res.json() as Promise<T>;
|
|
}
|