into-stream
into-stream converts an already available value or producer into a Node.js Readable stream. Version 9 accepts strings, Uint8Arrays, typed arrays, ArrayBuffers, sync or async iterables, web ReadableStreams, and promises of those inputs; intoStream.object handles objects and object iterables. It uses Readable.from under the hood and respects consumer backpressure. It does not stream a file path, fetch a URL, serialize objects, buffer a source more efficiently, or make a fully materialized value use less memory.
A clean convenience adapter when a Node API insists on Readable and the source may arrive in several value forms. Skip it for file streaming, browser output, CommonJS, or simple iterable conversion where built-in Readable.from is already clear enough.
Use it if
- A Node API requires a Readable but your data currently exists as a string, byte array, promise, or iterable
- You want one typed adapter for sync iterables, async generators, and web ReadableStreams
- You need object-mode conversion through a clearly named intoStream.object entry
- You are writing ESM for Node 20 or newer and prefer a tested zero-dependency convenience wrapper
- You already have a file or other native stream source: the README says to use fs.createReadStream for child-process stdio, and it avoids materializing the file first
- You run CommonJS or Node below 20: version 9.1.0 is ESM-only and declares Node 20 or newer
- You need a browser-native stream as output: the function returns node:stream Readable even when the input is a WHATWG ReadableStream
- You expect objects to become JSON or text automatically: the byte-mode API rejects invalid object chunks, while object mode emits the original objects unchanged
- You only convert an iterable on modern Node and do not need the convenience types: Readable.from is built in and is the implementation this package wraps
Setup reality
npm install into-stream brings no runtime dependencies, peer packages, native compilation, credentials, or config. The constraints are runtime and stream mode. Version 9.1.0 requires Node 20 and exposes only an ESM default export, so use import intoStream from 'into-stream'; a CommonJS require is not supported. The returned object is a Node Readable, not a WHATWG ReadableStream, although a web stream can be accepted as input on modern runtimes through async iteration. Byte mode accepts strings and binary views. Arrays and iterables are emitted element by element, so every element must be a valid string or byte-like chunk; numbers are converted to one-byte Uint8Arrays by the implementation, but that behavior is broader than the published Input type and should not be a typed contract. Use intoStream.object for plain objects, arrays of records, or object-generating iterables. A single object in byte mode is not serialized for you. Promise inputs defer their value until consumption, and rejection or generator failure surfaces as a stream error, so use pipeline from node:stream/promises or install an error listener instead of piping blindly. Backpressure controls how quickly iterators are pulled, but passing a prebuilt string, Buffer, array, or ArrayBuffer means that memory is already allocated. Finally, the README explicitly warns that these generated streams cannot be used as child_process stdio entries; use a real file stream, pipe through stdin after spawn, or choose another supported stdio source.
Patterns
Convert a string to a Readablestream-string
import intoStream from 'into-stream';
const readable = intoStream('hello world');
readable.pipe(process.stdout);The entire string already exists in memory; conversion changes the interface, not the allocation cost.
Convert bytes to a Readablestream-buffer
const bytes = Buffer.from('binary payload');
const readable = intoStream(bytes);Buffer is a Uint8Array subclass and is accepted directly. It is not copied merely to become a stream source.
Stream an ArrayBufferstream-array-buffer
const arrayBuffer = await response.arrayBuffer();
const readable = intoStream(arrayBuffer);The implementation converts the view to Uint8Array, but response.arrayBuffer already buffered the full response. Prefer streaming response.body when size matters.
Emit an array as separate chunksstream-chunk-array
const readable = intoStream([
'first line\n',
'second line\n',
Buffer.from('third line\n'),
]);Each array element becomes a chunk. Elements must be valid string or byte-like chunks in normal stream mode.
Adapt a synchronous generatorstream-generator
function* rows() {
yield 'id,name\n';
yield '1,Ada\n';
yield '2,Grace\n';
}
const readable = intoStream(rows());Backpressure determines when the iterator advances, so this can avoid building one large combined string.
Adapt an async generatorstream-async-generator
async function* pages() {
for (let page = 1; page <= 3; page++) {
const response = await fetch(`https://api.example.com/items?page=${page}`);
yield JSON.stringify(await response.json()) + '\n';
}
}
const readable = intoStream(pages());Generator errors become stream errors. Consume through pipeline or otherwise handle the Readable's error event.
Convert a promised inputstream-promise
const promisedText = fetchMessage().then((message) => `${message}\n`);
const readable = intoStream(promisedText);The promise is awaited by the stream's reader. A rejection is asynchronous and surfaces through stream error handling.
Create an object-mode streamstream-objects
const records = intoStream.object([
{ id: 1, name: 'Ada' },
{ id: 2, name: 'Grace' },
]);
for await (const record of records) {
console.log(record.id);
}Object mode emits each object unchanged. It does not serialize records to JSON.
Emit one object in object modestream-single-object
const readable = intoStream.object({
type: 'ready',
timestamp: Date.now(),
});Use intoStream.object for a plain object. Passing it to the default byte-mode call produces an invalid non-byte stream chunk.
Consume safely with pipelinepipe-with-errors
import { createGzip } from 'node:zlib';
import { createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream/promises';
await pipeline(
intoStream(generateReport()),
createGzip(),
createWriteStream('report.txt.gz'),
);Promise-based pipeline propagates source, transform, and destination failures and closes the chain more safely than bare pipe calls.
Convert a fetch body to a Node Readableadapt-web-stream
const response = await fetch('https://example.com/archive');
if (!response.ok || !response.body) throw new Error(`HTTP ${response.status}`);
const nodeReadable = intoStream(response.body);The input is a web ReadableStream, but the output is a Node Readable. Node 20's Readable.fromWeb is a direct built-in alternative.
Use Readable.from when the input is already iterableuse-built-in-alternative
import { Readable } from 'node:stream';
const readable = Readable.from(asyncGenerator());into-stream itself delegates to Readable.from. The built-in is often clearer when you do not need its input normalization or object helper.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| to-readable-stream | npm | You only need a simpler string or Buffer to Readable conversion |
| from2 | npm | You maintain older CommonJS stream code and want explicit pull-based readable construction |
| readable-stream | npm | You need the userland Node streams implementation for compatibility across runtimes |
| streamifier | npm | A legacy CommonJS project needs a minimal Buffer or string conversion helper |