WebSockets
Lucent provides built-in WebSocket support via a singleton wsManager and an Elysia plugin.
Setup
To enable WebSockets, mount the lucentWs plugin in your main entry point:
typescript
// src/index.ts
import { Elysia } from "elysia";
import { lucent, lucentWs } from "@codesordinatestudio/lucent-cms";
import config from "./lucent.config";
const app = new Elysia()
.use(await lucent(config))
.use(lucentWs({ path: "/ws" })) // Mount the WS handler
.listen(3000);Usage in Hooks
You can use the wsManager singleton to broadcast messages from anywhere in your application, such as inside collection hooks:
typescript
// src/collections/Posts.ts
import { wsManager, defineCollection } from "@codesordinatestudio/lucent-cms";
export const Posts = defineCollection({
slug: "posts",
fields: [
/* ... */
],
hooks: {
afterCreate: [
async ({ doc }) => {
// Broadcast to all users in the "posts" room
wsManager.broadcastToRoom("posts", {
type: "post:created",
doc,
});
},
],
},
});Manager API
The wsManager provides several methods for managing connections and rooms:
Rooms
joinRoom(id, room): Adds a connection to a room.leaveRoom(id, room): Removes a connection from a room.getRoomMembers(room): Returns an array of connection IDs in a room.listRooms(): Lists all active rooms.
Sending Messages
sendTo(id, payload): Send a private message to a specific connection ID.broadcastToRoom(room, payload, options?): Send a message to everyone in a room.options.exclude: Array of connection IDs to skip.
broadcastAll(payload, options?): Send a message to every connected client.
Client-Side Usage
The default lucentWs plugin handles several message types out of the box:
typescript
const ws = new WebSocket("ws://localhost:3000/ws");
ws.onopen = () => {
// Join a room
ws.send(JSON.stringify({ type: "join", room: "posts" }));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === "post:created") {
console.log("New post:", msg.doc);
}
};Supported Message Types
join:{ "type": "join", "room": "name" }leave:{ "type": "leave", "room": "name" }broadcast:{ "type": "broadcast", "room": "name", "payload": { ... } }(Broadcasts to room members, excluding sender)ping:{ "type": "ping" }(Returns{ "type": "pong" })