import type { Kysely, Selectable } from 'kysely'; import type { Database, RoomsTable } from '../../db/schema'; export type RoomRow = Selectable; export interface RoomMemberWithUser { user_id: string; role: string; joined_at: Date; username: string; display_name: string; avatar_ref: string | null; } export interface RoomsRepository { createWithOwner(name: string, ownerId: string): Promise; findById(id: string): Promise; listForUser(userId: string): Promise; isMember(roomId: string, userId: string): Promise; getRole(roomId: string, userId: string): Promise; addMember(roomId: string, userId: string, role: string): Promise; removeMember(roomId: string, userId: string): Promise; listMembers(roomId: string): Promise; } export const createRoomsRepository = (db: Kysely): RoomsRepository => ({ createWithOwner: (name, ownerId) => db.transaction().execute(async (trx) => { const room = await trx .insertInto('rooms') .values({ name, created_by: ownerId }) .returningAll() .executeTakeFirstOrThrow(); await trx .insertInto('room_members') .values({ room_id: room.id, user_id: ownerId, role: 'owner' }) .execute(); return room; }), findById: (id) => db.selectFrom('rooms').selectAll().where('id', '=', id).executeTakeFirst(), listForUser: (userId) => db .selectFrom('rooms') .innerJoin('room_members', 'room_members.room_id', 'rooms.id') .where('room_members.user_id', '=', userId) .selectAll('rooms') .orderBy('rooms.created_at', 'desc') .execute(), isMember: async (roomId, userId) => { const row = await db .selectFrom('room_members') .select('user_id') .where('room_id', '=', roomId) .where('user_id', '=', userId) .executeTakeFirst(); return row !== undefined; }, getRole: async (roomId, userId) => { const row = await db .selectFrom('room_members') .select('role') .where('room_id', '=', roomId) .where('user_id', '=', userId) .executeTakeFirst(); return row?.role; }, addMember: async (roomId, userId, role) => { await db .insertInto('room_members') .values({ room_id: roomId, user_id: userId, role }) .onConflict((oc) => oc.columns(['room_id', 'user_id']).doNothing()) .execute(); }, removeMember: async (roomId, userId) => { await db .deleteFrom('room_members') .where('room_id', '=', roomId) .where('user_id', '=', userId) .execute(); }, listMembers: (roomId) => db .selectFrom('room_members') .innerJoin('users', 'users.id', 'room_members.user_id') .where('room_members.room_id', '=', roomId) .select([ 'room_members.user_id as user_id', 'room_members.role as role', 'room_members.joined_at as joined_at', 'users.username as username', 'users.display_name as display_name', 'users.avatar_ref as avatar_ref', ]) .orderBy('room_members.joined_at', 'asc') .execute(), });