npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cbortech/cbor

v0.25.9

Published

Convert between CBOR, CDN (CBOR-EDN), and JavaScript values

Downloads

1,446

Readme

@cbortech/cbor

TypeScript library for converting between CBOR, CDN (CBOR-EDN), and JavaScript values.

A live playground is available at https://cbor.tech/cbor/.

This package exposes the CBOR facade plus a separate AST entrypoint for the CBOR node classes needed by extensions. Lower-level parser and encoder internals are not part of the documented public API.

Install

npm install @cbortech/cbor

Import

import { CBOR } from '@cbortech/cbor';

Default import is also supported:

import CBOR from '@cbortech/cbor';

Quick Examples

JavaScript to CBOR bytes

import { CBOR } from '@cbortech/cbor';

const bytes = CBOR.encode({ hello: 'world', n: 42 });

console.log(bytes);
// Uint8Array(...)

CBOR bytes to JavaScript

import { CBOR } from '@cbortech/cbor';

const value = CBOR.decode(
  new Uint8Array([
    0xa2, 0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x65, 0x77, 0x6f, 0x72, 0x6c,
    0x64, 0x61, 0x6e, 0x18, 0x2a,
  ])
);

console.log(value);
// { hello: 'world', n: 42 }

CBOR Sequence to JavaScript values

decodeSeq reads concatenated CBOR items as a CBOR Sequence and yields each item as a JavaScript value.

import { CBOR } from '@cbortech/cbor';

const a = CBOR.encode({ id: 1 });
const b = CBOR.encode({ id: 2 });
const seq = new Uint8Array([...a, ...b]);

const values = [...CBOR.decodeSeq(seq)];
// [{ id: 1 }, { id: 2 }]

CBOR bytes to CDN

decompile converts CBOR binary data to a CDN text string. It handles CBOR Sequences automatically: multiple concatenated items produce newline-separated CDN output.

import { CBOR } from '@cbortech/cbor';

// Single item
const text = CBOR.decompile(new Uint8Array([0x83, 0x01, 0x02, 0x03]));
console.log(text);
// [1,2,3]

// CBOR Sequence — each item on its own line
const seq = new Uint8Array([...CBOR.encode(1), ...CBOR.encode('two')]);
console.log(CBOR.decompile(seq));
// 1
// "two"

CDN to CBOR bytes

compile converts a CDN text string to CBOR binary data. Multi-item CDN Sequences automatically produce a CBOR Sequence (RFC 8742): concatenated items.

import { CBOR } from '@cbortech/cbor';

// Single item
const bytes = CBOR.compile('[1, 2, 3]');
console.log(bytes);
// Uint8Array([0x83, 0x01, 0x02, 0x03])

// CDN Sequence — output is a CBOR Sequence
const seq = CBOR.compile('{"id":1}\n{"id":2}');
console.log([...CBOR.decodeSeq(seq)]);
// [{ id: 1 }, { id: 2 }]

CBOR bytes to hex dump

toHex converts CBOR binary data to an annotated hex dump string. CBOR Sequences are handled automatically: each item produces its own dump, separated by newlines.

import { CBOR } from '@cbortech/cbor';

const bytes = CBOR.encode([1, 2, 3]);
console.log(CBOR.toHex(bytes));
// 83        -- Array of length 3
//    01     -- 1
//    02     -- 2
//    03     -- 3

Hex dump to CBOR bytes

fromHex parses an annotated hex dump back to CBOR binary data. Multi-item dumps produce a CBOR Sequence (RFC 8742): concatenated items.

import { CBOR } from '@cbortech/cbor';

const bytes = CBOR.fromHex(`
83        -- Array of length 3
   01     -- 1
   02     -- 2
   03     -- 3
`);
console.log([...CBOR.decodeSeq(bytes)]);
// [[1, 2, 3]]

JavaScript to CDN

import { CBOR } from '@cbortech/cbor';

const text = CBOR.stringify({ a: 1, b: true, c: null });

console.log(text);
// {"a":1,"b":true,"c":null}

Pretty CDN

import { CBOR } from '@cbortech/cbor';

const text = CBOR.stringify({ items: [1, 2, 3], ok: true }, { indent: 2 });

console.log(text);
// {
//   "items": [
//     1,
//     2,
//     3
//   ],
//   "ok": true
// }

CDN to JavaScript

import { CBOR } from '@cbortech/cbor';

