Skip to main content

Clients

Start here: init takes a factory that makes the client of each drawing, which connects it to ClassCAD: the engine in the page (WASMClient), a native engine (WSClient) or the ClassCAD server (SocketIOClient).

Functions​

init()​

function init(source, options?): void;

Sets up buerli: tells it how to reach ClassCAD, with a factory that makes the client for each drawing.

Call it once, before the first drawing connects. Every drawing that connects afterwards (BuerliCadFacade.connect, BuerliCadFacade.utils.connect, react-cad, Buerligons) gets its client from source; the client connects right after it is made. Calling init again replaces the factory for the drawings that connect from then on. options go to the buerli store (init of @buerli.io/core).

Parameters​

ParameterTypeDescription
source(drawingId) => AwvNodeClientMakes the client for a drawing: called with the new drawing's id, returns a client that is not connected yet.
options?Partial<{ config: { geometry: GeometryConfig; }; elements: any; globalPlugins: (Plugin | Promise<Plugin>)[]; plugins: Record<string, PluginImpl>; theme: { dark: string; highlightedGeom: string; hoveredGeom: string; primary: string; secondary: string; }; }>Options of the buerli store: theme colors, how geometry is shown (config.geometry), plugins.

Returns​

void

Examples​

import { init, WASMClient } from '@buerli.io/classcad'

// The engine in the browser, with a public access token from classcad.ch/account
init(drawingId => new WASMClient(drawingId, { token: 'ccpk_…' }))
import { init, SocketIOClient, WSClient } from '@buerli.io/classcad'

// A ClassCAD server (classcad-socketio)
init(drawingId => new SocketIOClient('ws://localhost:9091', drawingId))
// Or the native engine's own WebSocket server (classcad-cli worker)
init(drawingId => new WSClient('ws://localhost:9094', drawingId))

onClient()​

function onClient(callback): () => void;

Calls back with every drawing's client: the ones there are, and each new one before it connects.

A new client is passed as soon as the factory has made it. An app that prepares the clients a host makes (session sharing, engine settings) registers here instead of wrapping the host's factory. Returns a function that unregisters.

A callback that throws is logged; the drawing connects all the same.

Parameters​

ParameterTypeDescription
callback(client, drawingId) => voidCalled with each client and the id of its drawing.

Returns​

A function that unregisters callback.

() => void

Example​

import { onClient, syncSelection, WASMClient, WSClient } from '@buerli.io/classcad'

// Prepares every client a host makes (react-cad, Buerligons, a facade), before it connects
const unregister = onClient((client, drawingId) => {
// Shares the selection where the session can be shared
if (client instanceof WSClient || client instanceof WASMClient) syncSelection(client)
// Hidden objects are not needed in this app
client.on('connected', () => client.setEmissionConfig({ sendGraphic_Invisible: false }).catch(console.warn))
client.on('conn_error', (_client, reason) => console.error(`Drawing ${drawingId} lost ClassCAD:`, reason))
})

Classes​

WASMClient​

Runs the ClassCAD engine in the browser, as WebAssembly in a web worker, and hosts its session for guests.

connect gets the engine's key first: from token (fetched from ClassCAD, cached in localStorage and renewed), getKey or classcadKey (see resolveEngineKey). Then it loads the engine from url, by default from ClassCAD's CDN in the version this package is made for, and starts it in a worker. A public access token (ccpk_…, from classcad.ch/account) may sit in a web page; it yields keys for the account's registered domains and for localhost.

Nobody can connect to a page, so the page hosts its session itself. With the first invite (WASMClient.createInvite) it offers its invites at sessionUrl, a ClassCAD MCP on the same machine or the ClassCAD share relay, where guests join with ?invite=<token> as they would join a server. Undo and redo are not supported by this client.

Examples​

import { init, WASMClient } from '@buerli.io/classcad'

// A public access token from classcad.ch/account; it works on the account's domains and on localhost
init(drawingId => new WASMClient(drawingId, { token: 'ccpk_…' }))

Its events (connected, conn_error, …) and the members all clients share are on AwvNodeClient.

import { init, WASMClient } from '@buerli.io/classcad'
import type { EngineKey } from '@buerli.io/classcad'

// The app's own sign-in: its server hands signed-in users a key (see requestEngineKey)
init(
drawingId =>
new WASMClient(drawingId, {
getKey: async () => {
const res = await fetch('/api/engine-key', { headers: { authorization: `Bearer ${await idToken()}` } })
if (!res.ok) throw new Error(`No engine key: ${res.status}`)
return (await res.json()) as EngineKey
},
}),
)

Extends​

Accessors​

drawingId​
Get Signature​
get drawingId(): DrawingID;

The drawing this client serves.

Returns​

DrawingID

Inherited from​

AwvNodeClient.drawingId

identities​
Get Signature​
get identities(): Record<string, ClientIdentity>;

What the other participants said about themselves (ClientIdentity), by peer id.

Returns​

Record<string, ClientIdentity>

