import type { Database } from '@pascal-app/db' import { schema } from '@pascal-app/db' import type { BetterAuthOptions } from 'better-auth' import { betterAuth } from 'better-auth' import { drizzleAdapter } from 'better-auth/adapters/drizzle' import { magicLink } from 'better-auth/plugins' export interface SendMagicLinkParams { email: string url: string token: string } export interface AuthConfig { db: Database appName: string baseURL: string secret: string /** Callback to send magic link emails */ sendMagicLink?: (params: SendMagicLinkParams) => Promise /** Additional plugins to add (e.g., nextCookies for web) */ additionalPlugins?: BetterAuthOptions['plugins'] } /** * Creates a Better Auth instance with full configuration including: * - Magic link authentication * - Custom session with activePropertyId * - Session cookie caching */ export function createAuth(config: AuthConfig): ReturnType { return betterAuth({ appName: config.appName, baseURL: config.baseURL, secret: config.secret, basePath: '/api/auth', database: drizzleAdapter(config.db, { provider: 'pg', usePlural: true, schema, }), advanced: { database: { generateId: false, // Use our prefixed nanoid IDs from schema }, }, session: { // Session caching to reduce database queries cookieCache: { enabled: true, maxAge: 5 * 60, // Cache duration in seconds (5 minutes) }, additionalFields: { // Additional fields for the session table activePropertyId: { type: 'string', }, }, }, plugins: [ ...(config.additionalPlugins ?? []), // Magic link authentication ...(config.sendMagicLink ? [ magicLink({ sendMagicLink: config.sendMagicLink, expiresIn: 300, // 5 minutes disableSignUp: false, // Allow new users to sign up via magic link }), ] : []), ], }) } export type Auth = ReturnType