wsmini
Version:
Minimalist WebSocket client and server for real-time applications with RPC, PubSub, Rooms and Game state synchronization.
338 lines (258 loc) • 10.2 kB
Markdown
# WSServerPubSub API Documentation
The `WSServerPubSub` class extends `WSServer` to provide Publish-Subscribe (PubSub) functionality and Remote Procedure Call (RPC) capabilities for WebSocket communication. It allows clients to subscribe to channels, publish messages, and call server-side functions. Look at [WSServerRoomManager](./WSServerRoomManager.md) for room-based management features.
## Table of Contents
- [Constructor](#constructor)
- [Channel Management](#channel-management)
- [addChannel](#addchannel-name-options)
- [hasChannel](#haschannelchanname)
- [removeChannel](#removechannelchanname)
- [pub](#pubchanname-msg)
- [RPC Management](#rpc-management)
- [addRpc](#addrpcname-callback)
- [removeRpc](#removerpcname)
- [Command Broadcasting](#command-broadcasting)
- [sendCmd](#sendcmdclient-cmd-data)
- [broadcastCmd](#broadcastcmdcmd-data)
- [broadcastOthersCmd](#broadcastotherscmdclient-cmd-data)
- [Server Control](#server-control)
- [start](#start)
- [stop](#stop)
- [close](#close)
- [Internal Methods](#internal-methods)
## Constructor
### `new WSServerPubSub(options)`
Creates a new WebSocket PubSub server instance.
**Parameters:**
- `options` (object): Server configuration options (inherits from `WSServer`)
- `port` (number, optional): The port number to run the server on. Default: `443`
- `maxNbOfClients` (number, optional): Maximum number of allowed clients. Default: `1000`
- `maxInputSize` (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: `30000`
- `authCallback` (function, optional): Authentication callback function `(token, request, wsServer) => {}`. 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: `null`
**authCallback**: This function is called when a client connects. It must return an object with user metadata if authentication is successful, or `false` if authentication fails. The metadata will be added to the client object and can be used in RPCs and PubSub hooks. An `id` metadata will be automatically generated for the client if not provided.
**Example:**
```javascript
import { WSServerPubSub, WSServerError } from 'wsmini';
const wsServer = new WSServerPubSub({
port: 8887,
origins: '*',
maxNbOfClients: 500,
maxInputSize: 50000,
pingTimeout: 30000,
logLevel: 'info',
authCallback: (token, request, wsServer) => {
// Return user metadata or false if authentication fails
// Token validation is not implemented here, just an example
if (token !== 'valid-token') return false;
return { nickname: 'user123', role: 'admin' };
}
});
```
## Channel Management
### `addChannel(name, options)`
Adds a new channel to the server. Channels allow clients to subscribe and publish messages.
**Parameters:**
- `name` (string): The channel name
- `options` (object, optional): Channel configuration options
- `usersCanPub` (boolean, optional): Whether users can publish to this channel. Default: `true`
- `usersCanSub` (boolean, optional): Whether users can subscribe to this channel. Default: `true`
- `hookPub` (function, optional): Hook called before publishing a message. Default: `(msg, client, wsServer) => msg`
- `hookSub` (function, optional): Hook called before subscribing a client. Default: `(client, wsServer) => true`
- `hookUnsub` (function, optional): Hook called before unsubscribing a client. Default: `(client, wsServer) => null`
**Returns:** `boolean` - `true` if channel was added successfully, `false` if channel already exists
**Example:**
```javascript
// Basic channel
wsServer.addChannel('chat');
// Advanced channel with hooks
wsServer.addChannel('admin-chat', {
usersCanPub: true,
usersCanSub: true,
hookPub: (msg, client, wsServer) => {
// Transform message before broadcasting
return {
...msg,
from: client.userId,
timestamp: Date.now()
};
},
hookSub: (client, wsServer) => {
// return false if the user is not allowed to subscribe to this channel
return client.isAdmin;
},
hookUnsub: (client, wsServer) => {
console.log(`User ${client.userId} unsubscribed from chat`);
}
});
```
### `hasChannel(chanName)`
Checks if a channel exists.
**Parameters:**
- `chanName` (string): The channel name to check
**Returns:** `boolean` - `true` if channel exists, `false` otherwise
**Example:**
```javascript
if (wsServer.hasChannel('chat')) {
console.log('Chat channel exists');
}
```
### `removeChannel(chanName)`
Removes a channel from the server. All subscribed clients will be unsubscribed.
**Parameters:**
- `chanName` (string): The channel name to remove
**Returns:** `boolean` - `true` if channel was removed successfully, `false` if channel doesn't exist
**Example:**
```javascript
// Remove a channel
wsServer.removeChannel('old-channel');
```
### `pub(chanName, msg)`
Publishes a message to all subscribers of a channel. This is a server-side publish that bypasses the `hookPub` function.
**Parameters:**
- `chanName` (string): The channel name
- `msg` (any): The message to publish
**Returns:** `boolean` - `true` if message was published successfully, `false` if channel doesn't exist
**Example:**
```javascript
// Publish a server message
wsServer.pub('chat', {
user: 'System',
message: 'Server maintenance in 5 minutes',
timestamp: Date.now()
});
// Bot message example
setInterval(() => {
wsServer.pub('chat', {
user: 'Bot',
message: 'Automated message',
timestamp: Date.now()
});
}, 30000);
```
## RPC Management
### `addRpc(name, callback)`
Adds a Remote Procedure Call (RPC) endpoint that clients can invoke.
**Parameters:**
- `name` (string): The RPC name
- `callback` (function): The RPC callback function
- Parameters: `(data, clientMetadata, client, wsServer)`
- Returns: The response to send back to the client
- Can throw `WSServerError` to send an error response (The promise will then be rejected with the error message on the client side)
**Returns:** `boolean` - `true` if RPC was added successfully, `false` if RPC already exists
**Example:**
```javascript
import { WSServerError } from 'wsmini';
// Simple RPC
wsServer.addRpc('add', (data, clientMetadata, client, wsServer) => {
if (typeof data.a !== 'number' || typeof data.b !== 'number') {
throw new WSServerError('Both a and b must be numbers');
}
return data.a + data.b;
});
// Complex RPC with rights check
wsServer.addRpc('getUserData', (data, clientMetadata, client, wsServer) => {
if (!clientMetadata.isAdmin) {
throw new WSServerError('Authentication required');
}
// Simulate database lookup
return {
id: clientMetadata.id,
profile: { /* user profile data */ }
};
});
```
### `removeRpc(name)`
Removes an RPC endpoint from the server.
**Parameters:**
- `name` (string): The RPC name to remove
**Returns:** `boolean` - `true` if RPC was removed successfully, `false` if RPC doesn't exist
**Example:**
```javascript
// Remove an RPC
wsServer.removeRpc('getUserData');
```
## Command Broadcasting
### `sendCmd(client, cmd, data)`
Sends a command to a specific client.
**Parameters:**
- `client` (WebSocket): The client WebSocket connection
- `cmd` (string): The command name
- `data` (object, optional): The command data. Default: `{}`
**Example:**
```javascript
// Send command to specific client
wsServer.sendCmd(client, 'notification', {
type: 'info',
message: 'Welcome to the server!'
});
```
### `broadcastCmd(cmd, data)`
Broadcasts a command to all connected clients.
**Parameters:**
- `cmd` (string): The command name
- `data` (object, optional): The command data. Default: `{}`
**Example:**
```javascript
// Broadcast server announcement
wsServer.broadcastCmd('announcement', {
message: 'Server will restart in 5 minutes',
priority: 'high'
});
```
### `broadcastOthersCmd(client, cmd, data)`
Broadcasts a command to all clients except the specified one.
**Parameters:**
- `client` (WebSocket): The client to exclude from the broadcast
- `cmd` (string): The command name
- `data` (object, optional): The command data. Default: `{}`
**Example:**
```javascript
// Notify others when a user joins
wsServer.broadcastOthersCmd(client, 'user-joined', {
id: clientMetadata.id,
timestamp: Date.now()
});
```
## Server Control
### `start()`
Starts the WebSocket server. Inherited from `WSServer`.
**Example:**
```javascript
wsServer.start();
```
### `stop()`
Stops the WebSocket server. Inherited from `WSServer`.
**Example:**
```javascript
wsServer.stop();
```
### `close()`
Closes the WebSocket server and cleans up all channels and RPCs.
**Example:**
```javascript
wsServer.close();
```
## Internal Methods
The following methods are used internally by the server and typically don't need to be called directly:
### `managePubSub(client, data)`
Handles PubSub actions (`sub`, `unsub`, `pub`, `pub-simple`) from clients.
### `manageRpc(client, data)`
Handles RPC calls from clients.
### `onMessage(client, message)`
Processes incoming messages from clients.
### `onClose(client)`
Handles client disconnections and cleanup.
### `isActionValid(action)`
Validates if an action is supported by the server.
### Response Methods
- `sendError(client, msg)`
- `sendRpcError(client, id, name, response)`
- `sendRpcSuccess(client, id, name, response)`
- `sendSubError(client, id, chan, response)`
- `sendSubSuccess(client, id, chan, response)`
- `sendPubError(client, id, chan, response)`
- `sendPubSuccess(client, id, chan, response)`
- `sendJson(client, data)`