Files
tessera-ctl/apps/web/src/lib/accounting-request.ts
T
schalli 201765afd4
Tessera CI/CD / Lint & Type Check (push) Successful in 58s
Tessera CI/CD / Tests (push) Failing after 2m20s
Tessera CI/CD / Desktop-Pakete bauen (push) Has been skipped
Tessera CI/CD / Build & Publish Images (push) Has been skipped
refactor(cert-manager): einheitlicher Name Zertifikatsmanager
Seitenleiste/Marktplatz (Seed), Seitentitel, Anleitungen, Kommentare
und unveroeffentlichter CHANGELOG heissen jetzt Zertifikatsmanager.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 17:34:48 +02:00

71 lines
2.1 KiB
TypeScript

/**
* Gemeinsame Anfragehilfen der Finanzbuchhaltungs-Module (Kantinenabrechnung,
* Handelsware; quick-261002-fm5). `credentials: 'include'` fuer Cookie-Auth,
* `NEXT_PUBLIC_API_URL` als Basis — Muster `custom-modules-api.ts`.
*/
export const ACCOUNTING_API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
/** Dateiantwort der API (Base64) — wie beim Zertifikatsmanager. */
export interface FileResponse {
filename: string;
content: string;
mimeType: string;
}
/**
* Fehler mit HTTP-Status, maschinenlesbarer Kennung (`code`, falls die API
* eine liefert) und deutscher Servermeldung.
*/
export class AccountingRequestError extends Error {
constructor(
readonly status: number,
readonly code: string | null,
message: string,
readonly details: unknown = null,
) {
super(message);
this.name = 'AccountingRequestError';
}
}
async function failure(res: Response): Promise<AccountingRequestError> {
let message = `Request failed (${res.status})`;
let code: string | null = null;
let details: unknown = null;
try {
const body = await res.json();
const raw = body?.message;
if (Array.isArray(raw)) message = raw.join(' ');
else if (typeof raw === 'string') message = raw;
if (typeof body?.code === 'string') code = body.code;
details = body?.errors ?? null;
} catch {
// Antwort ohne JSON-Koerper — Standardmeldung bleibt.
}
return new AccountingRequestError(res.status, code, message, details);
}
export async function accountingRequest<T>(
path: string,
init: { method?: string; json?: unknown; form?: FormData } = {},
): Promise<T> {
const headers: Record<string, string> = {};
let body: BodyInit | undefined;
if (init.form) {
body = init.form;
} else if (init.json !== undefined) {
headers['Content-Type'] = 'application/json';
body = JSON.stringify(init.json);
}
const res = await fetch(`${ACCOUNTING_API_URL}${path}`, {
method: init.method ?? 'GET',
credentials: 'include',
headers,
body,
});
if (!res.ok) throw await failure(res);
if (res.status === 204) return undefined as T;
return (await res.json()) as T;
}