playsocketjs
v2.6.3
Published
WebSocket wrapper for creating simple multiplayer systems with ease.
Maintainers
Readme
PlaySocket Client
A reactive, optimistic WebSocket library that simplifies game & app development by abstracting away complex sync logic.
Why use PlaySocket?
PlaySocket eliminates the traditional complexity of collaborative experiences:
- Streamlined architecture: No additional backend code is required, but server-authoritative behavior supported
- State synchronization: Built-in storage system keeps the full state synchronized across all clients, always conflict-free and in order
- Resilient & secure connections: Automatic reconnection handling & strict rate-limiting
- Lightweight: Uses WebSockets for efficient, predictable, reliable communication and has little dependencies
Installation
npm install playsocketjsUsage examples
Note that in production, you should always try...catch promises, such as socket.init() – they can reject!
Initializing the client:
import PlaySocket from 'playsocketjs';
// Create a new instance
const socket = new PlaySocket('unique-client-id', { // You can pass no ID to let the server pick one
endpoint: 'wss://example.com/socket'
});
// Set up event handlers (optional)
socket.onEvent('status', status => console.log('Status:', status));
socket.onEvent('error', status => console.log('Error:', status));
const clientId = await socket.init(); // Initialize the socketCreating a room:
// Create a new room
const roomId = await socket.createRoom();
// Optionally, with initial storage
const roomId = await socket.createRoom({
players: ["this-player"],
latestPlayer: null,
});Joining a room:
await socket.joinRoom('room-id'); // Join an existing roomLeaving a room:
socket.destroy(); // To leave the room, destroy the instanceUsing the storage update event for reactivity:
const reactiveVariable = useState(); // Or $state(), reactive(), depending on your framework
socket.onEvent('storageUpdated', storage => (reactiveVariable = storage)); // Assign on updateInterfacing with the synchronized storage (examples):
const currentState = socket.getStorage; // Synchronous, local access
socket.updateStorage('players', 'array-add-unique', { username: 'Player4', level: 2 }); // Special method to enable conflict-free additions for arrays
socket.updateStorage('latestPlayer', 'set', 'Player4'); // Regular synced storage updateSending traditional requests to the server:
socket.sendRequest('chosen-request-name', { fact: "You can build server-authoritative logic using this!" })API reference
Constructor
Creates a new PlaySocket instance with a specified ID and configuration options.
The ID can be set to null to let the server pick a unique one.
new PlaySocket(id?: string, options: PlaySocketOptions)Configuration options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| endpoint | string | none - set this! | WebSocket server endpoint (e.g., 'wss://example.com/socket') |
| customData | object | {} | Arbitrary data to pass to the "clientRegistered" server event (optional) |
| debug | boolean | false | Set to true to enable extra logging |
Methods
| Method | Parameters | Return type | Description |
|--------|------------|-------------|-------------|
| init() | - | Promise<string> | Initialize the WebSocket connection – Returns Promise which resolves with the client's ID |
| createRoom() | initialStorage?: object, size?: number | Promise<string> | Create a new room and become host – Returns Promise which resolves with the room ID. The room participant maximum is 100 |
| joinRoom() | roomId: string | Promise<void> | Join an existing room |
| destroy() | - | void | Use this to leave a room and close the connection |
| updateStorage() | key: string, type: 'set' \| 'array-add' \| 'array-add-unique' \| 'array-remove-matching' \| 'array-update-matching', value: any, updateValue?: any | void | Update a key in the shared storage (max. 100 keys). Array operation types allow for conflict-free simultaneous array updates. For '-matching' operations, value becomes the value to match, and updateValue the replacement |
| sendRequest() | name: string, data?: any | void | Send requests to the server with optional custom data (handle these in the requestReceived server event) |
| onEvent() | event: string, callback: Function | void | Register an event callback |
Event types
| Event | Callback parameter | Description |
|-------|-------------------|-------------|
| status | status: string | Connection status updates |
| error | error: string | Error events |
| instanceDestroyed | - | Destruction event - triggered by manual .destroy() method invocation or by fatal errors and disconnects |
| storageUpdated | storage: object | Storage state changes |
| hostMigrated | roomId: string | Host changes |
| clientConnected | clientId: string | New client connected to the room |
| clientDisconnected | clientId: string, roomId?: string | Client disconnected from the room |
Properties (Read-only)
| Property | Type | Description |
|----------|------|-------------|
| id | string | Client's unique identifier on the WebSocket server |
| isHost | boolean | If this user is currently assigned the host role |
| connectionCount | number | Number of active client connections in room (without yourself) |
| getStorage | object | Retrieve storage object |
PlaySocket Server
PlaySocket includes a server implementation that can be set up in seconds.
Installation
To use the server component, you'll need to install playsocketjs and the ws package:
npm install playsocketjs wsUsage examples
Here are usage examples for a standalone server and an Express.js application.
Standalone server
import PlaySocketServer from 'playsocketjs/server'; // Both ES Module & CommonJS Module syntax is supported
const server = new PlaySocketServer(); // Create and start the server (default path is /)
// Gracefully disconnect all clients and close the server (optional)
function shutdown() {
server.stop();
process.exit(0);
}
// Handle both SIGINT (Ctrl+C) and SIGTERM (Docker stop)
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);Together with Express.js (or other Backend frameworks)
const express = require('express');
const http = require('http');
const PlaySocketServer = require('playsocketjs/server');
const app = express();
const httpServer = http.createServer(app);
// Create PlaySocket server with your HTTP server
const playSocketServer = new PlaySocketServer({
server: httpServer,
path: '/socket'
});
// Start the server
httpServer.listen(3000, () => {
console.log('Server running on port 3000');
});
// Gracefully disconnect all clients and close the server (recommended)
function shutdown() {
server.stop();
process.exit(0);
}
// Handle both SIGINT (Ctrl+C) and SIGTERM (Docker stop)
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);API reference
Constructor
Creates a new PlaySocket Server instance with configuration options.
new PlaySocket(options: PlaySocketServerOptions)Configuration options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| port | number | 3000 | Port to listen on (used only if no server provided) |
| path | string | '/' | WebSocket endpoint path |
| server | http.Server | - | Existing http server (optional) |
| rateLimit | number | 20 | Adjust the messages/second rate limit |
| debug | boolean | false | Set to true to enable extra logging |
Methods
| Method | Parameters | Return type | Description |
|--------|------------|-------------|-------------|
| stop() | - | void | Closes all active client connections, the websocket server and the underlying http server if it's standalone |
| kick() | clientId: string, reason?: string | void | Kick a client by their clientID – this will close their connection and set an error message |
| onEvent() | event: string, callback: Function | void | Register a server-side event callback |
| getRoomStorage() | roomId: string | object | Get a snapshot of the current room storage |
| updateRoomStorage() | roomId: string, key: string, type: 'set' \| 'array-add' \| 'array-add-unique' \| 'array-remove-matching' \| 'array-update-matching', value: any, updateValue?: any | void | Update a key in the shared room storage from the server |
| createRoom() | initialStorage?: object, size?: number, host?: string | object | Create a room (returns object containing room ID and state) – Rooms created with a non-player host like "server" (default) will not be deleted when the last participant leaves |
| destroyRoom() | roomId: string | void | Destroy a room & kick all participants |
Event types
| Event | Callback parameters | Description | Return for action |
|-------|-------------------|-------------|--------------|
| clientRegistered | clientId: string, customData: object | Client registered with the server | - |
| clientRegistrationRequested | clientId: string, customData: object | Client requests to register | Return false or rejection reason string to block |
| clientDisconnected | clientId: string | Client disconnected from the server | - |
| clientJoinedRoom | clientId: string, roomId: string | Client joined a room (clients can only leave by disconnecting) | - |
| clientJoinRequested | clientId: string, roomId: string | Client requests to join a room | Return false or rejection reason string to block |
| roomCreated | roomId: string | Client created a room | - |
| roomDestroyed | roomId: string | Room was destroyed (happens when all participants leave) | - |
| roomCreationRequested | {clientId: string, initialStorage: object} | Room creation requested by client | Return object to override initial storage, false to deny |
| storageUpdated | {clientId: string, roomId: string, update: object, storage: object} | Room storage property updated | - |
| storageUpdateRequested | {clientId: string, roomId: string, update: object, storage: object} | Room storage property update requested by client | Return false to block the update |
| requestReceived | {clientId: string, roomId?: string, requestName: string, data?: any} | Request from client was received by the server | - |
Properties (Read-only)
| Property | Type | Description |
|----------|------|-------------|
| getRooms | object | Retrieve the rooms object |
License
MIT
