DEV Community

Cover image for Releasing @hsblabs/web-stream-extras: small utilities for WHATWG byte stream pipelines
mktbsh
mktbsh

Posted on • Originally published at hsb.horse

Releasing @hsblabs/web-stream-extras: small utilities for WHATWG byte stream pipelines

I published @hsblabs/web-stream-extras.

It started as internal plumbing I kept copy-pasting across projects. Enough utility collected around ReadableStream<Uint8Array> that it made sense to package it properly.

npm install @hsblabs/web-stream-extras
Enter fullscreen mode Exit fullscreen mode

Node.js ≥22 and modern browsers. No runtime dependencies.


What's in the root package

The root export handles the everyday byte stream operations.

import {
  readableFromChunks,
  readAllBytes,
  stringToBinary,
  binaryToString,
} from "@hsblabs/web-stream-extras";

const stream = readableFromChunks([
  stringToBinary("hello"),
  stringToBinary(" world"),
]);

const result = await readAllBytes(stream);
console.log(binaryToString(result)); // "hello world"
Enter fullscreen mode Exit fullscreen mode

readableFromChunks wraps an array of Uint8Array chunks into a proper ReadableStream. readAllBytes collects everything from a stream into a single Uint8Array. The string and buffer conversion helpers — stringToBinary, binaryToString, toU8Array, toArrayBuffer, concatU8Arrays — exist because converting between string, Uint8Array, and ArrayBuffer is repetitive and easy to get subtly wrong.

ByteTransformStream is an abstract base for building typed binary transform pipelines. ByteQueue handles internal buffering with a clean read/write interface — useful when you need to track partial byte reads across chunks.

Base64url encoding is included too: encodeBase64Url and decodeBase64Url, without padding.


Stream encryption

The encryption subpath adds encryption built on the Web Crypto API.

import {
  encryptStream,
  decryptStream,
} from "@hsblabs/web-stream-extras/encryption";

const key = crypto.getRandomValues(new Uint8Array(32));
const encrypted = encryptStream(key, plaintext);
const decrypted = decryptStream(key, encrypted);
Enter fullscreen mode Exit fullscreen mode

encryptStream and decryptStream take a ReadableStream and return a ReadableStream. The underlying EncryptionStream and DecryptionStream are exposed as TransformStream wrappers if you need to compose them differently.

For cases where you need key management, webCryptoStream(masterKey) handles deriving and encrypting per-stream keys with an AES-GCM master key.


Why Web Streams

The WHATWG Streams API is available natively in Node.js ≥18 and all modern browsers. Using it directly avoids Node.js-specific stream abstractions and keeps the code portable. If you're targeting environments where both sides — browser and server — need to handle the same byte pipeline, the WHATWG API is the right base layer.


npm · GitHub

Issues and feedback welcome.

Top comments (0)