Web Stream Tools
This library contains both basic convenience functions such as readToEnd
, concat
, slice
, clone
, webToNode
and nodeToWeb
, and more complex functions for transforming and parsing streams. Examples of the latter can be found below.
Table of Contents
Usage
npm install --save web-stream-tools
import stream from 'web-stream-tools';
Documentation
See the documentation for a full list of functions.
Examples
Transforming a stream
In this example we're encrypting a stream using an imaginary API which has process
and finish
methods.
const encryptor = new Encryptor();
const encrypted = stream.transform(input, function process(chunk) {
return encryptor.process(chunk);
}, function finish() {
return encryptor.finish();
});
Both the process
and finish
functions:
- are optional (by default no data is written to the transformed stream)
- may be asynchronous
- may throw (in which case the error is forwarded to the transformed stream)
input
can be a stream containing anything, or it can be a plain value (Uint8Array or String) in which case transform()
will simply return process(input)
and finish()
concatenated together.
Transforming a stream in chunks of 1024 bytes
In this example we're encrypting a stream using an imaginary API which has a process
method that requires us to pass in chunks of size 1024 (unless it's the last chunk).
const encrypted = stream.transformPair(input, async (readable, writable) => {
const reader = stream.getReader(readable);
const writer = stream.getWriter(writable);
try {
while (true) {
await writer.ready;
const chunk = await reader.readBytes(1024);
if (chunk === undefined) {
await writer.close();
break;
}
await writer.write(encryptor.process(chunk));
}
} catch(e) {
await writer.abort(e);
}
});
The above example may seem more complicated than necessary, but it correctly handles:
- Backpressure (if
encrypted
gets read slowly, input
gets read slowly as well) - Cancellation (if
encrypted
gets canceled, input
gets cancelled as well) - Erroring (if
input
errors, encrypted
gets errored as well)
Unlike transform
, transformPair
will always return a stream, even if input
is not.
Parsing data on a stream which is expected to be in a specific format
There are also helper functions for reading a specific number of bytes, or a single line, etc:
stream.parse(input, reader => {
const byte = await reader.readByte();
const bytes = await reader.readBytes(n);
const line = await reader.readLine();
const stream = reader.remainder();
});
Most of the functions above are also available when getting a reader using stream.getReader()
instead of stream.parse()
.
All of the functions above also work when reading a stream containing Strings instead of a Uint8Arrays, and will return Strings in that case.
Cloning and slicing streams
There are also a few functions not for reading the stream, but for manipulating the stream for another function to read:
stream.slice(input, begin, end);
stream.clone(input);
stream.passiveClone(input);
Note: these three functions do not work well with Node streams. Please convert Node streams to Web streams with stream.nodeToWeb
first before using them.