@velajs/live-protocol
v1.23.0
Published
Normative wire protocol for Vela live queries: frame types, the shared keyed-delta codec, and golden conformance fixtures
Maintainers
Readme
@velajs/live-protocol
The normative wire protocol for Vela live queries — the single source of truth both the server (@velajs/vela/live) and the client (@velajs/client) implement against, so the two sides cannot drift.
Zero runtime dependencies. Ships four things:
- The frame catalog — live frames ride Vela's WebSocket envelope under the reserved event
$live, discriminated ont:- client → server:
sub,unsub,presence - server → client:
ack,data,delta,settled,resume,error - plus the
Vela-Commit-Cursor/Vela-Commit-EpochHTTP header names used to gate optimistic-update drops.
- client → server:
- The shared keyed-delta codec —
encodeListDelta(previous, next)/applyListDelta(current, ops)with identical correctness bail rules on both sides, and an exact-reconstruction guarantee: whenever the encoder does not bail, applying the ops reproducesnextbyte-for-byte, ordering included. The codec does not guess whether a valid delta is cheaper from its operation count; delivery code compares the completed canonical delta and snapshot wire encodings. - Golden conformance fixtures —
runProtocolConformance(codec)runs byte-exact frame fixtures, pinned delta fixtures, and a seeded randomized sweep. The server and client test suites both call it; a wire change that forgets to update the fixtures fails a test instead of shipping an incompatibility. - Portable query definitions —
defineLiveQuery({ args, result })infers argument and result types from two runtime parsers. Share the same definition with the server's@LiveQuerydecorator and the client's query map; any schema exposingparse(unknown)fits without adding a protocol runtime dependency.
Versioning
LIVE_PROTOCOL is 2. Every subscription must advertise v: 2; omitted or older versions are rejected. Receivers still ignore unknown frame types and unknown fields within the same version. Any wire change releases in lockstep: live-protocol → @velajs/vela → @velajs/cloudflare → @velajs/client.
Delivery semantics (normative summary)
- At-least-once frames; keyed delta merge is idempotent, so replay after reconnect is harmless.
- Cursor + epoch identify a position in a log scope (one Durable Object on Cloudflare, one process on Node). Epoch mismatch ⇒ full snapshot, never a delta.
settledmeans the re-run result was byte-identical: no payload, but the cursor still advances (this is what drops optimistic layers for writes that didn't change a query's result).resumemeans nothing relevant changed while the client was away: keep the cached value, advance the cursor.- Optimistic updates gate on a subscription frame whose
cursorpasses the mutation'sVela-Commit-Cursor— never on HTTP response timing, which races the broadcast.
Validation and limits
Both endpoints must run the exported frame guards before dispatch. They reject non-JSON/prototype-bearing payloads, unsafe or negative cursors, incomplete cursor/epoch pairs, unsupported advertised versions, oversized strings, and malformed row operations. Defaults are 64 KiB per envelope, 1,000 delta operations, and 4 KiB of presence metadata. Clients ignore regressive cursors and cold-resubscribe when an epoch or watermark cannot continue safely.
See the live-query guide for the full feature documentation.
