Current Dev State

This commit is contained in:
Tim Lorsbach
2025-06-23 20:13:54 +02:00
parent b4f9bb277d
commit ded50edaa2
22617 changed files with 4345095 additions and 174 deletions

View File

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2013 Nicolas Froidure, <http://insertafter.com/>
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.

View File

@ -0,0 +1,29 @@
# Plexer
> A stream duplexer embracing Streams 2.0 (for real).
[![NPM version](https://badge.fury.io/js/plexer.png)](https://npmjs.org/package/plexer) [![Build Status](https://travis-ci.org/nfroidure/plexer.png?branch=master)](https://travis-ci.org/nfroidure/plexer) [![Dependency Status](https://david-dm.org/nfroidure/plexer.png)](https://david-dm.org/nfroidure/plexer) [![devDependency Status](https://david-dm.org/nfroidure/plexer/dev-status.png)](https://david-dm.org/nfroidure/plexer#info=devDependencies) [![Coverage Status](https://coveralls.io/repos/nfroidure/plexer/badge.png?branch=master)](https://coveralls.io/r/nfroidure/plexer?branch=master)
## Usage
### plexer([options,] writable, readable)
#### options.reemitErrors
Type: `Boolean`
Default value: `true`
Tells the duplexer to reemit given streams errors.
#### writable
Type: `Stream`
Required. Any writable stream.
### readable
Type: `Stream`
Required. Any readable stream.
## Contributing
Feel free to pull your code if you agree with publishing it under the MIT license.

View File

@ -0,0 +1,74 @@
{
"_from": "plexer@0.0.1",
"_id": "plexer@0.0.1",
"_inBundle": false,
"_integrity": "sha1-aYLbjRzIPIivYIrNnOpdKSCPuZ8=",
"_location": "/gulp-spawn/plexer",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "plexer@0.0.1",
"name": "plexer",
"escapedName": "plexer",
"rawSpec": "0.0.1",
"saveSpec": null,
"fetchSpec": "0.0.1"
},
"_requiredBy": [
"/gulp-spawn"
],
"_resolved": "https://registry.npmjs.org/plexer/-/plexer-0.0.1.tgz",
"_shasum": "6982db8d1cc83c88af608acd9cea5d29208fb99f",
"_spec": "plexer@0.0.1",
"_where": "/home/manfred/enviPath/ketcher2/ketcher/node_modules/gulp-spawn",
"author": {
"name": "Nicolas Froidure",
"url": "http://www.insertafter.com/blog.html"
},
"bugs": {
"url": "https://github.com/nfroidure/plexer/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Streams2 duplexer.",
"devDependencies": {
"coveralls": "~2.8.x",
"event-stream": "~3.1.0",
"istanbul": "~0.2.4",
"mocha": "~1.17.1",
"mocha-lcov-reporter": "0.0.1"
},
"engines": {
"node": ">= 0.10.0"
},
"homepage": "https://github.com/nfroidure/plexer",
"keywords": [
"duplexer",
"streaming",
"stream2",
"stream",
"readable",
"writable",
"async",
"pipe"
],
"licenses": [
{
"type": "MIT",
"url": "https://github.com/nfroidure/plexer/blob/master/LICENSE"
}
],
"main": "src/index.js",
"name": "plexer",
"repository": {
"type": "git",
"url": "git://github.com/nfroidure/plexer.git"
},
"scripts": {
"cover": "./node_modules/istanbul/lib/cli.js cover --report html ./node_modules/mocha/bin/_mocha -- tests/*.mocha.js -R spec -t 5000",
"coveralls": "./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha --report lcovonly -- tests/*.mocha.js -R spec -t 5000 && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage",
"test": "node_modules/mocha/bin/mocha tests/*.mocha.js"
},
"version": "0.0.1"
}

View File

@ -0,0 +1,112 @@
var Stream = require('stream')
, util = require('util')
;
// Inherit of Readable stream
util.inherits(Duplexer, Stream.Duplex);
// Constructor
function Duplexer(options, writableStream, readableStream) {
var _self = this;
// Ensure new were used
if (!(this instanceof Duplexer)) {
return new (Duplexer.bind.apply(Duplexer,
[Duplexer].concat([].slice.call(arguments,0))));
}
// Mapping args
if(options instanceof Stream) {
readableStream = writableStream;
writableStream = options;
options = {};
} else {
options = options || {};
}
this._reemitErrors = 'boolean' === typeof options.reemitErrors
? options.reemitErrors : true;
delete options.reemitErrors;
// Checking arguments
if(!(writableStream instanceof Stream.Writable
|| writableStream instanceof Stream.Duplex)) {
throw new Error('The writable stream must be an instanceof Writable or Duplex.');
}
if(!(readableStream instanceof Stream.Readable)) {
throw new Error('The readable stream must be an instanceof Readable.');
}
// Parent constructor
Stream.Duplex.call(this, options);
// Save streams refs
this._writable = writableStream;
this._readable = readableStream;
// Internal state
this._waitDatas = false;
this._hasDatas = false;
if('undefined' == typeof this._readable._readableState) {
this._readable = (new Stream.Readable({
objectMode: options.objectMode || false
})).wrap(this._readable);
}
if(this._reemitErrors) {
this._writable.on('error', function(err) {
_self.emit('error', err);
});
this._readable.on('error', function(err) {
_self.emit('error', err);
});
}
this._writable.on("drain", function() {
_self.emit("drain");
});
this.once('finish', function() {
_self._writable.end();
});
this._writable.once('finish', function() {
_self.end();
});
this._readable.on('readable', function() {
_self._hasDatas = true;
if(_self._waitDatas) {
_self._pushAll();
}
});
this._readable.once('end', function() {
_self.push(null);
});
}
Duplexer.prototype._read = function(n) {
this._waitDatas = true;
if(this._hasDatas) {
this._pushAll();
}
};
Duplexer.prototype._pushAll = function() {
var _self = this, chunk;
do {
chunk = _self._readable.read();
if(null !== chunk) {
this._waitDatas = _self.push(chunk);
}
this._hasDatas = (null !== chunk);
} while(this._waitDatas && this._hasDatas);
};
Duplexer.prototype._write = function(chunk, encoding, callback) {
return this._writable.write(chunk, encoding, callback);
};
module.exports = Duplexer;

View File

@ -0,0 +1,733 @@
var assert = require('assert')
, es = require('event-stream')
, Duplexer = require('../src')
, Stream = require('stream')
;
// Tests
describe('Duplexer', function() {
describe('in binary mode', function() {
describe('and with async streams', function() {
it('should work with functionnal API', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = Duplexer({}, writable, readable)
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
done();
}));
setImmediate(function() {
// Writing content to duplex
duplex.write('oude');
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.write('beloola');
readable.end();
});
});
it('should work with POO API', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = new Duplexer(writable, readable)
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
done();
}));
setImmediate(function() {
// Writing content to duplex
duplex.write('oude');
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.write('beloola');
readable.end();
});
});
it('should reemit errors', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = new Duplexer(writable, readable)
, errorsCount = 0
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
assert.equal(errorsCount, 2);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
setImmediate(function() {
// Writing content to duplex
duplex.write('oude');
writable.emit('error', new Error('hip'));
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.emit('error', new Error('hip'));
readable.write('beloola');
readable.end();
});
});
it('should not reemit errors when option is set', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = new Duplexer({reemitErrors: false}, writable, readable)
, errorsCount = 0
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
assert.equal(errorsCount, 0);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
// Catch error events
readable.on('error', function(){})
writable.on('error', function(){})
setImmediate(function() {
// Writing content to duplex
duplex.write('oude');
writable.emit('error', new Error('hip'));
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.emit('error', new Error('hip'));
readable.write('beloola');
readable.end();
});
});
});
describe('and with sync streams', function() {
it('should work with functionnal API', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = Duplexer({}, writable, readable)
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
done();
}));
// Writing content to duplex
duplex.write('oude');
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.write('beloola');
readable.end();
});
it('should work with POO API', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = new Duplexer(writable, readable)
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
done();
}));
// Writing content to duplex
duplex.write('oude');
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.write('beloola');
readable.end();
});
it('should reemit errors', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = new Duplexer(null, writable, readable)
, errorsCount = 0
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
assert.equal(errorsCount, 2);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
// Writing content to duplex
duplex.write('oude');
writable.emit('error', new Error('hip'));
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.emit('error', new Error('hip'));
readable.write('beloola');
readable.end();
});
it('should not reemit errors when option is set', function(done) {
var readable = new Stream.PassThrough()
, writable = new Stream.PassThrough()
, duplex = new Duplexer({reemitErrors: false}, writable, readable)
, errorsCount = 0
;
// Checking writable content
writable.pipe(es.wait(function(err, data) {
assert.equal(data,'oudelali');
}));
// Checking duplex output
duplex.pipe(es.wait(function(err, data) {
assert.equal(data,'bibabeloola');
assert.equal(errorsCount, 0);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
// Catch error events
readable.on('error', function(){})
writable.on('error', function(){})
// Writing content to duplex
duplex.write('oude');
writable.emit('error', new Error('hip'));
duplex.write('lali');
duplex.end();
// Writing content to readable
readable.write('biba');
readable.emit('error', new Error('hip'));
readable.write('beloola');
readable.end();
});
});
});
describe('in object mode', function() {
describe('and with async streams', function() {
it('should work with functionnal API', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = Duplexer({objectMode: true}, writable, readable)
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
done();
}));
setImmediate(function() {
// Writing content to duplex
duplex.write({cnt: 'oude'});
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.write({cnt: 'beloola'});
readable.end();
});
});
it('should work with POO API', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = new Duplexer({objectMode: true}, writable, readable)
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
done();
}));
setImmediate(function() {
// Writing content to duplex
duplex.write({cnt: 'oude'});
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.write({cnt: 'beloola'});
readable.end();
});
});
it('should reemit errors', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = new Duplexer({objectMode: true}, writable, readable)
, errorsCount = 0
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
assert.equal(errorsCount, 2);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
setImmediate(function() {
// Writing content to duplex
duplex.write({cnt: 'oude'});
writable.emit('error', new Error('hip'));
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.emit('error', new Error('hip'));
readable.write({cnt: 'beloola'});
readable.end();
});
});
it('should not reemit errors when option is set', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = new Duplexer({objectMode: true, reemitErrors: false}, writable, readable)
, errorsCount = 0
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
assert.equal(errorsCount, 0);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
// Catch error events
readable.on('error', function(){})
writable.on('error', function(){})
setImmediate(function() {
// Writing content to duplex
duplex.write({cnt: 'oude'});
writable.emit('error', new Error('hip'));
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.emit('error', new Error('hip'));
readable.write({cnt: 'beloola'});
readable.end();
});
});
});
describe('and with sync streams', function() {
it('should work with functionnal API', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = Duplexer({objectMode: true}, writable, readable)
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
done();
}));
// Writing content to duplex
duplex.write({cnt: 'oude'});
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.write({cnt: 'beloola'});
readable.end();
});
it('should work with POO API', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = new Duplexer({objectMode: true}, writable, readable)
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
done();
}));
// Writing content to duplex
duplex.write({cnt: 'oude'});
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.write({cnt: 'beloola'});
readable.end();
});
it('should reemit errors', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = new Duplexer({objectMode: true}, writable, readable)
, errorsCount = 0
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
assert.equal(errorsCount, 2);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
// Writing content to duplex
duplex.write({cnt: 'oude'});
writable.emit('error', new Error('hip'));
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.emit('error', new Error('hip'));
readable.write({cnt: 'beloola'});
readable.end();
});
it('should not reemit errors when option is set', function(done) {
var readable = new Stream.PassThrough({objectMode: true})
, writable = new Stream.PassThrough({objectMode: true})
, duplex = new Duplexer({objectMode: true, reemitErrors: false}, writable, readable)
, errorsCount = 0
, wrtCount = 0
, dplCount = 0
;
// Checking writable content
writable.pipe(es.map(function(data, cb) {
if(1 == ++wrtCount) {
assert.equal(data.cnt, 'oude');
} else {
assert.equal(data.cnt, 'lali');
}
cb();
}));
// Checking duplex output
duplex.pipe(es.map(function(data, cb) {
if(1 == ++dplCount) {
assert.equal(data.cnt, 'biba');
} else {
assert.equal(data.cnt, 'beloola');
}
cb();
})).pipe(es.wait(function(data, cb) {
assert.equal(wrtCount, 2);
assert.equal(dplCount, 2);
assert.equal(errorsCount, 0);
done();
}));
duplex.on('error', function() {
errorsCount++;
});
// Catch error events
readable.on('error', function(){})
writable.on('error', function(){})
// Writing content to duplex
duplex.write({cnt: 'oude'});
writable.emit('error', new Error('hip'));
duplex.write({cnt: 'lali'});
duplex.end();
// Writing content to readable
readable.write({cnt: 'biba'});
readable.emit('error', new Error('hip'));
readable.write({cnt: 'beloola'});
readable.end();
});
});
});
it('should throw an error with bad writeable stream', function() {
assert.throws(function() {
new Duplexer({}, {}, new Stream.PassThrough());
});
assert.throws(function() {
new Duplexer({}, new Stream.Readable(), new Stream.PassThrough());
});
});
it('should throw an error with bad readable stream', function() {
assert.throws(function() {
new Duplexer({}, new Stream.PassThrough(), {});
});
assert.throws(function() {
new Duplexer({}, new Stream.PassThrough(), new Stream.Writable());
});
});
});