// Single source of truth for all backend communication. async function http(path, { method = 'GET', body } = {}) { const headers = { 'Content-Type': 'application/json' }; const res = await fetch(path, { method, headers, credentials: 'include', body: body ? JSON.stringify(body) : undefined, }); if (!res.ok) { let message = res.statusText; let data; try { data = await res.json(); message = data.error || data.message || message; } catch { message = (await res.text().catch(() => message)) || message; } const err = new Error(message || `Request failed (${res.status})`); err.status = res.status; err.data = data; throw err; } if (res.status === 204) return null; return res.json(); } export const auth = { async me() { try { const data = await http('/api/auth/me'); return { user: data.user ?? null, googleClientId: data.googleClientId ?? null, }; } catch (err) { if (err.status === 401 || err.status === 403) { return { user: null, googleClientId: err.data?.googleClientId ?? null, forbidden: err.status === 403, message: err.message, }; } throw err; } }, async loginWithGoogle(idToken) { const data = await http('/api/auth/login', { method: 'POST', body: { idToken }, }); return { user: data.user }; }, async logout() { try { await http('/api/auth/logout', { method: 'POST' }); } catch (err) { if (err.status !== 401) throw err; } }, }; export default { auth };