Inherited from​

AwvNodeClient.identities

invites​
Get Signature​
get invites(): SessionInvite[];

The invites this client minted and has not revoked.

Returns​

SessionInvite[]

Inherited from​

AwvNodeClient.invites

peers​
Get Signature​
get peers(): SessionPeer[];

The guests in this page's session.

Returns​

SessionPeer[]

Overrides​

AwvNodeClient.peers

Constructors​

Constructor​
new WASMClient(drawingId, config): WASMClient;
Parameters​
ParameterTypeDescription
drawingIdDrawingIDThe drawing the client serves (the factory given to init is called with it).
config{ classcadKey?: string; getKey?: () => Promise<string | EngineKey>; identity?: ClientIdentity; keyUrl?: string; logToConsole?: boolean; sessionAuth?: (refresh) => Promise<string | null | undefined>; sessionUrl?: string; token?: string; url?: string; }The engine's key (token, getKey or classcadKey), where the engine is loaded from, and the session's settings.
config.classcadKey?stringAn engine key itself; when given, nothing is fetched.
config.getKey?() => Promise<string | EngineKey>Or the app supplies the key itself, for example from its own sign-in.
config.identity?ClientIdentityWho this client is, for the guests of its session.
config.keyUrl?stringThe token exchange, if not ClassCAD's (see DEFAULT_KEY_URL).
config.logToConsole?booleanLets the engine log to the browser console. Default false.
config.sessionAuth?(refresh) => Promise<string | null | undefined>The sign-in the relay takes an invite with: a Firebase ID token of the reader's ClassCAD account, a fresh one when refresh is set.
config.sessionUrl?stringWhere guests of this page's session join: the session address of a local ClassCAD MCP (default DEFAULT_SESSION_URL), or of the ClassCAD share relay (wss://<relay>/session), which wants sessionAuth.
config.token?stringA ClassCAD access token (ccpk_…, from classcad.ch/account): the engine's key is fetched, cached and renewed with it.
config.url?stringWhere the engine's files are (ClassCADWasmWorker.js and the engine), when they are hosted elsewhere. A path is taken on the page's origin. By default ClassCAD's CDN, in the engine version this package is made for.
Returns​

WASMClient

Overrides​

AwvNodeClient.constructor

Methods​

connect()​
connect(): Promise<WASMClient>;

Gets the engine's key, loads the engine's worker from url and starts the engine. Rejects with an EngineKeyError when there is no key, and when the engine cannot be loaded.

Returns​

Promise<WASMClient>

Overrides​

AwvNodeClient.connect

createInvite()​
createInvite(role?, name?): Promise<SessionInvite>;

Mints an invite for this page's session. Guests join with it at the session address (sessionUrl: a local ClassCAD MCP, or the share relay), which introduces them to this page; the invite stays joinable until it is revoked or the client disconnects.

When the share relay will not take the invite (no sign-in, a plan that does not share), it is dropped and the client emits invite_refused.

Parameters​
ParameterTypeDefault valueDescription
role?SessionRole'edit'What guests with the invite may do: 'edit' (default) or 'view'.
name?string''A name to show for the invite.
Returns​

Promise<SessionInvite>

Example​
import { BuerliCadFacade, buildShareUrl, init, WASMClient } from '@buerli.io/classcad'
import type { OfferRefusal, SessionInvite } from '@buerli.io/classcad'

// The engine in the page; guests join from anywhere through the share relay
let client!: WASMClient
init(
drawingId =>
(client = new WASMClient(drawingId, {
token: 'ccpk_…',
sessionUrl: 'wss://<relay>/session',
// The relay takes invites from signed-in ClassCAD accounts
sessionAuth: refresh => classcadIdToken(refresh),
})),
)
await new BuerliCadFacade().connect()

client.on('invite_refused', (_client, invite: SessionInvite, refusal: OfferRefusal) =>
showError(refusal.code === 4403 ? 'Your plan does not share sessions' : `${invite.name}: ${refusal.reason}`),
)
const invite = await client.createInvite('edit', 'team')
const link = buildShareUrl(invite)
Overrides​

AwvNodeClient.createInvite

disconnect()​
disconnect(): Promise<AwvNodeClient>;

Ends the session (guests are closed, invites taken back) and terminates the engine's worker.

Returns​

Promise<AwvNodeClient>

Overrides​

AwvNodeClient.disconnect

executeMiddleware()​
executeMiddleware(command, data): Promise<ServerResponse>;

Sends a command of the server's own (a middleware command), with the fields of data.

Parameters​
ParameterTypeDescription
commandstringThe command's name.
dataanyFields sent along with the command.
Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.executeMiddleware

executeRequest()​
executeRequest(
task,
streamMap?,
options?
): Promise<ServerResponse>;

Runs task (API calls) on the engine with an Execute request. Rejects with the reply when it carries an error.

The drawing's API (createApi) calls through here; the streams of streamMap are deflated and sent as base64.

