import { cookies } from "next/headers"; import { PB_URL } from "./pocketbase"; import type { AppUser } from "./types"; const COOKIE_NAME = "pb_auth"; const COOKIE_MAX_AGE = 60 * 60 * 24 * 7; // 7 days export interface AuthState { user: AppUser | null; token: string | null; } /** * Server-side auth: read the PB token from the cookie and verify it against * the PB API. We use plain fetch (not the PocketBase SDK) to avoid Next.js * RSC's auto-cancellation of the SDK's internal fetch. */ export async function getAuth(): Promise { const cookieStore = await cookies(); const cookie = cookieStore.get(COOKIE_NAME); if (!cookie?.value) return { user: null, token: null }; try { const res = await fetch(`${PB_URL}/api/collections/users/auth-refresh`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: cookie.value, }, cache: "no-store", }); if (!res.ok) { return { user: null, token: null }; } const data = await res.json(); const record = data.record; return { user: { id: record.id, email: record.email, name: record.name, verified: record.verified, }, token: cookie.value, }; } catch { return { user: null, token: null }; } } export async function requireAuth(): Promise { const auth = await getAuth(); if (!auth.user) { throw new Error("Unauthorized"); } return auth; } export async function setAuthCookie(token: string) { const cookieStore = await cookies(); cookieStore.set(COOKIE_NAME, token, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", path: "/", maxAge: COOKIE_MAX_AGE, }); } export async function clearAuthCookie() { const cookieStore = await cookies(); cookieStore.delete(COOKIE_NAME); }