better-auth
Version:
The most comprehensive authentication framework for TypeScript.
127 lines (125 loc) • 3.98 kB
JavaScript
import { getGlobalBroadcastChannel } from "./broadcast-channel.mjs";
import { getGlobalFocusManager } from "./focus-manager.mjs";
import { getGlobalOnlineManager } from "./online-manager.mjs";
//#region src/client/session-refresh.ts
const now = () => Math.floor(Date.now() / 1e3);
/**
* Rate limit: don't refetch on focus if a session request was made within this many seconds
*/
const FOCUS_REFETCH_RATE_LIMIT_SECONDS = 5;
function createSessionRefreshManager(opts) {
const { sessionAtom, sessionSignal, $fetch, options = {} } = opts;
const refetchInterval = options.sessionOptions?.refetchInterval ?? 0;
const refetchOnWindowFocus = options.sessionOptions?.refetchOnWindowFocus ?? true;
const refetchWhenOffline = options.sessionOptions?.refetchWhenOffline ?? false;
const state = {
lastSync: 0,
lastSessionRequest: 0,
cachedSession: void 0
};
const shouldRefetch = () => {
return refetchWhenOffline || getGlobalOnlineManager().isOnline;
};
const triggerRefetch = (event) => {
if (!shouldRefetch()) return;
if (event?.event === "storage") {
state.lastSync = now();
sessionSignal.set(!sessionSignal.get());
return;
}
const currentSession = sessionAtom.get();
if (event?.event === "poll") {
state.lastSessionRequest = now();
$fetch("/get-session").then((res) => {
if (res.error) sessionAtom.set({
...currentSession,
data: null,
error: res.error
});
else sessionAtom.set({
...currentSession,
data: res.data,
error: null
});
state.lastSync = now();
sessionSignal.set(!sessionSignal.get());
}).catch(() => {});
return;
}
if (event?.event === "visibilitychange") {
if (now() - state.lastSessionRequest < FOCUS_REFETCH_RATE_LIMIT_SECONDS && currentSession?.data !== null && currentSession?.data !== void 0) return;
}
if (currentSession?.data === null || currentSession?.data === void 0 || event?.event === "visibilitychange") {
if (event?.event === "visibilitychange") state.lastSessionRequest = now();
state.lastSync = now();
sessionSignal.set(!sessionSignal.get());
}
};
const broadcastSessionUpdate = (trigger) => {
getGlobalBroadcastChannel().post({
event: "session",
data: { trigger },
clientId: Math.random().toString(36).substring(7)
});
};
const setupPolling = () => {
if (refetchInterval && refetchInterval > 0) state.pollInterval = setInterval(() => {
if (sessionAtom.get()?.data) triggerRefetch({ event: "poll" });
}, refetchInterval * 1e3);
};
const setupBroadcast = () => {
state.unsubscribeBroadcast = getGlobalBroadcastChannel().subscribe(() => {
triggerRefetch({ event: "storage" });
});
};
const setupFocusRefetch = () => {
if (!refetchOnWindowFocus) return;
state.unsubscribeFocus = getGlobalFocusManager().subscribe(() => {
triggerRefetch({ event: "visibilitychange" });
});
};
const setupOnlineRefetch = () => {
state.unsubscribeOnline = getGlobalOnlineManager().subscribe((online) => {
if (online) triggerRefetch({ event: "visibilitychange" });
});
};
const init = () => {
setupPolling();
setupBroadcast();
setupFocusRefetch();
setupOnlineRefetch();
getGlobalBroadcastChannel().setup();
getGlobalFocusManager().setup();
getGlobalOnlineManager().setup();
};
const cleanup = () => {
if (state.pollInterval) {
clearInterval(state.pollInterval);
state.pollInterval = void 0;
}
if (state.unsubscribeBroadcast) {
state.unsubscribeBroadcast();
state.unsubscribeBroadcast = void 0;
}
if (state.unsubscribeFocus) {
state.unsubscribeFocus();
state.unsubscribeFocus = void 0;
}
if (state.unsubscribeOnline) {
state.unsubscribeOnline();
state.unsubscribeOnline = void 0;
}
state.lastSync = 0;
state.lastSessionRequest = 0;
state.cachedSession = void 0;
};
return {
init,
cleanup,
triggerRefetch,
broadcastSessionUpdate
};
}
//#endregion
export { createSessionRefreshManager };
//# sourceMappingURL=session-refresh.mjs.map