const value = CBOR.parse("[1, h'deadbeef', true, null]");

console.log(value);
// [1, Uint8Array(...), true, null]

CDN Sequence to JavaScript values

parseSeq parses multiple CDN items separated by whitespace, commas, or comments, and also accepts JSONL / NDJSON input.

import { CBOR } from '@cbortech/cbor';

const values = [...CBOR.parseSeq('1  "two"  [3]')];
// [1, 'two', [3]]

const jsonl = '{"id":1}\n{"id":2}\n{"id":3}';
const rows = [...CBOR.parseSeq(jsonl)];
// [{ id: 1 }, { id: 2 }, { id: 3 }]

Normalize CDN

import { CBOR } from '@cbortech/cbor';

const text = CBOR.format('{ "b" : [ 1,2 ], "a" : true }', { indent: 2 });

console.log(text);
// {
//   "b": [
//     1,
//     2
//   ],
//   "a": true
// }

Split text strings while formatting

textStringFormat can split long text strings with CDN string concatenation. It is applied when indent is specified.

import { CBOR } from '@cbortech/cbor';

const text = CBOR.format('{"text": "line1\\nline2\\nline3"}', {
  indent: 2,
  textStringFormat: ['newline'],
});

console.log(text);
// {
//   "text": "line1\n" +
//     "line2\n" +
//     "line3"
// }

For strings that contain CDN or JSON-like content, use cdn.

import { CBOR } from '@cbortech/cbor';

const text = CBOR.format('{"cdn": "[1,2,3]"}', {
  indent: 2,
  textStringFormat: ['cdn'],
});

console.log(text);
// {
//   "cdn": "[" +
//       "1," +
//       "2," +
//       "3" +
//     "]"
// }

Working With The AST

CBOR.fromCBOR(), CBOR.fromCDN(), and CBOR.fromJS() return a CBOR item. Concrete node classes such as CborTextString, CborByteString, CborArray, and CborTag are exported from @cbortech/cbor/ast for extensions. Every item supports these methods:

import { CBOR } from '@cbortech/cbor';
import { CborItem } from '@cbortech/cbor/ast';

const item = CBOR.fromCDN('{ "x": 1 }');
item satisfies CborItem;

const bytes = item.toCBOR();
const text = item.toCDN();
const value = item.toJS();

Parse to AST, then serialize

import { CBOR } from '@cbortech/cbor';

const item = CBOR.fromCDN('[_ 1, 2, 3]');

console.log(item.toCDN());
// [_ 1,2,3]

console.log(item.toCBOR());
// Uint8Array(...)

Decode to AST, then inspect as CDN

import { CBOR } from '@cbortech/cbor';

const item = CBOR.fromCBOR(new Uint8Array([0x83, 0x01, 0x02, 0x03]));

console.log(item.toCDN());
// [1,2,3]

console.log(item.toJS());
// [1, 2, 3]

JSON-like API

CBOR.parse() and CBOR.stringify() intentionally feel similar to JSON.parse() and JSON.stringify().

Unlike JSON, CBOR can represent undefined as a value. Use CBOR.OMIT from a reviver or replacer when you want to remove an object entry or map entry explicitly, instead of producing an undefined value.

Reviver function

import { CBOR } from '@cbortech/cbor';

const value = CBOR.parse(
  '{"createdAt": "2026-05-06T00:00:00Z"}',
  (key, value) => {
    if (key === 'createdAt') return new Date(value);
    return value;
  }
);

console.log(value);
// { createdAt: 2026-05-06T00:00:00.000Z }

Replacer function

import { CBOR } from '@cbortech/cbor';

const text = CBOR.stringify({ id: 1, password: 'secret' }, (key, value) =>
  key === 'password' ? CBOR.OMIT : value
);

console.log(text);
// {"id":1}

Replacer key list

import { CBOR } from '@cbortech/cbor';

const text = CBOR.stringify(
  { id: 1, name: 'Alice', password: 'secret' },
  ['id', 'name'],
  2
);

console.log(text);
// {
//   "id": 1,
//   "name": "Alice"
// }

Default Options

Create a CBOR instance when you want to reuse the same options.

import { CBOR } from '@cbortech/cbor';

const cbor = new CBOR({
  extensions: [CBOR.dt_as_Date],
  indent: 2,
});

const value = cbor.parse("DT'2026-05-06T00:00:00Z'");

console.log(value);
// Date(...)

