Map Downlink

Version Note

This documentation describes Swim JS packages v4.0.0 or later. Users of earlier package versions may experience differences in behavior.

A MapDownlink synchronizes a shared real-time key-value map with with any Web Agent lane backed by a map. In addition to map lanes, this includes join value lanes and join map lanes, which are maps where each entry is its own value lane or maps lane, respectively. In addition to the standard Downlink callbacks, MapDownlink supports registering didUpdate, and didRemove callbacks for observing changes to downlinked map state — whether remote or local. didUpdate is invoked when an existing map key is updated or a new key is added. didRemove gets called when a map key is removed.

Create a MapDownlink with a WARP client’s downlinkMap method.

MapDownlink implements the standard JavaScript Map interface. Use the get method to get the value associated with a given key. Use the set method to update the value associated with a key. And use the delete method to remove a key and its associated value.

import { WarpClient } from "@swim/client";

const mapDownlink = client.downlinkMap({
  hostUri: "warp://example.com",
  nodeUri: "/hotel/lobby",
  laneUri: "elevators"
})
.open();
mapDownlink.get("guest"); // get the locally cached value associated with the key
mapDownlink.set("service", newElevator); // locally and remotely insert a new entry
mapDownlink.delete("parking"); // locally and remotely remove an existing entry

For the most part, client code can treat a MapDownlink like an ordinary JavaScript Map; the WARP client will ensure that the downlink is continuously made consistent with the remote lane. Using didUpdate and didRemove 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. Callbacks may be provided as an option during downlink initialization or defined later on, as shown below.

mapDownlink.didUpdate = (key, value) => {
  if (hasChildElement(key)) {
    // update existing UI view for key
  } else {
    // insert new UI view for key
  }
}
mapDownlink.didRemove((key) => {
  // remove UI view for key
})

State Type Disambiguation

A MapDownlink views its keys and values as Values by default. Provide an instance of a Form to the keyForm and/or valueForm options to create a typed projection of a MapDownlink that automatically transforms its keys and values, respectively, and provides type annotations. The Form class comes with a number of ready-to-use instances for basic use cases. For example, you can use Form.forBoolean() to coerce a MapDownlink’s state to a boolean. Form.forAny() can be used to create a MapDownlink that coerces its state to an untyped JavaScript value; it’s able to recognize primitive JavaScript values as well as arrays and plain old JavaScript objects, including nested objects. Forms for coercing state to a string, number, Value, and Item are also provided.

const elevators = client.downlinkMap({
  hostUri("warp://example.com"),
  nodeUri("/hotel/lobby"),
  laneUri("elevators"),
  keyForm(Form.forString()),
  valueForm(Form.forAny()),
  didUpdate((key, value) => /* ... */),
  didRemove((key) => /* ... */),
})
.open();

Typescript

MapDownlink state may also be given a type annotation. All that is required is for a custom Form to be provided to the valueForm option. See our article on Forms for an example on how to do this.

import { WarpClient } from "@swim/client";
import { Form } from "@swim/structure";

const elevators = client.downlinkValue<Record<string, Elevator>>({
  hostUri: "warp://example.com",
  nodeUri: "/hotel/lobby",
  laneUri: "elevators",
  keyForm: Form.forString(),
  valueForm: new ElevatorForm(),
})
.open();

// typed Elevators object
elevators.get("guest"); // { id: 12345, currentFloor: 1, occupied: false, lastInspection: 1707216815650 }