export type AuthSession = { session: { id: string; userId: string }; user: { id: string; email: string | null; name: string | null }; }; function toSession(value: unknown): AuthSession | null { if (!value || typeof value !== "object") return null; const record = value as Record; const sessionValue = record.session; const userValue = record.user; if (!sessionValue || typeof sessionValue !== "object") return null; if (!userValue || typeof userValue !== "object") return null; const session = sessionValue as Record; const user = userValue as Record; if (typeof session.id !== "string" || typeof session.userId !== "string") return null; if (typeof user.id !== "string") return null; return { session: { id: session.id, userId: session.userId }, user: { id: user.id, email: typeof user.email === "string" ? user.email : null, name: typeof user.name === "string" ? user.name : null, }, }; } async function authPost(path: string, body: Record) { const res = await fetch(`/api/auth${path}`, { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); const payload = await res.json().catch(() => null); if (!res.ok) { const message = (payload as { error?: { message?: string } | string } | null)?.error && typeof (payload as { error?: { message?: string } | string }).error === "object" ? ((payload as { error?: { message?: string } }).error?.message ?? `Request failed: ${res.status}`) : (payload as { error?: string } | null)?.error ?? `Request failed: ${res.status}`; throw new Error(message); } return payload; } export const authApi = { getSession: async (): Promise => { const res = await fetch("/api/auth/get-session", { credentials: "include", headers: { Accept: "application/json" }, }); if (res.status === 401) return null; const payload = await res.json().catch(() => null); if (!res.ok) { throw new Error(`Failed to load session (${res.status})`); } const direct = toSession(payload); if (direct) return direct; const nested = payload && typeof payload === "object" ? toSession((payload as Record).data) : null; return nested; }, signInEmail: async (input: { email: string; password: string }) => { await authPost("/sign-in/email", input); }, signUpEmail: async (input: { name: string; email: string; password: string }) => { await authPost("/sign-up/email", input); }, signOut: async () => { await authPost("/sign-out", {}); }, };