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