The WSServerRoomManager class extends WSServerPubSub to provide room-based functionality for WebSocket communication. It allows clients to create, join, leave, and manage rooms with dedicated messaging and command systems. It's better to read the documentation for WSServerPubSub first to understand the PubSub and RPC features. You will find a complete example of a room-based WebSocket server in the examples directory. It demonstrates how to create rooms, manage clients, and handle messages with custom hooks.
Creates a new WebSocket room manager server instance.
The server will handle room creation, joining, leaving, and broadcasting messages to clients in rooms.
The server will automatically manage room lifecycle, including cleanup of empty rooms and broadcasting room updates to clients as well as room listing and user management.
You can disable some of these features by setting the corresponding options to false in the options object.
For the details of the roomClass option, see the documentation of the Room Class Hooks below.
Parameters:
options(object): Server configuration options (inherits fromWSServerPubSub)port(number, optional): The port number to run the server on. Default:443maxNbOfClients(number, optional): Maximum number of allowed clients. Default:1000maxInputSize(number, optional): Maximum size of input messages in bytes. Default:100000(100KB)origins(string, optional): Allowed origins. Default:'*'pingTimeout(number, optional): The timeout in milliseconds for ping responses. Default:30000authCallback(function, optional): Authentication callback function. Default:(token, request, wsServer) => ({})logLevel(string, optional): Log level: 'none', 'error', 'warn', 'info', 'debug'. Default:'info'logger(object, optional): External logger instance for logging. Default:nullmaxUsersByRoom(number, optional): Maximum number of users per room. Default:10usersCanCreateRoom(boolean, optional): Whether users can create rooms. Default:trueusersCanNameRoom(boolean, optional): Whether users can name rooms. Default:trueusersCanListRooms(boolean, optional): Whether users can list rooms. Default:trueusersCanGetRoomUsers(boolean, optional): Whether users can get room user lists. Default:trueroomClass(class, optional): Custom room class extendingWSServerRoom. Default:class extends WSServerRoom {}autoJoinCreatedRoom(boolean, optional): Whether room creators automatically join. Default:trueautoDeleteEmptyRoom(boolean, optional): Whether empty rooms are automatically deleted. Default:trueautoSendRoomListOnUsersChange(boolean, optional): Whether to send room list updates on user changes. Default:truesyncMode(string, optional): Synchronization mode: 'immediate', 'immediate-other', 'patch'. Default:'immediate'(or'patch'for game rooms)
Example:
import { WSServerRoomManager, WSServerRoom, WSServerError } from 'wsmini';
const wsServer = new WSServerRoomManager({
port: 8889,
origins: '*',
maxUsersByRoom: 10,
usersCanCreateRoom: true,
usersCanNameRoom: true,
usersCanListRooms: true,
roomClass: class extends WSServerRoom {
onMsg(msg, clientMeta, client) {
return {
time: Date.now(),
user: 'User-' + clientMeta.id.slice(0, 4),
message: msg
};
}
onCreate(name, msg, clientMeta, client) {
return { createdAt: Date.now() };
}
}
});Creates a new room on the server.
Parameters:
roomName(string, optional): The room name. Ifnull, generates a UUID. Default:nullwithHook(boolean, optional): Whether to call theonCreatehook. Default:false
Returns: string|false - The room name if successful, false if room already exists or creation failed
Example:
// Create room with auto-generated name
const roomName = wsServer.createRoom();
// Create room with specific name
const roomName = wsServer.createRoom('game-lobby');
// Create room with onCreate hook
const roomName = wsServer.createRoom('custom-room', true);Deletes a room from the server. All clients in the room will be removed.
Parameters:
roomName(string): The room name to delete
Returns: boolean - true if room was deleted successfully, false if room doesn't exist
Example:
// Delete a room
wsServer.deleteRoom('old-room');Gets all clients in a specific room.
Parameters:
roomName(string): The room name
Returns: array - Array of client metadata objects
Example:
const clients = wsServer.getClientsOfRoom('game-lobby');
console.log(`Room has ${clients.length} clients`);Checks if a room is full (at maximum capacity).
Parameters:
roomName(string): The room name
Returns: boolean - true if room is full, false otherwise
Example:
if (wsServer.isRoomFull('game-lobby')) {
console.log('Room is full');
}Gets the metadata of a specific room.
Parameters:
roomName(string): The room name
Returns: object|false - Room metadata object or false if room doesn't exist
Example:
const meta = wsServer.getRoomMeta('game-lobby');
if (meta) {
console.log('Room created at:', meta.createdAt);
}Broadcasts a message to all clients in a room.
Parameters:
room(object): The room objectmsg(any): The message to broadcast
Returns: boolean - true if successful
Example:
const room = wsServer.rooms.get('game-lobby');
wsServer.broadcastRoom(room, {
type: 'announcement',
message: 'Game starting in 30 seconds'
});Broadcasts a message to all clients in a room by room name.
Parameters:
roomName(string): The room namemsg(any): The message to broadcast
Returns: boolean - true if successful, false if room doesn't exist
Example:
wsServer.broadcastRoomName('game-lobby', {
type: 'game-update',
score: { player1: 10, player2: 8 }
});Broadcasts a command to all clients in a room.
Parameters:
room(object): The room objectcmd(string): The command namedata(object, optional): The command data. Default:{}
Returns: boolean - true if successful
Example:
const room = wsServer.rooms.get('game-lobby');
wsServer.broadcastRoomCmd(room, 'game-start', {
mode: 'competitive',
duration: 300
});Broadcasts a command to all clients in a room by room name.
Parameters:
roomName(string): The room namecmd(string): The command namedata(object, optional): The command data. Default:{}
Returns: boolean - true if successful, false if room doesn't exist
Example:
wsServer.broadcastRoomNameCmd('game-lobby', 'timer-update', {
timeLeft: 120
});Sends a message to a specific client in a room.
Parameters:
room(object): The room objectclient(WebSocket): The client WebSocket connectionmsg(any): The message to send
Returns: boolean - true if successful, false if client not in room
Example:
const room = wsServer.rooms.get('game-lobby');
wsServer.sendRoom(room, client, {
type: 'private-message',
message: 'You are the game moderator'
});Sends a message to a specific client in a room by room name.
Parameters:
roomName(string): The room nameclient(WebSocket): The client WebSocket connectionmsg(any): The message to send
Returns: boolean - true if successful, false if room doesn't exist or client not in room
Example:
wsServer.sendRoomName('game-lobby', client, {
type: 'role-assignment',
role: 'spectator'
});Sends a command to a specific client in a room.
Parameters:
room(object): The room objectclient(WebSocket): The client WebSocket connectioncmd(string): The command namedata(object, optional): The command data. Default:{}
Returns: boolean - true if successful, false if client not in room
Example:
const room = wsServer.rooms.get('game-lobby');
wsServer.sendRoomCmd(room, client, 'turn-notification', {
isYourTurn: true
});Sends a command to a specific client in a room by room name.
Parameters:
roomName(string): The room nameclient(WebSocket): The client WebSocket connectioncmd(string): The command namedata(object, optional): The command data. Default:{}
Returns: boolean - true if successful, false if room doesn't exist or client not in room
Example:
wsServer.sendRoomNameCmd('game-lobby', client, 'game-over', {
winner: 'player1',
score: { player1: 15, player2: 10 }
});Starts the WebSocket server. Inherited from WSServerPubSub.
Example:
wsServer.start();
console.log('Room manager server started');Closes the WebSocket server and cleans up all rooms.
Example:
wsServer.close();When extending WSServerRoom, you can override these methods to customize room behavior. For real-time multiplayer games with fixed timestep simulation and world state synchronization, see the WSServerGameRoom documentation which provides specialized game room functionality.
Called when a room is created. Returns room metadata or false to abort creation.
If the user does provided a name, it will be used as the room name.
If you return a name prop in the metadata, it will be used as the room name instead.
If no name is provided, a UUID will be generated as the room name.
You can throw a WSServerError to abort creation with an error message. The promise will reject with the error message on the client side.
Parameters:
name(string): The room namemsg(any): Additional data sent by the clientclientMeta(object): Client metadata (null if created by server)client(WebSocket): Client connection (null if created by server)
Returns: object|false - Room metadata object or false to abort creation
Example:
class CustomRoom extends WSServerRoom {
onCreate(name, msg, clientMeta, client) {
if (name === 'forbidden') {
throw new WSServerError('Room name not allowed');
}
// do not forget to validate the input received from the client
if (!msg?.gameMode || !['normal', 'hardcore'].includes(msg.gameMode)) {
throw new WSServerError('Invalid or missing game mode');
}
return {
createdAt: Date.now(),
gameMode: msg.gameMode,
};
}
}Called when a client joins the room.
Parameters:
msg(any): Additional data sent by the clientclientMeta(object): Client metadataclient(WebSocket): Client connection
Returns: object|false - Additional client metadata or false to abort join
Example:
class CustomRoom extends WSServerRoom {
onJoin(msg, clientMeta, client) {
if (msg?.team !== 'red' && msg?.team !== 'blue') {
throw new WSServerError('Invalid team selection');
}
return {
team: msg.team,
joinedAt: Date.now()
};
}
}Called when a client sends a message to the room.
Parameters:
msg(any): The message from the clientclientMeta(object): Client metadataclient(WebSocket): Client connection
Returns: any - The message to broadcast to all room clients
Example:
class CustomRoom extends WSServerRoom {
onMsg(msg, clientMeta, client) {
// Validate and transform message
if (!msg.text || msg.text.length > 500) {
throw new WSServerError('Invalid message');
}
return {
time: Date.now(),
user: clientMeta.nickname,
team: clientMeta.team,
text: msg.text
};
}
}Called when a client leaves the room.
Parameters:
clientMeta(object): Client metadataclient(WebSocket): Client connection
Example:
class CustomRoom extends WSServerRoom {
onLeave(clientMeta, client) {
// Broadcast to other clients
this.broadcastCmd('player-left', {
playerId: clientMeta.id,
nickname: clientMeta.nickname
});
}
}Called when the room is being deleted.
Example:
class CustomRoom extends WSServerRoom {
onDispose() {
// Clean up timers, save game state, etc.
if (this.gameTimer) {
clearInterval(this.gameTimer);
}
}
}Called when sending client metadata to clients. You can use this to filter or transform the client metadata before the server sends it to other clients.
Parameters:
clientMeta(object): The client metadata
Returns: object - The filtered client metadata to send
Example:
class CustomRoom extends WSServerRoom {
onSendClient(clientMeta) {
// Hide sensitive information
return {
id: clientMeta.id,
nickname: clientMeta.nickname,
team: clientMeta.team,
isReady: clientMeta.isReady
};
}
}Called when sending room metadata to clients. You can use this to filter or transform the room metadata before the server sends it to clients.
Returns: object - The room metadata to send
Example:
class CustomRoom extends WSServerRoom {
onSendRoom() {
return {
name: this.name,
gameMode: this.meta.gameMode,
maxScore: this.meta.maxScore,
status: this.meta.status || 'waiting'
};
}
}Called when sending the room list to clients. You can use this to filter or transform the room list before the server sends it to clients. For example, you can hide full rooms, private rooms or running games.
Parameters:
rooms(array): Array of room objects
Returns: array - The filtered room list to send
Example:
class CustomRoom extends WSServerRoom {
static onSendRoomsList(rooms) {
// Hide full rooms or private rooms
return rooms.filter(room =>
room.nbUsers < room.maxUsers &&
!room.meta.isPrivate
);
}
}The following methods are used internally by the server and typically don't need to be called directly:
clientCreateRoom(data, clientMeta, client)- Handles room creation requestsclientJoinRoom(data, clientMeta, client)- Handles room join requestsclientCreateOrJoinRoom(data, clientMeta, client)- Handles create-or-join requestsclientLeaveRoom(data, clientMeta, client)- Handles room leave requestsclientListRooms(data, clientMeta, client)- Handles room list requests
addClientToRoom(roomName, clientMeta, client)- Adds a client to a roomremoveClientFromRoom(roomName, client)- Removes a client from a roomprepareRoomList()- Prepares room list for client consumptionprepareRoomClients(room)- Prepares client list for a roompubRoomList()- Publishes room list updatespubRoomClients(room)- Publishes client list updates for a room
manageRoomActions(client, data)- Handles room-specific actionsonMessage(client, message)- Processes incoming messagesonClose(client)- Handles client disconnectionsisActionValid(action)- Validates action types