Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018BAUeCFpDkRD6tU5wGsc1C
51 lines
1.8 KiB
TypeScript
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;
|
|
}
|