import { ApiErrorCode, apiErrorCode, isApiErrorCode, isBrokerageAccessLoss, } from "./problem-details"; type ReadState = { error: unknown; isError: boolean; isFetching: boolean }; type RetryableRead = ReadState & { refetch: () => Promise }; // Automatic retries run inside one fetchAppRead call and Query's own retry is // off, so a query in the error state has exhausted them. The state stays // "error" while a manual retry runs, which keeps the warning in place. Access // loss and a lost session keep their own actions and never offer a plain retry. function isReadFailureExhausted(state: ReadState): boolean { if (!state.isError) return false; const code = apiErrorCode(state.error); return !isBrokerageAccessLoss(code) && !isApiErrorCode(code, ApiErrorCode.Unauthorized); } // Retry repeats only the GET of the failed queries, never a source sync. function readRetry(reads: RetryableRead[]) { const failed = reads.filter(read => isReadFailureExhausted(read)); return { exhausted: failed.length > 0, onRetry: () => { void Promise.allSettled(failed.map(read => read.refetch())); }, retrying: failed.some(read => read.isFetching), }; } export { isReadFailureExhausted, readRetry };