// /composables/useAuth.ts // Define User interface interface User { id: string; email: string; nickname: string; } /** * Composable for authentication management. * All state is managed by Nuxt's useState to ensure it's shared and SSR-safe. */ export function useAuth() { // --- State --- // All state is defined here, inside the composable function. // Nuxt's useState ensures this state is a singleton across the app. const user = useState('user', () => null); const loading = useState('auth_loading', () => false); const initialized = useState('auth_initialized', () => false); // --- Composables --- const api = useApi(); // --- Computed Properties --- const isAuthenticated = computed(() => !!user.value); // --- Methods --- /** * Fetches the current user from the backend. * Runs only once, guarded by the 'initialized' state. */ const fetchMe = async () => { if (initialized.value) { return; } loading.value = true; initialized.value = true; try { const fetchedUser = await api('/auth/me', { method: 'GET' }); user.value = fetchedUser; } catch (error) { user.value = null; // Silently handle 401s or other errors } finally { loading.value = false; } }; /** * Logs the user in and fetches their data on success. */ const login = async (email, password) => { loading.value = true; try { await api('/auth/login', { method: 'POST', body: { email, password }, }); // We must re-fetch the user after logging in. // Resetting 'initialized' allows fetchMe to run again. initialized.value = false; await fetchMe(); await navigateTo('/'); } catch (error) { console.error('Login failed:', error); throw error; // Re-throw to allow the UI to handle it } finally { loading.value = false; } }; /** * Logs the user out. */ const logout = async () => { loading.value = true; try { await api('/auth/logout', { method: 'POST' }); } catch (error) { console.error('Logout API call failed, proceeding with client-side logout:', error); } finally { user.value = null; initialized.value = false; // Allow re-fetch on next app load/login loading.value = false; await navigateTo('/login'); } }; return { user, loading, isAuthenticated, fetchMe, login, logout, }; }