Browse packages

Package · v0.13.0

stream

Standard library streams

Stream utilities for JavaScript runtimes.

What is @rcompat/stream?#

A cross-runtime module providing utilities for working with Web Streams. Convert ReadableStream to strings and other common stream operations. Works consistently across Node, Deno, and Bun.

Installation#

bash
npm install @rcompat/stream
bash
pnpm add @rcompat/stream
bash
yarn add @rcompat/stream
bash
bun add @rcompat/stream

Usage#

Convert stream to string#

js
import stream from "@rcompat/stream";

// From a ReadableStream
const readable = new ReadableStream({
  start(controller) {
    controller.enqueue(new TextEncoder().encode("Hello, "));
    controller.enqueue(new TextEncoder().encode("World!"));
    controller.close();
  }
});

const text = await stream.stringify(readable);
console.log(text); // "Hello, World!"

With fetch response#

js
import stream from "@rcompat/stream";

const response = await fetch("https://example.com/data.txt");
const text = await stream.stringify(response.body);
console.log(text);

With file streams#

js
import stream from "@rcompat/stream";
import fs from "@rcompat/fs";

const file = fs.ref("./data.txt");
const content = await stream.stringify(file.stream());
console.log(content);

API Reference#

stringify#

ts
import stream from "@rcompat/stream";

stream.stringify(readable: ReadableStream<Uint8Array>): Promise<string>;

Reads all chunks from a byte ReadableStream, decodes them as streaming UTF-8 text, and concatenates them into a single string. Multibyte characters remain intact when their bytes span chunks.

Parameter Type Description
readable ReadableStream<Uint8Array> The stream to read from

Returns: Promise<string> — The complete stream content as a string.

Throws: If the input is not a ReadableStream instance.

How It Works#

The stringify function:

  1. Gets a reader from the stream via getReader()
  2. Reads chunks until done is true
  3. Decodes each chunk with a per-call streaming UTF-8 decoder
  4. Flushes the decoder and releases the reader lock
js
// Simplified implementation
const decoder = new TextDecoder();

async function stringify(stream) {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  let output = "";

  try {
    for (;;) {
      const { done, value } = await reader.read();
      if (done) return output + decoder.decode();

      output += decoder.decode(value, { stream: true });
    }
  } finally {
    reader.releaseLock();
  }
}

Examples#

Process streaming API response#

js
import stream from "@rcompat/stream";

async function fetchJSON(url) {
  const response = await fetch(url);
  const text = await stream.stringify(response.body);
  return JSON.parse(text);
}

const data = await fetchJSON("https://api.example.com/users");

Read subprocess output#

js
import stream from "@rcompat/stream";
import io from "@rcompat/io";

const { stdout } = io.spawn("ls", ["-la"], { cwd: "." });
const output = await stream.stringify(stdout);
console.log(output);

Collect streaming chunks#

js
import stream from "@rcompat/stream";

async function collectSSE(url) {
  const response = await fetch(url);
  // note: For actual SSE, you'd process chunks individually
  // this example just collects everything
  return await stream.stringify(response.body);
}

Transform and stringify#

js
import stream from "@rcompat/stream";

const source = new ReadableStream({
  start(controller) {
    controller.enqueue(new TextEncoder().encode("line1\n"));
    controller.enqueue(new TextEncoder().encode("line2\n"));
    controller.close();
  }
});

// transform stream (uppercase)
const transformed = source.pipeThrough(new TransformStream({
  transform(chunk, controller) {
    const text = new TextDecoder().decode(chunk);
    controller.enqueue(new TextEncoder().encode(text.toUpperCase()));
  }
}));

const result = await stream.stringify(transformed);
console.log(result); // "LINE1\nLINE2\n"

Cross-Runtime Compatibility#

Runtime Supported
Node.js ✓
Deno ✓
Bun ✓

No configuration required — just import and use.

License#

MIT

Contributing#

See CONTRIBUTING.md in the repository root.