Type aliases
DownlinkDidClose
DownlinkDidClose: function
DownlinkDidConnect
DownlinkDidConnect: function
DownlinkDidDisconnect
DownlinkDidDisconnect: function
DownlinkDidFail
DownlinkDidFail: function
Type declaration
-
- (error: unknown, downlink: Downlink): void
DownlinkDidLink
DownlinkDidLink: function
DownlinkDidSync
DownlinkDidSync: function
DownlinkDidUnlink
DownlinkDidUnlink: function
DownlinkOnCommand
DownlinkOnCommand: function
DownlinkOnEvent
DownlinkOnEvent: function
DownlinkType
DownlinkType: "event" | "list" | "map" | "value"
DownlinkWillLink
DownlinkWillLink: function
DownlinkWillSync
DownlinkWillSync: function
DownlinkWillUnlink
DownlinkWillUnlink: function
ListDownlinkDidClear
ListDownlinkDidClear<V, VU>: function
Type parameters
ListDownlinkDidDrop
ListDownlinkDidDrop<V, VU>: function
Type parameters
ListDownlinkDidMove
ListDownlinkDidMove<V, VU>: function
Type parameters
Type declaration
-
- (fromIndex: number, toIndex: number, value: V, downlink: ListDownlink<V, VU>): void
-
Parameters
-
fromIndex: number
-
toIndex: number
-
value: V
-
Returns void
ListDownlinkDidRemove
ListDownlinkDidRemove<V, VU>: function
Type parameters
Type declaration
-
- (index: number, oldValue: V, downlink: ListDownlink<V, VU>): void
-
Parameters
-
index: number
-
oldValue: V
-
Returns void
ListDownlinkDidTake
ListDownlinkDidTake<V, VU>: function
Type parameters
ListDownlinkDidUpdate
ListDownlinkDidUpdate<V, VU>: function
Type parameters
Type declaration
-
- (index: number, newValue: V, oldValue: V, downlink: ListDownlink<V, VU>): void
-
Parameters
-
index: number
-
newValue: V
-
oldValue: V
-
Returns void
ListDownlinkWillClear
ListDownlinkWillClear<V, VU>: function
Type parameters
ListDownlinkWillDrop
ListDownlinkWillDrop<V, VU>: function
Type parameters
ListDownlinkWillMove
ListDownlinkWillMove<V, VU>: function
Type parameters
Type declaration
-
- (fromIndex: number, toIndex: number, value: V, downlink: ListDownlink<V, VU>): void
-
Parameters
-
fromIndex: number
-
toIndex: number
-
value: V
-
Returns void
ListDownlinkWillRemove
ListDownlinkWillRemove<V, VU>: function
Type parameters
ListDownlinkWillTake
ListDownlinkWillTake<V, VU>: function
Type parameters
ListDownlinkWillUpdate
ListDownlinkWillUpdate<V, VU>: function
Type parameters
Type declaration
-
- (index: number, newValue: V, downlink: ListDownlink<V, VU>): V | void
-
Parameters
-
index: number
-
newValue: V
-
Returns V
|
void
MapDownlinkDidClear
MapDownlinkDidClear<K, V, KU, VU>: function
Type parameters
MapDownlinkDidDrop
MapDownlinkDidDrop<K, V, KU, VU>: function
Type parameters
Type declaration
-
- (lower: number, downlink: MapDownlink<K, V, KU, VU>): void
MapDownlinkDidRemove
MapDownlinkDidRemove<K, V, KU, VU>: function
Type parameters
Type declaration
-
- (key: K, oldValue: V, downlink: MapDownlink<K, V, KU, VU>): void
MapDownlinkDidTake
MapDownlinkDidTake<K, V, KU, VU>: function
Type parameters
Type declaration
-
- (upper: number, downlink: MapDownlink<K, V, KU, VU>): void
MapDownlinkDidUpdate
MapDownlinkDidUpdate<K, V, KU, VU>: function
Type parameters
Type declaration
-
- (key: K, newValue: V, oldValue: V, downlink: MapDownlink<K, V, KU, VU>): void
-
Parameters
-
key: K
-
newValue: V
-
oldValue: V
-
downlink: MapDownlink<K, V, KU, VU>
Returns void
MapDownlinkWillClear
MapDownlinkWillClear<K, V, KU, VU>: function
Type parameters
MapDownlinkWillDrop
MapDownlinkWillDrop<K, V, KU, VU>: function
Type parameters
Type declaration
-
- (lower: number, downlink: MapDownlink<K, V, KU, VU>): void
MapDownlinkWillRemove
MapDownlinkWillRemove<K, V, KU, VU>: function
Type parameters
MapDownlinkWillTake
MapDownlinkWillTake<K, V, KU, VU>: function
Type parameters
Type declaration
-
- (upper: number, downlink: MapDownlink<K, V, KU, VU>): void
MapDownlinkWillUpdate
MapDownlinkWillUpdate<K, V, KU, VU>: function
Type parameters
Type declaration
-
- (key: K, newValue: V, downlink: MapDownlink<K, V, KU, VU>): V | void
-
Parameters
Returns V
|
void
ValueDownlinkWillSet
ValueDownlinkWillSet<V, VU>: function
Type parameters
Type declaration
-
-
Parameters
Returns V
|
void
VaueDownlinkDidSet
VaueDownlinkDidSet<V, VU>: function
Type parameters
WarpDidAuthenticate
WarpDidAuthenticate: function
Type declaration
-
- (body: Value, host: Host, warp: WarpRef): void
WarpDidConnect
WarpDidConnect: function
WarpDidDeauthenticate
WarpDidDeauthenticate: function
Type declaration
-
- (body: Value, host: Host, warp: WarpRef): void
WarpDidDisconnect
WarpDidDisconnect: function
WarpDidFail
WarpDidFail: function
Type declaration
-
- (error: unknown, host: Host, warp: WarpRef): void
-
Parameters
-
error: unknown
-
host: Host
-
Returns void
@swim/client
@swim/client is a streaming API client for linking to lanes of stateful Web Agents using the WARP protocol, enabling massively real-time applications that continuously synchronize all shared states with ping latency. WARP is like pub-sub without the broker, enabling every state of a Web API to be streamed, without interference from billions of queues. @swim/client is part of the @swim/mesh framework.
Overview
WarpRef
A
WarpRef
is a handle through which WARP downlinks can be opened.WarpClient
implements theWarpRef
interface, as does the exported @swim/client module object, and by extension, the globalswim
namespace object used web browsers and other non-module contexts.WarpRef
instances have four methods that open different kinds of downlinks. Thedownlink
method creates anEventDownlink
for streaming raw events from any Web Agent lane. ThevalueDownlink
method creates aValueDownlink
for synchronizing state with a Web Agent value lane. ThemapDownlink
method creates aMapDownlink
for synchronizing state with a Web Agent map lane. And thelistDownlink
method creates aListDownlink
for synchronizing state with a Web Agent list lane.swim.downlink() .hostUri("warp://traffic.swim.services") .nodeUri("swim:meta:mesh") .laneUri("linkStats") .onEvent((value) => console.log(value.toAny())) .open();
WarpRef
instances can also be used to observe key lifecycle events. TheWarpRef.didConnect
method registers an observer callback that gets invoked whenever a connection to a WARP host is establishes. TheWarpRef.didDisconnect
method registers an observer callback that gets invoked whenever a WARP host disconnects.WarpRef.didAuthenticate
registers an observer callback that gets invoked whenever the client successfully authenticates with a WARP host.WarpRef.didDeauthenticate
gets invoked when a WARP host rejects the client's authentication credentials. And theWarpRef.didFail
method registers an observer callback that gets invoked when the client encounters an unexpected error.swim.didConnect((host) => console.log("connected to", host)); swim.didDisconnect((host) => console.log("disconnected from", host)); swim.didAuthenticate((session, host) => console.log("authenticated to", host, "with session", session.toAny())); swim.didDeauthenticate((reason, host) => console.log("deauthenticated from", host, "because", reason.toAny())); swim.didFail((error, host) => console.log("host", host, "failed because", error));
WarpClient
The
WarpClient
class handles connection management and link routing, and implements theWarpRef
interface. In addition to opening downlinks,WarpClient
instances can be used to send arbitrary WARP commands, to provide authentication credentials for hosts, to control network reconnection behavior, and to createHostRef
,NodeRef
, andLaneRef
scopes to facilitate downlink management.The
WarpClient.authenticate
method associates a credentials structure with a particular host URI. The credentials will be sent in a WARP@auth
envelope whenever the client connects to the specified host.swim.authenticate("warps://example.com", {"@openId": jwt});
Distinct
WarpClient
instances can be used to create isolated connection pools for different security domains.const userClient = new WarpClient(); userClient.authenticate("warps://example.com", {"@openId": userJwt}); const toolClient = new WarpClient(); toolClient.authenticate("warps://example.com", {"@oauth": toolJwt});
The
WarpClient.command
method sends a WARP command message to a lane of a remote node.WarpClient.command
takes either three our four arguments. The three argumentcommand
overload takes a node URI, a lane URI, and a command payload. The node URI must have an authority component that specifies the host to which the command should be sent. The four argumentcommand
overload takes a host URI, a node URI, a lane URI, and a command payload; the node URI is interpreted relative to the host URI.swim.command("warp://example.com/house/kitchen", "light", "on"); swim.command("warp://example.com", "/house/kitchen", "light", "off");
The
WarpClient.isOnline
method returnstrue
when the the client has access to a network; it can also be used to force a client online or offline. TheWarpClient.keepOnline
method controls whether or not the client should automatically reopen connections after a network failure. Note that thekeepOnline
state of the client overrides thekeepLinked
state of individual downlinks. SettingkeepOnline
to false can be useful for ephemeral clients, but should typically be lefttrue
.swim.isOnline(); // true most of the time swim.isOnline(false); // force offline swim.isOnline(true); // force online swim.keepOnline(); // defaults to true swim.keepOnline(false); // disable network reconnection
The
WarpClient.hostRef
method returns a newHostRef
bound to the given host URI. TheWarpClient.nodeRef
method returns a newNodeRef
bound to the given host and node URIs. TheWarpClient.laneRef
method returns a newLaneRef
bound to the given host, node, and lane URIs.HostRef
A
HostRef
is aWarpRef
that automatically provides its bound host URI when opening downlinks, sending commands, and providing authentication credentials.HostRef
instances keep track of all the downlinks they directly open. When aHostRef
is closed, it automatically closes all of its open downlink views.const hostRef = swim.hostRef("warp://traffic.swim.services"); hostRef.downlink() .nodeUri("swim:meta:mesh") .laneUri("linkStats") .onEvent((value) => console.log(value.toAny())}) .open(); // ... hostRef.close();
The
HostRef.nodeRef
andHostRef.laneRef
instance methods can be used to create further resolvedWarpRef
scopes.const hostRef = swim.hostRef("warp://traffic.swim.services"); const nodeRef = hostRef.nodeRef("swim:meta:mesh"); const laneRef = hostRef.laneRef("swim:meta:mesh", "linkStats");
NodeRef
A
NodeRef
is aWarpRef
that automatically provides its bound host and node URIs when opening downlinks and sending commands.NodeRef
instances keep track of all the downlinks they directly open. When aNodeRef
is closed, it automatically closes all of its open downlink views.const nodeRef = swim.nodeRef("warp://traffic.swim.services", "swim:meta:mesh"); nodeRef.downlink() .laneUri("linkStats") .onEvent((value) => console.log(value.toAny())}) .open(); // ... nodeRef.close();
The
NodeRef.laneRef
instance method can be used to create further resolvedWarpRef
scopes.const nodeRef = swim.nodeRef("warp://traffic.swim.services", "swim:meta:mesh"); const laneRef = nodeRef.laneRef("linkStats");
LaneRef
A
LaneRef
is aWarpRef
that automatically provides its bound host, node, and lane URIs when opening downlinks and sending commands.LaneRef
instances keep track of all the downlinks they directly open. When aLaneRef
is closed, it automatically closes all of its open downlink views.const laneRef = swim.laneRef("warp://traffic.swim.services", "swim:meta:mesh", "linkStats"); laneRef.downlink() .onEvent((value) => console.log(value.toAny())}) .open(); // ... laneRef.close();
Downlink
A
Downlink
provides a virtual bidirectional stream between the client and a lane of a remote Web Agent. WARP clients transparently multiplex all links to Web Agents on a given host over a single WebSocket connection, and automatically manage the network connection to each host, including reconnection and resynchronization after a network failure. WARP clients also seamlessly handle multicast event routing when multiple downlinks are opened to the same lane of the same remote Web Agent.Downlinks come in several flavors, depending on the WARP subprotocol to which they conform. An
EventDownlink
observes raw WARP events, and can be used to observe lanes of any kind. AValueDownlink
synchronizes a structured value with a remote value lane. AMapDownlink
implements the WARP map subprotocol to synchronize key-value state with a remote map lane. AListDownlink
implements the WARP list subprotocol to to synchronize sequential list state with a remote list lane.Before opening, a downlink must be addressed with the
hostUri
,nodeUri
, andlaneUri
to which the link should connect. A downlink may also be configured with a relativeprio
rity, a maxrate
, and an optionalbody
structure that can contain query or other link parameters to be passed to the remote lane.The
keepLinked
parameter determines whether or not a downlink should be automatically reopened after a network failure; it defaults totrue
. ThekeepSynced
parameter determines whether or not a downlink should synchronize with the remote lane when opened; it defaults totrue
for stateful lanes.The
open
method is used to open a downlink after it has been configured. Theclose
method closes a downlink. Closing a downlink does not necessarily close the underlying WARP link. The WARP client will keep a link open so long as at least one downlink to a given node and lane URI remains open. This prevents application components from stepping on each other's toes when they link to the same lanes of the same Web Agents. This can happen, for example, when a UI has a summary view and a detail view both display information derived from the same remote lane. The WARP link should not be closed when a detail view is hidden, if state updates are still required by the summary view. Events should also not be sent twice: once for the summary view, and once for the detail view. Neither the summary view nor the detail view should have to know about each other. And no global event dispatcher should be required, which could introduce consistency problems. WARP clients efficiently, and transparently handle all of these cases on behalf of all downlinks.The
isConnected
method returnstrue
if the underlying connection to the remote host is currently open. TheisAuthenticated
method returnstrue
if the underlying connection to the remote host is currently authenticated. TheisLinked
method returnstrue
if the logical WARP link is currently open. And theisSynced
method returnstrue
if the WARP link is currently synchronized.All downlinks support registering
onEvent
,onCommand
,willLink
,didLink
,willSync
,didSync
,willUnlink
,didUnlink
,willConnect
,didConnect
,didDisconnect
,didClose
, anddidFail
callbacks.EventDownlink
An
EventDownlink
provides a raw view of a WARP link.swim.downlink() .hostUri("warp://example.com") .nodeUri("/house") .laneUri("power/meter") .onEvent((body) => /* ... */) .open();
ValueDownlink
A
ValueDownlink
synchronizes a shared real-time value with a remote value lane. In addition to the standardDownlink
callbacks,ValueDownlink
supports registeringwillSet
anddidSet
callbacks to observe all changes to downlinked state—whether remote or local.A
ValueDownlink
views its state as a @swim/structureValue
by default. Use thevalueForm
method to create a typed projection of aValueDownlink
that automatically transforms its state using a @swim/structureForm
. For example, you can useForm.foString()
to create aValueDownlink
that coerces its state to a string; and you can also useForm.forAny()
to create aValueDownlink
that coerces its state to a plain old JavaScript value.const value = swim.downlinkValue() .hostUri("warp://example.com") .nodeUri("/house/kitchen") .laneUri("light") .valueForm(swim.Form.forAny()) .didSet((value) => /* ... */) .open();
Use the
ValueDownlink.get
method to get the current state value. Use theValueDownlink.set
method to set the current state value.value.get(); // get the current local state of the downlink value.set(newValue); // update the local and remote state of the downlink
For the most part, client code can treat a
ValueDownlink
like an ordinary mutable variable; the WARP client will ensure that the downlink is continuously made consistent with the remote lane. UsingdidSet
callbacks, applications can update UI views, and other dependent components, to keep them consistent with the shared state of the remote value lane in network real-time.swim.downlinkValue() .didSet((value) => { // update UI view with latest value document.getElementById("value").innerText = value; })
MapDownlink
A
MapDownlink
synchronizes a shared real-time key-value map with a remote map lane. In addition to the standardDownlink
callbacks,MapDownlink
supports registeringwillUpdate
,didUpdate
,willRemove
, anddidRemove
callbacks to observe all changes to downlinked map state—whether remote or local.A
MapDownlink
views its keys and values as @swim/structureValue
s by default. Use thekeyForm
andvalueForm
methods to create a typed projection of aMapDownlink
that automatically transforms its keys and values using @swim/structureForm
s.const map = swim.downlinkMap() .hostUri("warp://example.com") .nodeUri("/house") .laneUri("rooms") .keyForm(swim.Form.forString()) .valueForm(swim.Form.forAny()) .didUpdate((key, value) => /* ... */) .didRemove((key) => /* ... */) .open();
MapDownlink
implements the standard JavaScriptMap
interface. Use theMapDownlink.get
method to get the value associated with a given key. Use theMapDownlink.set
method to update the value associated with a key. And use theMapDownlink.delete
method to remove a key and its associated value.map.get("kitchen"); // get the locally cached value associated with the key map.set("garage", newRoom); // locally and remotely insert a new entry
For the most part, client code can treat a
MapDownlink
like an ordinary JavaScriptMap
; the WARP client will ensure that the downlink is continuously made consistent with the remote lane. UsingdidUpdate
anddidRemove
callbacks, applications can update UI collection views, and other dependent components, to keep them consistent with the shared state of the remote map lane in network real-time.swim.downlinkMap() .didUpdate((key, value) => { if (hasChildElement(key)) { // update existing UI view for key } else { // insert new UI view for key } }) .didRemove((key) => { // remove UI view for key })
ListDownlink
A
ListDownlink
synchronizes a shared real-time list with a remote list lane. In addition to the standardDownlink
callbacks,ListDownlink
supports registeringwillUpdate
,didUpdate
,willMove
,didMove
,willRemove
, anddidRemove
callbacks to observe all changes to downlinked list state—whether remote or local.A
ListDownlink
views its items as @swim/structureValue
s by default. Use thevalueForm
method to create a typed projection of aListDownlink
that automatically transforms its items using a @swim/structureForm
.const list = swim.downlinkList() .hostUri("warp://example.com") .nodeUri("/house") .laneUri("todo") .valueForm(swim.Form.forAny()) .didUpdate((index, value) => /* ... */) .didMove((fromIndex, toIndex, value) => /* ... */) .didRemove((index) => /* ... */) .open();
ListDownlink
behaves similarly to a JavaScript array. Use theListDownlink.get
method to get the item at a given index. Use theListDownlink.set
method to update the item at some index. And use theListDownlink.splice
method to insert and remove items from the list. You can alsopush
,pop
,shift
, andunshift
items, andmove
an item from one index to another.list.get(0); // get the first item in the list list.set(0, "build"); // locally and remotely update an item list.push("paint"); // locally and remotely append an item
For the most part, client code can treat a
ListDownlink
like an ordinary JavaScript list; the WARP client will ensure that the downlink is continuously made consistent with the remote lane. UsingdidUpdate
,didMove
, anddidRemove
callbacks, applications can update UI list views, and other dependent components, to keep them consistent with the shared state of the remote list lane in network real-time.swim.downlinkList() .didUpdate((index, value) => { if (hasChildElement(index)) { // update existing UI view at index } else { // insert new UI view at index } }) .didMove((fromIndex, toIndex, value)) { // move existing UI view from old index to new index } .didRemove((index) => { // remove UI view at index })
Installation
npm
For an npm-managed project,
npm install @swim/client
to make it a dependency. TypeScript sources will be installed intonode_modules/@swim/client/main
. Transpiled JavaScript and TypeScript definition files install intonode_modules/@swim/client/lib/main
. And a pre-built UMD script can be found innode_modules/@swim/client/dist/main/swim-client.js
.Browser
Browser applications can load
swim-mesh.js
—which bundles the @swim/client library—along with itsswim-core.js
dependency, directly from the Swim CDN.<script src="https://cdn.swim.ai/js/latest/swim-core.js"></script> <script src="https://cdn.swim.ai/js/latest/swim-mesh.js"></script>
Alternatively, the standalone
swim-system.js
script may be loaded from the Swim CDN, which bundles @swim/client together with all other @swim/system libraries.<script src="https://cdn.swim.ai/js/latest/swim-system.js"></script>
Usage
ES6/TypeScript
@swim/client can be imported as an ES6 module from TypeScript and other ES6-compatible environments.
import * as client from "@swim/client";
CommonJS/Node.js
@swim/client can also be used as a CommonJS module in Node.js applications.
var client = require("@swim/client");
Browser
When loaded by a web browser, the
swim-mesh.js
script adds all @swim/client library exports to the globalswim
namespace. Theswim-mesh.js
script requires thatswim-core.js
has already been loaded.The
swim-system.js
script also adds all @swim/client library exports to the globalswim
namespace, making it a drop-in replacement for 'swim-core.js' andswim-mesh.js
when additional @swim/system libraries are needed.