Files
scoreodonto.com/backend/dist/infra/socket/socketServer.js
T

68 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildSocketServer = buildSocketServer;
const socket_io_1 = require("socket.io");
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const env_1 = require("../../config/env");
const logger_1 = require("../../config/logger");
const dragonfly_1 = require("../cache/dragonfly");
// TTL em segundos: 70 = 2× o heartbeat do frontend (30s) + margem
const PRESENCE_TTL = 70;
function buildSocketServer(httpServer) {
const io = new socket_io_1.Server(httpServer, {
cors: {
origin: env_1.env.FRONTEND_URL,
credentials: true,
},
transports: ['websocket', 'polling'],
});
// Autenticação por token JWT no handshake
io.use((socket, next) => {
const token = socket.handshake.auth?.token;
if (!token) {
next(new Error('Token não fornecido'));
return;
}
try {
const payload = jsonwebtoken_1.default.verify(token, env_1.env.JWT_SECRET);
socket.data.userId = payload.sub;
socket.data.role = payload.role;
next();
}
catch {
next(new Error('Token inválido'));
}
});
io.on('connection', (socket) => {
const userId = socket.data.userId;
logger_1.logger.debug({ userId, socketId: socket.id }, 'Socket conectado');
// Cliente entra na sala do seu tenant automaticamente
socket.join(`tenant:${userId}`);
// Registra presença do usuário no Dragonfly com TTL
dragonfly_1.dragonfly.set(`presence:user:${userId}`, socket.id, PRESENCE_TTL).catch(() => { });
// Cliente pode entrar em salas específicas de instância ou chat
socket.on('join:instance', (instanceId) => {
socket.join(`instance:${instanceId}`);
});
socket.on('join:chat', (chatId) => {
socket.join(`chat:${chatId}`);
});
socket.on('leave:chat', (chatId) => {
socket.leave(`chat:${chatId}`);
});
// Heartbeat do frontend a cada 30s — renova TTL de presença
socket.on('user:heartbeat', () => {
dragonfly_1.dragonfly.set(`presence:user:${userId}`, socket.id, PRESENCE_TTL).catch(() => { });
});
socket.on('disconnect', (reason) => {
logger_1.logger.debug({ userId, reason }, 'Socket desconectado');
// Remove presença imediatamente ao desconectar
dragonfly_1.dragonfly.del(`presence:user:${userId}`).catch(() => { });
});
});
return io;
}