import { betterAuth } from 'better-auth'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; import { nextCookies } from 'better-auth/next-js'; import { admin, magicLink, organization } from 'better-auth/plugins'; import { db } from '@/lib/server/db'; import { authSchema } from '@/lib/server/db/schema'; type BetterAuthInstance = ReturnType; let authInstance: BetterAuthInstance | null = null; function parseCsvList(value: string | undefined) { return (value ?? '') .split(',') .map((entry) => entry.trim()) .filter((entry) => entry.length > 0); } function buildAuth() { const adminUserIds = parseCsvList(process.env.BETTER_AUTH_ADMIN_USER_IDS); const trustedOrigins = parseCsvList(process.env.BETTER_AUTH_TRUSTED_ORIGINS); const baseURL = process.env.BETTER_AUTH_BASE_URL?.trim() || process.env.BETTER_AUTH_URL?.trim() || undefined; const secret = process.env.BETTER_AUTH_SECRET?.trim() || undefined; return betterAuth({ database: drizzleAdapter(db, { provider: 'pg', schema: authSchema }), baseURL, secret, emailAndPassword: { enabled: true }, trustedOrigins: trustedOrigins.length > 0 ? trustedOrigins : undefined, plugins: [ admin(adminUserIds.length > 0 ? { adminUserIds } : undefined), magicLink({ sendMagicLink: async ({ email, url }) => { console.info(`[better-auth] Magic link requested for ${email}: ${url}`); } }), organization(), nextCookies() ] }); } export function getAuth() { if (!authInstance) { authInstance = buildAuth(); } return authInstance; } export async function ensureAuthSchema() { return getAuth(); }