import { useMemo, useState } from 'react' import type { PropsWithChildren } from 'react' import { clearAuthSession, getAuthSession, isAccessTokenStale, setAuthSession } from '../lib/auth-storage' import type { AuthSession } from '../lib/auth-storage' import { loginCenter, logoutCenter, meGuildsCenter, refreshCenter } from '../lib/center-auth-client' import { AuthContext } from './auth-context' import type { AuthContextValue } from './auth-context' export function AuthProvider({ children }: PropsWithChildren) { const [session, setSession] = useState(getAuthSession()) const value = useMemo( () => ({ session, isAuthed: !!session, login: async (centerApiBase: string, email: string, password: string) => { const next = await loginCenter(centerApiBase, { email, password }) setAuthSession(next) setSession(next) }, logout: async () => { if (session?.refreshToken) { try { await logoutCenter(session.centerApiBase, session.refreshToken) } catch { // noop } } clearAuthSession() setSession(null) }, ensureFreshToken: async () => { if (!session) return null if (!isAccessTokenStale(session.accessToken)) return session.accessToken const refreshed = await refreshCenter(session.centerApiBase, session.refreshToken) const next: AuthSession = { ...session, accessToken: refreshed.accessToken, refreshToken: refreshed.refreshToken, tokenType: refreshed.tokenType, expiresIn: refreshed.expiresIn, } setAuthSession(next) setSession(next) return next.accessToken }, refreshGuilds: async () => { if (!session) return let accessToken = session.accessToken let refreshToken = session.refreshToken let tokenType = session.tokenType let expiresIn = session.expiresIn if (isAccessTokenStale(session.accessToken)) { const refreshed = await refreshCenter(session.centerApiBase, session.refreshToken) accessToken = refreshed.accessToken refreshToken = refreshed.refreshToken tokenType = refreshed.tokenType expiresIn = refreshed.expiresIn } const guildData = await meGuildsCenter(session.centerApiBase, accessToken) const next: AuthSession = { ...session, accessToken, refreshToken, tokenType, expiresIn, guilds: guildData.guilds, guildAccessTokens: guildData.guildAccessTokens, } setAuthSession(next) setSession(next) }, }), [session], ) return {children} }