Parameters​
ParameterTypeDescription
taskTaskThe API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }].
streamMap?StreamMapData the calls read, by stream key (a file to import, for example).
options?RequestOptionsOptions of the request, such as undoable.
Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.executeRequest

getEmissionConfig()​
getEmissionConfig(): Promise<EmissionConfig>;

The effective emission config of this connection (EmissionConfig): what the engine sends back after a command.

Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command.

Returns​

Promise<EmissionConfig>

Inherited from​

AwvNodeClient.getEmissionConfig

redo()​
redo(options?): Promise<ServerResponse>;

Not supported by this client: sends the engine an empty command with options, which does not step forward.

Parameters​
ParameterTypeDescription
options?RedoOptionsSent along with the command.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.redo

requestByName()​
requestByName(name, command?): Promise<ServerResponse>;

Runs command on the engine and resolves to its reply. What the command changed (structure, graphic) goes into the drawing, and to the session's guests. Rejects with the reply when it carries an error.

Parameters​
ParameterTypeDescription
namestringNot used by this client.
command?ServerRequestThe request.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.requestByName

requestTree()​
requestTree(): Promise<ServerResponse>;

Loads the drawing's structure tree from the engine and sets it in the buerli store.

Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.requestTree

revokeInvite()​
revokeInvite(invite): Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>;

Takes an invite back; guests that joined with it are cut off.

Parameters​
ParameterTypeDescription
invitestringThe invite token.
Returns​

Promise<{ invite: string; kicked: number; revoked: boolean; }>

The token, whether this client had made it, and how many guests were cut off.

Overrides​

AwvNodeClient.revokeInvite

sendPresence()​
sendPresence(channel, data): void;

Presence to the guests of this page's session (see WSClient.sendPresence). Nothing happens while nobody was invited.

Parameters​
ParameterTypeDescription
channelstringThe channel, e.g. 'view' for a camera viewpoint.
dataRecord<string, any>The payload, sent as it is; the last one per channel is kept for guests who join later.
Returns​

void

Overrides​

AwvNodeClient.sendPresence

setEmissionConfig()​
setEmissionConfig(partial): Promise<EmissionConfig>;

Merges partial into the emission config of this connection and resolves to the effective flags.

The engine keeps the config for every command that follows, until it is changed again. Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command. EmissionConfig has an example, and onClient sets flags as every client connects.

Parameters​
ParameterTypeDescription
partialPartial<EmissionConfig>The flags to change; the others stay as they are.
Returns​

Promise<EmissionConfig>

Inherited from​

AwvNodeClient.setEmissionConfig

undo()​
undo(options?): Promise<ServerResponse>;

Not supported by this client: sends the engine an empty command with options, which does not step back.

Parameters​
ParameterTypeDescription
options?UndoOptionsSent along with the command.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.undo

Properties​

PropertyModifierTypeDefault valueDescriptionOverridesInherited from
inviteNamepublicstring''Name of the invite this connection joined with ('' for the host or unnamed tokens).-AwvNodeClient.inviteName
rolepublicSessionRole'edit'This connection's role within a shared session ('edit' unless a guest with a view invite).-AwvNodeClient.role
shareKindpublic readonly"invite"'invite'Invites are honoured: guests join at sessionUrl with ?invite=<token>.AwvNodeClient.shareKind-

WSClient​

Connects buerli to a native ClassCAD engine through the engine's own WebSocket server (classcad-cli worker).

The server owns the session. Without an invite it creates one for this connection, which lasts as long as the connection; others join it with an invite from WSClient.createInvite, passed as config.invite. A URL without a scheme (/session) is on the server the page came from.

Connection flow:

  1. WebSocket handshake (server auto-creates session)
  2. SetEmissionConfig command stores this connection's emission flags on the server
  3. fetchTree() retrieves initial object tree
  4. Connection promise resolves

Undo and redo are not supported by this client yet: undo sends StoreState, redo sends LoadState, and neither steps through an undo history.

Examples​

import { init, WSClient } from '@buerli.io/classcad'

// The native engine's own WebSocket server (classcad-cli worker)
init(drawingId => new WSClient('ws://localhost:9094', drawingId))
import { BuerliCadFacade, buildShareUrl, init, WSClient } from '@buerli.io/classcad'
import type { SessionPeer } from '@buerli.io/classcad'

// The host: a session of its own on the engine, and an invite to it
let host!: WSClient
init(drawingId => (host = new WSClient('ws://localhost:9094', drawingId, { identity: { app: 'my-app' } })))
await new BuerliCadFacade().connect()

host.on('peers_changed', (_client, peers: SessionPeer[]) => {
console.log(peers.map(peer => `${peer.inviteName}: ${peer.role}`))
})
const invite = await host.createInvite('view', 'review')
console.log('Join at', buildShareUrl(invite))
// Later: the token stops working, its guests are cut off
await host.revokeInvite(invite.invite)

Its events (connected, conn_error, …) and the members all clients share are on AwvNodeClient.