console.log(cbor.stringify({ value }));
// {
//   "value": DT'2026-05-06T00:00:00Z'
// }

Dates

CDN dt'...' and DT'...' literals are parsed by default. Add CBOR.dt_as_Date when you want JavaScript Date objects.

import { CBOR } from '@cbortech/cbor';

const value = CBOR.parse("DT'2026-05-06T00:00:00Z'", {
  extensions: [CBOR.dt_as_Date],
});

console.log(value instanceof Date);
// true
import { CBOR } from '@cbortech/cbor';

const text = CBOR.stringify(new Date('2026-05-06T00:00:00Z'), {
  extensions: [CBOR.dt_as_Date],
});

console.log(text);
// DT'2026-05-06T00:00:00Z'

Optional Extensions

This package includes several bundled extensions that are not enabled by default. Import what you need and pass it through the extensions option.

b32 / h32

Byte-string literals using RFC 4648 Base32 encoding. These prefixes are described in §8 of RFC 8949 and also mentioned in draft-ietf-cbor-edn-literals.

  • b32 — §6 Base32 (A–Z 2–7 alphabet)
  • h32 — §7 Base32Hex (0–9 A–V alphabet)
import { CBOR, b32, h32 } from '@cbortech/cbor';

const v1 = CBOR.fromCDN("b32'AEBAGBA'", { extensions: [b32] });
console.log(v1.toCDN({ appStrings: false }));
// h'01020304'

const v2 = CBOR.fromCDN("h32'00P00'", { extensions: [h32] });
console.log(v2.toCDN({ appStrings: false }));
// h'003200'

float

Interprets a hex bit-pattern as an IEEE 754 floating-point value. This extension is described in draft-bormann-cbor-edn-app-ext and also used in cbor-test-vectors.

import { CBOR, float } from '@cbortech/cbor';

const v = CBOR.fromCDN("float'7e00'", { extensions: [float] });
console.log(v.toCDN({ appStrings: false }));
// NaN

// Interpret bytes as float bits
const v2 = CBOR.fromCDN("float<<h'3f800000'>>", { extensions: [float] });
console.log(v2.toCDN({ appStrings: false }));
// 1.0_2

same

same<<expr, expr, ...>> verifies that every item in the sequence encodes to identical CBOR bytes and returns the first item. This extension is described in draft-bormann-cbor-edn-app-ext.

import { CBOR, same } from '@cbortech/cbor';

const v = CBOR.fromCDN("same<<h'0102', h'0102'>>", { extensions: [same] });
console.log(v.toCDN({ appStrings: false }));
// h'0102'

// A single-item sequence always passes
const v2 = CBOR.fromCDN('same<<42>>', { extensions: [same] });
console.log(v2.toCDN({ appStrings: false }));
// 42

Additional application extensions are published as separate packages. Install the ones you need and pass them through the extensions option.

hash

hash is an application extension defined in §3.3 of draft-ietf-cbor-edn-literals. It represents cryptographic hash values in the form hash'algorithm:value'. Because it requires an external cryptographic library, it is provided separately as @cbortech/hash-extension.

npm install @cbortech/hash-extension
import { CBOR } from '@cbortech/cbor';
import { hash } from '@cbortech/hash-extension';

const cbor = new CBOR({ extensions: [hash] });

const digest = cbor.parse(
  "hash'sha-256:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='"
);
// Uint8Array(32) [227, 176, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200,
//                 153, 111, 185, 36, 39, 174, 65, 228, 100, 155, 147, 76,
//                 164, 149, 153, 27, 120, 82, 184, 85]

uuid

uuid is a library-specific application extension, provided separately as @cbortech/uuid-extension.

npm install @cbortech/uuid-extension
import { CBOR } from '@cbortech/cbor';
import { uuid } from '@cbortech/uuid-extension';

const cbor = new CBOR({ extensions: [uuid] });

const id = cbor.parse("uuid'550e8400-e29b-41d4-a716-446655440000'");
// Uint8Array(16) [85, 14, 132, 0, 226, 155, 65, 212, 167, 22, 68, 102, 85, 68, 0, 0]

Tags

Use CBOR.Tag for CBOR tagged values in JavaScript.

import { CBOR } from '@cbortech/cbor';

const tagged = CBOR.Tag.set('hello', 42n);
const text = CBOR.stringify(tagged);

console.log(text);
// 42("hello")
import { CBOR } from '@cbortech/cbor';

