feat: add realtime with socket.io

This commit is contained in:
Divlo
2022-01-13 16:33:16 +00:00
parent 97b1d04261
commit 5643ab420f
7 changed files with 483 additions and 363 deletions

View File

@ -1,18 +1,88 @@
import fastifyPlugin from 'fastify-plugin'
import { Server as SocketIoServer, ServerOptions } from 'socket.io'
import { authorize } from '@thream/socketio-jwt'
import prisma from '../database/prisma.js'
import { JWT_ACCESS_SECRET } from '../configurations/index.js'
interface EmitEventOptions {
event: string
payload: {
action: 'create' | 'delete' | 'update'
item: object
}
}
interface EmitToAuthorizedUsersOptions extends EmitEventOptions {
/** tests whether the current connected userId is authorized to get the event, if the callback returns true, the server will emit the event to that user */
isAuthorizedCallback: (userId: number) => Promise<boolean>
}
type EmitToAuthorizedUsers = (
options: EmitToAuthorizedUsersOptions
) => Promise<void>
interface EmitToMembersOptions extends EmitEventOptions {
guildId: number
}
type EmitToMembers = (options: EmitToMembersOptions) => Promise<void>
interface FastifyIo {
instance: SocketIoServer
emitToAuthorizedUsers: EmitToAuthorizedUsers
emitToMembers: EmitToMembers
}
declare module 'fastify' {
export interface FastifyInstance {
io: SocketIoServer
io: FastifyIo
}
}
export default fastifyPlugin(
async (fastify, options: Partial<ServerOptions>) => {
const socket = new SocketIoServer(fastify.server, options)
fastify.decorate('io', socket)
const instance = new SocketIoServer(fastify.server, options)
instance.use(
authorize({
secret: JWT_ACCESS_SECRET
})
)
const emitToAuthorizedUsers: EmitToAuthorizedUsers = async (options) => {
const { event, payload, isAuthorizedCallback } = options
const clients = await instance.sockets.allSockets()
for (const clientId of clients) {
const client = instance.sockets.sockets.get(clientId)
if (client != null) {
const userId = client.decodedToken.id
const isAuthorized = await isAuthorizedCallback(userId)
if (isAuthorized) {
client.emit(event, payload)
}
}
}
}
const emitToMembers: EmitToMembers = async (options) => {
const { event, payload, guildId } = options
await emitToAuthorizedUsers({
event,
payload,
isAuthorizedCallback: async (userId) => {
const memberCount = await prisma.member.count({
where: { userId, guildId }
})
return memberCount > 0
}
})
}
const io: FastifyIo = {
instance,
emitToAuthorizedUsers,
emitToMembers
}
fastify.decorate('io', io)
fastify.addHook('onClose', async (fastify) => {
fastify.io.close()
fastify.io.instance.close()
})
},
{ fastify: '3.x' }