Added Gulp.js for compiling SCSS stylesheets
This commit is contained in:
13
node_modules/cloneable-readable/.travis.yml
generated
vendored
Normal file
13
node_modules/cloneable-readable/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
- "4"
|
||||
- "5"
|
||||
- "6"
|
||||
- "7"
|
||||
- "8"
|
||||
- "9"
|
||||
- "10"
|
||||
- "12"
|
21
node_modules/cloneable-readable/LICENSE
generated
vendored
Normal file
21
node_modules/cloneable-readable/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Matteo Collina
|
||||
|
||||
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.
|
54
node_modules/cloneable-readable/README.md
generated
vendored
Normal file
54
node_modules/cloneable-readable/README.md
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
# cloneable-readable
|
||||
|
||||
[](https://greenkeeper.io/)
|
||||
|
||||
[](https://travis-ci.org/mcollina/cloneable-readable)
|
||||
|
||||
Clone a Readable stream, safely.
|
||||
|
||||
```js
|
||||
'use strict'
|
||||
|
||||
var cloneable = require('cloneable-readable')
|
||||
var fs = require('fs')
|
||||
var pump = require('pump')
|
||||
|
||||
var stream = cloneable(fs.createReadStream('./package.json'))
|
||||
|
||||
pump(stream.clone(), fs.createWriteStream('./out1'))
|
||||
|
||||
// simulate some asynchronicity
|
||||
setImmediate(function () {
|
||||
pump(stream, fs.createWriteStream('./out2'))
|
||||
})
|
||||
```
|
||||
|
||||
**cloneable-readable** automatically handles `objectMode: true`.
|
||||
|
||||
This module comes out of an healthy discussion on the 'right' way to
|
||||
clone a Readable in https://github.com/gulpjs/vinyl/issues/85
|
||||
and https://github.com/nodejs/readable-stream/issues/202. This is my take.
|
||||
|
||||
**YOU MUST PIPE ALL CLONES TO START THE FLOW**
|
||||
|
||||
You can also attach `'data'` and `'readable'` events to them.
|
||||
|
||||
## API
|
||||
|
||||
### cloneable(stream)
|
||||
|
||||
Create a `Cloneable` stream.
|
||||
A Cloneable has a `clone()` method to create more clones.
|
||||
All clones must be resumed/piped to start the flow.
|
||||
|
||||
### cloneable.isCloneable(stream)
|
||||
|
||||
Check if `stream` needs to be wrapped in a `Cloneable` or not.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This project was kindly sponsored by [nearForm](http://nearform.com).
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
14
node_modules/cloneable-readable/example.js
generated
vendored
Normal file
14
node_modules/cloneable-readable/example.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict'
|
||||
|
||||
var cloneable = require('./')
|
||||
var fs = require('fs')
|
||||
var pump = require('pump')
|
||||
|
||||
var stream = cloneable(fs.createReadStream('./package.json'))
|
||||
|
||||
pump(stream.clone(), fs.createWriteStream('./out1'))
|
||||
|
||||
// simulate some asynchronicity
|
||||
setImmediate(function () {
|
||||
pump(stream, fs.createWriteStream('./out2'))
|
||||
})
|
153
node_modules/cloneable-readable/index.js
generated
vendored
Normal file
153
node_modules/cloneable-readable/index.js
generated
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
'use strict'
|
||||
|
||||
var PassThrough = require('readable-stream').PassThrough
|
||||
var inherits = require('inherits')
|
||||
var p = require('process-nextick-args')
|
||||
|
||||
function Cloneable (stream, opts) {
|
||||
if (!(this instanceof Cloneable)) {
|
||||
return new Cloneable(stream, opts)
|
||||
}
|
||||
|
||||
var objectMode = stream._readableState.objectMode
|
||||
this._original = stream
|
||||
this._clonesCount = 1
|
||||
|
||||
opts = opts || {}
|
||||
opts.objectMode = objectMode
|
||||
|
||||
PassThrough.call(this, opts)
|
||||
|
||||
forwardDestroy(stream, this)
|
||||
|
||||
this.on('newListener', onData)
|
||||
this.once('resume', onResume)
|
||||
|
||||
this._hasListener = true
|
||||
}
|
||||
|
||||
inherits(Cloneable, PassThrough)
|
||||
|
||||
function onData (event, listener) {
|
||||
if (event === 'data' || event === 'readable') {
|
||||
this._hasListener = false
|
||||
this.removeListener('newListener', onData)
|
||||
this.removeListener('resume', onResume)
|
||||
p.nextTick(clonePiped, this)
|
||||
}
|
||||
}
|
||||
|
||||
function onResume () {
|
||||
this._hasListener = false
|
||||
this.removeListener('newListener', onData)
|
||||
p.nextTick(clonePiped, this)
|
||||
}
|
||||
|
||||
Cloneable.prototype.clone = function () {
|
||||
if (!this._original) {
|
||||
throw new Error('already started')
|
||||
}
|
||||
|
||||
this._clonesCount++
|
||||
|
||||
// the events added by the clone should not count
|
||||
// for starting the flow
|
||||
this.removeListener('newListener', onData)
|
||||
var clone = new Clone(this)
|
||||
if (this._hasListener) {
|
||||
this.on('newListener', onData)
|
||||
}
|
||||
|
||||
return clone
|
||||
}
|
||||
|
||||
Cloneable.prototype._destroy = function (err, cb) {
|
||||
if (!err) {
|
||||
this.push(null)
|
||||
this.end()
|
||||
this.emit('close')
|
||||
}
|
||||
|
||||
p.nextTick(cb, err)
|
||||
}
|
||||
|
||||
function forwardDestroy (src, dest) {
|
||||
src.on('error', destroy)
|
||||
src.on('close', onClose)
|
||||
|
||||
function destroy (err) {
|
||||
src.removeListener('close', onClose)
|
||||
dest.destroy(err)
|
||||
}
|
||||
|
||||
function onClose () {
|
||||
dest.end()
|
||||
}
|
||||
}
|
||||
|
||||
function clonePiped (that) {
|
||||
if (--that._clonesCount === 0 && !that._readableState.destroyed) {
|
||||
that._original.pipe(that)
|
||||
that._original = undefined
|
||||
}
|
||||
}
|
||||
|
||||
function Clone (parent, opts) {
|
||||
if (!(this instanceof Clone)) {
|
||||
return new Clone(parent, opts)
|
||||
}
|
||||
|
||||
var objectMode = parent._readableState.objectMode
|
||||
|
||||
opts = opts || {}
|
||||
opts.objectMode = objectMode
|
||||
|
||||
this.parent = parent
|
||||
|
||||
PassThrough.call(this, opts)
|
||||
|
||||
forwardDestroy(parent, this)
|
||||
|
||||
parent.pipe(this)
|
||||
|
||||
// the events added by the clone should not count
|
||||
// for starting the flow
|
||||
// so we add the newListener handle after we are done
|
||||
this.on('newListener', onDataClone)
|
||||
this.on('resume', onResumeClone)
|
||||
}
|
||||
|
||||
function onDataClone (event, listener) {
|
||||
// We start the flow once all clones are piped or destroyed
|
||||
if (event === 'data' || event === 'readable' || event === 'close') {
|
||||
p.nextTick(clonePiped, this.parent)
|
||||
this.removeListener('newListener', onDataClone)
|
||||
}
|
||||
}
|
||||
|
||||
function onResumeClone () {
|
||||
this.removeListener('newListener', onDataClone)
|
||||
p.nextTick(clonePiped, this.parent)
|
||||
}
|
||||
|
||||
inherits(Clone, PassThrough)
|
||||
|
||||
Clone.prototype.clone = function () {
|
||||
return this.parent.clone()
|
||||
}
|
||||
|
||||
Cloneable.isCloneable = function (stream) {
|
||||
return stream instanceof Cloneable || stream instanceof Clone
|
||||
}
|
||||
|
||||
Clone.prototype._destroy = function (err, cb) {
|
||||
if (!err) {
|
||||
this.push(null)
|
||||
this.end()
|
||||
this.emit('close')
|
||||
}
|
||||
|
||||
p.nextTick(cb, err)
|
||||
}
|
||||
|
||||
module.exports = Cloneable
|
39
node_modules/cloneable-readable/package.json
generated
vendored
Normal file
39
node_modules/cloneable-readable/package.json
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "cloneable-readable",
|
||||
"version": "1.1.3",
|
||||
"description": "Clone a Readable stream, safely",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "standard && tape test.js | tap-spec"
|
||||
},
|
||||
"precommit": "test",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mcollina/cloneable-readable.git"
|
||||
},
|
||||
"keywords": [
|
||||
"readable",
|
||||
"stream",
|
||||
"clone"
|
||||
],
|
||||
"author": "Matteo Collina <hello@matteocollina.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mcollina/cloneable-readable/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mcollina/cloneable-readable#readme",
|
||||
"devDependencies": {
|
||||
"flush-write-stream": "^1.0.0",
|
||||
"from2": "^2.1.1",
|
||||
"pre-commit": "^1.1.2",
|
||||
"pump": "^3.0.0",
|
||||
"standard": "^11.0.0",
|
||||
"tap-spec": "^4.1.1",
|
||||
"tape": "^4.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.1",
|
||||
"process-nextick-args": "^2.0.0",
|
||||
"readable-stream": "^2.3.5"
|
||||
}
|
||||
}
|
702
node_modules/cloneable-readable/test.js
generated
vendored
Normal file
702
node_modules/cloneable-readable/test.js
generated
vendored
Normal file
@ -0,0 +1,702 @@
|
||||
'use strict'
|
||||
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var test = require('tape').test
|
||||
var from = require('from2')
|
||||
var crypto = require('crypto')
|
||||
var sink = require('flush-write-stream')
|
||||
var pump = require('pump')
|
||||
var cloneable = require('./')
|
||||
|
||||
test('basic passthrough', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
|
||||
test('clone sync', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var cloned = instance.clone()
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
cloned.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
|
||||
test('clone async', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var cloned = instance.clone()
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
setImmediate(function () {
|
||||
cloned.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
test('basic passthrough in obj mode', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var read = false
|
||||
var source = from.obj(function (size, next) {
|
||||
if (read) {
|
||||
return this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push({ hello: 'world' })
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
instance.pipe(sink.obj(function (chunk, enc, cb) {
|
||||
t.deepEqual(chunk, { hello: 'world' }, 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
|
||||
test('multiple clone in object mode', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
var read = false
|
||||
var source = from.obj(function (size, next) {
|
||||
if (read) {
|
||||
return this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push({ hello: 'world' })
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var cloned = instance.clone()
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
instance.pipe(sink.obj(function (chunk, enc, cb) {
|
||||
t.deepEqual(chunk, { hello: 'world' }, 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
setImmediate(function () {
|
||||
cloned.pipe(sink.obj(function (chunk, enc, cb) {
|
||||
t.deepEqual(chunk, { hello: 'world' }, 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
test('basic passthrough with data event', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var data = ''
|
||||
instance.on('data', function (chunk) {
|
||||
data += chunk.toString()
|
||||
})
|
||||
|
||||
instance.on('end', function () {
|
||||
t.equal(data, 'hello world', 'chunk matches')
|
||||
})
|
||||
})
|
||||
|
||||
test('basic passthrough with data event on clone', function (t) {
|
||||
t.plan(3)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
var cloned = instance.clone()
|
||||
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var data = ''
|
||||
cloned.on('data', function (chunk) {
|
||||
data += chunk.toString()
|
||||
})
|
||||
|
||||
cloned.on('end', function () {
|
||||
t.equal(data, 'hello world', 'chunk matches in clone')
|
||||
})
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches in instance')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
|
||||
test('errors if cloned after start', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var source = from(function (size, next) {
|
||||
this.push('hello world')
|
||||
this.push(null)
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
t.throws(function () {
|
||||
instance.clone()
|
||||
}, 'throws if cloned after start')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
|
||||
test('basic passthrough with readable event', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var data = ''
|
||||
instance.on('readable', function () {
|
||||
var chunk
|
||||
while ((chunk = this.read()) !== null) {
|
||||
data += chunk.toString()
|
||||
}
|
||||
})
|
||||
|
||||
instance.on('end', function () {
|
||||
t.equal(data, 'hello world', 'chunk matches')
|
||||
})
|
||||
})
|
||||
|
||||
test('basic passthrough with readable event on clone', function (t) {
|
||||
t.plan(3)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
var cloned = instance.clone()
|
||||
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var data = ''
|
||||
cloned.on('readable', function () {
|
||||
var chunk
|
||||
while ((chunk = this.read()) !== null) {
|
||||
data += chunk.toString()
|
||||
}
|
||||
})
|
||||
|
||||
cloned.on('end', function () {
|
||||
t.equal(data, 'hello world', 'chunk matches in clone')
|
||||
})
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches in instance')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
|
||||
test('source error destroys all', function (t) {
|
||||
t.plan(3)
|
||||
|
||||
var source = from()
|
||||
var instance = cloneable(source)
|
||||
var clone = instance.clone()
|
||||
|
||||
source.on('error', function (err) {
|
||||
t.ok(err, 'source errors')
|
||||
|
||||
instance.on('error', function (err2) {
|
||||
t.ok(err === err2, 'instance receives same error')
|
||||
})
|
||||
|
||||
clone.on('error', function (err3) {
|
||||
t.ok(err === err3, 'clone receives same error')
|
||||
})
|
||||
})
|
||||
|
||||
source.emit('error', new Error())
|
||||
})
|
||||
|
||||
test('source destroy destroys all', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var source = from()
|
||||
var instance = cloneable(source)
|
||||
var clone = instance.clone()
|
||||
|
||||
instance.on('end', function () {
|
||||
t.pass('instance has ended')
|
||||
})
|
||||
|
||||
clone.on('end', function () {
|
||||
t.pass('clone has ended')
|
||||
})
|
||||
|
||||
clone.resume()
|
||||
instance.resume()
|
||||
|
||||
source.destroy()
|
||||
})
|
||||
|
||||
test('instance error destroys all but the source', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var source = from()
|
||||
var instance = cloneable(source)
|
||||
var clone = instance.clone()
|
||||
|
||||
source.on('close', function () {
|
||||
t.fail('source should not be closed')
|
||||
})
|
||||
|
||||
instance.on('error', function (err) {
|
||||
t.is(err.message, 'beep', 'instance errors')
|
||||
})
|
||||
|
||||
instance.on('close', function () {
|
||||
t.fail('close should not be emitted')
|
||||
})
|
||||
|
||||
clone.on('error', function (err) {
|
||||
t.is(err.message, 'beep', 'instance errors')
|
||||
})
|
||||
|
||||
clone.on('close', function () {
|
||||
t.fail('close should not be emitted')
|
||||
})
|
||||
|
||||
instance.destroy(new Error('beep'))
|
||||
})
|
||||
|
||||
test('instance destroy destroys all but the source', function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var source = from()
|
||||
var instance = cloneable(source)
|
||||
var clone = instance.clone()
|
||||
|
||||
source.on('close', function () {
|
||||
t.fail('source should not be closed')
|
||||
})
|
||||
|
||||
instance.on('end', function () {
|
||||
t.pass('instance has ended')
|
||||
})
|
||||
|
||||
clone.on('end', function () {
|
||||
t.pass('clone has ended')
|
||||
})
|
||||
|
||||
instance.resume()
|
||||
clone.resume()
|
||||
|
||||
instance.destroy()
|
||||
})
|
||||
|
||||
test('clone destroy does not affect other clones, cloneable or source', function (t) {
|
||||
t.plan(1)
|
||||
|
||||
var source = from()
|
||||
var instance = cloneable(source)
|
||||
var clone = instance.clone()
|
||||
var other = instance.clone()
|
||||
|
||||
source.on('close', function () {
|
||||
t.fail('source should not be closed')
|
||||
})
|
||||
|
||||
instance.on('close', function () {
|
||||
t.fail('instance should not be closed')
|
||||
})
|
||||
|
||||
other.on('close', function () {
|
||||
t.fail('other clone should not be closed')
|
||||
})
|
||||
|
||||
clone.on('close', function () {
|
||||
t.pass('clone is closed')
|
||||
})
|
||||
|
||||
clone.destroy()
|
||||
})
|
||||
|
||||
test('clone remains readable if other is destroyed', function (t) {
|
||||
t.plan(3)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
var clone = instance.clone()
|
||||
var other = instance.clone()
|
||||
|
||||
instance.pipe(sink.obj(function (chunk, enc, cb) {
|
||||
t.deepEqual(chunk.toString(), 'hello', 'instance chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
clone.pipe(sink.obj(function (chunk, enc, cb) {
|
||||
t.deepEqual(chunk.toString(), 'hello', 'clone chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
clone.on('close', function () {
|
||||
t.fail('clone should not be closed')
|
||||
})
|
||||
|
||||
instance.on('close', function () {
|
||||
t.fail('instance should not be closed')
|
||||
})
|
||||
|
||||
other.on('close', function () {
|
||||
t.pass('other is closed')
|
||||
})
|
||||
|
||||
other.destroy()
|
||||
})
|
||||
|
||||
test('clone of clone', function (t) {
|
||||
t.plan(6)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var cloned = instance.clone()
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var replica = cloned.clone()
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
cloned.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
replica.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), 'hello world', 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
})
|
||||
|
||||
test('from vinyl', function (t) {
|
||||
t.plan(3)
|
||||
|
||||
var source = from(['wa', 'dup'])
|
||||
|
||||
var instance = cloneable(source)
|
||||
var clone = instance.clone()
|
||||
|
||||
var data = ''
|
||||
var data2 = ''
|
||||
var ends = 2
|
||||
|
||||
function latch () {
|
||||
if (--ends === 0) {
|
||||
t.equal(data, data2)
|
||||
}
|
||||
}
|
||||
|
||||
instance.on('data', function (chunk) {
|
||||
data += chunk.toString()
|
||||
})
|
||||
|
||||
process.nextTick(function () {
|
||||
t.equal('', data, 'nothing was written yet')
|
||||
t.equal('', data2, 'nothing was written yet')
|
||||
|
||||
clone.on('data', function (chunk) {
|
||||
data2 += chunk.toString()
|
||||
})
|
||||
})
|
||||
|
||||
instance.on('end', latch)
|
||||
clone.on('end', latch)
|
||||
})
|
||||
|
||||
test('waits till all are flowing', function (t) {
|
||||
t.plan(1)
|
||||
|
||||
var source = from(['wa', 'dup'])
|
||||
|
||||
var instance = cloneable(source)
|
||||
|
||||
// we create a clone
|
||||
instance.clone()
|
||||
|
||||
instance.on('data', function (chunk) {
|
||||
t.fail('this should never happen')
|
||||
})
|
||||
|
||||
process.nextTick(function () {
|
||||
t.pass('wait till nextTick')
|
||||
})
|
||||
})
|
||||
|
||||
test('isCloneable', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
var source = from(['hello', ' ', 'world'])
|
||||
t.notOk(cloneable.isCloneable(source), 'a generic readable is not cloneable')
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.ok(cloneable.isCloneable(instance), 'a cloneable is cloneable')
|
||||
|
||||
var clone = instance.clone()
|
||||
t.ok(cloneable.isCloneable(clone), 'a clone is cloneable')
|
||||
|
||||
var cloneClone = clone.clone()
|
||||
t.ok(cloneable.isCloneable(cloneClone), 'a clone of a clone is cloneable')
|
||||
})
|
||||
|
||||
test('emits finish', function (t) {
|
||||
var chunks = ['a', 'b', 'c', 'd', null]
|
||||
var e1 = ['a', 'b', 'c', 'd']
|
||||
var e2 = ['a', 'b', 'c', 'd']
|
||||
|
||||
t.plan(2 + e1.length + e2.length)
|
||||
|
||||
var source = from(function (size, next) {
|
||||
setImmediate(next, null, chunks.shift())
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
|
||||
var clone = instance.clone()
|
||||
|
||||
clone.on('finish', t.pass.bind(null, 'clone emits finish'))
|
||||
instance.on('finish', t.pass.bind(null, 'main emits finish'))
|
||||
|
||||
instance.pipe(sink(function (chunk, enc, cb) {
|
||||
t.equal(chunk.toString(), e1.shift(), 'chunk matches')
|
||||
cb()
|
||||
}))
|
||||
|
||||
clone.on('data', function (chunk) {
|
||||
t.equal(chunk.toString(), e2.shift(), 'chunk matches')
|
||||
})
|
||||
})
|
||||
|
||||
test('clone async w resume', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
var read = false
|
||||
var source = from(function (size, next) {
|
||||
if (read) {
|
||||
this.push(null)
|
||||
} else {
|
||||
read = true
|
||||
this.push('hello world')
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
var instance = cloneable(source)
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
var cloned = instance.clone()
|
||||
t.notOk(read, 'stream not started')
|
||||
|
||||
instance.on('end', t.pass.bind(null, 'end emitted'))
|
||||
instance.resume()
|
||||
|
||||
setImmediate(function () {
|
||||
cloned.on('end', t.pass.bind(null, 'end emitted'))
|
||||
cloned.resume()
|
||||
})
|
||||
})
|
||||
|
||||
test('big file', function (t) {
|
||||
t.plan(13)
|
||||
|
||||
var stream = cloneable(fs.createReadStream(path.join(__dirname, 'big')))
|
||||
var hash = crypto.createHash('sha1')
|
||||
hash.setEncoding('hex')
|
||||
|
||||
var toCheck
|
||||
|
||||
fs.createReadStream(path.join(__dirname, 'big'))
|
||||
.pipe(hash)
|
||||
.once('readable', function () {
|
||||
toCheck = hash.read()
|
||||
t.ok(toCheck)
|
||||
})
|
||||
|
||||
function pipe (s, num) {
|
||||
s.on('end', function () {
|
||||
t.pass('end for ' + num)
|
||||
})
|
||||
|
||||
var dest = path.join(__dirname, 'out')
|
||||
|
||||
s.pipe(fs.createWriteStream(dest))
|
||||
.on('finish', function () {
|
||||
t.pass('finish for ' + num)
|
||||
|
||||
var destHash = crypto.createHash('sha1')
|
||||
destHash.setEncoding('hex')
|
||||
|
||||
fs.createReadStream(dest)
|
||||
.pipe(destHash)
|
||||
.once('readable', function () {
|
||||
var hash = destHash.read()
|
||||
t.ok(hash)
|
||||
t.equal(hash, toCheck)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Pipe in another event loop tick <-- this one finished only, it's the original cloneable.
|
||||
setImmediate(pipe.bind(null, stream, 1))
|
||||
|
||||
// Pipe in the same event loop tick
|
||||
pipe(stream.clone(), 0)
|
||||
|
||||
// Pipe a long time after
|
||||
setTimeout(pipe.bind(null, stream.clone(), 2), 1000)
|
||||
})
|
||||
|
||||
test('pump error', function (t) {
|
||||
t.plan(1)
|
||||
|
||||
var err = new Error('kaboom')
|
||||
|
||||
pump([
|
||||
cloneable(from(function () {
|
||||
this.destroy(err)
|
||||
})),
|
||||
sink(function (chunk, enc, cb) {
|
||||
t.fail('this should not be called')
|
||||
})
|
||||
], function (_err) {
|
||||
t.equal(_err, err)
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user