import 'server-only' import { sql } from 'drizzle-orm' import { userDb, adminDb, type UserDb, type AdminDb } from './index' export type DrizzleTransaction = Parameters[0]>[0] /** * Runs fn inside a transaction with app.user_id SET LOCAL to userId. * All RLS policies read this GUC via app_current_user_id(). * The GUC is LOCAL so it is automatically cleared when the transaction ends. */ export async function withUser( userId: string, fn: (tx: DrizzleTransaction) => Promise ): Promise { return userDb.transaction(async (tx) => { await tx.execute(sql`SELECT set_config('app.user_id', ${userId}, true)`) return fn(tx) }) } /** * Runs fn against the admin (BYPASSRLS) pool. * Use only for: admin user CRUD, service operations that legitimately bypass RLS. * Never use for regular user data access. */ export async function asAdmin(fn: (db: AdminDb) => Promise): Promise { return fn(adminDb) }