Typed JavaScript and TypeScript byte utilities for base64, base64url, hex, Z85, UTF-8 strings, JSON, gzip, concatenation, comparison, and byte-source normalization. The package ships tree-shakeable ESM plus CommonJS entry points and keeps the same API across Node, Bun, Deno, browsers, and edge runtimes.
- Runtimes: Node, Bun, Deno, browsers, and edge runtimes.
- Module formats: ESM by default, with CommonJS exports for
require()consumers in Node and Bun. - Node and Bun runtime behavior: uses
Bufferfor base64 helpers andnode:zlibfor gzip. - Browser and edge gzip support requires
CompressionStreamandDecompressionStream. - TypeScript: bundled types.
- Developer-friendly API for base64, base64url, hex, Z85, UTF-8, JSON, gzip, concat, equality, and byte normalization.
- No runtime dependencies or bundler shims.
- Tree-shakeable ESM by default with CommonJS compatibility and no side effects.
- Returns copies for safety when normalizing inputs.
- Consistent behavior across Node, browsers, and edge runtimes.
npm install @sovereignbase/bytecodec
# or
pnpm add @sovereignbase/bytecodec
# or
yarn add @sovereignbase/bytecodec
# or
bun add @sovereignbase/bytecodec
# or
deno add jsr:@sovereignbase/bytecodec
# or
vlt install jsr:@sovereignbase/bytecodecimport { Bytes } from '@sovereignbase/bytecodec'
// The `Bytes` convenience class wraps the same functions as static methods.
const encoded = Bytes.toBase64String(new Uint8Array([1, 2, 3])) // base64 stringimport { toBase64String, fromBase64String } from '@sovereignbase/bytecodec'
const bytes = new Uint8Array([104, 101, 108, 108, 111])
const encoded = toBase64String(bytes) // string of base64 chars
const decoded = fromBase64String(encoded) // Uint8Arrayconst { toBase64String, fromBase64String } = require('@sovereignbase/bytecodec')
const encoded = toBase64String([104, 101, 108, 108, 111]) // string of base64 chars
const decoded = fromBase64String(encoded) // Uint8Arrayimport {
toBase64UrlString,
fromBase64UrlString,
} from '@sovereignbase/bytecodec'
const bytes = new Uint8Array([104, 101, 108, 108, 111])
const encoded = toBase64UrlString(bytes) // string of base64url chars
const decoded = fromBase64UrlString(encoded) // Uint8Arrayimport { toHex, fromHex } from '@sovereignbase/bytecodec'
const bytes = new Uint8Array([222, 173, 190, 239])
const encoded = toHex(bytes) // "deadbeef"
const decoded = fromHex(encoded) // Uint8Arrayimport { toZ85String, fromZ85String } from '@sovereignbase/bytecodec'
const bytes = new Uint8Array([0x86, 0x4f, 0xd2, 0x6f, 0xb5, 0x59, 0xf7, 0x5b])
const encoded = toZ85String(bytes) // "HelloWorld"
const decoded = fromZ85String(encoded) // Uint8ArrayZ85 encodes 4 input bytes into 5 output characters, so toZ85String() requires a byte length divisible by 4 and fromZ85String() requires a string length divisible by 5.
import { fromString, toString } from '@sovereignbase/bytecodec'
const textBytes = fromString('caffe and rockets') // Uint8Array
const text = toString(textBytes) // "caffe and rockets"import { fromJSON, toJSON } from '@sovereignbase/bytecodec'
const jsonBytes = fromJSON({ ok: true, count: 3 }) // Uint8Array
const obj = toJSON(jsonBytes) // { ok: true, count: 3 }import { toCompressed, fromCompressed } from '@sovereignbase/bytecodec'
const compressed = await toCompressed(new Uint8Array([1, 2, 3])) // Uint8Array
const restored = await fromCompressed(compressed) // Uint8Arrayimport {
toUint8Array,
toArrayBuffer,
toBufferSource,
} from '@sovereignbase/bytecodec'
const normalized = toUint8Array([1, 2, 3]) // Uint8Array
const copied = toArrayBuffer(normalized) // ArrayBuffer
const bufferSource = toBufferSource(normalized) // Uint8Array as BufferSourceAccepted byte inputs (ByteSource) are:
Uint8ArrayArrayBufferArrayBufferViewnumber[]
import { equals } from '@sovereignbase/bytecodec'
const isSame = equals(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])) // true | falseimport { concat } from '@sovereignbase/bytecodec'
const joined = concat([new Uint8Array([1, 2]), new Uint8Array([3, 4]), [5, 6]]) // Uint8ArrayUses Buffer.from for base64 helpers, TextEncoder and TextDecoder when available with Buffer fallback for UTF-8, and node:zlib for gzip.
Uses the same API shape as Node. ESM and CommonJS entry points are both exported.
Uses TextEncoder, TextDecoder, btoa, and atob. Gzip uses CompressionStream and DecompressionStream when available.
Validation failures throw BytecodecError instances with a code string, for example BASE64URL_INVALID_LENGTH, HEX_INVALID_CHARACTER, Z85_INVALID_BLOCK, BASE64_DECODER_UNAVAILABLE, UTF8_DECODER_UNAVAILABLE, and GZIP_COMPRESSION_UNAVAILABLE. Messages are prefixed with {@sovereignbase/bytecodec}.
toUint8Array, toArrayBuffer, and toBufferSource always return copies. concat normalizes each input to a fresh Uint8Array before joining.
npm test covers:
- 68 unit tests
- 6 integration tests
- Node E2E: ESM and CommonJS
- Bun E2E: ESM and CommonJS
- Deno E2E: ESM
- Edge Runtime E2E: ESM
- Browser E2E: Chromium, Firefox, WebKit, mobile-chrome, and mobile-safari
- Coverage gate: 100% statements, branches, functions, and lines
Latest local npm run bench run on 2026-03-23 with Node v22.14.0 (win32 x64):
| Benchmark | Result |
|---|---|
| base64 encode | 1,391,126 ops/s (35.9 ms) |
| base64 decode | 2,089,279 ops/s (23.9 ms) |
| base64url encode | 697,088 ops/s (71.7 ms) |
| base64url decode | 1,095,554 ops/s (45.6 ms) |
| hex encode | 1,053,832 ops/s (47.4 ms) |
| hex decode | 1,027,413 ops/s (48.7 ms) |
| z85 encode | 244,928 ops/s (204.1 ms) |
| z85 decode | 1,596,730 ops/s (31.3 ms) |
| utf8 encode | 1,537,199 ops/s (32.5 ms) |
| utf8 decode | 3,481,143 ops/s (14.4 ms) |
| json encode | 681,747 ops/s (29.3 ms) |
| json decode | 989,746 ops/s (20.2 ms) |
| concat 3 buffers | 846,612 ops/s (59.1 ms) |
| toUint8Array | 9,396,818 ops/s (21.3 ms) |
| toArrayBuffer | 884,096 ops/s (226.2 ms) |
| toBufferSource | 9,279,881 ops/s (21.6 ms) |
| equals same | 3,932,572 ops/s (50.9 ms) |
| equals diff | 4,060,534 ops/s (49.3 ms) |
| gzip compress | 4,126 ops/s (96.9 ms) |
| gzip decompress | 5,550 ops/s (72.1 ms) |
Command: npm run bench
Results vary by machine and Node version.
Apache-2.0