Awareness (Presence) #
PlexusAwareness is a multi-channel presence protocol on top of y-protocols/awareness with
the same wire format, so it works with existing providers (y-websocket, y-webrtc, …)
unchanged. Serialization format is richer than ordinary JSON; Plexus models can be used as fields or field parts.
import { PlexusAwareness } from "@here.build/plexus";
type Presence = { cursor: { x: number; y: number }; name: string };
const awareness = new PlexusAwareness<Presence>(plexus.doc);
awareness.setField("name", "User"); // broadcast once, then sleeps
awareness.setField("cursor", { x: 10, y: 20 }); // only the cursor channel updates
awareness.getField("cursor");
awareness.clearField("cursor");
awareness.getPeerIds(); // base clientIds of live peers
awareness.getPeer(peerId); // assembled Partial<Presence> for one peer
The wire codecs (encodeAwarenessUpdate, applyAwarenessUpdate,
removeAwarenessStates, modifyAwarenessUpdate) are exported for provider integration.
PlexusAwareness is non-reactive lower-level API that is y-protocols compatible.
For high-level reactive API, use FieldAwareness.
Reading a field reactively #
FieldAwareness is a MobX lens over one field. Atoms are per (field, peer), so a reaction
reading one lane is never woken by traffic on another lane, by another peer's cell, or by a
heartbeat — which is the whole point, since awareness is one flat map on the wire and observing
it wholesale re-runs every observer on every keystroke of every peer.
import { FieldAwareness } from "@here.build/plexus";
const cursors = new FieldAwareness(awareness, "cursor");
cursors.set({ x: 10, y: 20 }); // writes the local lane
cursors.clear(); // retracts it
cursors.get(); // own value
cursors.getOther(peerId); // one peer's value
cursors.getOthers(); // Map<clientId, value> — excludes self
cursors.clientIds; // every base publishing "cursor", self included
A lane answers membership per field, not per peer: "everyone who introduced themselves via
info" is a lane, and asking it field by field is the entire vocabulary — there is no
bag-of-properties to enumerate by design. getOthers() skips the local base deliberately; compose it with
get() when you want yourself back.
Reads are frozen. A lens hands out a snapshot of wire state, and a mutable one invites edits that
never reach the wire. The freeze stops at PlexusModel — entity references stay live.