Skip to content
Moku
@moku-labs/room pages

API reference

Every export of @moku-labs/room and @moku-labs/room/server, with signatures.

On this page

Entries

ImportFormatFor
@moku-labs/roomESM and CJSThe browser app: the framework, the plugins, the adapters. Also runs under Node and Bun with inMemory().
@moku-labs/room/serverESM only, no typesThe worker: hubPlugin and the Hub class. Needs @moku-labs/worker.

Signatures below are simplified for reading. The installed dist/index.d.mts is the source.

createApp

function createApp<const ExtraPlugins extends readonly AnyPluginInstance[] = readonly []>(options?: {
  plugins?: ExtraPlugins;
  pluginConfigs?: { [pluginName: string]: Partial<PluginConfig> };
  onReady?: (ctx: AppCallbackContext) => void;
  onError?: (error: Error, ctx: AppCallbackContext) => void;
  onStart?: (ctx: AppCallbackContext) => void | Promise<void>;
  onStop?: (ctx: AppCallbackContext) => void | Promise<void>;
}): App;

Creates and initializes an app, synchronously. The four engines and the core log and env plugins are always there. Add stagePlugin or controllerPlugin, and your own plugins.

MemberWhat it is
start()Runs every onStart. Starts the broadcast and retry timers.
stop()Runs every onStop. Closes connections and timers.
transport, session, intent, syncThe engine APIs.
stage or controllerThe facade, when added.
log, envThe core plugin APIs.

createPlugin

function createPlugin<Name extends string, Config, State, Api, Deps, Events, Hooks>(
  name: Name,
  spec: {
    config?: Config;
    depends?: Deps;
    createState?: (ctx) => State;
    events?: (register) => Events;
    api?: (ctx) => Api;
    hooks?: (ctx) => Hooks;
    onInit?: (ctx) => void;
    onStart?: (ctx) => void | Promise<void>;
    onStop?: (ctx) => void | Promise<void>;
  }
): PluginInstance<Name, Config, State, Api, Events>;

Writes a plugin bound to Room's core. Never pass type parameters. With depends: [stagePlugin], hooks has typed room:* events.

src/plugins/lobby.ts
import { createPlugin, stagePlugin } from "@moku-labs/room";

export const lobbyPlugin = createPlugin("lobby", {
  depends: [stagePlugin],
  config: { minPlayers: 2 },
  api: ctx => ({
    ready: () => ctx.require(stagePlugin).roster().length >= ctx.config.minPlayers
  })
});

Plugins

ExportNameWiringPage
transportPlugintransportDefaulttransport
sessionPluginsessionDefaultsession
intentPluginintentDefaultintent
syncPluginsyncDefaultsync
stagePluginstageAdd on the shared screenstage
controllerPlugincontrollerAdd on the phonecontroller
hubPluginhubWorker app, from /serverhub

Hub is the Durable Object class, from @moku-labs/room/server. Re-export it from your worker entry.

Signaling adapters

function publicRendezvous(options?: { backbone?: "nostr" | "torrent"; relayRedundancy?: number }): Signaling;
function inMemory(options?: { server?: boolean }): Signaling;
function serverSignaling(url: string): Signaling;

Constants

ExportValueMeaning
MAX_CONTROLLERS8The default of session.maxControllers.
ROOM_CODE_LENGTH6The default of session.codeLength.

Types

All from @moku-labs/room.

TypeWhat it is
StageApi, ControllerApiThe facades' APIs.
RoomDescriptor{ code, joinUrl, qr, hostToken }.
QrMatrix{ size, modules }: row by row, true is dark.
JoinResult{ ok: true, selfId } or { ok: false, reason }.
RosterEntry{ id, reconnectToken, name?, joinedAt }.
PeerId, NamespaceStrings.
JsonValue, Snapshot, OpState values, the whole state, one cell write.
RoomEventsThe six room:* events and their payloads.
TransportConfig, IceServersProvider, IceCandidateInitTransport config.
Signaling, SignalingSession, SignalingJoinOpts, SignalMsgThe adapter contract.
Wire, FrameThe channel and its union.
IntentFrame, IntentAckFrame, SyncSnapshotFrame, SyncDeltaFrame, SyncResyncFrameGameplay frames.
HeartbeatPingFrame, HeartbeatPongFrameHeartbeat frames.
RecoveryHelloFrame, RecoveryWelcomeFrame, RecoveryFlushFrameRecovery frames.

SessionConfig, IntentConfig and IntentSchema are not exported by name. To annotate a schema, use Parameters<typeof app.intent.register>[1].