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
| Parameter | Type | Description |
|---|---|---|
source | (drawingId) => AwvNodeClient | Makes 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
| Parameter | Type | Description |
|---|---|---|
callback | (client, drawingId) => void | Called 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
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
invites
Get Signature
get invites(): SessionInvite[];
The invites this client minted and has not revoked.
Returns
Inherited from
peers
Get Signature
get peers(): SessionPeer[];
The guests in this page's session.
Returns
Overrides
Constructors
Constructor
new WASMClient(drawingId, config): WASMClient;
Parameters
| Parameter | Type | Description |
|---|---|---|
drawingId | DrawingID | The 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? | string | An 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? | ClientIdentity | Who this client is, for the guests of its session. |
config.keyUrl? | string | The token exchange, if not ClassCAD's (see DEFAULT_KEY_URL). |
config.logToConsole? | boolean | Lets 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? | string | Where 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? | string | A ClassCAD access token (ccpk_…, from classcad.ch/account): the engine's key is fetched, cached and renewed with it. |
config.url? | string | Where 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
Overrides
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
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
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
disconnect()
disconnect(): Promise<AwvNodeClient>;
Ends the session (guests are closed, invites taken back) and terminates the engine's worker.
Returns
Promise<AwvNodeClient>
Overrides
executeMiddleware()
executeMiddleware(command, data): Promise<ServerResponse>;
Sends a command of the server's own (a middleware command), with the fields of data.
Parameters
| Parameter | Type | Description |
|---|---|---|
command | string | The command's name. |
data | any | Fields 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
| Parameter | Type | Description |
|---|---|---|
task | Task | The API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }]. |
streamMap? | StreamMap | Data the calls read, by stream key (a file to import, for example). |
options? | RequestOptions | Options of the request, such as undoable. |
Returns
Promise<ServerResponse>
Inherited from
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
| Parameter | Type | Description |
|---|---|---|
options? | RedoOptions | Sent along with the command. |
Returns
Promise<ServerResponse>
Overrides
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
| Parameter | Type | Description |
|---|---|---|
name | string | Not used by this client. |
command? | ServerRequest | The request. |
Returns
Promise<ServerResponse>
Overrides
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
revokeInvite()
revokeInvite(invite): Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>;
Takes an invite back; guests that joined with it are cut off.
Parameters
| Parameter | Type | Description |
|---|---|---|
invite | string | The 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
sendPresence()
sendPresence(channel, data): void;
Presence to the guests of this page's session (see WSClient.sendPresence). Nothing happens while nobody was invited.
Parameters
| Parameter | Type | Description |
|---|---|---|
channel | string | The channel, e.g. 'view' for a camera viewpoint. |
data | Record<string, any> | The payload, sent as it is; the last one per channel is kept for guests who join later. |
Returns
void
Overrides
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
| Parameter | Type | Description |
|---|---|---|
partial | Partial<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
| Parameter | Type | Description |
|---|---|---|
options? | UndoOptions | Sent along with the command. |
Returns
Promise<ServerResponse>
Overrides
Properties
| Property | Modifier | Type | Default value | Description | Overrides | Inherited from |
|---|---|---|---|---|---|---|
inviteName | public | string | '' | Name of the invite this connection joined with ('' for the host or unnamed tokens). | - | AwvNodeClient.inviteName |
role | public | SessionRole | 'edit' | This connection's role within a shared session ('edit' unless a guest with a view invite). | - | AwvNodeClient.role |
shareKind | public 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:
- WebSocket handshake (server auto-creates session)
- SetEmissionConfig command stores this connection's emission flags on the server
fetchTree()retrieves initial object tree- 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
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
invites
Get Signature
get invites(): SessionInvite[];
The invites this client minted and has not revoked.
Returns
Inherited from
peers
Get Signature
get peers(): SessionPeer[];
Snapshot of the guests currently sharing this session (main connection only).
Returns
Overrides
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
| Parameter | Type | Description |
|---|---|---|
_url | string | The server's WebSocket address, e.g. ws://localhost:9094, or a path on the page's own server. |
drawingId | DrawingID | The drawing the client serves (the factory given to init is called with it). |
config? | WSClientConfig | Sub-path, invite, identity and emission config (WSClientConfig). |
Returns
Overrides
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
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
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
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
executeMiddleware()
executeMiddleware(command, data): Promise<ServerResponse>;
Sends a command of the server's own (a middleware command), with the fields of data.
Parameters
| Parameter | Type | Description |
|---|---|---|
command | string | The command's name. |
data | any | Fields 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
| Parameter | Type | Description |
|---|---|---|
task | Task | The API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }]. |
streamMap? | StreamMap | Data the calls read, by stream key (a file to import, for example). |
options? | RequestOptions | Options of the request, such as undoable. |
Returns
Promise<ServerResponse>
Inherited from
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
| Parameter | Type | Description |
|---|---|---|
options? | RedoOptions | Sent along with the command. |
Returns
Promise<ServerResponse>
Overrides
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
| Parameter | Type | Description |
|---|---|---|
_name | string | Not used by this client. |
command? | ServerRequest | The request. |
Returns
Promise<ServerResponse>
Overrides
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
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
| Parameter | Type | Description |
|---|---|---|
invite | string | The invite token. |
Returns
Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>
The token, whether it was revoked, and how many guests were cut off.
Overrides
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
| Parameter | Type | Description |
|---|---|---|
channel | string | The channel, e.g. 'view' for a camera viewpoint. |
data | Record<string, any> | The payload, sent as it is. The server drops a frame larger than 8 KB. |
Returns
void
Overrides
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
| Parameter | Type | Description |
|---|---|---|
partial | Partial<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
| Parameter | Type | Description |
|---|---|---|
options? | UndoOptions | Sent along with the command. |
Returns
Promise<ServerResponse>
Overrides
Properties
| Property | Modifier | Type | Default value | Description | Overrides | Inherited from |
|---|---|---|---|---|---|---|
inviteName | public | string | '' | Name of the invite this connection joined with ('' for the host or unnamed tokens). | - | AwvNodeClient.inviteName |
role | public | SessionRole | 'edit' | This connection's role within a shared session ('edit' unless a guest with a view invite). | - | AwvNodeClient.role |
shareKind | public 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
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
invites
Get Signature
get invites(): SessionInvite[];
The invites this client minted and has not revoked.
Returns
Inherited from
peers
Get Signature
get peers(): SessionPeer[];
Guests currently sharing this session (host side).
Returns
Inherited from
Constructors
Constructor
new SocketIOClient(url, drawingId): SocketIOClient;
Parameters
| Parameter | Type | Description |
|---|---|---|
url | string | The server's address, e.g. ws://localhost:9091. |
drawingId | DrawingID | The drawing the client serves (the factory given to init is called with it). |
Returns
Overrides
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
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
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
disconnect()
disconnect(): Promise<AwvNodeClient>;
Closes the connection to the server.
Returns
Promise<AwvNodeClient>
Overrides
executeMiddleware()
executeMiddleware(command, data): Promise<ServerResponse>;
Sends a command of the server's own (a middleware command), with the fields of data.
Parameters
| Parameter | Type | Description |
|---|---|---|
command | string | The command's name. |
data | any | Fields 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
| Parameter | Type | Description |
|---|---|---|
task | Task | The API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }]. |
streamMap? | StreamMap | Data the calls read, by stream key (a file to import, for example). |
options? | RequestOptions | Options of the request, such as undoable. |
Returns
Promise<ServerResponse>
Inherited from
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
| Parameter | Type | Description |
|---|---|---|
options? | RedoOptions | The state to go forward to, and options for the server. |
Returns
Promise<ServerResponse>
Overrides
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
| Parameter | Type | Description |
|---|---|---|
name | string | The server's event: send for requests, undo, redo. |
command? | ServerRequest | The request. |
Returns
Promise<ServerResponse>
Overrides
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
revokeInvite()
revokeInvite(invite): Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>;
Revokes a token and kicks the guests using it.
Parameters
| Parameter | Type | Description |
|---|---|---|
invite | string | The 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
sendPresence()
sendPresence(channel, data): void;
Fire-and-forget presence broadcast to session siblings (camera, cursor …). No-op on non-sharing transports.
Parameters
| Parameter | Type | Description |
|---|---|---|
channel | string | The channel, e.g. 'view' for a camera viewpoint; others get it in their presence event. |
data | Record<string, any> | The payload, sent as it is. A frame larger than 8 KB is dropped. |
Returns
void
Inherited from
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
| Parameter | Type | Description |
|---|---|---|
partial | Partial<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
| Parameter | Type | Description |
|---|---|---|
options? | UndoOptions | The state to go back to, and options for the server. |
Returns
Promise<ServerResponse>
Overrides
Properties
| Property | Modifier | Type | Default value | Description | Inherited from |
|---|---|---|---|---|---|
inviteName | public | string | '' | Name of the invite this connection joined with ('' for the host or unnamed tokens). | AwvNodeClient.inviteName |
role | public | SessionRole | 'edit' | This connection's role within a shared session ('edit' unless a guest with a view invite). | AwvNodeClient.role |
shareKind | public readonly | "invite" | null | null | How 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
| Property | Type | Description |
|---|---|---|
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? | ClientIdentity | Who this client is, for the others in the session: published once after connecting on the 'client' presence channel (see ClientIdentity). |
invite? | string | Invite 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? | string | WebSocket 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
peers
Get Signature
get peers(): SessionPeer[];
Guests currently sharing this session (host side).
Returns
Constructors
Constructor
new AwvNodeClient(): AwvNodeClient;
Returns
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
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
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
executeMiddleware()
executeMiddleware(command, data): Promise<ServerResponse>;
Sends a command of the server's own (a middleware command), with the fields of data.
Parameters
| Parameter | Type | Description |
|---|---|---|
command | string | The command's name. |
data | any | Fields sent along with the command. |
Returns
Promise<ServerResponse>
Implementation of
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
| Parameter | Type | Description |
|---|---|---|
task | Task | The API calls to run, e.g. [{ 'v1.part.create': [{ name: 'Part' }] }]. |
streamMap? | StreamMap | Data the calls read, by stream key (a file to import, for example). |
options? | RequestOptions | Options of the request, such as undoable. |
Returns
Promise<ServerResponse>
Implementation of
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
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
| Parameter | Type | Description |
|---|---|---|
options? | RedoOptions | The state to go forward to, and options for the engine. |
Returns
Promise<ServerResponse>
Implementation of
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
| Parameter | Type | Description |
|---|---|---|
name | string | Names the request on the transport: the event of the ClassCAD server (SocketIOClient); the other clients ignore it. |
command? | ServerRequest | The 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
revokeInvite()
revokeInvite(invite): Promise<{
invite: string;
kicked: number;
revoked: boolean;
}>;
Revokes a token and kicks the guests using it.
Parameters
| Parameter | Type | Description |
|---|---|---|
invite | string | The 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
| Parameter | Type | Description |
|---|---|---|
channel | string | The channel, e.g. 'view' for a camera viewpoint; others get it in their presence event. |
data | Record<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
| Parameter | Type | Description |
|---|---|---|
partial | Partial<EmissionConfig> | The flags to change; the others stay as they are. |
Returns
Promise<EmissionConfig>
Implementation of
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
| Parameter | Type | Description |
|---|---|---|
options? | UndoOptions | The state to go back to, and options for the engine. |
Returns
Promise<ServerResponse>
Implementation of
Properties
| Property | Modifier | Type | Default value | Description |
|---|---|---|---|---|
inviteName | public | string | '' | Name of the invite this connection joined with ('' for the host or unnamed tokens). |
role | public | SessionRole | 'edit' | This connection's role within a shared session ('edit' unless a guest with a view invite). |
shareKind | public readonly | "invite" | null | null | How this client's invites are honoured; null = this client cannot share. |