xpeditis2.0/apps/frontend/src/lib/api/errors.ts
2026-09-07 21:40:55 +02:00

51 lines
1.8 KiB
TypeScript

import { ApiError } from './client';
/**
* Message d'erreur destiné à un écran.
*
* Une page ne doit jamais afficher « Internal server error », ni « Failed to
* fetch », ni une trace : ces textes ne disent pas ce qui s'est passé, ne
* disent pas quoi faire, et n'existent dans aucune langue.
*
* L'ordre de préférence :
*
* 1. Le **code** renvoyé par l'API, traduit ici — c'est le cas des pannes
* (`service_unavailable`, `unexpected_error`) et de la perte de réseau.
* 2. Le **message** du serveur, déjà traduit et rédigé pour l'utilisateur :
* « Cette adresse email est déjà utilisée », les erreurs de validation…
* 3. Un repli fourni par l'appelant.
*/
export interface ApiErrorLabels {
network: string;
serviceUnavailable: string;
unexpected: string;
fallback: string;
}
export function apiErrorMessage(error: unknown, labels: ApiErrorLabels): string {
if (error instanceof ApiError) {
switch (error.code) {
case 'network_error':
return labels.network;
case 'service_unavailable':
return labels.serviceUnavailable;
case 'unexpected_error':
return labels.unexpected;
}
// Une liste, c'est la validation champ par champ : la première suffit à
// corriger, les suivantes sont déjà signalées sous les champs.
const message = error.response?.message;
if (Array.isArray(message) && message.length) return String(message[0]);
if (typeof message === 'string' && message) return message;
if (error.message) return error.message;
}
return labels.fallback;
}
/** Référence d'incident à montrer sous le message, quand le serveur en donne une. */
export function apiErrorReference(error: unknown): string | undefined {
return error instanceof ApiError ? error.reference : undefined;
}