This commit is contained in:
2026-09-24 11:42:02 +05:30
parent f3fe53d2ac
commit beeee893f6
2 changed files with 55 additions and 1 deletions

View File

@@ -6,9 +6,38 @@
* changes. Nothing else in the app calls `fetch`.
*/
import { authHeader } from '@/auth/token';
import { authHeader, forgetSession, readSessionToken } from '@/auth/token';
import type { FiestaEnvelope } from './types';
/**
* A 401 on a call we authenticated means the session is over.
*
* Twelve hours after signing in, or the moment the signing key is rotated under
* an open tab, every request starts coming back 401. Without this the console
* keeps sending the dead token and each page renders its own error — which a
* shopkeeper reads as "my data has gone", not as "sign in again". The screen
* fills with failures and nothing tells them the one thing that would fix it.
*
* Only when a token was actually SENT. A 401 on an anonymous call is the
* server declining to serve a stranger, not a session ending — and the
* sign-in probe deliberately posts with no password to read a 401 back, so
* reacting to that one would clear the session at the login screen and make
* signing in impossible.
*
* `location.reload()` rather than a router push: the session is held in React
* state that this module cannot reach, and a reload is the one move guaranteed
* to land on the sign-in screen from anywhere in the app. It happens once,
* because the storage is cleared first — the reloaded app has no token, so the
* next 401 cannot loop.
*/
function endDeadSession(path: string): void {
if (!readSessionToken()) return;
forgetSession();
// eslint-disable-next-line no-console
console.warn(`[nearle] session rejected on ${path}; signing out`);
if (typeof window !== 'undefined') window.location.reload();
}
/**
* Where Fiesta is.
*
@@ -182,6 +211,10 @@ async function request<T>(path: string, options: RequestOptions = {}): Promise<T
throw new FiestaError(`Malformed response (HTTP ${response.status})`, response.status, path);
}
if (response.status === 401) {
endDeadSession(path);
}
if (!response.ok || envelope.status === false) {
throw new FiestaError(
envelope.message ?? `Request failed (HTTP ${response.status})`,