Files
sub2api-cn-relay-manager/frontend/src/utils/apiError.ts

72 lines
2.0 KiB
TypeScript
Raw Normal View History

/**
* Centralized API error message extraction
*
* The API client interceptor rejects with a plain object: { status, code, message, error }
* This utility extracts the user-facing message from any error shape.
*/
interface ApiErrorLike {
status?: number
code?: number | string
message?: string
error?: string
reason?: string
metadata?: Record<string, unknown>
response?: {
data?: {
detail?: string
message?: string
code?: number | string
}
}
}
/**
* Extract the error code from an API error object.
*/
export function extractApiErrorCode(err: unknown): string | undefined {
if (!err || typeof err !== 'object') return undefined
const e = err as ApiErrorLike
const code = e.code ?? e.reason ?? e.response?.data?.code
return code != null ? String(code) : undefined
}
/**
* Extract a displayable error message from an API error.
*
* @param err - The caught error (unknown type)
* @param fallback - Fallback message if none can be extracted (use t('common.error') or similar)
* @param i18nMap - Optional map of error codes to i18n translated strings
*/
export function extractApiErrorMessage(
err: unknown,
fallback = 'Unknown error',
i18nMap?: Record<string, string>,
): string {
if (!err) return fallback
// Try i18n mapping by error code first
if (i18nMap) {
const code = extractApiErrorCode(err)
if (code && i18nMap[code]) return i18nMap[code]
}
// Plain object from API client interceptor (most common case)
if (typeof err === 'object' && err !== null) {
const e = err as ApiErrorLike
// Interceptor shape: { message, error }
if (e.message) return e.message
if (e.error) return e.error
// Legacy axios shape: { response.data.detail }
if (e.response?.data?.detail) return e.response.data.detail
if (e.response?.data?.message) return e.response.data.message
}
// Standard Error
if (err instanceof Error) return err.message
// Last resort
const str = String(err)
return str === '[object Object]' ? fallback : str
}