import { BuerliCadFacade, init, WSClient } from '@buerli.io/classcad'
import type { PresenceMessage } from '@buerli.io/classcad'

// A guest: joins the host's session with its token
let guest!: WSClient
init(drawingId => (guest = new WSClient('ws://localhost:9094', drawingId, { invite: token })))
await new BuerliCadFacade().connect()
// With a 'view' invite the app keeps the guest from changing the model
setReadOnly(guest.role === 'view')

// The cameras follow each other
guest.on('presence', (_client, msg: PresenceMessage) => {
if (msg.channel === 'view') moveCamera(msg.data)
})
guest.sendPresence('view', myCamera())

Extends​

Accessors​

drawingId​
Get Signature​
get drawingId(): DrawingID;

The drawing this client serves.

Returns​

DrawingID

Inherited from​

AwvNodeClient.drawingId

identities​
Get Signature​
get identities(): Record<string, ClientIdentity>;

What the other participants said about themselves (ClientIdentity), by peer id.

Returns​

Record<string, ClientIdentity>

Inherited from​

AwvNodeClient.identities

invites​
Get Signature​
get invites(): SessionInvite[];

The invites this client minted and has not revoked.

Returns​

SessionInvite[]

Inherited from​

AwvNodeClient.invites

peers​
Get Signature​
get peers(): SessionPeer[];

Snapshot of the guests currently sharing this session (main connection only).

Returns​

SessionPeer[]

Overrides​

AwvNodeClient.peers

url​
Get Signature​
get url(): string;

The address the client was given; one without a scheme (/session) is on the server the page came from.

Returns​

string

Constructors​

Constructor​
new WSClient(
_url,
drawingId,
config?
): WSClient;
Parameters​
ParameterTypeDescription
_urlstringThe server's WebSocket address, e.g. ws://localhost:9094, or a path on the page's own server.
drawingIdDrawingIDThe drawing the client serves (the factory given to init is called with it).
config?WSClientConfigSub-path, invite, identity and emission config (WSClientConfig).
Returns​

WSClient

Overrides​

AwvNodeClient.constructor

Methods​

connect()​
connect(): Promise<WSClient>;

Opens the WebSocket, sets the connection's emission config, loads the structure tree and publishes identity. Rejects when the socket fails before that, or when the engine predates SetEmissionConfig.

Returns​

Promise<WSClient>

Overrides​

AwvNodeClient.connect

createInvite()​
createInvite(role?, name?): Promise<SessionInvite>;

Mints an invite token for this connection's session (multi-client invite model). The returned token can be handed to other clients, which join via new WSClient(url, id, { invite }). Server-side this is a controller-level meta command; it is rejected when this connection itself joined via invite.

name is optional and purely for display (e.g. "workgroup"); it has no effect on behavior. Multiple tokens can be minted (e.g. a named group token plus an unnamed one-off token). The examples of WSClient show the host and a guest.

Parameters​
ParameterTypeDefault valueDescription
role?SessionRole'edit'What guests with the invite may do: 'edit' (default) or 'view'.
name?string''A name to show for the invite.
Returns​

Promise<SessionInvite>

Overrides​

AwvNodeClient.createInvite

disconnect()​
disconnect(): Promise<AwvNodeClient>;

Closes the WebSocket; the server ends the session if this connection made it. No conn_error is emitted.

Returns​

Promise<AwvNodeClient>

Overrides​

AwvNodeClient.disconnect

executeMiddleware()​
executeMiddleware(command, data): Promise<ServerResponse>;

Sends a command of the server's own (a middleware command), with the fields of data.

Parameters​
ParameterTypeDescription
commandstringThe command's name.
dataanyFields sent along with the command.
Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.executeMiddleware

executeRequest()​
executeRequest(
task,
streamMap?,
options?
): Promise<ServerResponse>;

Runs task (API calls) on the engine with an Execute request. Rejects with the reply when it carries an error.

The drawing's API (createApi) calls through here; the streams of streamMap are deflated and sent as base64.

Parameters​
ParameterTypeDescription
taskTaskThe API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }].
streamMap?StreamMapData the calls read, by stream key (a file to import, for example).
options?RequestOptionsOptions of the request, such as undoable.
Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.executeRequest

getEmissionConfig()​
getEmissionConfig(): Promise<EmissionConfig>;

The effective emission config of this connection (EmissionConfig): what the engine sends back after a command.

Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command.

Returns​

Promise<EmissionConfig>

Inherited from​

AwvNodeClient.getEmissionConfig

redo()​
redo(options?): Promise<ServerResponse>;

Sends the engine a LoadState command with options. It does not step forward: this client has no redo yet.

Parameters​
ParameterTypeDescription
options?RedoOptionsSent along with the command.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.redo

requestByName()​
requestByName(_name, command?): Promise<ServerResponse>;

Sends command to the server and resolves to its reply, once the server's Result frame arrives. Structure, graphic and messages that come before it go into the drawing on the way. Rejects with the reply when it carries an error, and when the socket closes first.

