unreal-chat/apps/api/src/resolvers/room.ts
Juan Sebastian Montoya 16731409df refactor: migrate from Next.js to SolidJS and GraphQL
- Converted web application from Next.js to SolidJS with Vite
- Replaced React components with SolidJS components
- Implemented GraphQL client using URQL
- Added authentication, room, and chat components
- Updated project structure and configuration files
- Removed unnecessary Next.js and docs-related files
- Added Docker support for web and API applications
2025-03-04 01:08:52 -05:00

161 lines
3.9 KiB
TypeScript

import { PrismaClient } from '@prisma/client';
import { AuthenticationError, ForbiddenError } from 'apollo-server-express';
import { PubSub } from 'graphql-subscriptions';
const prisma = new PrismaClient();
const pubsub = new PubSub();
export const ROOM_ADDED = 'ROOM_ADDED';
export const roomResolvers = {
Query: {
rooms: async () => {
return prisma.room.findMany({
where: { isPrivate: false },
});
},
room: async (_: any, { id }: { id: string }) => {
return prisma.room.findUnique({
where: { id },
});
},
},
Mutation: {
createRoom: async (
_: any,
{
name,
description,
isPrivate = false,
}: { name: string; description?: string; isPrivate?: boolean },
context: any
) => {
if (!context.userId) {
throw new AuthenticationError('You must be logged in to create a room');
}
const room = await prisma.room.create({
data: {
name,
description,
isPrivate,
owner: {
connect: { id: context.userId },
},
members: {
connect: { id: context.userId },
},
},
});
pubsub.publish(ROOM_ADDED, { roomAdded: room });
return room;
},
joinRoom: async (_: any, { roomId }: { roomId: string }, context: any) => {
if (!context.userId) {
throw new AuthenticationError('You must be logged in to join a room');
}
const room = await prisma.room.findUnique({
where: { id: roomId },
include: { members: true },
});
if (!room) {
throw new ForbiddenError('Room not found');
}
if (room.isPrivate) {
// In a real application, you would check if the user has been invited
throw new ForbiddenError(
'You cannot join a private room without an invitation'
);
}
// Check if user is already a member
const isMember = room.members.some(
(member: { id: string }) => member.id === context.userId
);
if (isMember) {
return room;
}
return prisma.room.update({
where: { id: roomId },
data: {
members: {
connect: { id: context.userId },
},
},
});
},
leaveRoom: async (_: any, { roomId }: { roomId: string }, context: any) => {
if (!context.userId) {
throw new AuthenticationError('You must be logged in to leave a room');
}
const room = await prisma.room.findUnique({
where: { id: roomId },
include: { members: true },
});
if (!room) {
throw new ForbiddenError('Room not found');
}
// Check if user is a member
const isMember = room.members.some(
(member: { id: string }) => member.id === context.userId
);
if (!isMember) {
throw new ForbiddenError('You are not a member of this room');
}
// If user is the owner, they cannot leave
if (room.ownerId === context.userId) {
throw new ForbiddenError('You cannot leave a room you own');
}
await prisma.room.update({
where: { id: roomId },
data: {
members: {
disconnect: { id: context.userId },
},
},
});
return true;
},
},
Subscription: {
roomAdded: {
subscribe: () => pubsub.asyncIterator([ROOM_ADDED]),
},
},
Room: {
messages: async (parent: any) => {
return prisma.message.findMany({
where: { roomId: parent.id },
orderBy: { createdAt: 'asc' },
});
},
members: async (parent: any) => {
return prisma.user.findMany({
where: {
rooms: {
some: {
id: parent.id,
},
},
},
});
},
owner: async (parent: any) => {
return prisma.user.findUnique({
where: { id: parent.ownerId },
});
},
},
};