Stand vor Einführung des Nacht-Agenten

This commit is contained in:
Kundencenter 2026-09-27 00:51:32 +02:00
commit 4763548bfb
168 changed files with 12726 additions and 0 deletions

13
apps/web/src/lib/api.ts Normal file
View file

@ -0,0 +1,13 @@
'use client';
export class ApiError extends Error { constructor(public status: number, public code: string, message: string, public details?: { path: string; message: string }[]) { super(message); } }
let csrf = '';
export const setCsrf = (t: string) => { csrf = t; };
/** Einheitlicher API-Zugriff über den same-origin Proxy /api (Cookie, CSRF-Header, normalisierte Fehler). */
export async function api<T = unknown>(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', path: string, body?: unknown): Promise<T> {
const res = await fetch(`/api${path}`, { method, credentials: 'same-origin', headers: { ...(body !== undefined ? { 'content-type': 'application/json' } : {}), ...(csrf ? { 'x-csrf-token': csrf } : {}) }, body: body !== undefined ? JSON.stringify(body) : undefined });
const data = res.headers.get('content-type')?.includes('json') ? await res.json() : null;
if (!res.ok) throw new ApiError(res.status, data?.error?.code ?? 'ERROR', data?.error?.message ?? 'Anfrage fehlgeschlagen', data?.error?.details);
return data as T;
}
export const errMsg = (e: unknown): string => e instanceof ApiError ? (e.details?.length ? `${e.message}: ${e.details.map((d) => d.message).join(', ')}` : e.message) : 'Der Server ist nicht erreichbar. Bitte später erneut versuchen.';