103 lines
3.1 KiB
TypeScript
103 lines
3.1 KiB
TypeScript
import type { Kysely, Selectable } from 'kysely';
|
|
import type { Database, RoomsTable } from '../../db/schema';
|
|
|
|
export type RoomRow = Selectable<RoomsTable>;
|
|
|
|
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<RoomRow>;
|
|
findById(id: string): Promise<RoomRow | undefined>;
|
|
listForUser(userId: string): Promise<RoomRow[]>;
|
|
isMember(roomId: string, userId: string): Promise<boolean>;
|
|
getRole(roomId: string, userId: string): Promise<string | undefined>;
|
|
addMember(roomId: string, userId: string, role: string): Promise<void>;
|
|
removeMember(roomId: string, userId: string): Promise<void>;
|
|
listMembers(roomId: string): Promise<RoomMemberWithUser[]>;
|
|
}
|
|
|
|
export const createRoomsRepository = (db: Kysely<Database>): 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(),
|
|
});
|