Parameters​
ParameterTypeDescription
_namestringNot used by this client.
command?ServerRequestThe request.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.requestByName

requestTree()​
requestTree(): Promise<ServerResponse>;

Loads the drawing's structure tree from the engine and sets it in the buerli store.

Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.requestTree

revokeInvite()​
revokeInvite(invite): Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>;

Revokes a previously minted invite token. Any guests currently connected with that token are immediately disconnected, and the token can no longer be used to join. Owner-only; rejected on connections that joined via invite.

Parameters​
ParameterTypeDescription
invitestringThe invite token.
Returns​

Promise<{ invite: string; kicked: number; revoked: boolean; }>

The token, whether it was revoked, and how many guests were cut off.

Overrides​

AwvNodeClient.revokeInvite

sendPresence()​
sendPresence(channel, data): void;

Fire-and-forget ephemeral presence broadcast to the session's siblings (e.g. this client's camera viewpoint on the 'view' channel). Handled by a server fast-path that bypasses the command queue entirely; the server stamps the sender's peerId and fans the frame out. Siblings receive it via the presence event; late joiners get the last frame per channel as a snapshot. NOTE: the server matches on the exact serialized prefix {"command":"Presence", so command must stay the first key here.

The guest example of WSClient shares the camera this way.

Parameters​
ParameterTypeDescription
channelstringThe channel, e.g. 'view' for a camera viewpoint.
dataRecord<string, any>The payload, sent as it is. The server drops a frame larger than 8 KB.
Returns​

void

Overrides​

AwvNodeClient.sendPresence

setEmissionConfig()​
setEmissionConfig(partial): Promise<EmissionConfig>;

Merges partial into the emission config of this connection and resolves to the effective flags.

The engine keeps the config for every command that follows, until it is changed again. Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command. EmissionConfig has an example, and onClient sets flags as every client connects.

Parameters​
ParameterTypeDescription
partialPartial<EmissionConfig>The flags to change; the others stay as they are.
Returns​

Promise<EmissionConfig>

Inherited from​

AwvNodeClient.setEmissionConfig

undo()​
undo(options?): Promise<ServerResponse>;

Sends the engine a StoreState command with options. It does not step back: this client has no undo yet.

Parameters​
ParameterTypeDescription
options?UndoOptionsSent along with the command.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.undo

Properties​

PropertyModifierTypeDefault valueDescriptionOverridesInherited from
inviteNamepublicstring''Name of the invite this connection joined with ('' for the host or unnamed tokens).-AwvNodeClient.inviteName
rolepublicSessionRole'edit'This connection's role within a shared session ('edit' unless a guest with a view invite).-AwvNodeClient.role
shareKindpublic readonly"invite"'invite'The server owns the session: invites are honoured by joining with ?invite= on the server URL.AwvNodeClient.shareKind-

SocketIOClient​

Connects buerli to a ClassCAD server (classcad-socketio) over Socket.IO.

The server runs the engine and keeps the drawing's undo history, so undo, redo and undoable requests work with this client. It cannot share its session (shareKind is null). When the connection drops and comes back, the client reconnects the drawing, recalculates it and emits reconnect.

Its events (connected, conn_error, …) and the members all clients share are on AwvNodeClient.

Example​

import { init, SocketIOClient } from '@buerli.io/classcad'

// The ClassCAD server (classcad-socketio); a connection that drops is picked up again
init(drawingId => {
const client = new SocketIOClient('ws://localhost:9091', drawingId)
client.on('conn_error', () => notify('The connection to ClassCAD is lost'))
client.on('reconnect', () => notify('Connected again; the model was recalculated'))
return client
})

Extends​

Accessors​

drawingId​
Get Signature​
get drawingId(): DrawingID;

The drawing this client serves.

Returns​

DrawingID

Inherited from​

AwvNodeClient.drawingId

identities​
Get Signature​
get identities(): Record<string, ClientIdentity>;

What the other participants said about themselves (ClientIdentity), by peer id.

Returns​

Record<string, ClientIdentity>

Inherited from​

AwvNodeClient.identities

invites​
Get Signature​
get invites(): SessionInvite[];

The invites this client minted and has not revoked.

Returns​

SessionInvite[]

Inherited from​

AwvNodeClient.invites

peers​
Get Signature​
get peers(): SessionPeer[];

Guests currently sharing this session (host side).

Returns​

SessionPeer[]

Inherited from​

AwvNodeClient.peers

Constructors​

Constructor​
new SocketIOClient(url, drawingId): SocketIOClient;
Parameters​
ParameterTypeDescription
urlstringThe server's address, e.g. ws://localhost:9091.
drawingIdDrawingIDThe drawing the client serves (the factory given to init is called with it).
Returns​

SocketIOClient

Overrides​

AwvNodeClient.constructor

Methods​

connect()​
connect(): Promise<SocketIOClient>;

