this repo has no description
1import { api, type Session, type CreateAccountParams, type CreateAccountResult, ApiError } from './api' 2 3const STORAGE_KEY = 'bspds_session' 4 5interface AuthState { 6 session: Session | null 7 loading: boolean 8 error: string | null 9} 10 11let state = $state<AuthState>({ 12 session: null, 13 loading: true, 14 error: null, 15}) 16 17function saveSession(session: Session | null) { 18 if (session) { 19 localStorage.setItem(STORAGE_KEY, JSON.stringify(session)) 20 } else { 21 localStorage.removeItem(STORAGE_KEY) 22 } 23} 24 25function loadSession(): Session | null { 26 const stored = localStorage.getItem(STORAGE_KEY) 27 if (stored) { 28 try { 29 return JSON.parse(stored) 30 } catch { 31 return null 32 } 33 } 34 return null 35} 36 37export async function initAuth() { 38 state.loading = true 39 state.error = null 40 41 const stored = loadSession() 42 if (stored) { 43 try { 44 const session = await api.getSession(stored.accessJwt) 45 state.session = { ...session, accessJwt: stored.accessJwt, refreshJwt: stored.refreshJwt } 46 } catch (e) { 47 if (e instanceof ApiError && e.status === 401) { 48 try { 49 const refreshed = await api.refreshSession(stored.refreshJwt) 50 state.session = refreshed 51 saveSession(refreshed) 52 } catch { 53 saveSession(null) 54 state.session = null 55 } 56 } else { 57 saveSession(null) 58 state.session = null 59 } 60 } 61 } 62 63 state.loading = false 64} 65 66export async function login(identifier: string, password: string): Promise<void> { 67 state.loading = true 68 state.error = null 69 70 try { 71 const session = await api.createSession(identifier, password) 72 state.session = session 73 saveSession(session) 74 } catch (e) { 75 if (e instanceof ApiError) { 76 state.error = e.message 77 } else { 78 state.error = 'Login failed' 79 } 80 throw e 81 } finally { 82 state.loading = false 83 } 84} 85 86export async function register(params: CreateAccountParams): Promise<CreateAccountResult> { 87 try { 88 const result = await api.createAccount(params) 89 return result 90 } catch (e) { 91 if (e instanceof ApiError) { 92 state.error = e.message 93 } else { 94 state.error = 'Registration failed' 95 } 96 throw e 97 } 98} 99 100export async function confirmSignup(did: string, verificationCode: string): Promise<void> { 101 state.loading = true 102 state.error = null 103 104 try { 105 const result = await api.confirmSignup(did, verificationCode) 106 const session: Session = { 107 did: result.did, 108 handle: result.handle, 109 accessJwt: result.accessJwt, 110 refreshJwt: result.refreshJwt, 111 } 112 state.session = session 113 saveSession(session) 114 } catch (e) { 115 if (e instanceof ApiError) { 116 state.error = e.message 117 } else { 118 state.error = 'Verification failed' 119 } 120 throw e 121 } finally { 122 state.loading = false 123 } 124} 125 126export async function resendVerification(did: string): Promise<void> { 127 try { 128 await api.resendVerification(did) 129 } catch (e) { 130 if (e instanceof ApiError) { 131 throw e 132 } 133 throw new Error('Failed to resend verification code') 134 } 135} 136 137export async function logout(): Promise<void> { 138 if (state.session) { 139 try { 140 await api.deleteSession(state.session.accessJwt) 141 } catch { 142 // Ignore errors on logout 143 } 144 } 145 state.session = null 146 saveSession(null) 147} 148 149export function getAuthState() { 150 return state 151} 152 153export function getToken(): string | null { 154 return state.session?.accessJwt ?? null 155} 156 157export function isAuthenticated(): boolean { 158 return state.session !== null 159} 160 161export function _testSetState(newState: { session: Session | null; loading: boolean; error: string | null }) { 162 state.session = newState.session 163 state.loading = newState.loading 164 state.error = newState.error 165} 166 167export function _testReset() { 168 state.session = null 169 state.loading = true 170 state.error = null 171 localStorage.removeItem(STORAGE_KEY) 172}