feat: add realtime with socket.io
This commit is contained in:
parent
97b1d04261
commit
5643ab420f
@ -12,7 +12,10 @@
|
||||
"prettier/prettier": "error",
|
||||
"import/order": [
|
||||
"error",
|
||||
{ "groups": ["builtin", "external", "internal"] }
|
||||
{
|
||||
"groups": ["builtin", "external", "internal"],
|
||||
"newlines-between": "always"
|
||||
}
|
||||
],
|
||||
"import/extensions": ["error", "always"],
|
||||
"unicorn/prefer-node-protocol": "error",
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ node_modules
|
||||
|
||||
# production
|
||||
build
|
||||
.swc
|
||||
|
||||
# testing
|
||||
coverage
|
||||
|
721
package-lock.json
generated
721
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@ -18,7 +18,7 @@
|
||||
"generate": "plop",
|
||||
"lint:commit": "commitlint",
|
||||
"lint:editorconfig": "editorconfig-checker",
|
||||
"lint:markdown": "markdownlint '**/*.md' --dot --ignore 'node_modules'",
|
||||
"lint:markdown": "markdownlint '**/*.md' --dot --ignore-path '.gitignore'",
|
||||
"lint:typescript": "eslint '**/*.{js,ts,jsx,tsx}'",
|
||||
"lint:prettier": "prettier '.' --check",
|
||||
"lint:staged": "lint-staged",
|
||||
@ -31,21 +31,22 @@
|
||||
"postinstall": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "3.7.0",
|
||||
"@prisma/client": "3.8.0",
|
||||
"@sinclair/typebox": "0.23.2",
|
||||
"@thream/socketio-jwt": "2.1.1",
|
||||
"axios": "0.24.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"dotenv": "10.0.0",
|
||||
"dotenv": "11.0.0",
|
||||
"ejs": "3.1.6",
|
||||
"fastify": "3.25.3",
|
||||
"fastify-cors": "6.0.2",
|
||||
"fastify-helmet": "5.3.2",
|
||||
"fastify-helmet": "6.0.0",
|
||||
"fastify-multipart": "5.2.1",
|
||||
"fastify-plugin": "3.0.0",
|
||||
"fastify-rate-limit": "5.7.0",
|
||||
"fastify-sensible": "3.1.2",
|
||||
"fastify-static": "4.5.0",
|
||||
"fastify-swagger": "4.13.0",
|
||||
"fastify-swagger": "4.13.1",
|
||||
"fastify-url-data": "3.0.3",
|
||||
"http-errors": "2.0.0",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
@ -55,18 +56,18 @@
|
||||
"socket.io": "4.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "16.0.1",
|
||||
"@commitlint/cli": "16.0.2",
|
||||
"@commitlint/config-conventional": "16.0.0",
|
||||
"@saithodev/semantic-release-backmerge": "2.1.0",
|
||||
"@swc/cli": "0.1.55",
|
||||
"@swc/core": "1.2.127",
|
||||
"@swc/jest": "0.2.15",
|
||||
"@swc/core": "1.2.129",
|
||||
"@swc/jest": "0.2.17",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/busboy": "0.3.1",
|
||||
"@types/busboy": "1.3.0",
|
||||
"@types/ejs": "3.1.0",
|
||||
"@types/http-errors": "1.8.1",
|
||||
"@types/jest": "27.4.0",
|
||||
"@types/jsonwebtoken": "8.5.6",
|
||||
"@types/jsonwebtoken": "8.5.7",
|
||||
"@types/ms": "0.7.31",
|
||||
"@types/node": "17.0.8",
|
||||
"@types/nodemailer": "6.4.4",
|
||||
@ -86,12 +87,12 @@
|
||||
"jest": "27.4.7",
|
||||
"jest-mock-extended": "2.0.4",
|
||||
"jest-ts-webcompat-resolver": "1.0.0",
|
||||
"lint-staged": "12.1.5",
|
||||
"lint-staged": "12.1.7",
|
||||
"markdownlint-cli": "0.30.0",
|
||||
"nodemon": "2.0.15",
|
||||
"plop": "3.0.5",
|
||||
"prettier": "2.5.1",
|
||||
"prisma": "3.7.0",
|
||||
"prisma": "3.8.0",
|
||||
"rimraf": "3.0.2",
|
||||
"semantic-release": "18.0.1",
|
||||
"typescript": "4.5.4"
|
||||
|
@ -102,7 +102,7 @@ export const postMessageByChannelIdService: FastifyPluginAsync = async (
|
||||
}
|
||||
})
|
||||
reply.statusCode = 201
|
||||
return {
|
||||
const item = {
|
||||
...message,
|
||||
member: {
|
||||
...memberCheck,
|
||||
@ -112,6 +112,12 @@ export const postMessageByChannelIdService: FastifyPluginAsync = async (
|
||||
}
|
||||
}
|
||||
}
|
||||
await fastify.io.emitToMembers({
|
||||
event: 'messages',
|
||||
guildId: item.member.guildId,
|
||||
payload: { action: 'create', item }
|
||||
})
|
||||
return item
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ export const postMessageUploadsByChannelIdService: FastifyPluginAsync = async (
|
||||
}
|
||||
})
|
||||
reply.statusCode = 201
|
||||
return {
|
||||
const item = {
|
||||
...message,
|
||||
member: {
|
||||
...memberCheck,
|
||||
@ -117,6 +117,12 @@ export const postMessageUploadsByChannelIdService: FastifyPluginAsync = async (
|
||||
}
|
||||
}
|
||||
}
|
||||
await fastify.io.emitToMembers({
|
||||
event: 'messages',
|
||||
guildId: item.member.guildId,
|
||||
payload: { action: 'create', item }
|
||||
})
|
||||
return item
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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' }
|
||||
|
Reference in New Issue
Block a user