@cloudflare/actors
Version:
An easier way to build with Cloudflare Durable Objects
80 lines • 3.5 kB
JavaScript
export class Sockets {
constructor(ctx, parent) {
this.connections = new Map();
this.context = ctx;
this.parent = parent;
if (ctx) {
// When the actor is initialized, we should load any existing websockets
// that are currently connected to this actor.
const webSockets = ctx.getWebSockets();
this.connections = new Map();
webSockets.forEach((socket) => {
// Retrieve the attachment data which contains connectionId and queryParams
const attachment = socket.deserializeAttachment?.() || {};
// Use the connection ID from attachment, or generate a new one if not available
const connectionId = attachment.connectionId || crypto.randomUUID();
// Store the connection with its ID
this.connections.set(connectionId, socket);
// If a user wants to get access to additional metadata that was part of the query
// params from when they established the connection, they can do so by using the
// `deserializeAttachment` method on the socket.
// const queryParams = socket.deserializeAttachment?.()?.queryParams || {};
});
}
}
message(message, to, exclude) {
for (const [id, socket] of this.connections.entries()) {
// Skip if the `id` or `socket` is in the `exclude` list
if (exclude?.includes(id) || exclude?.includes(socket)) {
continue;
}
// Send to all if 'to' is '*' or empty, otherwise only to specified recipients
if (to === "*" || !to?.length || to.includes(id) || to.includes(socket)) {
socket.send(message);
}
}
}
async webSocketMessage(ws, message) {
}
async webSocketClose(ws, code) {
// When a particular user has ended its websocket connection, we should
// find their entry in our connections map and prune it from our list we are
// managing.
for (const [id, socket] of this.connections.entries()) {
if (socket === ws) {
// Remove from connections map
this.connections.delete(id);
break;
}
}
ws.close(code, "Durable Object is closing WebSocket");
}
acceptWebSocket(request) {
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
// Parse the URL and get all query parameters
const url = new URL(request.url);
const params = url.searchParams;
// Create an object to store all query parameters
const queryParams = {};
params.forEach((value, key) => {
queryParams[key] = value;
});
// If no ID was provided, generate one
const connectionId = queryParams.id || crypto.randomUUID();
if (!queryParams.id) {
queryParams.id = connectionId;
}
// Store all query parameters in the WebSocket's attachment to persist across hibernation
if (server.serializeAttachment) {
server.serializeAttachment({
connectionId,
queryParams
});
}
this.connections.set(connectionId, server);
this.context?.acceptWebSocket(server);
return { client, server };
}
}
//# sourceMappingURL=index.js.map