import { users } from "@db/schema"; import { eq } from "drizzle-orm"; import { DrizzleClient } from "@shared/db/DrizzleClient"; import { withTransaction } from "@/lib/db"; import type { Transaction } from "@shared/lib/types"; export const userService = { /** Fetch a user by Discord ID, including their class relation. */ getUserById: async (id: string) => { const user = await DrizzleClient.query.users.findFirst({ where: eq(users.id, BigInt(id)), with: { class: true } }); return user; }, /** Fetch a user by their username. */ getUserByUsername: async (username: string) => { const user = await DrizzleClient.query.users.findFirst({ where: eq(users.username, username) }); return user; }, /** Fetch a user by ID, creating a new record if one does not exist. */ getOrCreateUser: async (id: string, username: string, tx?: Transaction) => { return await withTransaction(async (txFn) => { let user = await txFn.query.users.findFirst({ where: eq(users.id, BigInt(id)), with: { class: true } }); if (!user) { await txFn.insert(users).values({ id: BigInt(id), username, }).returning(); // Re-query to get the user with class relation user = await txFn.query.users.findFirst({ where: eq(users.id, BigInt(id)), with: { class: true } }); } return user; }, tx); }, /** Get the class assigned to a user, or undefined if none. */ getUserClass: async (id: string) => { const user = await DrizzleClient.query.users.findFirst({ where: eq(users.id, BigInt(id)), with: { class: true } }); return user?.class; }, /** Create a new user with an optional initial class assignment. */ createUser: async (id: string | bigint, username: string, classId?: bigint, tx?: Transaction) => { return await withTransaction(async (txFn) => { const [user] = await txFn.insert(users).values({ id: BigInt(id), username, classId, }).returning(); return user; }, tx); }, /** Update a user record with partial data. */ updateUser: async (id: string, data: Partial, tx?: Transaction) => { return await withTransaction(async (txFn) => { const [user] = await txFn.update(users) .set(data) .where(eq(users.id, BigInt(id))) .returning(); return user; }, tx); }, /** Delete a user by ID. */ deleteUser: async (id: string, tx?: Transaction) => { return await withTransaction(async (txFn) => { await txFn.delete(users).where(eq(users.id, BigInt(id))); }, tx); }, };