/** * Supabase client for Server Components and Route Handlers. * Uses the cookies() API to read+write the user's session. * * If NEXT_PUBLIC_SUPABASE_URL is not set (e.g., local dev without Supabase), * returns a stub that throws — callers should check `isSupabaseConfigured()`. */ import { createServerClient, type CookieOptions } from "@supabase/ssr"; import { cookies } from "next/headers"; export function isSupabaseConfigured(): boolean { return Boolean(process.env.NEXT_PUBLIC_SUPABASE_URL && process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY); } export async function createClient() { const url = process.env.NEXT_PUBLIC_SUPABASE_URL; const key = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; if (!url || !key) { throw new Error("Supabase env vars not set"); } const cookieStore = await cookies(); return createServerClient(url, key, { cookies: { getAll() { return cookieStore.getAll(); }, setAll(toSet: Array<{ name: string; value: string; options?: CookieOptions }>) { try { toSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options)); } catch { // setAll fails in Server Components (no setter); ignore — middleware handles refresh. } }, }, }); } /** * Admin client using service_role key. Bypasses RLS. USE ONLY in trusted server * code (never expose to clients). Required for inserting usage_events under * service_role, deleting users, etc. */ export function createServiceClient() { const url = process.env.NEXT_PUBLIC_SUPABASE_URL; const key = process.env.SUPABASE_SERVICE_ROLE_KEY; if (!url || !key) throw new Error("Supabase service env vars not set"); // Lazy import to avoid bundling on client // eslint-disable-next-line @typescript-eslint/no-require-imports const { createClient } = require("@supabase/supabase-js"); return createClient(url, key, { auth: { autoRefreshToken: false, persistSession: false }, }); }