PlayMesh
The root class. Import from @playmesh/server.
Constructor
import { PlayMesh } from '@playmesh/server';
const mesh = new PlayMesh(options?: PlayMeshOptions);
| Method / Property | Description | Returns |
|---|
port | Port to listen on. Defaults to 3000. Pass 0 for ephemeral port. | number |
server | Attach to a pre-existing HTTP server. | http.Server |
redis | Redis connection options or URL string. Enables distributed mode. | RedisOptions | string |
socket | Options forwarded to the Socket.IO server. | Partial<ServerOptions> |
signing | Sign all application events with ECDSA P-256. Clients must enable signing too. | boolean |
uniqueUser | One live session per userId: 'replace' kicks existing sessions, 'reject' refuses the new login. Omit to allow concurrent sessions. | 'replace' | 'reject' |
Topology
| Method / Property | Description | Returns |
|---|
createDomain(id, options?) | Create and register a new Domain. { roles: [...] } restricts joining to those roles. | Domain |
domain(id) | Get an existing Domain by id. Throws if not found. | Domain |
hasDomain(id) | Check whether a Domain with this id exists. | boolean |
domains | All registered Domains. | Domain[] |
sessions | All active Sessions on this node. | Session[] |
resolveInstance(ref) | Resolve "domainId/instanceId" or a bare instance id. | Instance |
getDomain(id) | Non-throwing lookup: Domain or undefined. | Domain | undefined |
getInstance(ref) | Non-throwing lookup by path or unique bare id. | Instance | undefined |
getSession(sessionId) | Session by id on this node. | Session | undefined |
getUserSessions(userId) | All of a user's sessions on this node. | Session[] |
Hooks
| Method / Property | Description | Returns |
|---|
bootstrap(hook) | Async setup before the server accepts connections. | this |
onAuthenticate(hook) | Register the authentication hook. | this |
onAdmission(hook) | Decide which instances a session joins. | this |
onChatMessage(hook) | Moderate built-in chat: return true, a rewritten string, or false/throw to block. | this |
onSessionCreate(hook) | Called once per session, after authentication. | this |
onConnect(hook) | Called when a session connects. | this |
onDisconnect(hook) | Called when a session disconnects. | this |
onStarted(hook) | Called after the server is listening. | this |
onShutdown(hook) | Called at the start of graceful shutdown. | this |
Messaging & extensions
| Method / Property | Description | Returns |
|---|
broadcast(event, payload?) | Send an event to every connected session across all nodes. | void |
sessionsOf(userId) | Session ids of a user across all nodes. | Promise<string[]> |
use(middleware) | Register a middleware function. | this |
use(plugin) | Install a plugin with an install() method. | this |
Infrastructure & lifecycle
| Method / Property | Description | Returns |
|---|
io | The underlying Socket.IO server. Available after start(). | SocketIOServer |
redis | The shared Redis client (when Redis is configured). | Redis |
queues | The QueueManager (requires Redis). | QueueManager |
start() | Start the server. | Promise<{ port: number }> |
shutdown() | Gracefully shut down. | Promise<void> |
metrics() | Current runtime metrics. | Metrics |
const mesh = new PlayMesh({ port: 4000, redis: { host: 'localhost', port: 6379 } });
mesh.bootstrap(async ({ mesh }) => { /* create domains and instances */ });
mesh.onAuthenticate(async request => ({ userId: request.auth.userId as string }));
mesh.onStarted(() => console.log('Server ready'));
const { port } = await mesh.start();
process.on('SIGTERM', () => mesh.shutdown());
Domain
Retrieved via mesh.createDomain(id) or mesh.domain(id).
| Method / Property | Description | Returns |
|---|
id | The domain identifier. | string |
instances | All Instances in this domain. | Instance[] |
createInstance(id, options?) | Create a new Instance. { autoDestroy: ms | true } makes it temporary; { roles: [...] } restricts joining (on top of domain roles). | Instance |
on(event, handler) | Domain-level event handler - runs for events from sessions inside this domain. | this |
off(event, handler) | Remove a domain-level handler. | this |
instance(id) | Get an Instance by id. | Instance |
hasInstance(id) | Check whether an Instance exists. | boolean |
destroyInstance(id) | Remove sessions, clear state, delete the instance. | Promise<void> |
broadcast(event, payload?) | Send to every session in any instance of this domain. | void |
onInstanceCreated(hook) | Called when a new instance is created. | this |
onInstanceDestroyed(hook) | Called when an instance is destroyed. | this |
Instance
An isolated multiplayer environment. Sessions join to receive broadcasts and have events routed.
| Method / Property | Description | Returns |
|---|
id | The instance identifier. | string |
domain | The owning Domain. | Domain |
path | "domainId/instanceId" - globally unique reference. | string |
sessions | Sessions on this node that are members. | Session[] |
state | Server-only runtime key-value state. | ScopedState |
publicState | State synced live to every client in this instance. | ScopedState |
userState(userId) | Private state synced only to that user's clients. | ScopedState |
temporary | Whether this instance auto-destroys when it empties out. | boolean |
on(event, handler) | Register an event handler. | this |
off(event, handler) | Remove an event handler. | this |
broadcast(event, payload?) | Send to all member sessions across all nodes. | void |
memberCount() | Presence-backed total member count across all nodes. | Promise<number> |
onJoin(hook) | Called when a session joins. | this |
onLeave(hook) | Called when a session leaves. | this |
onJoinRequest(hook) | Allow/veto client-initiated joins. Without this hook, client joins are denied. | this |
ℹinstance.sessions is local-node only. Use instance.memberCount() for the cluster total.
Session
Represents a single connected client.
| Method / Property | Description | Returns |
|---|
id | Socket ID (unique per connection). | string |
userId | Assigned by your authenticate hook. | string |
roles | Roles granted by the authenticate hook. | string[] |
hasRole(role) | Check whether the session holds a role. | boolean |
data | Application data from the auth result. | Record<string, unknown> |
instances | Instances this session is currently a member of. | Instance[] |
isIn(instance) | Check membership by Instance or id string. | boolean |
join(instance) | Join an instance. No-op if already a member. | Promise<void> |
leave(instance) | Leave an instance. No-op if not a member. | Promise<void> |
send(event, payload?) | Send an event to this client only. | void |
kick(reason?) | Notify the client why (playmesh:kicked), then force-disconnect it. | void |
disconnect() | Forcibly disconnect this client. | void |
Typed events
Both SDKs accept event-map generics that type emit, on, send, and broadcast payloads end to end. Compile-time only - still validate payloads at runtime.
type ClientEvents = { 'player:move': { x: number; y: number } };
type ServerEvents = { 'player:update': { x: number; y: number; by: string } };
const mesh = new PlayMesh<ClientEvents, ServerEvents>();
city.on('player:move', (session, payload) => {
// payload is { x: number; y: number }
session.send('player:update', { ...payload, by: session.userId });
});
ScopedState
| Method / Property | Description | Returns |
|---|
get(key) | Get a value. Returns undefined if not set. | Promise<unknown> |
set(key, value) | Set a value (JSON-serialized). | Promise<void> |
delete(key) | Delete a key. | Promise<void> |
keys() | List all keys in this instance scope. | Promise<string[]> |
clear() | Delete all keys in this instance scope. | Promise<void> |
Metrics
const m = mesh.metrics();
// {
// sessions: number, - active sessions on this node
// domains: number,
// instances: number,
// uptimeMs: number,
// }