Compatibility
Written against @waylocate/embed@0.2.1, which speaks wire protocol waylocate: 1.
Two versions, moving independently
You pin @waylocate/embed in your package.json. Waylocate deploys the map.
The two are not coordinated, which means the map an integration talks to is
almost always newer than the SDK installed against it.
The compatibility burden therefore runs one way only, and the goal is narrow: an integration written today keeps working, unchanged, against maps deployed later.
Three mechanisms deliver that.
The protocol only grows. Commands, events, and payload fields are added. None are renamed, repurposed, or removed. An older SDK keeps working; it simply has no method for commands introduced after it shipped.
Capabilities are advertised. Each map build sends its command list during
the handshake, so a host can check before sending and get an immediate
UNSUPPORTED rather than a timeout.
Unknown data passes through. Neither side strips fields it does not recognise, so an older SDK keeps receiving events that have since gained information.
What is promised
The package is deliberately split into three tiers, and the promise attached to each is different.
Tier 1: stable, and free of transport
Imported from @waylocate/embed and @waylocate/embed/react.
| Export | Role |
|---|---|
mount() | Hand over a container and intent; receive a handle |
<CampusMap>, useCampusMap() | React bindings over mount() |
WaylocateMap | The handle, and its command namespaces |
| Payload types | MapState, SelectionChangedPayload, CameraPosition, and the rest |
WaylocateError, isWaylocateError | Typed errors with a stable code |
SDK_VERSION | Version string, for support and telemetry |
Nothing in this tier names a transport. There is no iframe, no origin, and
no postMessage in any signature, which is what allows the way the map is
delivered to change without any of this changing with it. That constraint is
enforced by a test rather than by review.
Signatures and semantics are additive within a major line.
Tier 2: stable, but coupled to transport
Also imported from @waylocate/embed.
| Export | Role |
|---|---|
buildEmbedUrl() | Construct the embed URL |
connect() | Attach to a frame element you already have |
These exist for integrations that own the element, which necessarily means knowing there is one. They are supported, and will not be removed without a major version and a migration path. If the delivery mechanism changes they may shift internally.
Tier 3: internals
Imported from @waylocate/embed/protocol.
Wire helpers, the raw client, origin parsing, and message builders. These are published because implementing a host against the protocol directly is a legitimate thing to do, not because they are a supported interface. They may change in any release.
Choosing a tier
// Ordinary integrations
import { mount } from "@waylocate/embed";
import { CampusMap } from "@waylocate/embed/react";
// You own the element
import { buildEmbedUrl, connect } from "@waylocate/embed";
// You are implementing the protocol yourself
import { createEmbedHostClient } from "@waylocate/embed/protocol";
If more than one of these would work, take the highest one on the list. It is the one insulated from the most future change.
Versioning
The package's version and the wire protocol's version are independent. The
protocol is versioned by the waylocate field on every message and changes very
rarely. The package versions its own JavaScript interface.
While the package is on a 0.x line:
| Change | Release |
|---|---|
| Bug fixes, documentation, internal refactoring | Patch |
| Additive Tier 1 surface | Minor |
| Breaking Tier 1 change | Avoided. If unavoidable, a minor with a migration note in the changelog |
Every release notes which protocol version it speaks, and where relevant the minimum map build a feature requires.
Upgrading
Upgrading the package is normally a version bump and nothing else. Read the changelog for the range you are crossing, and check for a migration note.
Adopting a capability added after your map deployment is the case worth guarding:
if (map.supports("camera.orbit")) {
await map.camera.orbit({ ref: "muntz-hall", secondsPerRevolution: 20 });
}