forked from paperclipai/paperclip
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquery-auth-recheck.ts
More file actions
41 lines (37 loc) · 1.7 KB
/
Copy pathquery-auth-recheck.ts
File metadata and controls
41 lines (37 loc) · 1.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import type { QueryClient } from "@tanstack/react-query";
import { isAuthFailure } from "./query-auth-policy";
import { queryKeys } from "./queryKeys";
const SESSION_KEY = JSON.stringify(queryKeys.auth.session);
/**
* Give CloudAccessGate a feedback path from the rest of the app.
*
* The gate decides "signed out, go to /auth/sign-in" from its own session
* query alone. That query is stale-cached, so when a session dies mid-visit
* nothing tells the gate: every other query starts returning 401 and just
* keeps polling on its interval, and the user sits in front of an app that
* quietly stops loading instead of being sent to sign-in.
*
* Any auth failure anywhere is therefore treated as a reason to re-ask the one
* question that matters. If the session really is gone the session query
* resolves null and the gate redirects once; if it is fine (a per-resource 403)
* the answer is unchanged and nothing happens.
*/
export function installAuthFailureRecheck(queryClient: QueryClient): () => void {
let recheckInFlight = false;
return queryClient.getQueryCache().subscribe((event) => {
if (event.type !== "updated") return;
if (event.query.state.status !== "error") return;
if (!isAuthFailure(event.query.state.error)) return;
// The session query answering 401 IS the answer; re-asking would loop.
if (JSON.stringify(event.query.queryKey) === SESSION_KEY) return;
// A dead session fails every query on the page at once. One re-check
// answers all of them.
if (recheckInFlight) return;
recheckInFlight = true;
void queryClient
.refetchQueries({ queryKey: queryKeys.auth.session, exact: true })
.finally(() => {
recheckInFlight = false;
});
});
}