Import Upstream version 0.1.4
This commit is contained in:
commit
23535d1dd8
|
@ -0,0 +1 @@
|
|||
/node_modules
|
|
@ -0,0 +1,5 @@
|
|||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- "4"
|
||||
- "5"
|
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2013, Deoxxa Development
|
||||
======================================
|
||||
All rights reserved.
|
||||
--------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Deoxxa Development nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DEOXXA DEVELOPMENT ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL DEOXXA DEVELOPMENT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,115 @@
|
|||
# duplexer3 [![Build Status](https://travis-ci.org/floatdrop/duplexer3.svg?branch=master)](https://travis-ci.org/floatdrop/duplexer3) [![Coverage Status](https://coveralls.io/repos/floatdrop/duplexer3/badge.svg?branch=master&service=github)](https://coveralls.io/github/floatdrop/duplexer3?branch=master)
|
||||
|
||||
Like [duplexer2](https://github.com/deoxxa/duplexer2) but using Streams3 without readable-stream dependency
|
||||
|
||||
```javascript
|
||||
var stream = require("stream");
|
||||
|
||||
var duplexer3 = require("duplexer3");
|
||||
|
||||
var writable = new stream.Writable({objectMode: true}),
|
||||
readable = new stream.Readable({objectMode: true});
|
||||
|
||||
writable._write = function _write(input, encoding, done) {
|
||||
if (readable.push(input)) {
|
||||
return done();
|
||||
} else {
|
||||
readable.once("drain", done);
|
||||
}
|
||||
};
|
||||
|
||||
readable._read = function _read(n) {
|
||||
// no-op
|
||||
};
|
||||
|
||||
// simulate the readable thing closing after a bit
|
||||
writable.once("finish", function() {
|
||||
setTimeout(function() {
|
||||
readable.push(null);
|
||||
}, 500);
|
||||
});
|
||||
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
duplex.on("data", function(e) {
|
||||
console.log("got data", JSON.stringify(e));
|
||||
});
|
||||
|
||||
duplex.on("finish", function() {
|
||||
console.log("got finish event");
|
||||
});
|
||||
|
||||
duplex.on("end", function() {
|
||||
console.log("got end event");
|
||||
});
|
||||
|
||||
duplex.write("oh, hi there", function() {
|
||||
console.log("finished writing");
|
||||
});
|
||||
|
||||
duplex.end(function() {
|
||||
console.log("finished ending");
|
||||
});
|
||||
```
|
||||
|
||||
```
|
||||
got data "oh, hi there"
|
||||
finished writing
|
||||
got finish event
|
||||
finished ending
|
||||
got end event
|
||||
```
|
||||
|
||||
## Overview
|
||||
|
||||
This is a reimplementation of [duplexer](https://www.npmjs.com/package/duplexer) using the
|
||||
Streams3 API which is standard in Node as of v4. Everything largely
|
||||
works the same.
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
[Available via `npm`](https://docs.npmjs.com/cli/install):
|
||||
|
||||
```
|
||||
$ npm i duplexer3
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### duplexer3
|
||||
|
||||
Creates a new `DuplexWrapper` object, which is the actual class that implements
|
||||
most of the fun stuff. All that fun stuff is hidden. DON'T LOOK.
|
||||
|
||||
```javascript
|
||||
duplexer3([options], writable, readable)
|
||||
```
|
||||
|
||||
```javascript
|
||||
const duplex = duplexer3(new stream.Writable(), new stream.Readable());
|
||||
```
|
||||
|
||||
Arguments
|
||||
|
||||
* __options__ - an object specifying the regular `stream.Duplex` options, as
|
||||
well as the properties described below.
|
||||
* __writable__ - a writable stream
|
||||
* __readable__ - a readable stream
|
||||
|
||||
Options
|
||||
|
||||
* __bubbleErrors__ - a boolean value that specifies whether to bubble errors
|
||||
from the underlying readable/writable streams. Default is `true`.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
3-clause BSD. [A copy](./LICENSE) is included with the source.
|
||||
|
||||
## Contact
|
||||
|
||||
* GitHub ([deoxxa](http://github.com/deoxxa))
|
||||
* Twitter ([@deoxxa](http://twitter.com/deoxxa))
|
||||
* Email ([deoxxa@fknsrs.biz](mailto:deoxxa@fknsrs.biz))
|
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var stream = require("stream");
|
||||
|
||||
var duplexer3 = require("./");
|
||||
|
||||
var writable = new stream.Writable({objectMode: true}),
|
||||
readable = new stream.Readable({objectMode: true});
|
||||
|
||||
writable._write = function _write(input, encoding, done) {
|
||||
if (readable.push(input)) {
|
||||
return done();
|
||||
} else {
|
||||
readable.once("drain", done);
|
||||
}
|
||||
};
|
||||
|
||||
readable._read = function _read(n) {
|
||||
// no-op
|
||||
};
|
||||
|
||||
// simulate the readable thing closing after a bit
|
||||
writable.once("finish", function() {
|
||||
setTimeout(function() {
|
||||
readable.push(null);
|
||||
}, 500);
|
||||
});
|
||||
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
duplex.on("data", function(e) {
|
||||
console.log("got data", JSON.stringify(e));
|
||||
});
|
||||
|
||||
duplex.on("finish", function() {
|
||||
console.log("got finish event");
|
||||
});
|
||||
|
||||
duplex.on("end", function() {
|
||||
console.log("got end event");
|
||||
});
|
||||
|
||||
duplex.write("oh, hi there", function() {
|
||||
console.log("finished writing");
|
||||
});
|
||||
|
||||
duplex.end(function() {
|
||||
console.log("finished ending");
|
||||
});
|
|
@ -0,0 +1,76 @@
|
|||
"use strict";
|
||||
|
||||
var stream = require("stream");
|
||||
|
||||
function DuplexWrapper(options, writable, readable) {
|
||||
if (typeof readable === "undefined") {
|
||||
readable = writable;
|
||||
writable = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
stream.Duplex.call(this, options);
|
||||
|
||||
if (typeof readable.read !== "function") {
|
||||
readable = (new stream.Readable(options)).wrap(readable);
|
||||
}
|
||||
|
||||
this._writable = writable;
|
||||
this._readable = readable;
|
||||
this._waiting = false;
|
||||
|
||||
var self = this;
|
||||
|
||||
writable.once("finish", function() {
|
||||
self.end();
|
||||
});
|
||||
|
||||
this.once("finish", function() {
|
||||
writable.end();
|
||||
});
|
||||
|
||||
readable.on("readable", function() {
|
||||
if (self._waiting) {
|
||||
self._waiting = false;
|
||||
self._read();
|
||||
}
|
||||
});
|
||||
|
||||
readable.once("end", function() {
|
||||
self.push(null);
|
||||
});
|
||||
|
||||
if (!options || typeof options.bubbleErrors === "undefined" || options.bubbleErrors) {
|
||||
writable.on("error", function(err) {
|
||||
self.emit("error", err);
|
||||
});
|
||||
|
||||
readable.on("error", function(err) {
|
||||
self.emit("error", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DuplexWrapper.prototype = Object.create(stream.Duplex.prototype, {constructor: {value: DuplexWrapper}});
|
||||
|
||||
DuplexWrapper.prototype._write = function _write(input, encoding, done) {
|
||||
this._writable.write(input, encoding, done);
|
||||
};
|
||||
|
||||
DuplexWrapper.prototype._read = function _read() {
|
||||
var buf;
|
||||
var reads = 0;
|
||||
while ((buf = this._readable.read()) !== null) {
|
||||
this.push(buf);
|
||||
reads++;
|
||||
}
|
||||
if (reads === 0) {
|
||||
this._waiting = true;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function duplex2(options, writable, readable) {
|
||||
return new DuplexWrapper(options, writable, readable);
|
||||
};
|
||||
|
||||
module.exports.DuplexWrapper = DuplexWrapper;
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "duplexer3",
|
||||
"version": "0.1.4",
|
||||
"description": "Like duplexer but using streams3",
|
||||
"engine": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "mocha -R tap"
|
||||
},
|
||||
"repository": "floatdrop/duplexer3",
|
||||
"keywords": [
|
||||
"duplex",
|
||||
"duplexer",
|
||||
"stream",
|
||||
"stream3",
|
||||
"join",
|
||||
"combine"
|
||||
],
|
||||
"author": "Conrad Pankoff <deoxxa@fknsrs.biz> (http://www.fknsrs.biz/)",
|
||||
"license": "BSD-3-Clause",
|
||||
"devDependencies": {
|
||||
"mocha": "^2.2.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
"use strict";
|
||||
|
||||
var assert = require("assert");
|
||||
var stream = require("stream");
|
||||
|
||||
var duplexer3 = require("../");
|
||||
|
||||
describe("duplexer3", function() {
|
||||
var writable, readable;
|
||||
|
||||
beforeEach(function() {
|
||||
writable = new stream.Writable({objectMode: true});
|
||||
readable = new stream.Readable({objectMode: true});
|
||||
|
||||
writable._write = function _write(input, encoding, done) {
|
||||
return done();
|
||||
};
|
||||
|
||||
readable._read = function _read(n) {
|
||||
};
|
||||
});
|
||||
|
||||
it("should interact with the writable stream properly for writing", function(done) {
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
writable._write = function _write(input, encoding, _done) {
|
||||
assert.strictEqual(input.toString(), "well hello there");
|
||||
|
||||
return done();
|
||||
};
|
||||
|
||||
duplex.write("well hello there");
|
||||
});
|
||||
|
||||
it("should interact with the readable stream properly for reading", function(done) {
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
duplex.on("data", function(e) {
|
||||
assert.strictEqual(e.toString(), "well hello there");
|
||||
|
||||
return done();
|
||||
});
|
||||
|
||||
readable.push("well hello there");
|
||||
});
|
||||
|
||||
it("should end the writable stream, causing it to finish", function(done) {
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
writable.once("finish", done);
|
||||
|
||||
duplex.end();
|
||||
});
|
||||
|
||||
it("should finish when the writable stream finishes", function(done) {
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
duplex.once("finish", done);
|
||||
|
||||
writable.end();
|
||||
});
|
||||
|
||||
it("should end when the readable stream ends", function(done) {
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
// required to let "end" fire without reading
|
||||
duplex.resume();
|
||||
duplex.once("end", done);
|
||||
|
||||
readable.push(null);
|
||||
});
|
||||
|
||||
it("should bubble errors from the writable stream when no behaviour is specified", function(done) {
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
var originalErr = Error("testing");
|
||||
|
||||
duplex.on("error", function(err) {
|
||||
assert.strictEqual(err, originalErr);
|
||||
|
||||
return done();
|
||||
});
|
||||
|
||||
writable.emit("error", originalErr);
|
||||
});
|
||||
|
||||
it("should bubble errors from the readable stream when no behaviour is specified", function(done) {
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
var originalErr = Error("testing");
|
||||
|
||||
duplex.on("error", function(err) {
|
||||
assert.strictEqual(err, originalErr);
|
||||
|
||||
return done();
|
||||
});
|
||||
|
||||
readable.emit("error", originalErr);
|
||||
});
|
||||
|
||||
it("should bubble errors from the writable stream when bubbleErrors is true", function(done) {
|
||||
var duplex = duplexer3({bubbleErrors: true}, writable, readable);
|
||||
|
||||
var originalErr = Error("testing");
|
||||
|
||||
duplex.on("error", function(err) {
|
||||
assert.strictEqual(err, originalErr);
|
||||
|
||||
return done();
|
||||
});
|
||||
|
||||
writable.emit("error", originalErr);
|
||||
});
|
||||
|
||||
it("should bubble errors from the readable stream when bubbleErrors is true", function(done) {
|
||||
var duplex = duplexer3({bubbleErrors: true}, writable, readable);
|
||||
|
||||
var originalErr = Error("testing");
|
||||
|
||||
duplex.on("error", function(err) {
|
||||
assert.strictEqual(err, originalErr);
|
||||
|
||||
return done();
|
||||
});
|
||||
|
||||
readable.emit("error", originalErr);
|
||||
});
|
||||
|
||||
it("should not bubble errors from the writable stream when bubbleErrors is false", function(done) {
|
||||
var duplex = duplexer3({bubbleErrors: false}, writable, readable);
|
||||
|
||||
var timeout = setTimeout(done, 25);
|
||||
|
||||
duplex.on("error", function(err) {
|
||||
clearTimeout(timeout);
|
||||
|
||||
return done(Error("shouldn't bubble error"));
|
||||
});
|
||||
|
||||
// prevent uncaught error exception
|
||||
writable.on("error", function() {});
|
||||
|
||||
writable.emit("error", Error("testing"));
|
||||
});
|
||||
|
||||
it("should not bubble errors from the readable stream when bubbleErrors is false", function(done) {
|
||||
var duplex = duplexer3({bubbleErrors: false}, writable, readable);
|
||||
|
||||
var timeout = setTimeout(done, 25);
|
||||
|
||||
duplex.on("error", function(err) {
|
||||
clearTimeout(timeout);
|
||||
|
||||
return done(Error("shouldn't bubble error"));
|
||||
});
|
||||
|
||||
// prevent uncaught error exception
|
||||
readable.on("error", function() {});
|
||||
|
||||
readable.emit("error", Error("testing"));
|
||||
});
|
||||
|
||||
it("should export the DuplexWrapper constructor", function() {
|
||||
assert.equal(typeof duplexer3.DuplexWrapper, "function");
|
||||
});
|
||||
|
||||
it("should not force flowing-mode", function(done) {
|
||||
var writable = new stream.PassThrough();
|
||||
var readable = new stream.PassThrough();
|
||||
|
||||
assert.equal(readable._readableState.flowing, null);
|
||||
|
||||
var duplexStream = duplexer3(writable, readable);
|
||||
duplexStream.end("aaa");
|
||||
|
||||
assert.equal(readable._readableState.flowing, null);
|
||||
|
||||
var transformStream = new stream.Transform({
|
||||
transform: function(chunk, encoding, cb) {
|
||||
this.push(String(chunk).toUpperCase());
|
||||
cb();
|
||||
}
|
||||
});
|
||||
writable.pipe(transformStream).pipe(readable);
|
||||
|
||||
assert.equal(readable._readableState.flowing, null);
|
||||
|
||||
setTimeout(function() {
|
||||
assert.equal(readable._readableState.flowing, null);
|
||||
|
||||
var src = "";
|
||||
duplexStream.on("data", function(buf) {
|
||||
src += String(buf);
|
||||
});
|
||||
duplexStream.on("end", function() {
|
||||
assert.equal(src, "AAA");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
assert.equal(readable._readableState.flowing, null);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue