2024-12-30 01:47:21 +01:00
|
|
|
const { Server } = require('socket.io');
|
2025-04-05 10:37:53 +02:00
|
|
|
const { logger } = require('~/config');
|
2025-01-03 19:35:20 +01:00
|
|
|
|
|
|
|
|
class SocketIOService {
|
2025-04-05 10:37:53 +02:00
|
|
|
constructor(httpServer) {
|
2025-01-03 19:35:20 +01:00
|
|
|
this.io = new Server(httpServer, {
|
|
|
|
|
path: '/socket.io',
|
|
|
|
|
cors: {
|
|
|
|
|
origin: '*',
|
|
|
|
|
methods: ['GET', 'POST'],
|
|
|
|
|
},
|
|
|
|
|
});
|
2024-12-21 16:18:23 +01:00
|
|
|
|
2025-01-03 19:35:20 +01:00
|
|
|
this.connections = new Map();
|
2025-04-05 10:37:53 +02:00
|
|
|
this.eventHandlers = new Map();
|
2025-01-03 19:35:20 +01:00
|
|
|
this.setupSocketHandlers();
|
|
|
|
|
}
|
2024-12-21 16:18:23 +01:00
|
|
|
|
2025-01-03 19:35:20 +01:00
|
|
|
setupSocketHandlers() {
|
|
|
|
|
this.io.on('connection', (socket) => {
|
|
|
|
|
this.log(`Client connected: ${socket.id}`);
|
2025-04-05 10:37:53 +02:00
|
|
|
this.connections.set(socket.id, socket);
|
2024-12-21 16:18:23 +01:00
|
|
|
|
2025-04-05 10:37:53 +02:00
|
|
|
// Emit connection event for modules to handle
|
|
|
|
|
this.emitEvent('connection', socket);
|
2025-01-04 01:55:47 +01:00
|
|
|
|
2025-01-03 19:35:20 +01:00
|
|
|
socket.on('disconnect', () => {
|
|
|
|
|
this.log(`Client disconnected: ${socket.id}`);
|
2025-04-05 10:37:53 +02:00
|
|
|
this.emitEvent('disconnect', socket);
|
2025-01-03 19:35:20 +01:00
|
|
|
this.connections.delete(socket.id);
|
|
|
|
|
});
|
|
|
|
|
});
|
2024-12-21 16:18:23 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-05 10:37:53 +02:00
|
|
|
// Register a module to handle specific events
|
|
|
|
|
registerModule(moduleId, eventHandlers) {
|
|
|
|
|
for (const [eventName, handler] of Object.entries(eventHandlers)) {
|
|
|
|
|
if (!this.eventHandlers.has(eventName)) {
|
|
|
|
|
this.eventHandlers.set(eventName, new Map());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.eventHandlers.get(eventName).set(moduleId, handler);
|
|
|
|
|
|
|
|
|
|
// If this is a socket event, register it on all existing connections
|
|
|
|
|
if (eventName !== 'connection' && eventName !== 'disconnect') {
|
|
|
|
|
for (const socket of this.connections.values()) {
|
|
|
|
|
socket.on(eventName, (...args) => {
|
|
|
|
|
handler(socket, ...args);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unregister a module
|
|
|
|
|
unregisterModule(moduleId) {
|
|
|
|
|
for (const handlers of this.eventHandlers.values()) {
|
|
|
|
|
handlers.delete(moduleId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Emit an event to all registered handlers
|
|
|
|
|
emitEvent(eventName, ...args) {
|
|
|
|
|
const handlers = this.eventHandlers.get(eventName);
|
|
|
|
|
if (handlers) {
|
|
|
|
|
for (const handler of handlers.values()) {
|
|
|
|
|
handler(...args);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-04 01:55:47 +01:00
|
|
|
log(message, level = 'info') {
|
|
|
|
|
const timestamp = new Date().toISOString();
|
2025-04-05 10:37:53 +02:00
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
logger.debug(`[WebSocket] ${message}`, level);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(`[WebSocket ${timestamp}] [${level.toUpperCase()}] ${message}`);
|
|
|
|
|
console.error(`[WebSocket ${timestamp}] [ERROR] Error while logging: ${error.message}`);
|
|
|
|
|
}
|
2025-01-04 01:55:47 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-03 19:35:20 +01:00
|
|
|
shutdown() {
|
|
|
|
|
this.connections.clear();
|
2025-04-05 10:37:53 +02:00
|
|
|
this.eventHandlers.clear();
|
2025-01-03 19:35:20 +01:00
|
|
|
this.io.close();
|
2024-12-21 14:36:01 +01:00
|
|
|
}
|
2025-01-03 19:35:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = { SocketIOService };
|