const value = CBOR.parse('42("hello")');

console.log(CBOR.Tag.get(value));
// 42n

console.log(CBOR.Tag.getValue(value));
// "hello"

Use stripTags: true when you only need the tagged content as a plain JavaScript value.

import { CBOR } from '@cbortech/cbor';

const value = CBOR.parse('42("hello")', { stripTags: true });

console.log(value);
// "hello"

Simple Values

Use CBOR.Simple for CBOR simple values other than false, true, null, and undefined.

import { CBOR } from '@cbortech/cbor';

const text = CBOR.stringify(new CBOR.Simple(16));

console.log(text);
// simple(16)
import { CBOR } from '@cbortech/cbor';

const value = CBOR.parse('simple(16)');

console.log(value instanceof CBOR.Simple);
// true

console.log(value.value);
// 16

Maps

By default, CBOR maps with text keys become plain JavaScript objects.

import { CBOR } from '@cbortech/cbor';

const value = CBOR.parse('{"a": 1, "b": 2}');

console.log(value);
// { a: 1, b: 2 }

Use mapAs: 'entries' when you need to preserve non-string keys or duplicate keys.

import { CBOR } from '@cbortech/cbor';

const entries = CBOR.parse('{1: "one", 1: "uno"}', {
  mapAs: 'entries',
});

console.log(entries instanceof CBOR.MapEntries);
// true

console.log(entries);
// [[1, "one"], [1, "uno"]]

CBOR.MapEntries can be passed back to CBOR.stringify() or CBOR.encode().

import { CBOR } from '@cbortech/cbor';

const entries = new CBOR.MapEntries([1, 'one'], [1, 'uno']);

console.log(CBOR.stringify(entries));
// {1:"one",1:"uno"}

Hex Dumps

CBOR.toHex() and CBOR.fromHex() are the shortcut entry points (see Quick Examples). For full AST access — byte ranges, re-encoding, selective inspection — use item.toHexDump() and CBOR.fromHexDump() directly:

import { CBOR } from '@cbortech/cbor';

const item = CBOR.fromCDN('[_ 1, [2, 3]]');
const dump = item.toHexDump();

console.log(dump);
// 9F        -- Start indefinite-length array
// ...
import { CBOR } from '@cbortech/cbor';

const item = CBOR.fromHexDump(`
83        -- Array of length 3
   01     -- 1
   02     -- 2
   03     -- 3
`);

console.log(item.toCDN());
// [1,2,3]

Tokenization

The @cbortech/cbor/cdn subpath exposes the same lexer the parser uses, for tooling such as syntax highlighters that must stay in exact agreement with parsing behavior:

import { tokenize, tokenizeLenient } from '@cbortech/cbor/cdn';

const { tokens, comments } = tokenize('[1, "ab"] # note');
// tokens: [{ type: 'LBRACKET', offset: 0, endOffset: 1, ... }, ...]

const lenient = tokenizeLenient('[1, "ab');
// Never throws: clean tokens, then one ERROR token covering the
// unscannable tail, plus the failure in lenient.error.

Syntax errors thrown by fromCDN/parse/tokenize are CdnSyntaxError instances (a SyntaxError subclass, also exported from the main entry) and carry offset, line, column, and — where known — endOffset.

Public API

The documented public exports are:

  • CBOR
  • CdnSyntaxError

The CBOR facade also exposes:

  • CBOR.Tag
  • CBOR.Simple
  • CBOR.MapEntries
  • CBOR.dt_as_Date
  • CBOR.OMIT

Lower-level CDN tokenization lives in @cbortech/cbor/cdn (tokenize, tokenizeLenient, Token, TokenType, EdnComment), and AST node classes in @cbortech/cbor/ast.

Specifications

This library targets:

CDN is a human-readable text notation for CBOR data. It is useful for examples, test vectors, debugging, fixtures, and configuration-like files where raw CBOR bytes would be hard to read.

It looks similar to JSON for ordinary arrays, maps, strings, numbers, booleans, and null values, but it can also represent CBOR-specific features such as byte strings, tags, simple values, indefinite-length items, non-string map keys, and application literals like dt'2026-05-06T00:00:00Z'.

CDN is a superset of JSON and JSONC, so ordinary JSON data and commented JSON-style data can be parsed and formatted as CDN without special handling.

CDN is still an Internet-Draft rather than a widely deployed RFC.

License

Apache-2.0