UNPKG

@daveyplate/better-auth-persistent

Version:

Persistent session management for Better Auth

247 lines (233 loc) 6.46 kB
'use strict'; var react$1 = require('@nanostores/react'); var react$2 = require('react'); var persistent = require('@nanostores/persistent'); var SuperJSON = require('superjson'); var nanostores = require('nanostores'); var plugins = require('better-auth/client/plugins'); var react = require('better-auth/react'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var SuperJSON__default = /*#__PURE__*/_interopDefault(SuperJSON); // src/hooks/use-list-device-sessions.ts // src/empty-result.ts var emptyResult = { data: null, isPending: true, isRefetching: false, error: null, refetch: async () => { } }; var $authClient = nanostores.atom(null); // src/stores/device-sessions.ts var $deviceSessions = persistent.persistentAtom( "device-sessions", { ...emptyResult, isPending: false }, { encode: SuperJSON__default.default.stringify, decode: (value) => { const parsed = SuperJSON__default.default.parse(value); parsed.refetch = refetchDeviceSessions; return parsed; } } ); var refetchDeviceSessions = async () => { const authClient2 = $authClient.get(); if (!authClient2) { console.warn("$authClient not found"); return; } $deviceSessions.set({ ...$deviceSessions.get(), isRefetching: true }); const result = await authClient2.multiSession.listDeviceSessions(); if (result.error) { $deviceSessions.set({ ...$deviceSessions.get(), isRefetching: false, isPending: false, error: result.error }); } else { $deviceSessions.set({ ...$deviceSessions.get(), data: result.data, isRefetching: false, isPending: false, error: null }); } }; function subscribe() { return () => { }; } function useIsHydrated() { return react$2.useSyncExternalStore( subscribe, () => true, () => false ); } // src/hooks/use-list-device-sessions.ts function useListDeviceSessions(_) { const isHydrated = useIsHydrated(); const store = react$1.useStore($deviceSessions); const result = react$2.useMemo(() => { return isHydrated ? { ...store, data: store.data } : emptyResult; }, [isHydrated, store]); return result; } var $persistentSession = persistent.persistentAtom( "session", { ...emptyResult, isPending: false }, { encode: SuperJSON__default.default.stringify, decode: (value) => { const parsed = SuperJSON__default.default.parse(value); parsed.refetch = refetchSession; return parsed; } } ); var refetchSession = async () => { const authClient2 = $authClient.get(); if (!authClient2) { console.warn("$authClient not found"); return; } $persistentSession.set({ ...$persistentSession.get(), isRefetching: true }); const result = await authClient2.getSession(); if (result.error) { $persistentSession.set({ ...$persistentSession.get(), isRefetching: false, isPending: false, error: result.error }); } else { $persistentSession.set({ ...$persistentSession.get(), optimistic: false, data: result.data, isRefetching: false, isPending: false, error: null }); } }; // src/init-persist-session.ts function initPersistSession(authClient2) { if ($authClient.get()) return; $authClient.set(authClient2); const sessionResult = $persistentSession.get(); if (!sessionResult.data) return; sessionResult.refetch(); } // src/hooks/use-session.ts function useSession(authClient2) { const isHydrated = useIsHydrated(); const store = react$1.useStore($persistentSession); react$2.useEffect(() => { if (authClient2) initPersistSession(authClient2); }, [authClient2]); const result = react$2.useMemo(() => { return isHydrated ? { ...store, data: store.data } : emptyResult; }, [isHydrated, store]); return result; } // src/subscribe-device-sessions.ts function subscribeDeviceSessions() { const unsubscribe = $persistentSession.subscribe( ({ isPending, isRefetching, optimistic, data }) => { if (isPending || isRefetching || optimistic) return; const deviceSessions = $deviceSessions.get(); if (data) { deviceSessions.refetch(); } else { $deviceSessions.set({ ...deviceSessions, data: null, isPending: false, isRefetching: false, error: null }); } } ); const checkActiveSession = () => { const persistentSession = $persistentSession.get(); if (!persistentSession.optimistic || !persistentSession.data) return; const authClient2 = $authClient.get(); if (!authClient2) return; authClient2.multiSession.setActive({ sessionToken: persistentSession.data.session.token }).then((result) => { if (result.error) return; persistentSession.refetch(); }); }; checkActiveSession(); window.addEventListener("online", checkActiveSession); return () => { unsubscribe(); window.removeEventListener("online", checkActiveSession); }; } // src/hooks/use-subscribe-device-sessions.ts function useSubscribeDeviceSessions() { react$2.useEffect(() => { return subscribeDeviceSessions(); }, []); } var authClient = react.createAuthClient({ plugins: [plugins.multiSessionClient()] }); // src/set-active-session.ts async function setActiveSession({ sessionToken }) { var _a; const deviceSessions = $deviceSessions.get(); const session = (_a = deviceSessions.data) == null ? void 0 : _a.find( (session2) => session2.session.token === sessionToken ); if (!session) throw { error: { message: "Invalid session token", code: "INVALID_SESSION_TOKEN" } }; const persistentSession = $persistentSession.get(); $persistentSession.set({ ...persistentSession, optimistic: true, data: session, isPending: false, isRefetching: false, error: null }); authClient.multiSession.setActive({ sessionToken }).then((result) => { if (result.error) return; persistentSession.refetch(); }); } exports.$authClient = $authClient; exports.$persistentSession = $persistentSession; exports.setActiveSession = setActiveSession; exports.subscribeDeviceSessions = subscribeDeviceSessions; exports.useListDeviceSessions = useListDeviceSessions; exports.useSession = useSession; exports.useSubscribeDeviceSessions = useSubscribeDeviceSessions;