Opens the connection, registers the drawing with the server and loads its structure tree. Rejects on a connection error or timeout.

Returns​

Promise<SocketIOClient>

Overrides​

AwvNodeClient.connect

createInvite()​
createInvite(role?, name?): Promise<SessionInvite>;

Mints an invite token guests (apps, an MCP) can join with. Rejects with SESSION_SHARING_UNSUPPORTED on non-sharing transports.

Parameters​
ParameterTypeDefault valueDescription
role?SessionRole'edit'What guests with the invite may do: 'edit' (default) or 'view'.
name?string''A name to show for the invite, e.g. "workgroup"; it has no effect.
Returns​

Promise<SessionInvite>

Inherited from​

AwvNodeClient.createInvite

disconnect()​
disconnect(): Promise<AwvNodeClient>;

Closes the connection to the server.

Returns​

Promise<AwvNodeClient>

Overrides​

AwvNodeClient.disconnect

executeMiddleware()​
executeMiddleware(command, data): Promise<ServerResponse>;

Sends a command of the server's own (a middleware command), with the fields of data.

Parameters​
ParameterTypeDescription
commandstringThe command's name.
dataanyFields sent along with the command.
Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.executeMiddleware

executeRequest()​
executeRequest(
task,
streamMap?,
options?
): Promise<ServerResponse>;

Runs task (API calls) on the engine with an Execute request. Rejects with the reply when it carries an error.

The drawing's API (createApi) calls through here; the streams of streamMap are deflated and sent as base64.

Parameters​
ParameterTypeDescription
taskTaskThe API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }].
streamMap?StreamMapData the calls read, by stream key (a file to import, for example).
options?RequestOptionsOptions of the request, such as undoable.
Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.executeRequest

getEmissionConfig()​
getEmissionConfig(): Promise<EmissionConfig>;

The effective emission config of this connection (EmissionConfig): what the engine sends back after a command.

Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command.

Returns​

Promise<EmissionConfig>

Inherited from​

AwvNodeClient.getEmissionConfig

redo()​
redo(options?): Promise<ServerResponse>;

Steps forward in the drawing's undo history on the server: to options.state when given.

Parameters​
ParameterTypeDescription
options?RedoOptionsThe state to go forward to, and options for the server.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.redo

requestByName()​
requestByName(name, command?): Promise<ServerResponse>;

Sends command to the server as the event name and resolves to the reply once all its frames have arrived. Structure patches and graphic go into the drawing on the way. Rejects with the reply when it carries an error.

Parameters​
ParameterTypeDescription
namestringThe server's event: send for requests, undo, redo.
command?ServerRequestThe request.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.requestByName

requestTree()​
requestTree(): Promise<ServerResponse>;

Loads the drawing's structure tree from the engine and sets it in the buerli store.

Returns​

Promise<ServerResponse>

Inherited from​

AwvNodeClient.requestTree

revokeInvite()​
revokeInvite(invite): Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>;

Revokes a token and kicks the guests using it.

Parameters​
ParameterTypeDescription
invitestringThe invite token.
Returns​

Promise<{ invite: string; kicked: number; revoked: boolean; }>

The token, whether it was revoked, and how many guests were cut off.

Inherited from​

AwvNodeClient.revokeInvite

sendPresence()​
sendPresence(channel, data): void;

Fire-and-forget presence broadcast to session siblings (camera, cursor …). No-op on non-sharing transports.

Parameters​
ParameterTypeDescription
channelstringThe channel, e.g. 'view' for a camera viewpoint; others get it in their presence event.
dataRecord<string, any>The payload, sent as it is. A frame larger than 8 KB is dropped.
Returns​

void

Inherited from​

AwvNodeClient.sendPresence

setEmissionConfig()​
setEmissionConfig(partial): Promise<EmissionConfig>;

Merges partial into the emission config of this connection and resolves to the effective flags.

The engine keeps the config for every command that follows, until it is changed again. Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command. EmissionConfig has an example, and onClient sets flags as every client connects.

Parameters​
ParameterTypeDescription
partialPartial<EmissionConfig>The flags to change; the others stay as they are.
Returns​

Promise<EmissionConfig>

Inherited from​

AwvNodeClient.setEmissionConfig

undo()​
undo(options?): Promise<ServerResponse>;

Steps back in the drawing's undo history on the server: to options.state when given.

Parameters​
ParameterTypeDescription
options?UndoOptionsThe state to go back to, and options for the server.
Returns​

Promise<ServerResponse>

Overrides​

AwvNodeClient.undo

Properties​

PropertyModifierTypeDefault valueDescriptionInherited from
inviteNamepublicstring''Name of the invite this connection joined with ('' for the host or unnamed tokens).AwvNodeClient.inviteName
rolepublicSessionRole'edit'This connection's role within a shared session ('edit' unless a guest with a view invite).AwvNodeClient.role
shareKindpublic readonly"invite" | nullnullHow this client's invites are honoured; null = this client cannot share.AwvNodeClient.shareKind

Types​

