import { eq } from "drizzle-orm"; import { db } from "./db"; import { party, partyMember } from "./db/schema"; import type { PartySnapshot } from "./party-types"; type DbClient = typeof db; type DbTransaction = Parameters[0] extends ( tx: infer T, ) => Promise ? T : never; export type DbLike = DbClient | DbTransaction; export async function getPartyForUser(userId: string) { const memberships = await db.query.partyMember.findMany({ where: { userId, }, with: { party: true, }, limit: 1, }); return memberships[0]?.party ?? null; } export async function getMemberRecord(dbClient: DbLike, userId: string) { return ( (await dbClient.query.partyMember.findFirst({ where: { userId, }, orderBy: { joinedAt: "desc", }, })) ?? null ); } export async function getPartyStatus( partyId: string, ): Promise { const partyRecord = await db.query.party.findFirst({ where: { id: partyId, }, }); if (!partyRecord) return null; const members = await db.query.partyMember.findMany({ where: { partyId, }, with: { user: true, }, orderBy: { joinedAt: "asc", }, }); return { party: partyRecord, members, }; } export async function cleanupPartyIfEmpty(dbClient: DbLike, partyId: string) { const members = await dbClient.query.partyMember.findMany({ where: { partyId, }, limit: 1, }); if (members.length > 0) return; await dbClient.delete(party).where(eq(party.id, partyId)); } export async function leaveParty(dbClient: DbLike, userId: string) { const member = await getMemberRecord(dbClient, userId); if (!member) return null; await dbClient.delete(partyMember).where(eq(partyMember.id, member.id)); const nextHost = await dbClient.query.partyMember.findFirst({ where: { partyId: member.partyId, }, orderBy: { joinedAt: "asc", }, }); let newHostId: string | null = null; if (nextHost) { const currentParty = await dbClient.query.party.findFirst({ where: { id: member.partyId, }, }); if (currentParty?.hostId === userId) { await dbClient .update(party) .set({ hostId: nextHost.userId, lastUpdated: new Date(), }) .where(eq(party.id, member.partyId)); newHostId = nextHost.userId; } } await cleanupPartyIfEmpty(dbClient, member.partyId); return { partyId: member.partyId, newHostId, }; }