Skip to content

Server ​

Server authenticates connections and routes room activity to extensions.

ts
import { PresenceOnlyExtension, Server } from "@jolly-pixel/network";

const server = new Server();
server.register(new PresenceOnlyExtension("lobby"));

Constructor ​

ts
interface ServerOptions {
  logger?: Logger;
  rights?: RightsMap;
  defaultRole?: string;
  auth?: AuthenticationProvider;
  admits?: RoomAdmission;
  roomGraceMs?: number;
  limits?: RoomLimits;
  validateOutbound?: boolean;
}

new Server(options?) configures logging, access, grace periods, and room limits.

validateOutbound defaults to true. With false, rooms name each outbound message from its tags (MessageParser.identify) without validating it, and drop a message no tag names. A server running in the browser uses it to skip checking the messages it produces itself.

Methods ​

register(extension): void ​

Mounts a static room at extension.id.

authenticate(attempt): Promise<PeerIdentity | null> ​

Resolves a trusted identity or null.

connect(connection, identity): ServerConnection ​

connection is how the server reaches the client:

ts
interface ClientConnection {
  readonly id: string;
  sendSerialized(json: string): void;
  close(code: number, reason: string): void;
}

The server serializes every message it sends, once per broadcast. Extension hooks receive the client as a ClientHandle, { id, send }, whose send serializes its argument.

Returns a session with receive(raw) and close(). Activity is ordered per connection and room.

replaceRights(rights, defaultRole?): void ​

Swaps the rules of the rights table for every room. Later checks use the new rules; connected sessions keep their role, and rooms they joined keep them. Revoke a subject to make it join again under the new rules. Throws a TypeError when the server was built without rights or rights is empty.

revoke(subject): void ​

Blocks further activity, then requests reauthentication after in-flight work drains.

updateProfile(subject, patch): void ​

Merges patch into the server-owned profile of every connection of subject, so rooms it joins later carry it. After in-flight work drains, each room it is in sends peer-profile to every member, the subject's own connections included.

close(): Promise<void> ​

Disposes rooms and workers. Await it; close transport resources too.

Dynamic rooms ​

useRoomResolver(resolver) handles unknown names on join. Return { extension, onEvict?, graceMs?, readOnly? } or null; promises are supported.

readOnly: true caps every message right in that room at read, whatever the rights table says: members still join and update presence, their sync reports read for each message event, and their messages are denied. The extension must declare an inbound message protocol, or the join is refused with UngatedExtensionError.

Empty resolved rooms expire after roomGraceMs (default 30_000 ms). Eviction awaits onEvict, then dispose().

A join cancels pending eviction or waits for active eviction. settled(roomName?) waits for eviction already running.