Schema 3.4.0
Schema and wire-format change
ClientSample.scoreReasons changes shape, so producers and consumers should move to the 3.4.0
generated schemas together. (3.6.0 changed it once more, to a map of contributions.)
Changed — scoreReasons becomes a list
ClientSample.scoreReasons changed from an optional string to an optional array of strings,
so several independent reasons can be attached to a calculated score instead of encoding all the
detail into one string value.
// before
scoreReasons?: string | null;
// 3.4.0
scoreReasons?: string[] | null;Added — @observertc/samples-protobuf-codec
One package that both encodes and decodes, replacing the separate
@observertc/samples-encoder and @observertc/samples-decoder. Same wire idea as before: each
message carries only what changed since the previous sample, over the all-optional ClientSample
proto, where explicit presence is what “changed” means.
- Dual ESM/CommonJS build with an
exportsmap and full type declarations; noBufferor other Node built-ins, so it runs in the browser that produces the samples. ProtobufCodecErrorwith acode(MALFORMED_INPUT,STREAM_DESYNC,INVALID_VALUE,INVALID_OPTION) and acontext.pathpointing at the offending value, plus a non-throwingdecoder.tryDecode().identifiers: { callId | clientId | peerConnectionId | trackId: 'utf8' | 'uuid' }replaces the*IsUuidbooleans. A value declareduuidthat is not a UUID is now an error rather than a silent fallback.createClientSampleCodec()builds both halves from one options object, so they cannot disagree about identifier packing.reset()on either half is a keyframe: the next message is a full snapshot.- Silent by default — pass a
loggerto hear anything. - Regression suite with byte-exact golden fixtures for two recorded streams, plus randomised streams checked against an independent forward-fill model.
The generator emits only the sample and protobuf bindings into the package: the codec reads the field list, scalar types and nesting off the protobuf descriptor at runtime, so a new schema field reaches the published codec without any new per-field code.
Added — @observertc/samples-json-codec
The same delta codec over plain JSON, with zero runtime dependencies and a ~2.1 KB gzipped bundle (the protobuf codec is ~29.8 KB, since it carries the protobuf runtime and descriptor).
- A delta is a
ClientSamplewith the unchanged parts left out — nothing renamed, tagged or wrapped — so a message is readable in a log without a decoder, and a golden-fixture diff shows exactly which field started or stopped being sent. - Identical semantics to the protobuf codec: forward-fill, keyed collections,
reset()as a keyframe, matching error codes. The two are interchangeable. - On the recorded test stream, JSON is 2.73× the protobuf payload raw and 1.41× gzipped — so
with
permessage-deflateor any compressing transport the real cost is about 40%. NaNandInfinityare rejected rather than silently serialised tonull.- The decoder returns a sample it does not retain, so a pipeline that annotates samples in place cannot corrupt the stream.
- The whole codec is two pure functions — a
diffand amergethat are exact inverses — in under 300 lines. The only configuration is which arrays are keyed collections; a new schema field needs no change to it.
Unlike the protobuf artifact it does not require proto — JSON is self-describing, so the package
only needs the sample types.
Fixed — what the old encoder / decoder pair got wrong
Corrected in the new package; the old packages are unchanged.
| Bug | Consequence |
|---|---|
false could never be transmitted | The boolean encoder skipped any falsy value, so active, nominated and powerEfficientDecoder could go true but never come back |
| An empty string could never be transmitted | Same cause |
Two entries of the same type in one sample’s clientEvents lost the second one’s type | All events shared one stateful field encoder |
ClientMetaData.timestamp was dropped entirely on encode | — |
ClientMetaData.peerConnectionId and .trackId ignored the uuid settings | Always written as utf8 |
codecId, mid and transportId used a one-time-pass encoder | A value that legitimately changed mid-call was never re-sent. They are ordinary delta fields now |
attachments was compared by reference | An object rebuilt with identical content was re-sent on every sample. It is compared by value now |
| A decoder that joined a stream late returned a half-built sample | It now raises STREAM_DESYNC |
Removed — the encoder and decoder packages
samples-encoder and samples-decoder are deprecated
They stopped at 3.3.0 and will not be regenerated, versioned or published again; their sources
were removed from the repository along with the encoder and decoder generator artifacts.
3.3.0 stays installable from npm — removing the sources is not an unpublish — and the wire
format is unchanged, so either package still interoperates with
@observertc/samples-protobuf-codec and the two ends of a stream can migrate independently.
See the protobuf codec’s migration table for the API mapping.
← Back to version history · 3.3.0 →