import { getAccessToken, setAccessToken } from './token-store'; import { refreshRequest } from './api'; const API_URL = process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:3001/api/v1'; export class ApiError extends Error { status: number; constructor(status: number, message: string) { super(message); this.status = status; } } async function rawFetch(path: string, init: RequestInit): Promise { const token = getAccessToken(); return fetch(`${API_URL}${path}`, { ...init, credentials: 'include', headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), ...init.headers, }, }); } export interface BlobDownload { blob: Blob; filename: string; } function filenameFromContentDisposition(header: string | null, fallback: string): string { const match = header ? /filename="([^"]+)"/.exec(header) : null; return match?.[1] ?? fallback; } export async function apiFetchBlob(path: string, fallbackFilename: string): Promise { let response = await rawFetch(path, {}); if (response.status === 401) { const refreshed = await refreshRequest(); if (refreshed) { setAccessToken(refreshed.accessToken); response = await rawFetch(path, {}); } } if (!response.ok) { throw new ApiError(response.status, 'Export fehlgeschlagen'); } const blob = await response.blob(); const filename = filenameFromContentDisposition( response.headers.get('Content-Disposition'), fallbackFilename, ); return { blob, filename }; } export async function apiFetch(path: string, init: RequestInit = {}): Promise { let response = await rawFetch(path, init); if (response.status === 401) { const refreshed = await refreshRequest(); if (refreshed) { setAccessToken(refreshed.accessToken); response = await rawFetch(path, init); } } if (!response.ok) { const body: unknown = await response.json().catch(() => ({})); const message = typeof body === 'object' && body !== null && 'message' in body ? String((body as { message: unknown }).message) : 'Request failed'; throw new ApiError(response.status, message); } if (response.status === 204) { return undefined as T; } return response.json() as Promise; }