Referencia: Controladores Socket
@socketController(config?)
Decorador de clase. Registra un controlador WebSocket (Socket.IO).
import { socketController } from '@wabot-dev/framework'
@socketController()export class ChatSocketController { }
// Con namespace@socketController('ventas')export class VentasSocketController { }
// Con objeto de config@socketController({ namespace: 'ventas' })export class VentasSocketController { }La clase se vuelve inyectable. Se crea un contenedor hijo por conexión Socket.IO, por lo que puede inyectar dependencias con estado aislado por cliente.
@onSocketEvent(config)
Decorador de método. Suscribe el método a un evento de Socket.IO.
import { onSocketEvent } from '@wabot-dev/framework'| Forma | Descripción |
|---|---|
@onSocketEvent('nombre-evento') | String directo |
@onSocketEvent({ event: 'nombre-evento' }) | Objeto de config |
@socketController('chat')export class ChatController { @onSocketEvent('mensaje') async onMensaje(data: MensajeData, socket: Socket) { socket.to(data.salaId).emit('nuevo-mensaje', { texto: data.texto }) return { enviado: true } // se entrega como acknowledgment al cliente }
@onSocketEvent('unirse-sala') async onUnirse(data: SalaData, socket: Socket) { await socket.join(data.salaId) socket.to(data.salaId).emit('nuevo-miembro', { userId: socket.id }) return { unido: data.salaId } }}El handler acepta como máximo dos parámetros: el payload del evento (validado contra la clase del primer parámetro) y la instancia Socket. El valor de retorno se envía al cliente como acknowledgment (el callback de socket.emit); si el handler lanza un error, el cliente recibe { error: { message, ... } }.
Validación de parámetros
El primer parámetro del handler puede ser una clase validada automáticamente:
import { isString, isNotEmpty } from '@wabot-dev/framework'
export class MensajeData { @isString() @isNotEmpty() texto: string = ''
@isString() @isNotEmpty() salaId: string = ''}Middlewares de handshake
Los middlewares de handshake se ejecutan cuando un cliente se conecta, antes de aceptar la conexión. Se aplican al controlador con @handshakeMiddlewares([...]) (o el atajo @jwtHandshakeGuard() / @apiKeyHandshakeGuard() para autenticación).
IHandshakeMiddleware — handle(socket, container): lanza un error para rechazar la conexión; usa el contenedor para registrar datos de la sesión:
import { Auth, handshakeMiddlewares, IHandshakeMiddleware, injectable, socketController } from '@wabot-dev/framework'import type { Socket } from 'socket.io'import type { DependencyContainer } from 'tsyringe'
@injectable()export class JwtHandshakeMiddleware implements IHandshakeMiddleware { constructor(private jwtService: JwtService, private auth: Auth<{ userId: string }>) {}
async handle(socket: Socket, container: DependencyContainer): Promise<void> { const token = socket.handshake.auth?.token if (!token) throw new Error('Token requerido')
const payload = this.jwtService.verify(token) if (!payload) throw new Error('Token inválido')
// El Auth del contenedor de la conexión queda disponible en los handlers this.auth.assign({ userId: payload.sub }) }}
@socketController('chat')@handshakeMiddlewares([JwtHandshakeMiddleware])export class ChatController { /* ... */ }runSocketControllers(controllers)
Inicia el servidor Socket.IO y registra los controladores indicados. Solo es necesario fuera del runner del proyecto — run(config) descubre los @socketController y los registra automáticamente.
import { runSocketControllers } from '@wabot-dev/framework'
runSocketControllers([ChatSocketController, NotificacionesController])La variable de entorno SOCKET_CORS_ORIGIN controla los orígenes CORS aceptados: * o una lista separada por comas. Sin definirla, CORS queda deshabilitado.