pax_global_header00006660000000000000000000000064126405312350014513gustar00rootroot0000000000000052 comment=f1f047c1957c75d39da6d4c21bb1d5196427d6c6 node-lazystream-1.0.0/000077500000000000000000000000001264053123500146275ustar00rootroot00000000000000node-lazystream-1.0.0/.gitignore000066400000000000000000000000601264053123500166130ustar00rootroot00000000000000.DS_Store npm-debug.log node_modules/ test/tmp/ node-lazystream-1.0.0/.travis.yml000066400000000000000000000001451264053123500167400ustar00rootroot00000000000000sudo: false language: node_js node_js: - "5.2" - "4.2" - "0.12" - "0.10" # - "0.8" # - "0.6" node-lazystream-1.0.0/LICENSE-MIT000066400000000000000000000020621264053123500162630ustar00rootroot00000000000000Copyright (c) 2013 J. Pommerening, contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-lazystream-1.0.0/README.md000066400000000000000000000101511264053123500161040ustar00rootroot00000000000000# Lazy Streams > *Create streams lazily when they are read from or written to.* > `lazystream: 1.0.0` [![Build Status](https://travis-ci.org/jpommerening/node-lazystream.png?branch=master)](https://travis-ci.org/jpommerening/node-lazystream) ## Why? Sometimes you feel the itch to open *all the files* at once. You want to pass a bunch of streams around, so the consumer does not need to worry where the data comes from. From a software design point-of-view this sounds entirely reasonable. Then there is that neat little function `fs.createReadStream()` that opens a file and gives you a nice `fs.ReadStream` to pass around, so you use what the mighty creator deities of node bestowed upon you. > `Error: EMFILE, too many open files` > ─ *node* This package provides two classes based on the node's Streams3 API (courtesy of `readable-stream` to ensure a stable version). ## Class: lazystream.Readable A wrapper for readable streams. Extends [`stream.PassThrough`](http://nodejs.org/api/stream.html#stream_class_stream_passthrough). ### new lazystream.Readable(fn [, options]) * `fn` *{Function}* The function that the lazy stream will call to obtain the stream to actually read from. * `options` *{Object}* Options for the underlying `PassThrough` stream, accessible by `fn`. Creates a new readable stream. Once the stream is accessed (for example when you call its `read()` method, or attach a `data`-event listener) the `fn` function is called with the outer `lazystream.Readable` instance bound to `this`. If you pass an `options` object to the constuctor, you can access it in your `fn` function. ```javascript new lazystream.Readable(function (options) { return fs.createReadStream('/dev/urandom'); }); ``` ## Class: lazystream.Writable A wrapper for writable streams. Extends [`stream.PassThrough`](http://nodejs.org/api/stream.html#stream_class_stream_passthrough). ### new lazystream.Writable(fn [, options]) * `fn` *{Function}* The function that the lazy stream will call to obtain the stream to actually write to. * `options` *{Object}* Options for the underlying `PassThrough` stream, accessible by `fn`. Creates a new writable stream. Just like the one above but for writable streams. ```javascript new lazystream.Writable(function () { return fs.createWriteStream('/dev/null'); }); ``` ## Install ```console $ npm install lazystream --save lazystream@1.0.0 node_modules/lazystream └── readable-stream@2.0.5 ``` ## Changelog ### v1.0.0 - [#2](https://github.com/jpommerening/node-lazystream/pull/2): [unconditionally](https://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html) use `readable-stream` _2.x_. ### v0.2.0 - [#1](https://github.com/jpommerening/node-lazystream/pull/1): error events are now propagated ### v0.1.0 - _(this was the first release)_ ## Contributing Fork it, branch it, send me a pull request. We'll work out the rest together. ## Credits [Chris Talkington](https://github.com/ctalkington) and his [node-archiver](https://github.com/ctalkington/node-archiver) for providing a use-case. ## [License](LICENSE-MIT) Copyright (c) 2013 J. Pommerening, contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-lazystream-1.0.0/lib/000077500000000000000000000000001264053123500153755ustar00rootroot00000000000000node-lazystream-1.0.0/lib/lazystream.js000066400000000000000000000024471264053123500201350ustar00rootroot00000000000000var util = require('util'); var PassThrough = require('readable-stream/passthrough'); module.exports = { Readable: Readable, Writable: Writable }; util.inherits(Readable, PassThrough); util.inherits(Writable, PassThrough); // Patch the given method of instance so that the callback // is executed once, before the actual method is called the // first time. function beforeFirstCall(instance, method, callback) { instance[method] = function() { delete instance[method]; callback.apply(this, arguments); return this[method].apply(this, arguments); }; } function Readable(fn, options) { if (!(this instanceof Readable)) return new Readable(fn, options); PassThrough.call(this, options); beforeFirstCall(this, '_read', function() { var source = fn.call(this, options); var emit = this.emit.bind(this, 'error'); source.on('error', emit); source.pipe(this); }); this.emit('readable'); } function Writable(fn, options) { if (!(this instanceof Writable)) return new Writable(fn, options); PassThrough.call(this, options); beforeFirstCall(this, '_write', function() { var destination = fn.call(this, options); var emit = this.emit.bind(this, 'error'); destination.on('error', emit); this.pipe(destination); }); this.emit('writable'); } node-lazystream-1.0.0/package.json000066400000000000000000000017101264053123500171140ustar00rootroot00000000000000{ "name": "lazystream", "version": "1.0.0", "description": "Open Node Streams on demand.", "homepage": "https://github.com/jpommerening/node-lazystream", "author": { "name": "Jonas Pommerening", "email": "jonas.pommerening@gmail.com", "url": "https://npmjs.org/~jpommerening" }, "contributors": [ "Mario Casciaro " ], "repository": { "type": "git", "url": "https://github.com/jpommerening/node-lazystream.git" }, "bugs": { "url": "https://github.com/jpommerening/node-lazystream/issues" }, "license": "MIT", "main": "lib/lazystream.js", "engines": { "node": ">= 0.6.3" }, "scripts": { "test": "nodeunit test/readable_test.js test/writable_test.js test/pipe_test.js test/fs_test.js" }, "dependencies": { "readable-stream": "^2.0.5" }, "devDependencies": { "nodeunit": "^0.9.1" }, "keywords": [ "emfile", "lazy", "streams", "stream" ] } node-lazystream-1.0.0/test/000077500000000000000000000000001264053123500156065ustar00rootroot00000000000000node-lazystream-1.0.0/test/data.md000066400000000000000000000010731264053123500170420ustar00rootroot00000000000000> Never mind, hey, this is really exciting, so much to find out about, so much to > look forward to, I'm quite dizzy with anticipation . . . Or is it the wind? > > There really is a lot of that now, isn't there? And wow! Hey! What's this thing > suddenly coming toward me very fast? Very, very fast. So big and flat and round, > it needs a big wide-sounding name like . . . ow . . . ound . . . round . . . > ground! That's it! That's a good name- ground! > > I wonder if it will be friends with me? > > Hello Ground! And the rest, after a sudden wet thud, was silence. node-lazystream-1.0.0/test/fs_test.js000066400000000000000000000030731264053123500176160ustar00rootroot00000000000000 var stream = require('../lib/lazystream'); var fs = require('fs'); var tmpDir = 'test/tmp/'; var readFile = 'test/data.md'; var writeFile = tmpDir + 'data.md'; exports.fs = { readwrite: function(test) { var readfd, writefd; var readable = new stream.Readable(function() { return fs.createReadStream(readFile) .on('open', function(fd) { readfd = fd; }) .on('close', function() { readfd = undefined; step(); }); }); var writable = new stream.Writable(function() { return fs.createWriteStream(writeFile) .on('open', function(fd) { writefd = fd; }) .on('close', function() { writefd = undefined; step(); }); }); test.expect(3); test.equal(readfd, undefined, 'Input file should not be opened until read'); test.equal(writefd, undefined, 'Output file should not be opened until write'); if (!fs.existsSync(tmpDir)) { fs.mkdirSync(tmpDir); } if (fs.existsSync(writeFile)) { fs.unlinkSync(writeFile); } readable.on('end', function() { step(); }); writable.on('end', function() { step(); }); var steps = 0; function step() { steps += 1; if (steps == 4) { var input = fs.readFileSync(readFile); var output = fs.readFileSync(writeFile); test.ok(input >= output && input <= output, 'Should be equal'); fs.unlinkSync(writeFile); fs.rmdirSync(tmpDir); test.done(); } }; readable.pipe(writable); } }; node-lazystream-1.0.0/test/helper.js000066400000000000000000000015211264053123500174220ustar00rootroot00000000000000 var _Readable = require('readable-stream/readable'); var _Writable = require('readable-stream/writable'); var util = require('util'); module.exports = { DummyReadable: DummyReadable, DummyWritable: DummyWritable }; function DummyReadable(strings) { _Readable.call(this); this.strings = strings; this.emit('readable'); } util.inherits(DummyReadable, _Readable); DummyReadable.prototype._read = function _read(n) { if (this.strings.length) { this.push(new Buffer(this.strings.shift())); } else { this.push(null); } }; function DummyWritable(strings) { _Writable.call(this); this.strings = strings; this.emit('writable'); } util.inherits(DummyWritable, _Writable); DummyWritable.prototype._write = function _write(chunk, encoding, callback) { this.strings.push(chunk.toString()); if (callback) callback(); }; node-lazystream-1.0.0/test/pipe_test.js000066400000000000000000000017721264053123500201470ustar00rootroot00000000000000 var stream = require('../lib/lazystream'); var helper = require('./helper'); exports.pipe = { readwrite: function(test) { var expected = [ 'line1\n', 'line2\n' ]; var actual = []; var readableInstantiated = false; var writableInstantiated = false; test.expect(3); var readable = new stream.Readable(function() { readableInstantiated = true; return new helper.DummyReadable([].concat(expected)); }); var writable = new stream.Writable(function() { writableInstantiated = true; return new helper.DummyWritable(actual); }); test.equal(readableInstantiated, false, 'DummyReadable should only be instantiated when it is needed'); test.equal(writableInstantiated, false, 'DummyWritable should only be instantiated when it is needed'); writable.on('end', function() { test.equal(actual.join(''), expected.join(''), 'Piping on demand streams should keep data intact'); test.done(); }); readable.pipe(writable); } }; node-lazystream-1.0.0/test/readable_test.js000066400000000000000000000046421264053123500207500ustar00rootroot00000000000000 var Readable = require('../lib/lazystream').Readable; var DummyReadable = require('./helper').DummyReadable; exports.readable = { dummy: function(test) { var expected = [ 'line1\n', 'line2\n' ]; var actual = []; test.expect(1); new DummyReadable([].concat(expected)) .on('data', function(chunk) { actual.push(chunk.toString()); }) .on('end', function() { test.equal(actual.join(''), expected.join(''), 'DummyReadable should produce the data it was created with'); test.done(); }); }, options: function(test) { test.expect(3); var readable = new Readable(function(options) { test.ok(this instanceof Readable, "Readable should bind itself to callback's this"); test.equal(options.encoding, "utf-8", "Readable should make options accessible to callback"); this.ok = true; return new DummyReadable(["test"]); }, {encoding: "utf-8"}); readable.read(4); test.ok(readable.ok); test.done(); }, streams2: function(test) { var expected = [ 'line1\n', 'line2\n' ]; var actual = []; var instantiated = false; test.expect(2); var readable = new Readable(function() { instantiated = true; return new DummyReadable([].concat(expected)); }); test.equal(instantiated, false, 'DummyReadable should only be instantiated when it is needed'); readable.on('readable', function() { var chunk; while ((chunk = readable.read())) { actual.push(chunk.toString()); } }); readable.on('end', function() { test.equal(actual.join(''), expected.join(''), 'Readable should not change the data of the underlying stream'); test.done(); }); readable.read(0); }, resume: function(test) { var expected = [ 'line1\n', 'line2\n' ]; var actual = []; var instantiated = false; test.expect(2); var readable = new Readable(function() { instantiated = true; return new DummyReadable([].concat(expected)); }); readable.pause(); readable.on('data', function(chunk) { actual.push(chunk.toString()); }); readable.on('end', function() { test.equal(actual.join(''), expected.join(''), 'Readable should not change the data of the underlying stream'); test.done(); }); test.equal(instantiated, false, 'DummyReadable should only be instantiated when it is needed'); readable.resume(); } }; node-lazystream-1.0.0/test/writable_test.js000066400000000000000000000027651264053123500210260ustar00rootroot00000000000000 var Writable = require('../lib/lazystream').Writable; var DummyWritable = require('./helper').DummyWritable; exports.writable = { options: function(test) { test.expect(3); var writable = new Writable(function(options) { test.ok(this instanceof Writable, "Writable should bind itself to callback's this"); test.equal(options.encoding, "utf-8", "Writable should make options accessible to callback"); this.ok = true; return new DummyWritable([]); }, {encoding: "utf-8"}); writable.write("test"); test.ok(writable.ok); test.done(); }, dummy: function(test) { var expected = [ 'line1\n', 'line2\n' ]; var actual = []; test.expect(0); var dummy = new DummyWritable(actual); expected.forEach(function(item) { dummy.write(new Buffer(item)); }); test.done(); }, streams2: function(test) { var expected = [ 'line1\n', 'line2\n' ]; var actual = []; var instantiated = false; test.expect(2); var writable = new Writable(function() { instantiated = true; return new DummyWritable(actual); }); test.equal(instantiated, false, 'DummyWritable should only be instantiated when it is needed'); writable.on('end', function() { test.equal(actual.join(''), expected.join(''), 'Writable should not change the data of the underlying stream'); test.done(); }); expected.forEach(function(item) { writable.write(new Buffer(item)); }); writable.end(); } };