Repository navigation
2.3.0 - 2026-09-20
A consumer-driven release. Everything here came from reading how cdxgen actually
uses this library and pulling the parts it had to reimplement back into the
package, plus a protobuf-es upgrade that turned out to be worth roughly 2x
across the board.
Fixed
-
convertBomno longer throws across the 1.5/1.6 boundary. Two fields
changed cardinality in CycloneDX 1.6:metadata.licensesand
evidence.identitywere single objects in 1.5 and became arrays in 1.6.
protobuf-es rejects an array where the schema wants one message and vice
versa, so converting any BOM that used either field failed outright —
cannot decode message cyclonedx.v1_5.EvidenceIdentity from JSON: Array(2).convertBomnow reshapes both before decoding: wrap on the way up, keep the
first entry on the way down. What gets dropped in a collapse is reported in
warnings($.components[].evidence.identity[1]) rather than vanishing, so
downgrades stay lossy-but-visible. Theevidence.identityreshape walks the
whole document, so it covers components wherever they live — nested
components[].components[],metadata.componentand its subtree,
metadata.tools.components[],formulation[].components[]. That matters
more than it sounds: almost every real BOM has ametadata.component, so a
reshape that only handled top-levelcomponents[]would still have thrown on
nearly everything.A descriptor walk across all three schemas confirms these are the only two
cardinality boundaries; nothing changes between 1.6 and 1.7.
Added
-
toBomMessage(value, specVersion?, options?)— one entry point for BOM
input of any shape: an already-decoded message passes through, a JSON string
is parsed, a JSON object withspecVersionpicks its own schema, one without
falls back to the version you pass (latest by default), and anything else
yields an empty BOM. Replaces the input-dispatch function every consumer ends
up writing.isBomMessage(value)is the matching type guard, checking
$typeNameagainst the known Bom types rather than duck-typing. -
normalizeSpecVersion()andisSupportedSpecVersion()are now exported.
Both accept the spellings that turn up in the wild —"1.6","v1.6",1.6,
"1.6.0"— the first throwing, the second not. Consumers gating protobuf work
on version support no longer have to match againstsupportedSpecVersionsby
hand. -
@cdxgen/cdx-proto/nodesubpath withreadBomFile,writeBomFileand
isProtoBomFile. Format is chosen from the extension:.jsonfor canonical
JSON,.b64/.base64for base64, everything else as protobuf binary. The
list of extensions that mean "protobuf BOM" (.cdx,.cdx.bin,.proto)
lives here asprotoBomFileExtensionsso it stops being copied around. These
are in a separate subpath deliberately — the main entry still has nonode:
imports and runs unchanged in browsers and edge runtimes. -
Base64 codecs:
encodeBomBase64,decodeBomBase64,parseBomBase64.
Same bytes as the binary encoding, in a form that survives OCI labels,
in-toto predicates, JSON documents and environment variables. Uses
protobuf-es' own base64 rather thanBuffer, so it stays runtime-neutral.
The CLI reads and writes.b64/.base64files too.
Changed
-
@bufbuild/protobufandprotoc-gen-es2.13.0 → 2.15.0,buf→ 1.73.0.
2.14.0 was protobuf-es' performance release (growable writer buffers, native
base64, compiledcreate()) and the effect is large. Same machine, same Node
24.18.0, 10 000 components:operation 2.13.0 2.15.0 parseBomJson47.3 ms 24.6 ms encodeBomJson28.6 ms 17.7 ms encodeBomBinary66.0 ms 14.3 ms parseBomBinary45.2 ms 16.4 ms Full tables in
bench/BASELINE.md. Generated code changed only in its
generator-version comment. -
engines.nodeis now>=22. Node 20 reached end of life in April 2026.
CI runs 22.x, 24.x and 26.x. -
The CLI now builds on the new
/nodehelpers instead of its own file
plumbing.
Compatibility
No wire-format or schema changes — the vendored protos are untouched apart from
the generator comment, so binaries written by 2.2.0 read back identically. Every
addition is additive; nothing in the 2.2.0 API changed shape. The one behavioural
difference is that convertBom now succeeds where it used to throw, and may
return warnings on downgrades that previously produced no result at all.
Full Changelog: v2.2.0...v2.3.0