feat(frontend): polish web (logout, 401→pairing, reconnexion globale) (#13)
Flow logout : POST /api/logout puis retour à l'écran de pairing et déconnexion du live. 401 renvoie au pairing sans boucle. Bannière de reconnexion couvrant le cas live-only et le serveur indisponible. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -79,14 +79,33 @@ function resolveEndpoints(config: HttpWsGatewaysConfig): {
|
||||
*/
|
||||
export function createHttpWsGateways(config: HttpWsGatewaysConfig = {}): Gateways {
|
||||
const { baseUrl, wsUrl } = resolveEndpoints(config);
|
||||
// Route 401s back to the pairing screen via the shared web session (F2).
|
||||
// Route 401s back to the pairing screen via the shared web session (F2/F6).
|
||||
const session = getWebSession();
|
||||
// `ws` is referenced by the invoker's 401 handler (declared below); the closure
|
||||
// only runs after both are constructed, so the forward reference is safe.
|
||||
let ws: WsLiveClient;
|
||||
const http = new HttpInvoker({
|
||||
baseUrl,
|
||||
token: config.token,
|
||||
onUnauthorized: () => session.notifyUnauthorized(),
|
||||
onUnauthorized: () => {
|
||||
// F6: a 401 means the session cookie is gone/revoked. Route back to pairing
|
||||
// AND tear down the live socket so it stops its (now hopeless) reconnect
|
||||
// loop. Re-pairing brings the same client back up cleanly.
|
||||
session.notifyUnauthorized();
|
||||
ws?.disconnect();
|
||||
},
|
||||
});
|
||||
ws = new WsLiveClient({
|
||||
wsUrl,
|
||||
token: config.token,
|
||||
// F6: when a WS reconnect fails we cannot read its HTTP status, so probe with
|
||||
// a cheap `health` call. A revoked session answers `401` → the invoker's
|
||||
// `onUnauthorized` above bounces to pairing; a network error is swallowed and
|
||||
// the WS backoff keeps retrying.
|
||||
onReconnectFailed: () => {
|
||||
void http.invoke("health", { request: null }).catch(() => {});
|
||||
},
|
||||
});
|
||||
const ws = new WsLiveClient({ wsUrl, token: config.token });
|
||||
// Share the live client with the web feature so live surfaces can re-sync on
|
||||
// reconnect (F5). Inert on desktop (never called there).
|
||||
setWebLiveClient(ws);
|
||||
@ -120,5 +139,5 @@ export function createHttpWsGateways(config: HttpWsGatewaysConfig = {}): Gateway
|
||||
export { HttpInvoker } from "./httpInvoker";
|
||||
export { WsLiveClient } from "./wsLiveClient";
|
||||
export { WebSession, getWebSession, setWebSessionForTests } from "./webSession";
|
||||
export { getWebLiveClient, setWebLiveClient } from "./webLive";
|
||||
export { getWebLiveClient, setWebLiveClient, disconnectWebLive } from "./webLive";
|
||||
export type { ConnectionState } from "./wsLiveClient";
|
||||
|
||||
Reference in New Issue
Block a user