Files
cameleer-saas/ui/src/api/client.ts
2026-04-04 21:50:19 +02:00

47 lines
1.4 KiB
TypeScript

import { useAuthStore } from '../auth/auth-store';
const API_BASE = '/api';
async function apiFetch<T>(path: string, options: RequestInit = {}): Promise<T> {
const token = useAuthStore.getState().accessToken;
const headers: Record<string, string> = {
...(options.headers as Record<string, string> || {}),
};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
if (!headers['Content-Type'] && !(options.body instanceof FormData)) {
headers['Content-Type'] = 'application/json';
}
const response = await fetch(`${API_BASE}${path}`, { ...options, headers });
if (response.status === 401) {
useAuthStore.getState().logout();
window.location.href = '/login';
throw new Error('Unauthorized');
}
if (!response.ok) {
const text = await response.text();
throw new Error(`API error ${response.status}: ${text}`);
}
if (response.status === 204) return undefined as T;
return response.json();
}
export const api = {
get: <T>(path: string) => apiFetch<T>(path),
post: <T>(path: string, body?: unknown) =>
apiFetch<T>(path, {
method: 'POST',
body: body instanceof FormData ? body : JSON.stringify(body),
}),
patch: <T>(path: string, body: unknown) =>
apiFetch<T>(path, { method: 'PATCH', body: JSON.stringify(body) }),
put: <T>(path: string, body: FormData) =>
apiFetch<T>(path, { method: 'PUT', body }),
delete: <T>(path: string) => apiFetch<T>(path, { method: 'DELETE' }),
};