52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
function getXsrfToken(): string {
|
|
const match = document.cookie
|
|
.split('; ')
|
|
.find((row) => row.startsWith('XSRF-TOKEN='));
|
|
|
|
return match ? decodeURIComponent(match.split('=')[1] ?? '') : '';
|
|
}
|
|
|
|
export async function apiFetch<T>(url: string, options: RequestInit = {}): Promise<T> {
|
|
const response = await fetch(url, {
|
|
...options,
|
|
headers: {
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json',
|
|
'X-XSRF-TOKEN': getXsrfToken(),
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
...options.headers,
|
|
},
|
|
credentials: 'same-origin',
|
|
});
|
|
|
|
const contentType = response.headers.get('content-type') ?? '';
|
|
const isJson = contentType.includes('application/json');
|
|
|
|
if (!response.ok) {
|
|
if (isJson) {
|
|
const error = (await response.json().catch(() => ({}))) as {
|
|
message?: string;
|
|
errors?: Record<string, string[]>;
|
|
};
|
|
|
|
const firstValidationError = error.errors
|
|
? Object.values(error.errors).flat()[0]
|
|
: undefined;
|
|
|
|
throw new Error(firstValidationError ?? error.message ?? 'Permintaan gagal diproses.');
|
|
}
|
|
|
|
if (response.status === 401 || response.status === 419) {
|
|
throw new Error('Sesi Anda telah berakhir. Silakan muat ulang halaman dan coba lagi.');
|
|
}
|
|
|
|
throw new Error(`Permintaan gagal diproses (HTTP ${response.status}).`);
|
|
}
|
|
|
|
if (!isJson) {
|
|
throw new Error('Server mengembalikan respons yang tidak valid. Silakan muat ulang halaman.');
|
|
}
|
|
|
|
return response.json() as Promise<T>;
|
|
}
|