Comparing version 0.0.3 to 0.0.4
92
index.js
module.exports = chainit; | ||
function chainit(Constructor) { | ||
var instances = []; | ||
var fns = []; | ||
var Chain = function Chain() { | ||
instances.push(this); | ||
fns[instances.indexOf(this)] = {}; | ||
Constructor.apply(this, arguments); | ||
}; | ||
Chain.prototype = Object.create(Constructor.prototype); | ||
var Queue = require('queue'); | ||
@@ -48,2 +59,6 @@ var queues = []; | ||
var statics = Object.keys(Constructor).forEach(function(name) { | ||
Chain[name] = new Function(Constructor[name]); | ||
}); | ||
var methods = Object.keys(Constructor.prototype); | ||
@@ -53,41 +68,66 @@ methods.forEach(function(name) { | ||
var chained = function() { | ||
var ctx = this; | ||
var args = Array.prototype.slice.call(arguments); | ||
var customCb; | ||
if (typeof args[args.length - 1] === 'function') { | ||
customCb = args.pop(); | ||
} | ||
var chained = makeChain(); | ||
var ldepth = currentDepth; | ||
function makeChain(fn) { | ||
return function chained() { | ||
var ctx = this; | ||
var args = Array.prototype.slice.call(arguments); | ||
var customCb; | ||
if (typeof args[args.length - 1] === 'function') { | ||
customCb = args.pop(); | ||
} | ||
if (currentDepth > 0 && queues[currentDepth - 1].concurrency > 0) { | ||
queues[currentDepth - 1].concurrency = 0; | ||
} | ||
var ldepth = currentDepth; | ||
var task = function(cb) { | ||
currentDepth = ldepth + 1; | ||
args.push(function() { | ||
var cbArgs = arguments; | ||
if (currentDepth > 0 && queues[currentDepth - 1].concurrency > 0) { | ||
queues[currentDepth - 1].concurrency = 0; | ||
} | ||
if (customCb) { | ||
customCb.apply(ctx, cbArgs); | ||
var task = function(cb) { | ||
currentDepth = ldepth + 1; | ||
args.push(function() { | ||
var cbArgs = arguments; | ||
if (customCb) { | ||
customCb.apply(ctx, cbArgs); | ||
} | ||
cb(); | ||
}); | ||
if (typeof fn === 'function') { | ||
fn.apply(ctx, args); | ||
} else { | ||
original.apply(ctx, args); | ||
} | ||
} | ||
cb(); | ||
}); | ||
pushTo(currentDepth, task); | ||
return this; | ||
} | ||
} | ||
original.apply(ctx, args); | ||
Object.defineProperty(Chain.prototype, name, { | ||
set: function(func) { | ||
if (this === Chain.prototype) { | ||
original = func; | ||
} else { | ||
fns[instances.indexOf(this)][name] = makeChain(func); | ||
} | ||
}, | ||
get: function() { | ||
if (this === Chain.prototype || !fns[instances.indexOf(this)][name]) { | ||
return chained; | ||
} else { | ||
return fns[instances.indexOf(this)][name]; | ||
} | ||
} | ||
}); | ||
pushTo(currentDepth, task); | ||
return this; | ||
} | ||
Constructor.prototype[name] = chained; | ||
}); | ||
return Constructor; | ||
return Chain; | ||
} | ||
@@ -94,0 +134,0 @@ |
{ | ||
"name": "chainit", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "Turn an asynchronous JavaScript api into an asynchronous chainable JavaScript api.", | ||
"main": "index.js", | ||
"directories": { | ||
"example": "examples", | ||
"test": "test" | ||
"example": "examples" | ||
}, | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "zuul -- test/chain.js" | ||
}, | ||
@@ -16,6 +15,7 @@ "author": "Vincent Voyer <vincent@zeroload.net>", | ||
"devDependencies": { | ||
"mocha": "~1.13.0" | ||
"mocha": "~1.14.0", | ||
"zuul": "~1.0.2" | ||
}, | ||
"dependencies": { | ||
"queue": "~1.0.1" | ||
"queue": "~1.0.2" | ||
}, | ||
@@ -31,3 +31,7 @@ "keywords": [ | ||
"chain api" | ||
] | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/vvo/chainit.git" | ||
} | ||
} |
@@ -0,1 +1,3 @@ | ||
[![Build Status](https://travis-ci.org/vvo/chainit.png)](https://travis-ci.org/vvo/chainit) | ||
# chainit | ||
@@ -9,14 +11,6 @@ | ||
```js | ||
function MyApi() { | ||
// ... | ||
} | ||
function MyApi() {} | ||
MyApi.prototype.method1 = function(cb) {cb()} | ||
MyApi.prototype.method2 = function(cb) {cb()} | ||
MyApi.prototype.method1 = function(cb) { | ||
// ... | ||
} | ||
MyApi.prototype.method2 = function(cb) { | ||
// ... | ||
} | ||
var chainit = require('chainit'); | ||
@@ -34,2 +28,48 @@ var MyChainApi = chainit(MyApi); | ||
## Overriding methods | ||
You can override methods: | ||
* at the `.prototype` level | ||
* at the instance level | ||
And still benefits from the chain. | ||
You can also keep references to the original methods to set them back later. | ||
This is possible because we do not touch the | ||
`MyApi` original `constructor` nor `prototype`. | ||
```js | ||
function MyApi() {} | ||
MyApi.prototype.method1 = function(cb) {cb()} | ||
MyApi.prototype.method2 = function(cb) {cb()} | ||
var chainit = require('chainit'); | ||
var MyChainApi = chainit(MyApi); | ||
var original1 = MyChainApi.prototype.method1; | ||
MyChainApi.prototype.method1 = function(cb) {cb()} | ||
var obj = new MyChainApi(); | ||
obj | ||
.method1() // calls the newly added method1 | ||
.method2(); | ||
MyChainApi.prototype.method1 = original1; | ||
obj | ||
.method1() // calls the original method | ||
.method2(); | ||
original1 = obj.method1; | ||
obj.method1 = function(cb) {cb()} | ||
obj | ||
.method1() // calls the newly added method1 | ||
.method2(); | ||
obj.method1 = original1; | ||
``` | ||
## features | ||
@@ -46,2 +86,3 @@ | ||
* supports setTimeout(cb) | ||
* supports methods redifinition | ||
* fully tested! `npm test` | ||
@@ -48,0 +89,0 @@ |
@@ -16,2 +16,14 @@ describe('chaining an Api', function() { | ||
it('has the same instance type as an original object', function() { | ||
var originalO = new Api(); | ||
assert.ok(originalO instanceof Api); | ||
assert.ok(o instanceof Api); | ||
assert.ok(o instanceof ChainApi); | ||
assert.ok(o.constructor === originalO.constructor); | ||
}); | ||
it('does not modify original prototype', function() { | ||
assert.ok(Api.prototype !== ChainApi.prototype); | ||
}); | ||
it('supports individuals calls', function(done) { | ||
@@ -30,3 +42,3 @@ o.concat('he'); | ||
assert.equal(o.s, 'hola'); | ||
done(null); | ||
done(); | ||
}); | ||
@@ -183,2 +195,98 @@ }); | ||
it('handles multiple objects', function(done) { | ||
var o2 = new ChainApi(); | ||
var o3 = new ChainApi(); | ||
o.tripleConcat('one'); | ||
o2.tripleConcat('two'); | ||
o3.tripleConcat('three'); | ||
o | ||
.concat('-and-', function() { | ||
o2.concat('-or-') | ||
}) | ||
.tripleConcat('four') | ||
o3.concat('bon', function() { | ||
assert.equal(o.s, 'one1-one2-one3--and-four1-four2-four3-'); | ||
assert.equal(o2.s, 'two1-two2-two3--or-'); | ||
assert.equal(this.s, 'three1-three2-three3-bon'); | ||
done(null) | ||
}) | ||
}); | ||
it('supports methods redifinitions at the prototype level', function(done) { | ||
var o2 = new ChainApi(); | ||
var original = Api.prototype.concat; | ||
ChainApi.prototype.concat = function concat(sub, cb) { | ||
this.s = this.s.concat(sub + '#'); | ||
setTimeout(cb, ChainApi.getRandomArbitrary(5, 20)); | ||
} | ||
o2.concat('re'); | ||
o.concat('re'); | ||
o.concat('de', function() { | ||
o.tripleConcat('fi') | ||
}) | ||
.concat('nition', function() { | ||
assert.equal(this.s, 're#de#fi1-#fi2-#fi3-#nition#'); | ||
ChainApi.prototype.concat = original; | ||
o.concat('BOUH-', function() { | ||
ChainApi.prototype.concat = function (sub, cb) { | ||
this.s = this.s.concat(sub + '!!'); | ||
setTimeout(cb, ChainApi.getRandomArbitrary(5, 20)); | ||
}; | ||
o.concat('hello', function() { | ||
ChainApi.prototype.concat = Api.prototype.concat; | ||
o.concat('-ah', function() { | ||
o2.concat('def', function() { | ||
assert.equal(this.s, 're#def'); | ||
assert.equal(o.s, 're#de#fi1-#fi2-#fi3-#nition#BOUH-hello!!-ah'); | ||
done(); | ||
}) | ||
}) | ||
}) | ||
}); | ||
}); | ||
}); | ||
it('supports methods redifinitions at the instance level', function(done) { | ||
var o2 = new ChainApi(); | ||
var original = o.concat; | ||
o.concat = function(sub, cb) { | ||
this.s += sub + '#' | ||
setTimeout(cb, ChainApi.getRandomArbitrary(5, 20)); | ||
} | ||
o | ||
.concat('one') | ||
.concat('two', function() { | ||
this.concat('three'); | ||
}) | ||
.tripleConcat('four'); | ||
o2.concat('hey').concat('ho', function() { | ||
o.concat = original; | ||
o.concat('YO!', function() { | ||
assert.equal(this.s, 'one#two#three#four1-#four2-#four3-#YO!'); | ||
assert.equal(o2.s, 'heyho'); | ||
done(); | ||
}) | ||
}); | ||
}); | ||
it('supports constructor arguments', function(done) { | ||
var o2 = new ChainApi('allo'); | ||
o2.concat(' maman', function() { | ||
assert.equal(this.s, 'allo maman'); | ||
done(); | ||
}) | ||
}); | ||
xit('supports adding new methods', function() { | ||
}); | ||
}); |
module.exports = Api; | ||
function Api() { | ||
this.s = ''; | ||
function Api(s) { | ||
this.s = s || ''; | ||
} | ||
@@ -59,4 +59,6 @@ | ||
Api.getRandomArbitrary = getRandomArbitrary; | ||
function getRandomArbitrary(min, max) { | ||
return Math.random() * (max - min) + min; | ||
} |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
18003
13
443
130
0
2
1
Updatedqueue@~1.0.2