WSClientConfig​

type WSClientConfig = {
commandConfig?: Partial<EmissionConfig>;
identity?: ClientIdentity;
invite?: string;
path?: string;
};

Options of a WSClient: sub-path, an invite to join a shared session, identity and emission config.

Example​

import { getShareTokenFromUrl, init, WSClient } from '@buerli.io/classcad'
import type { WSClientConfig } from '@buerli.io/classcad'

const config: WSClientConfig = {
// Joins a shared session when the page was opened with a share link
invite: getShareTokenFromUrl()?.token,
identity: { app: 'configurator', version: '2.1.0', name: 'Ada', kind: 'app' },
// This app shows no hidden objects
commandConfig: { sendGraphic_Invisible: false },
}
init(drawingId => new WSClient('ws://localhost:9094', drawingId, config))

Properties​

PropertyTypeDescription
commandConfig?Partial<EmissionConfig>Startup emission config of this connection, merged on top of the client's defaults and sent once with SetEmissionConfig on connect. Set individual flags to false to disable them; change them later with setEmissionConfig(). Not to be confused with v1.common.setDatabaseSettings, which decides what the engine TESSELLATES - this decides what it SENDS. The defaults turn on the structure, every graphic category and messages, and stream them: structure patches, graphic as compressed binary frames, one package per object, messages as they come.
identity?ClientIdentityWho this client is, for the others in the session: published once after connecting on the 'client' presence channel (see ClientIdentity).
invite?stringInvite token for joining a shared session as a guest (sent as query param). Without it the server creates a fresh main session that lives for the duration of this connection; use createInvite() to let others join it. The server confirms an invite join with a SessionJoined frame carrying the invite's role — see the session_joined event and the role property.
path?stringWebSocket sub-path: '/', '/command', or '/api'. Defaults to '/'.

Advanced​

Most apps do not need these directly: types they meet through the exports above, and what is there for special cases or for building on buerli itself.

abstract AwvNodeClient​

The base of every client: what buerli asks of a connection to ClassCAD, and the session-sharing surface.

An app makes a WASMClient, WSClient or SocketIOClient in the factory it gives init; buerli connects it and sends the drawing's API calls through it. A client that cannot share its session (the base class, SocketIOClient) has shareKind null and rejects createInvite with SESSION_SHARING_UNSUPPORTED.

A client is an EventEmitter; every event passes the client first:

  • connected (client, true): the client has connected.
  • conn_error (client, reason): the connection failed or broke off.
  • conn_timeout (client, reason): connecting timed out (SocketIOClient).
  • reconnect (client): the connection is back, and the drawing reconnected (SocketIOClient).
  • session_joined (client, role, inviteName): the client joined a shared session with an invite (WSClient).
  • peer_joined / peer_left (client, SessionPeer): a guest joined or left this client's session.
  • peers_changed (client, SessionPeer[]): the guests in the session changed.
  • invites_changed (client, SessionInvite[]): an invite was made or taken back.
  • identities_changed (client, identities): a participant said who it is, or left.
  • presence (client, PresenceMessage): another participant published something.
  • invite_refused (client, SessionInvite, OfferRefusal): the share relay would not take an invite (WASMClient).

Example​

import { onClient } from '@buerli.io/classcad'
import type { PresenceMessage, SessionPeer } from '@buerli.io/classcad'

// A status line (an element of the app's page) for every drawing's connection and session
onClient(client => {
client.on('connected', () => (statusLine.textContent = 'Connected'))
client.on('conn_error', (_client, reason) => (statusLine.textContent = `No connection: ${reason}`))
client.on('peers_changed', (_client, peers: SessionPeer[]) => (statusLine.textContent = `${peers.length} guests`))
client.on('presence', (_client, msg: PresenceMessage) => {
if (msg.channel === 'leave') console.log(`${client.identities[msg.peerId]?.name ?? msg.peerId} left`)
})
})

Extends​

  • EventEmitter

Extended by​

Implements​

Accessors​

drawingId​
Get Signature​
get drawingId(): DrawingID;

The drawing this client serves.

Returns​

DrawingID

identities​
Get Signature​
get identities(): Record<string, ClientIdentity>;

What the other participants said about themselves (ClientIdentity), by peer id.

Returns​

Record<string, ClientIdentity>

invites​
Get Signature​
get invites(): SessionInvite[];

The invites this client minted and has not revoked.

Returns​

SessionInvite[]

peers​
Get Signature​
get peers(): SessionPeer[];

Guests currently sharing this session (host side).

Returns​

SessionPeer[]

Constructors​

Constructor​
new AwvNodeClient(): AwvNodeClient;
Returns​

AwvNodeClient

Overrides​
EventEmitter.constructor

Methods​

connect()​
abstract connect(): Promise<AwvNodeClient>;

Connects to the engine. buerli calls it when the drawing connects; it resolves once the drawing's structure tree is loaded and API calls can be made.

Returns​

Promise<AwvNodeClient>

