import { request, unwrapApiBody, type ApiResponse } from "../utils/http/factory"; export type AuthUser = { id: number; username: string; }; type MeResult = { user: AuthUser; }; export type AuthSessionState = { initialized: boolean; pending: boolean; loggedIn: boolean; user: AuthUser | null; }; export const AUTH_SESSION_STATE_KEY = "auth:session"; export const DEFAULT_AUTH_SESSION_STATE: AuthSessionState = { initialized: false, pending: false, loggedIn: false, user: null, }; function isUnauthorized(error: unknown) { if (typeof error !== "object" || error === null) { return false; } return "statusCode" in error && (error as { statusCode?: number }).statusCode === 401; } export function useAuthSession() { const state = useState(AUTH_SESSION_STATE_KEY, () => ({ ...DEFAULT_AUTH_SESSION_STATE, })); const applyUser = (user: AuthUser | null) => { state.value.user = user; state.value.loggedIn = Boolean(user); state.value.initialized = true; }; const clear = () => { applyUser(null); }; const refresh = async (force = false) => { if (state.value.initialized && !force) { return state.value.user; } if (state.value.pending) { return state.value.user; } state.value.pending = true; try { const fetcher = import.meta.server ? useRequestFetch() : request; const payload = await fetcher>("/api/auth/me"); const data = unwrapApiBody(payload); applyUser(data.user); return data.user; } catch (error: unknown) { if (isUnauthorized(error)) { clear(); return null; } throw error; } finally { state.value.pending = false; } }; return { initialized: computed(() => state.value.initialized), loggedIn: computed(() => state.value.loggedIn), user: computed(() => state.value.user), pending: computed(() => state.value.pending), refresh, clear, }; }