- 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
161 lines
3.9 KiB
TypeScript
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 },
|
|
});
|
|
},
|
|
},
|
|
};
|