Skip to content

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'
FormaDescripció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).

IHandshakeMiddlewarehandle(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 proyectorun(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.