Skip to content

WebSockets Guide

Build real-time features with the official WebSocket plugin and decorators. This guide matches current veloce-ts releases (see Changelog).

  • @WebSocket(path) — marks a class as a WebSocket handler for that path.
  • @OnConnect / @OnMessage / @OnDisconnect — lifecycle hooks.
  • WebSocketPlugin — registers routes and performs runtime-specific upgrades (Bun / Deno).
  • WebSocketConnectionsend, broadcast, join, leave, close, plus native WebSocket access.

One @OnMessage per class: metadata only stores a single message handler (the last @OnMessage wins if you declare more than one). Model different client payloads with one Zod schema (for example a discriminated union on a type field).

import 'reflect-metadata';
import {
VeloceTS,
WebSocketPlugin,
WebSocket,
OnConnect,
OnMessage,
OnDisconnect,
WebSocketConnection,
} from 'veloce-ts';
import { z } from 'zod';
const ChatMessage = z.object({
type: z.literal('chat'),
text: z.string().min(1),
});
@WebSocket('/ws/chat')
class ChatSocket {
@OnConnect()
onOpen(client: WebSocketConnection) {
client.join('lobby');
client.send({ type: 'welcome', message: 'Connected' });
}
@OnMessage(ChatMessage)
onData(client: WebSocketConnection, msg: z.infer<typeof ChatMessage>) {
client.broadcast({ type: 'chat', text: msg.text }, 'lobby');
}
@OnDisconnect()
onClose(client: WebSocketConnection) {
console.log('disconnected', client.id);
}
}
const app = new VeloceTS({ title: 'Chat', version: '1.0.0' });
app.usePlugin(new WebSocketPlugin());
app.include(ChatSocket);
await app.compile();
app.listen(3000);
  • Import WebSocketPlugin from veloce-ts (also available under veloce-ts/plugins).
  • The plugin constructor takes no options; the path is always the string passed to @WebSocket('/path').
  • Call await app.compile() after controllers/handlers are include()d so metadata is compiled.
APIPurpose
idStable connection id
send(data)Send JSON-serializable data to this client
broadcast(data, room?)Send to every connection in a room, or all connections if room is omitted
join(room) / leave(room)Room membership
close(code?, reason?)Close the socket
nativeUnderlying WebSocket instance

Optional Zod schema on @OnMessage(Schema) validates each incoming JSON payload. On failure the manager sends an error object to the client without tearing down the socket.

The examples/chat-api project (Bun) shows REST + JWT + SQLite alongside WebSocket flow, including notes on 426/501 when upgrade is not available (e.g. plain fetch tests).