pirandello

Pirandello

A better Stream abstraction for node.js. npm install pirandello

Use

There's a bunch of ways to create a Stream.

Creates a stream that sends a single value and ends.

Stream.of("hello world")
//> hello world 

Just ends immediately.

Sends each item in the array, then ends.

Stream.fromArray(["hello ","world"])
//> hello world 

Takes a node Readable stream and sends it one data chunk at a time.

Stream.fromReadable(fs.createReadStream('data.txt'))

To construct your own Streams, call the constructor (new is optional) with a function that takes two arguments. Each argument is a function: call the first one with an object to send it over the stream, call the second one to end the stream. From the implementation of fromArray:

Stream.fromArray = function(arr) {
    return Stream(function(next,end) {
        arr.forEach(next)
        end()
    })
}

Pirandello Streams are immutable; the methods below return a new stream. Streams are a fantasy-land MonadPlus.

Returns a new stream that sends the contents of the current stream followed by the contents of the other stream.

Stream.of("hello ").concat(Stream.of("world"))
//> hello world 

Takes a function that operates on each chunk and should return a new Stream. Useful for concatenating lists.

function read(f) {
    return Stream.fromReadable(fs.createReadStream(f));
}
 
Stream.fromArray(process.argv).chain(read).pipe(process.stdout)

Maps over the chunk.

Stream.fromArray(["hello ","world"]).map(function(s) {return s.toUpperCase()})
//> HELLO WORLD

Applies a stream of functions to a stream of inputs, returns a stream of outputs.

Stream.fromArray([
    function(s) { return s.toUpperCase(); },
    function(s) { return s.toLowerCase(); },
    function(s) { return s.substr(0,5); }
]).ap(Stream.of("Hello World "))
//> HELLO WORLD hello world Hello 

Converts a Stream of strings into a Stream of individual characters.

Given a number, returns a stream of the first n chunks. Useful with toCharstream.

Stream.of("hello world").toCharstream().take(5)
//> hello 

Given a number, returns a stream without the first n chunks. Useful with toCharstream.

Stream.of("hello world").toCharstream().drop(6)
//> world 

Mostly compatible with Readable::pipe, sends every chunk to the destination Writable.

When you really need low-level chunk functionality (maybe you're extending Pirandello? Good for you!), generator is what you want. It is, in fact, the function passed in when the Stream is instantiated; call it with two arguments, one function to deal with each chunk, and one which is called at the end. FUrom the implementation of pipe:

Stream.prototype.pipe = function(dest) {
    this.generator(
        function(chunk) { dest.write(chunk) }
        function() { dest.end() }
    )
}

Why?

I tried to make Readables look nice, I really did. The API is ugly, and the abstraction is leaky. Here's to a fresh start.

Licence

MIT