README
Brooklet
Streams for functional programming in Node.js
About
Inspired by Highland.js by Caolan, the goal of this project is to provide a minimalistic, (almost) dependency-free library for stream-based functional programming in Node.js.
Status
Under development, unstable. Mainly a way to learn a bit more about streams and functional programming. Serves as the basis for a stream-based attempt at a functional web framework.
Documentation
Install with:
$ npm install --save brooklet
Use with:
var brooklet = require('brooklet');
Brooklet builds upon node.js' native streams (tracked through the readable-stream
module) and extends them with a number of useful methods (see API).
- brooklet.extend(obj) - this function extends the
obj
argument with all the methods provided by brooklet. It can be used both on instances and prototypes. - brooklet.Transform() - this class extends the native
stream.Transform
class with all the methods provided bybrooklet.extend()
. - brooklet.Duplexer() - this class wraps a readable and a writable stream into a duplex stream. It extends the native
stream.Duplex
class with all the methods provided bybrooklet.extend()
.
Methods from brooklet.extend()
can also be called on a pre-existing stream through extend.fn.apply(stream, args)
or extend.fn.call(stream, arg1, arg2)
.
brooklet.extend.consume.call(stream, opts, function(chunk, next) {});
The readable-stream
module is always made available brooklet.stream
. Replacing the native stream
module with brooklet.stream
might be a good idea if you stumble into compatibility errors (but it might also make things even worse).
API
brooklet.Transform()
Constructor for the Transform
class.
var transform = brooklet.Transform({
objectMode: true,
transform: function timesTwo(chunk, enc, cb) {
this.push(chunk * 2);
cb();
}
});
brooklet.Duplexer()
Constructor for the Duplexer
class. A Duplexer
instance reads from its reader
stream and writes to its writer
stream.
var readable = brooklet.Transform();
var writable = brooklet.Transform();
var duplexer = brooklet.Duplexer({
reader: readable,
writer: writable
});
duplexer.reader === reader; // true
duplexer.writer === writer; // true
brooklet.extend.consume()
stream.consume()
allows for controlled asynchronous consumption of chunks.
stream.consume(function(chunk, cb) {
if (chunk === null) {
return; // stream has ended
}
somethingAsync(chunk, function() {
cb();
});
});
After all chunks have been read and the stream has ended, the consume()
callback is called with a null
chunk.
brooklet.extend.send()
Wrapper around writable.write()
, allows for both single chunks and array of chunks to be written to the stream. Supports chaining.
stream.send(['foo', 'bar'], 'utf8', stream.end.bind(stream));
brooklet.extend.decode()
Wrapper around readable.setEncoding()
, throws if the encoding is not supported. Supports chaining.
stream.decode('utf8').on('data', function() {});
brooklet.extend.into()
A readable.pipe()
wrapper that pipes the stream it is called upon - the source - into each stream in the provided array - the targets. Supports chaining and pipe options.
source.into([target1, target2], opts);
brooklet.extend.from()
A readable.pipe()
wrapper that pipes each stream in the provided array - the sources - into the stream it is called upon - the target. Supports chaining and pipe options. The end
option can be set to last
, which ends the target stream after all source streams have ended.
target.from([source1, source2], opts);
brooklet.extend.compact()
Waits for the end of the stream and returns an array of all chunks. Supports chaining.
stream.compact(function(err, chunks) {});
brooklet.extend.through()
Returns either the stream is it called upon or, if present, the object returned by the callback. Supports chaining.
stream.through(function(cb) { return {answer: 42}; }}).answer === 42; // true
brooklet.extend.extend()
Returns a new duplex stream that reads from the stream this method is called upon and writes into the stream that is returned by the callback. Support chaining.
// Documentation TBD
brooklet.extend.encode()
A .setDefaultEncoding()
wrapper that supports chaining and throws if provided an unsupported encoding.
brooklet.extend.decode()
A .setEncoding()
wrapper that supports chaining and throws if provided an unsupported encoding.
brooklet.extend.process()
Like .send()
but ends the stream automatically once all chunks have been written.
brooklet.extend.capture()
Captures an event out of an EventEmitter instance and writes a new chunk to the stream it is called upon each time the event is fired.
Assume an instance of events.EventEmitter
var ee;
ee.on('event', function(arg1, arg2) {});
If args
is an array of strings, these strings will be positionally paired with the event's arguments as (key, value) tuples in each chunk:
stream
.capture(ee, 'event', ['key1', 'key2'])
.on('data', function(chunk) {
chunk.key1 === arg1;
chunk.key2 === arg2;
});
Otherwise, chunk will be arrays of event args:
stream
.capture(ee, 'event')
.on('data', function(chunk) {
chunk[1] === arg1;
chunk[2] === arg2;
});
Testing
$ git clone git@github.com:jacoscaz/node-brooklet.git
$ cd node-brooklet
$ npm install
$ npm test
Browser build
$ git clone git@github.com:jacoscaz/node-brooklet.git
$ cd node-brooklet
$ npm install
$ npm run browserify
License
Released under the included MIT license. See LICENSE.
Jacopo Scazzosi (c) 2015 - 2016.