Files
native/src/lib/network-error.ts
T

40 lines
1.5 KiB
TypeScript

// Classify an error thrown by a JMAP call as a *transient* connectivity
// failure (server unreachable, offline, session not yet up) versus a
// *permanent* one (the server received the request and rejected it, e.g. a
// 4xx). The offline outbox uses this to decide whether to keep an operation
// queued for a later retry or to give up on it.
//
// We err on the side of "transient" only for signals we recognise as
// connectivity-related; anything else (including bare 4xx/5xx responses) is
// treated as permanent so a poison operation can't wedge the queue forever.
import { useNetworkStore } from '../stores/network-store';
const TRANSIENT_NAMES = new Set([
'NetworkError', // jmap-client transport wrapper
'AbortError', // request aborted (e.g. app backgrounded)
'TypeError', // RN fetch throws TypeError("Network request failed")
]);
const TRANSIENT_MESSAGE_HINTS = [
'network request failed',
'network error',
'failed to fetch',
'not connected',
'session expired', // token refresh will happen on the next live request
'timeout',
'timed out',
'connection',
];
export function isTransientNetworkError(err: unknown): boolean {
// If the device itself reports offline, treat any failure as transient.
if (!useNetworkStore.getState().online) return true;
if (!(err instanceof Error)) return false;
if (TRANSIENT_NAMES.has(err.name)) return true;
const msg = err.message?.toLowerCase() ?? '';
return TRANSIENT_MESSAGE_HINTS.some((hint) => msg.includes(hint));
}