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; }