WebSockets
WebSocket provides bidirectional, persistent connections with room-based pub/sub. Radiant automatically configures WebSocket endpoints when enabled in your DSL.
Enabling WebSockets
In your .radiant file, you can enable WebSockets for a collection. The runtime will automatically broadcast CRUD events to connected clients.
collection todos {
realtime: {
ws: ["create", "update", "delete"] // true = all events
}
fields: {
title: text
}
}
When enabled, the runtime mounts GET /api/ws as the WebSocket upgrade endpoint.
Connecting
const ws = new WebSocket("ws://localhost:3000/api/ws");
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(msg);
};
On connect, the server sends:
{ "type": "connected", "id": "conn-uuid" }
Joining a Room
Join a collection's room to receive change events:
ws.send(JSON.stringify({ type: "join", room: "todos" }));
Response:
{ "type": "joined", "room": "todos" }
Receiving Change Events
When a CRUD operation occurs on a collection you've joined, you receive:
{
"event": "todos:created",
"data": { "id": "abc-123", "title": "Buy groceries", "completed": false }
}
The event name follows the pattern <collection>:<action>:
todos:createdtodos:updatedtodos:deleted
Leaving a Room
ws.send(JSON.stringify({ type: "leave", room: "todos" }));
Broadcasting to a Room
From your TypeScript code, broadcast a custom message to all connections in a room:
import { RadiantWebsocket } from "@codesordinatestudio/radiant-bun";
RadiantWebsocket.broadcastToRoom("todos", {
type: "notification",
message: "System maintenance in 10 minutes",
});
WebSocket Manager API
// Send to a specific connection
RadiantWebsocket.sendTo(connectionId, { type: "ping" });
// Broadcast to all connections
RadiantWebsocket.broadcastAll({ type: "announcement" });
// Broadcast with exclusions
RadiantWebsocket.broadcastToRoom("todos", payload, { exclude: [senderId] });
// Get room members
const members = RadiantWebsocket.getRoomMembers("todos");
// Stats
const stats = RadiantWebsocket.getStats();
// { connections: 15, rooms: { todos: 12, posts: 3 }, heartbeatActive: true }
Ping/Pong Heartbeat
The WebSocket manager has a built-in heartbeat to detect dead connections:
// Client responds to server pings
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === "ping") {
ws.send(JSON.stringify({ type: "pong" }));
}
};