Skip to content

Instantly share code, notes, and snippets.

@heygema
Last active January 19, 2021 11:13
Show Gist options
  • Save heygema/ffe70894153b209e5b642bb0ab60cfdf to your computer and use it in GitHub Desktop.
Save heygema/ffe70894153b209e5b642bb0ab60cfdf to your computer and use it in GitHub Desktop.
chat server gql
import path from 'path';
import express from 'express';
import http from 'http';
import {ApolloServer, gql} from 'apollo-server-express';
import makeIO from 'socket.io';
import prisma from './prismaClient';
const typeDefs = gql`
type Query {
hello(name: String): String!
messages(roomId: String!): [String!]!
friends(email: String!): [Friendship!]!
users: [User!]!
}
type User {
id: String!
email: String!
name: String!
}
type Friendship {
id: String!
friendshipType: FriendshipType!
users: [User!]!
}
enum FriendshipType {
Friend
Group
}
type Mutation {
createUser(email: String, name: String): User
}
`;
const resolvers = {
Query: {
hello: (_: any, {name}: any) => {
return `hello ${name}`;
},
users: () => {
return prisma.user.findMany();
},
friends: async (_: any, {email}: {email: string}) => {
let friends = await prisma.friendship.findMany({
where: {
friendshipType: 'Friend',
users: {
some: {email},
},
},
include: {
users: {
where: {
NOT: {
email,
},
},
},
},
});
return friends;
},
messages: async (_: any, {roomId}: {roomId: string}) => {
let friendship = await prisma.friendship.findUnique({
where: {
id: roomId,
},
include: {
messages: {
include: {
sender: {},
},
},
},
});
return friendship?.messages;
},
},
Mutation: {
createUser: async (
_: any,
{email, name}: {email: string; name: string}
) => {
let result = await prisma.user.create({
data: {
email,
name,
},
});
return result;
},
},
};
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: (contexts) => ({
...contexts,
prisma,
}),
});
let app = express();
app.set('prisma', prisma);
app.use(express.static(path.join(__dirname, '../public')));
apolloServer.applyMiddleware({app});
let server = http.createServer(app);
// @ts-ignore
const io = makeIO(server);
io.on('connection', (socket: any) => {
console.log(`someone ${socket.id} in`);
socket.on('join-friend-room', (roomId: number) => {
socket.join(roomId);
socket.emit('message', `Welcome ${socket.id}`);
});
type MessageFromUser = {
senderId: string;
roomId: string;
content: string;
};
// for security purpose, get sender id from cached roomId on connectedsocket
socket.on(
'message-from-client',
async ({senderId, roomId, content}: MessageFromUser) => {
// persist to db here
let message = await prisma.message.create({
data: {
friendship: {
connect: {
id: roomId,
},
},
sender: {
connect: {
id: senderId,
},
},
content,
},
});
io.to(roomId).emit('message-from-server', message);
}
);
});
server.listen(4000, () => {
console.log(`Server running on http://localhost${4000}`);
});
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id String @id @default(cuid())
email String @unique
name String?
friendships Friendship[]
messages Message[]
createdAt DateTime @default(now()) @map(name: "created_at")
@@map(name: "users")
}
model Friendship {
id String @id @default(cuid())
users User[]
friendshipType FriendshipType
messages Message[]
createdAt DateTime @default(now()) @map(name: "created_at")
@@map(name: "friendships")
}
enum FriendshipType {
Group
Friend
}
model Message {
id String @id @default(cuid())
friendship Friendship @relation(fields: [friendshipId], references: [id])
sender User @relation(fields: [userId], references: [id])
friendshipId String
userId String
content String
createdAt DateTime @default(now()) @map(name: "created_at")
@@map(name: "messages")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment