Events, Errors, and Retries
Event System
TooLostClient extends a typed event emitter with four event channels:
requestresponseerrortokenRefresh
Event Listener Methods
ts
client.on(eventName, listener);
client.once(eventName, listener);
client.off(eventName, listener);Event Payloads
request
ts
interface RequestEvent {
method: string;
path: string;
url: string;
headers: Record<string, string>;
body?: unknown;
attempt: number;
}response
ts
interface ResponseEvent {
method: string;
path: string;
url: string;
status: number;
ok: boolean;
durationMs: number;
}error
ts
interface ErrorEvent {
method: string;
path: string;
url: string;
status?: number;
message: string;
}tokenRefresh
ts
interface TokenRefreshEvent {
accessToken: string;
refreshToken: string;
expiresAt: number;
}Important Event Semantics
erroris emitted for API or network failures observed by the REST layer.erroremission is guarded inTooLostClient: if noerrorlisteners are registered, it does not emit.responseis emitted for every fetch response, including non-2xx responses.request.attemptincreases when retry logic re-sends the request.
Error Types
TooLostAPIError
ts
class TooLostAPIError extends Error {
readonly status: number;
readonly body?: unknown;
}Thrown for non-2xx API responses and specific token refresh constraints.
Message extraction strategy
For non-2xx responses, message is selected in order:
body.messagebody.errorresponse.statusText- fallback
"Request failed"
Retry Behavior
Retry is implemented in REST.request.
Default retries
- Client default:
2 - Per-request override:
RequestOptions.retry
Retry conditions
Request retries occur when either is true:
- response status is
>= 500 - response status is
429 - fetch throws non-
TooLostAPIErrorerror (network/runtime fetch failure)
Backoff schedule
Backoff by attempt index (attempt is zero-based inside REST):
- attempt 0 -> 1000 ms
- attempt 1 -> 2000 ms
- attempt 2+ -> capped at 3000 ms
Formula:
ts
Math.min(1000 * (attempt + 1), 3000);Token Refresh Behavior
Pre-request refresh
Before each request, client may refresh if:
autoRefreshis enabledskipAuthis falserefreshTokenexistsexpiresAtis known- token expires within 30 seconds
401 refresh-and-retry
After request failure, client retries once when:
- error is
TooLostAPIError - status is
401 autoRefreshenabledskipAuthfalse- refresh token available
The original request is then re-sent after refresh.
Refresh deduplication
Concurrent refresh triggers share a single in-flight promise (inflightRefresh) to avoid duplicate token refresh requests.
Practical Guidance
- Register at least one
errorlistener for production observability. - Keep write operations idempotent when possible if using retry.
- Set explicit per-request retry to
0for non-repeatable calls when needed.