import { ApiRequestError, getLastRequestId } from '../api/client' import type { MessageKey } from '../i18n/en' type Translate = (key: MessageKey, vars?: Record) => string /** Turn any thrown error into a SAFE, localized message. We never render raw backend * exception text to the user. Network/timeout get dedicated messages; every other * failure shows a context-specific localized fallback plus the request ID (when known) * so support can trace it. `fallbackKey` is the operation-specific message key. */ export function localizeError(e: unknown, t: Translate, fallbackKey: MessageKey): string { if (e instanceof ApiRequestError) { if (e.status === 0) { return t(e.message === 'request timed out' ? 'error.timeout' : 'error.network') } const rid = e.requestId ?? getLastRequestId() ?? undefined return rid ? t('error.withRef', { msg: t(fallbackKey), id: rid }) : t(fallbackKey) } return t(fallbackKey) } /** Maps a few known biometric backend errors to an ACTIONABLE localized key (matched * on status + a safe substring — the raw text is never rendered). Returns null when * there is no specific mapping (caller falls back to localizeError). */ export function bioErrorKey(e: unknown): MessageKey | null { if (!(e instanceof ApiRequestError)) return null const m = (e.message || '').toLowerCase() if (e.status === 422 && m.includes('face')) return 'bio.err.noFace' return null }