export function errorMessageAsString(e: any, defaultMessage = "Request failed.") { // Note that despite the name, this can actually currently return an object, // depending on what data.err_msg is (e.g. an object) let message = defaultMessage; if (e && e.response && e.response.data && e.response.data.err_msg) { message = e.response.data.err_msg; } else if (e && e.data && e.data.err_msg) { message = e.data.err_msg; } else if (e && e.err_msg) { message = e.err_msg; } else if (e && e.response) { message = `${e.response.statusText} (${e.response.status})`; } else if (e instanceof Error) { message = e.message; } else if (typeof e == "string") { message = e; } return message; } export function rethrowSimple(e: any): never { if (process.env.NODE_ENV != "test") { console.debug(e); } throw Error(errorMessageAsString(e)); } export class ApiError extends Error { status?: number; constructor(message: string, status?: number) { super(message); this.status = status; } } export function rethrowSimpleWithStatus(e: any, response?: { status: number }): never { if (process.env.NODE_ENV != "test") { console.debug(e); } throw new ApiError(errorMessageAsString(e), response?.status); } export type GalaxyApiResult = { data: T; error: undefined } | { data: undefined; error: ApiError }; export const MAX_RETRIES = 3; const RETRYABLE_STATUSES = new Set([429, 500, 502, 503, 504]); export function isRetryableApiError(error: Error): boolean { if (error instanceof ApiError && error.status !== undefined) { return RETRYABLE_STATUSES.has(error.status); } return false; }