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
}