cbor-js
A minimal, dependency-free pure-JavaScript implementation of the CBOR binary data format for encoding and decoding ArrayBuffers.
Repository Health
Technical Analysis
cbor-js is a compact, dependency-free implementation of the Concise Binary Object Representation (CBOR) format defined in RFC 7049, written entirely in vanilla JavaScript with no build step or external libraries required. It exposes exactly two functions — CBOR.encode() and CBOR.decode() — that convert between native JavaScript values and ArrayBuffer-backed binary payloads, covering booleans, numbers (including large integers and floats), strings, arrays, plain objects, and typed Uint8Array byte strings.
The library was designed to pair naturally with binary-friendly browser APIs such as WebSocket (using binaryType = “arraybuffer”) and IndexedDB, making it a lightweight alternative to JSON when payload size or binary-safe transport matters. Because it has zero runtime dependencies and ships as a single ~12KB file, it can be dropped into a script tag, bundled via Browserify/Webpack, or required as a CommonJS/AMD module without any additional tooling.
What You Get
- A single-file, dependency-free CBOR codec (~12KB) that runs unmodified in browsers, Node.js, or via AMD loaders
- Two-function API — CBOR.encode(value) and CBOR.decode(buffer) — for converting between JS values and ArrayBuffers
- Support for the full CBOR major-type set: integers, floats (16/32/64-bit), byte strings, text strings, arrays, maps, and simple values
- Built-in handling of indefinite-length arrays, strings, and maps as defined by the CBOR spec
Common Use Cases
- Encoding WebSocket payloads as binary CBOR instead of JSON to reduce message size and enable binaryType=‘arraybuffer’ transport
- Serializing data for storage in IndexedDB or other binary-oriented browser storage APIs
- Interoperating with backend services or IoT/embedded systems that emit or consume CBOR-encoded messages
- Replacing JSON.stringify/parse in performance- or bandwidth-sensitive client code with a compact binary format
Under The Hood
Architecture cbor-js is implemented as a single self-invoking function in cbor.js that exposes exactly two entry points, encode() and decode(), each built as a closure over local read/write cursor state rather than any class or module hierarchy. The encoder starts from a growable ArrayBuffer/DataView pair (prepareWrite/commitWrite) that doubles in size on demand, delegates per-type serialization to writeTypeAndLength() and a set of writeUintN/writeFloat64 helpers, and recurses through encodeItem() for arrays, plain objects, and nested values. The decoder mirrors this with a matching decodeItem() that switches on CBOR major type and additional-information bits, using dedicated readLength()/readIndefiniteStringLength() helpers to handle both fixed- and indefinite-length arrays, strings, and maps. There is no separation between protocol logic and buffer management beyond function boundaries within the same closure, so the whole codec — encode, decode, and their UMD registration (AMD/CommonJS/global) — lives in one compact file; changing the core buffer-growth strategy or the major-type dispatch would require touching this single closure directly.
Tech Stack The runtime itself has zero dependencies — cbor.js is plain JavaScript relying only on built-in ArrayBuffer, DataView, and Uint8Array, and registers itself via a UMD-style pattern (AMD define, CommonJS module.exports, or a global CBOR object) so it can be dropped into a browser script tag or required from Node without a bundler. The development toolchain, by contrast, is entirely Grunt-based: grunt-contrib-jshint for linting, grunt-contrib-uglify for minification, grunt-contrib-compress for the release archive, grunt-contrib-connect for a local test server, grunt-contrib-qunit/grunt-qunit-istanbul for running QUnit tests with coverage, grunt-coveralls for reporting, and grunt-saucelabs for cross-browser testing; a bower.json indicates it was also published for Bower-based front-end dependency management, and a Travis CI config wires the whole pipeline together with an automatic GitHub release on tagged builds.
Code Quality Tests live in a QUnit suite exercised through an in-browser test harness page (and a minified variant) or via grunt-contrib-qunit in CI, with coverage data pushed to a coverage reporting service — a reasonably thorough setup for a project this size. Within cbor.js itself, error handling is minimal and non-idiomatic: invalid input paths throw bare strings rather than Error objects, and there is no TypeScript or type annotations anywhere in the codebase. Naming is consistent and low-level (writeUint8, readFloat16, commitRead), matching the bit-manipulation nature of the code, but there has been no linter or CI activity since the project’s last commit — the repository has been effectively unmaintained for several years.
API Design The public surface is deliberately tiny — CBOR.encode(value) and CBOR.decode(data, tagger, simpleValue) — which makes the library trivial to learn: the README’s entire usage example is four lines, with no configuration object, no class to instantiate, and no build step required to use it. The optional tagger and simpleValue callbacks on decode() expose CBOR’s extensibility (tag and simple-value handling) without forcing every caller to deal with them, keeping the common case as close to JSON.parse/JSON.stringify’s ergonomics as a binary format allows. This isn’t architecturally novel — it’s a straightforward, spec-faithful CBOR codec — but its minimalism and lack of dependencies is itself the differentiator against heavier alternatives in the same space.