Implementation of​

IComClient.connect

createInvite()​
createInvite(role?, name?): Promise<SessionInvite>;

Mints an invite token guests (apps, an MCP) can join with. Rejects with SESSION_SHARING_UNSUPPORTED on non-sharing transports.

Parameters​
ParameterTypeDefault valueDescription
role?SessionRole'edit'What guests with the invite may do: 'edit' (default) or 'view'.
name?string''A name to show for the invite, e.g. "workgroup"; it has no effect.
Returns​

Promise<SessionInvite>

disconnect()​
abstract disconnect(): Promise<AwvNodeClient>;

Closes the connection to the engine.

Returns​

Promise<AwvNodeClient>

Implementation of​

IComClient.disconnect

executeMiddleware()​
executeMiddleware(command, data): Promise<ServerResponse>;

Sends a command of the server's own (a middleware command), with the fields of data.

Parameters​
ParameterTypeDescription
commandstringThe command's name.
dataanyFields sent along with the command.
Returns​

Promise<ServerResponse>

Implementation of​

IComClient.executeMiddleware

executeRequest()​
executeRequest(
task,
streamMap?,
options?
): Promise<ServerResponse>;

Runs task (API calls) on the engine with an Execute request. Rejects with the reply when it carries an error.

The drawing's API (createApi) calls through here; the streams of streamMap are deflated and sent as base64.

Parameters​
ParameterTypeDescription
taskTaskThe API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }].
streamMap?StreamMapData the calls read, by stream key (a file to import, for example).
options?RequestOptionsOptions of the request, such as undoable.
Returns​

Promise<ServerResponse>

Implementation of​

IComClient.executeRequest

getEmissionConfig()​
getEmissionConfig(): Promise<EmissionConfig>;

The effective emission config of this connection (EmissionConfig): what the engine sends back after a command.

Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command.

Returns​

Promise<EmissionConfig>

Implementation of​

IComClient.getEmissionConfig

redo()​
abstract redo(options?): Promise<ServerResponse>;

Steps forward in the drawing's undo history: to options.state when given. The ClassCAD server (SocketIOClient) keeps that history.

Parameters​
ParameterTypeDescription
options?RedoOptionsThe state to go forward to, and options for the engine.
Returns​

Promise<ServerResponse>

Implementation of​

IComClient.redo

requestByName()​
abstract requestByName(name, command?): Promise<ServerResponse>;

Sends a raw request to the engine and resolves to its reply. Rejects with the reply when it carries an error.

Parameters​
ParameterTypeDescription
namestringNames the request on the transport: the event of the ClassCAD server (SocketIOClient); the other clients ignore it.
command?ServerRequestThe request.
Returns​

Promise<ServerResponse>

requestTree()​
requestTree(): Promise<ServerResponse>;

Loads the drawing's structure tree from the engine and sets it in the buerli store.

Returns​

Promise<ServerResponse>

Implementation of​

IComClient.requestTree

revokeInvite()​
revokeInvite(invite): Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>;

Revokes a token and kicks the guests using it.

Parameters​
ParameterTypeDescription
invitestringThe invite token.
Returns​

Promise<{ invite: string; kicked: number; revoked: boolean; }>

The token, whether it was revoked, and how many guests were cut off.

sendPresence()​
sendPresence(channel, data): void;

Fire-and-forget presence broadcast to session siblings (camera, cursor …). No-op on non-sharing transports.

Parameters​
ParameterTypeDescription
channelstringThe channel, e.g. 'view' for a camera viewpoint; others get it in their presence event.
dataRecord<string, any>The payload, sent as it is. A frame larger than 8 KB is dropped.
Returns​

void

setEmissionConfig()​
setEmissionConfig(partial): Promise<EmissionConfig>;

Merges partial into the emission config of this connection and resolves to the effective flags.

The engine keeps the config for every command that follows, until it is changed again. Rejects with an Error named EMISSION_CONFIG_UNSUPPORTED on engines that predate the command. EmissionConfig has an example, and onClient sets flags as every client connects.

Parameters​
ParameterTypeDescription
partialPartial<EmissionConfig>The flags to change; the others stay as they are.
Returns​

Promise<EmissionConfig>

Implementation of​

IComClient.setEmissionConfig

undo()​
abstract undo(options?): Promise<ServerResponse>;

Steps back in the drawing's undo history: to options.state when given. The ClassCAD server (SocketIOClient) keeps that history.

Parameters​
ParameterTypeDescription
options?UndoOptionsThe state to go back to, and options for the engine.
Returns​

Promise<ServerResponse>

Implementation of​

IComClient.undo

Properties​

PropertyModifierTypeDefault valueDescription
inviteNamepublicstring''Name of the invite this connection joined with ('' for the host or unnamed tokens).
rolepublicSessionRole'edit'This connection's role within a shared session ('edit' unless a guest with a view invite).
shareKindpublic readonly"invite" | nullnullHow this client's invites are honoured; null = this client cannot share.