up
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
export const NETWORK_ERROR_CODES = [
|
||||
'NETWORK',
|
||||
'TIMEOUT',
|
||||
'ABORTED',
|
||||
'ENOTFOUND',
|
||||
'EAI_AGAIN',
|
||||
'ECONNREFUSED',
|
||||
'ECONNRESET',
|
||||
'ETIMEDOUT',
|
||||
'UND_ERR_CONNECT_TIMEOUT',
|
||||
'CERT_HAS_EXPIRED',
|
||||
'DEPTH_ZERO_SELF_SIGNED_CERT',
|
||||
'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
||||
'ERR_TLS_CERT_ALTNAME_INVALID',
|
||||
] as const
|
||||
export type NetworkErrorCode = (typeof NETWORK_ERROR_CODES)[number]
|
||||
export class NetworkError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public code: NetworkErrorCode = 'NETWORK',
|
||||
) {
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
export class SessionChangedError extends Error {
|
||||
constructor() {
|
||||
super('Сессия изменилась. Повторите подключение игры')
|
||||
}
|
||||
}
|
||||
export class ApiError extends Error {
|
||||
constructor(public status: number) {
|
||||
super(
|
||||
status === 401
|
||||
? 'Сессия истекла. Войдите снова'
|
||||
: status === 403
|
||||
? 'Нет доступа к действию'
|
||||
: status === 400
|
||||
? 'Действие пока недоступно для этой игры'
|
||||
: `Ошибка сервера: HTTP ${status}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function causeCode(error: unknown, depth = 0): NetworkErrorCode | undefined {
|
||||
if (!error || typeof error !== 'object' || depth > 3) return
|
||||
const value = error as { code?: unknown; cause?: unknown; errors?: unknown[] }
|
||||
if (NETWORK_ERROR_CODES.includes(value.code as NetworkErrorCode))
|
||||
return value.code as NetworkErrorCode
|
||||
return (
|
||||
causeCode(value.cause, depth + 1) ??
|
||||
(Array.isArray(value.errors)
|
||||
? value.errors.map((e) => causeCode(e, depth + 1)).find(Boolean)
|
||||
: undefined)
|
||||
)
|
||||
}
|
||||
export function networkFailure(error: unknown, signal: AbortSignal): NetworkError {
|
||||
if (signal.aborted) {
|
||||
return signal.reason?.name === 'TimeoutError'
|
||||
? new NetworkError('Превышено время ожидания ответа сервера', 'TIMEOUT')
|
||||
: new NetworkError('Подготовка отменена', 'ABORTED')
|
||||
}
|
||||
if (error instanceof NetworkError) return error
|
||||
const code = causeCode(error) ?? 'NETWORK'
|
||||
const message =
|
||||
code === 'ENOTFOUND' || code === 'EAI_AGAIN'
|
||||
? 'Не удалось определить адрес сервера'
|
||||
: code.includes('CERT') || code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
|
||||
? 'Ошибка защищённого соединения с сервером'
|
||||
: code === 'ETIMEDOUT' || code === 'UND_ERR_CONNECT_TIMEOUT'
|
||||
? 'Превышено время ожидания соединения с сервером'
|
||||
: code === 'ECONNREFUSED'
|
||||
? 'Сервер отклонил соединение'
|
||||
: code === 'ECONNRESET'
|
||||
? 'Соединение с сервером прервано'
|
||||
: 'Сервер недоступен'
|
||||
return new NetworkError(message, code)
|
||||
}
|
||||
Reference in New Issue
Block a user