File size: 1,460 Bytes
de6cac5 36db998 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import { ApiRequestError, getLastRequestId } from '../api/client'
import type { MessageKey } from '../i18n/en'
type Translate = (key: MessageKey, vars?: Record<string, string | number>) => 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
}
|