middlewarify
Advanced tools
Comparing version 0.2.0 to 0.3.0
@@ -109,36 +109,5 @@ /** | ||
var midd = midds.shift(); | ||
var arity = midd.length; | ||
var argsLen = args.length; | ||
/** @type {boolean} User defined callback */ | ||
var hasCb = false; | ||
// check if there's a callback defined, be explicit expect arity | ||
// to be args.length + 1 | ||
if (arity - argsLen === 1) { | ||
hasCb = true; | ||
} | ||
function userCb(err) { | ||
if (err) { | ||
deferred.reject(err); | ||
} else { | ||
middlewarify._fetchAndInvoke(midds, args, deferred); | ||
} | ||
} | ||
var invokeArgs = Array.prototype.slice.call(args); | ||
if (hasCb) { | ||
invokeArgs.push(userCb); | ||
} | ||
middlewarify._invoke(midd, invokeArgs, function(err) { | ||
if (err) { | ||
return deferred.reject(err); | ||
} | ||
if (!hasCb) { | ||
middlewarify._fetchAndInvoke(midds, args, deferred); | ||
} | ||
}); | ||
middlewarify._invoke(midd, args).then(function() { | ||
middlewarify._fetchAndInvoke(midds, args, deferred); | ||
}, deferred.reject.bind(deferred)); | ||
}; | ||
@@ -151,17 +120,14 @@ | ||
* @param {Array} invokeArgs Arguments to invoke middleware with. | ||
* @param {Function(Error=)} cb callback. | ||
* @return {Promise} | ||
* @private | ||
*/ | ||
middlewarify._invoke = function(midd, invokeArgs, cb) { | ||
try { | ||
middlewarify._invoke = function(midd, invokeArgs) { | ||
return new Promise(function(resolve, reject) { | ||
var maybePromise = midd.apply(null, invokeArgs); | ||
if (Promise.is(maybePromise)) { | ||
return maybePromise.then(cb, function(err) { | ||
cb(err || new Error()); | ||
}); | ||
if (!maybePromise || typeof maybePromise.then !== 'function') { | ||
resolve(); | ||
} else { | ||
maybePromise.then(resolve, reject); | ||
} | ||
cb(); | ||
} catch(ex) { | ||
cb(ex); | ||
} | ||
}); | ||
}; | ||
@@ -181,3 +147,3 @@ | ||
var len = middlewares.length; | ||
if (0 === len) return; | ||
if (len === 0) return; | ||
@@ -184,0 +150,0 @@ function pushMidd(fn) { |
{ | ||
"name": "middlewarify", | ||
"description": "Apply the middleware pattern to any function.", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"homepage": "https://github.com/thanpolas/middlewarify", | ||
@@ -6,0 +6,0 @@ "author": { |
@@ -29,5 +29,4 @@ # Middlewarify | ||
// it will be the last callback to be invoked. | ||
function createTask(done) { | ||
function createTask() { | ||
console.log('createTask Final Fn to be invoked'); | ||
done(); | ||
} | ||
@@ -52,14 +51,7 @@ | ||
// add another middleware to the 'create' operation | ||
// this time use a callback to indicate asynchronicity | ||
tasks.create.use(function(next){ | ||
console.log('middleware 2'); | ||
next(); | ||
}); | ||
// add a third middleware to the 'create' operation | ||
// add a second middleware to the 'create' operation | ||
// this time use a promise to indicate asynchronicity | ||
tasks.create.use(function(){ | ||
tasks.create.use(function() { | ||
return new Promise(resolve, reject) { | ||
console.log('middleware 3'); | ||
console.log('middleware 2'); | ||
resolve(); | ||
@@ -80,3 +72,2 @@ }); | ||
// middleware 2 | ||
// middleware 3 | ||
// createTask Final Fn to be invoked | ||
@@ -107,5 +98,4 @@ ``` | ||
// and before any 'after' middleware. | ||
function createTask(done) { | ||
function createTask() { | ||
console.log('Invoked Second'); | ||
done(null); | ||
}; | ||
@@ -119,11 +109,9 @@ | ||
// add a before hook | ||
tasks.create.before(function(next) { | ||
tasks.create.before(function() { | ||
console.log('Invoked First'); | ||
next(); | ||
}); | ||
// add an after hook | ||
tasks.create.after(function(next) { | ||
tasks.create.after(function() { | ||
console.log('Invoked Third and last'); | ||
next(); | ||
}); | ||
@@ -220,28 +208,2 @@ | ||
#### Asynchronous Middleware Using Callbacks | ||
Middlewarify determines the arity of your middleware and if it detects that you have one, and only one, more argument that what the *Middleware Container* was invoked with, then it treats it as a callback and you need to invoke it to pass control to the next middleware. | ||
```js | ||
crud.create.use(function(next) { | ||
// Since we expect "create" to be invoked without any arguments | ||
// then Middlewarify assumes this middleware is async and expects | ||
// you to invoked "next" | ||
next(); | ||
}); | ||
crud.create(); // no arguments passed | ||
``` | ||
The first argument of the `next()` callback is the **error indicator**, any truthy value passed will be considered an error and stop executing the middleware chain right there and then. | ||
```js | ||
crud.create.use(function(next) { | ||
// something went wrong, bail out | ||
next('an error occured'); | ||
}); | ||
``` | ||
> If the Middleware Container is invoked with arguments, these arguments will be passed to all middleware and the callback function `next` **will always be the last argument**. Read the next section "Invoking the Middleware" for more. | ||
#### Invoking the Middleware | ||
@@ -286,2 +248,4 @@ | ||
## Release History | ||
- **v0.3.0**, *09 Feb 2014* | ||
- Removed callback API, 100% Promise based API now. | ||
- **v0.2.0**, *08 Feb 2014* | ||
@@ -288,0 +252,0 @@ - Major API change, introduced Promises to API. |
@@ -67,4 +67,3 @@ /** | ||
assert.ok(midd5.calledBefore(midd6), '"midd5" called before "midd6"'); | ||
done(); | ||
}, done).then(null, done); | ||
}).then(done, done); | ||
}); | ||
@@ -181,53 +180,2 @@ | ||
}); | ||
test('6.5.2 a Before middleware calls next with an error', function(done){ | ||
obj.create.before(function(next){ | ||
next(new Error('an error')); | ||
}); | ||
obj.create().then(noop, function(err){ | ||
assert.instanceOf(err, Error, '"err" should be instanceOf Error'); | ||
assert.equal(err.message, 'an error', 'Error message should match'); | ||
done(); | ||
}, done).then(null, done); | ||
}); | ||
test('6.5.2.1 a After middleware calls next with an error', function(done){ | ||
obj.create.after(function(next){ | ||
next(new Error('an error')); | ||
}); | ||
obj.create().then(noop, function(err) { | ||
assert.instanceOf(err, Error, '"err" should be instanceOf Error'); | ||
assert.equal(err.message, 'an error', 'Error message should match'); | ||
done(); | ||
}, done).then(null, done); | ||
}); | ||
test('6.5.3 a failing Before middleware prevents rest of middleware from executing', function(done){ | ||
obj.create.before(function(next){ | ||
next(new Error('an error')); | ||
}); | ||
var middSpy = sinon.spy(); | ||
var afterMiddSpy = sinon.spy(); | ||
obj.create.before(middSpy); | ||
obj.create.after(afterMiddSpy); | ||
obj.create().then(noop, function(){ | ||
assert.notOk(middSpy.called, 'second Before middleware should not be called'); | ||
assert.notOk(afterMiddSpy.called, 'After middleware should not be called'); | ||
done(); | ||
}).then(null, done); | ||
}); | ||
test('6.5.4 a failing After middleware prevents rest of middleware from executing', function(done){ | ||
obj.create.after(function(next){ | ||
next(new Error('an error')); | ||
}); | ||
var middSpy = sinon.spy(); | ||
obj.create.after(middSpy); | ||
obj.create().then(noop, function(){ | ||
assert.notOk(middSpy.called, 'second after middleware should not be called'); | ||
done(); | ||
}).then(null, done); | ||
}); | ||
}); |
@@ -43,14 +43,14 @@ /** | ||
teardown(function(){ | ||
obj.create(); | ||
assert.ok(firstMidd.calledOnce, 'firstMidd should be called only once'); | ||
assert.ok(secondMidd.calledOnce, 'secondMidd should be called only once'); | ||
assert.ok(thirdMidd.calledOnce, 'thirdMidd should be called only once'); | ||
assert.ok(lastMidd.calledOnce, 'lastMidd should be called only once'); | ||
teardown(function(done){ | ||
obj.create().then(function() { | ||
assert.ok(firstMidd.calledOnce, 'firstMidd should be called only once. Called: ' + firstMidd.callCount); | ||
assert.ok(secondMidd.calledOnce, 'secondMidd should be called only once. Called: ' + secondMidd.callCount); | ||
assert.ok(thirdMidd.calledOnce, 'thirdMidd should be called only once. Called: ' + thirdMidd.callCount); | ||
assert.ok(lastMidd.calledOnce, 'lastMidd should be called only once. Called: ' + lastMidd.callCount); | ||
assert.ok(firstMidd.calledBefore(secondMidd), 'firstMidd should be called before secondMidd'); | ||
assert.ok(secondMidd.calledAfter(firstMidd), 'secondMidd should be called after firstMidd'); | ||
assert.ok(thirdMidd.calledAfter(secondMidd), 'thirdMidd should be called after secondMidd'); | ||
assert.ok(lastMidd.calledAfter(thirdMidd), 'lastMidd should be called after thirdMidd'); | ||
assert.ok(firstMidd.calledBefore(secondMidd), 'firstMidd should be called before secondMidd'); | ||
assert.ok(secondMidd.calledAfter(firstMidd), 'secondMidd should be called after firstMidd'); | ||
assert.ok(thirdMidd.calledAfter(secondMidd), 'thirdMidd should be called after secondMidd'); | ||
assert.ok(lastMidd.calledAfter(thirdMidd), 'lastMidd should be called after thirdMidd'); | ||
}).then(done, done); | ||
}); | ||
@@ -85,21 +85,21 @@ | ||
obj = Object.create(null); | ||
lastMidd = function(next) {spyLastMidd();next();}; | ||
firstMidd = function(next) {spyFirstMidd();next();}; | ||
secondMidd = function(next) {spySecondMidd();next();}; | ||
thirdMidd = function(next) {spyThirdMidd();next();}; | ||
lastMidd = function() {spyLastMidd();}; | ||
firstMidd = function() {spyFirstMidd();}; | ||
secondMidd = function() {spySecondMidd();}; | ||
thirdMidd = function() {spyThirdMidd();}; | ||
midd.make(obj, 'create', lastMidd); | ||
}); | ||
teardown(function(){ | ||
obj.create(); | ||
assert.ok(spyFirstMidd.calledOnce, 'firstMidd should be called only once'); | ||
assert.ok(spySecondMidd.calledOnce, 'secondMidd should be called only once'); | ||
assert.ok(spyThirdMidd.calledOnce, 'thirdMidd should be called only once'); | ||
assert.ok(spyLastMidd.calledOnce, 'lastMidd should be called only once'); | ||
teardown(function(done) { | ||
obj.create().then(function(){ | ||
assert.ok(spyFirstMidd.calledOnce, 'firstMidd should be called only once'); | ||
assert.ok(spySecondMidd.calledOnce, 'secondMidd should be called only once'); | ||
assert.ok(spyThirdMidd.calledOnce, 'thirdMidd should be called only once'); | ||
assert.ok(spyLastMidd.calledOnce, 'lastMidd should be called only once'); | ||
assert.ok(spyFirstMidd.calledBefore(spySecondMidd), 'firstMidd should be called before secondMidd'); | ||
assert.ok(spySecondMidd.calledAfter(spyFirstMidd), 'secondMidd should be called after firstMidd'); | ||
assert.ok(spyThirdMidd.calledAfter(spySecondMidd), 'thirdMidd should be called after secondMidd'); | ||
assert.ok(spyLastMidd.calledAfter(spyThirdMidd), 'lastMidd should be called after thirdMidd'); | ||
assert.ok(spyFirstMidd.calledBefore(spySecondMidd), 'firstMidd should be called before secondMidd'); | ||
assert.ok(spySecondMidd.calledAfter(spyFirstMidd), 'secondMidd should be called after firstMidd'); | ||
assert.ok(spyThirdMidd.calledAfter(spySecondMidd), 'thirdMidd should be called after secondMidd'); | ||
assert.ok(spyLastMidd.calledAfter(spyThirdMidd), 'lastMidd should be called after thirdMidd'); | ||
}).then(done, done); | ||
}); | ||
@@ -130,4 +130,2 @@ | ||
test('3.1 Three arguments', function(done) { | ||
function checkMiddlewareArgs(arg1, arg2, arg3) { | ||
@@ -153,22 +151,82 @@ assert.equal(arg1, 1); | ||
}); | ||
test('3.2 Mutating arguments', function(done) { | ||
var count = 1; | ||
function checkMiddlewareArgs(foo, bar) { | ||
foo.a++; | ||
bar.b++; | ||
count++; | ||
assert.equal(foo.a, count); | ||
assert.deepEqual(bar.b, count + 1); | ||
} | ||
test('3.2 A callback as middleware invocation argument', function(done) { | ||
midd.make(obj, 'read', function(argCb, middDone) { | ||
argCb(666); | ||
middDone(null, 999); | ||
}); | ||
obj = Object.create(null); | ||
lastMidd = checkMiddlewareArgs; | ||
firstMidd = checkMiddlewareArgs; | ||
secondMidd = checkMiddlewareArgs; | ||
thirdMidd = checkMiddlewareArgs; | ||
midd.make(obj, 'create', lastMidd); | ||
obj.create.use(firstMidd, secondMidd, thirdMidd); | ||
obj.read.use(function(argCb, next) { | ||
assert.isFunction(argCb); | ||
next(); | ||
}); | ||
obj.read(function(arg) { | ||
assert.lengthOf(arguments, 1); | ||
assert.equal(arg, 666); | ||
var foo = {a: 1}; | ||
var bar = {b: 2}; | ||
obj.create(foo, bar).then(function() { | ||
done(); | ||
}); | ||
}, done).then(null, done); | ||
}); | ||
}); | ||
suite('4 middleware returning values', function() { | ||
function invoke(returnValue, done) { | ||
var lastMidd = function() {return returnValue;}; | ||
var firstMidd = function() {return returnValue;}; | ||
var obj = Object.create(null); | ||
midd.make(obj, 'create', lastMidd); | ||
obj.create.use(firstMidd); | ||
obj.create().then(done, done); | ||
} | ||
test('4.1 return undefined', function(done) { | ||
invoke(undefined, done); | ||
}); | ||
test('4.2 return null', function(done) { | ||
invoke(null, done); | ||
}); | ||
test('4.3 return void', function(done) { | ||
invoke(void 0, done); | ||
}); | ||
test('4.4 return boolean false', function(done) { | ||
invoke(false, done); | ||
}); | ||
test('4.5 return boolean true', function(done) { | ||
invoke(true, done); | ||
}); | ||
test('4.6 return empty object', function(done) { | ||
invoke({}, done); | ||
}); | ||
test('4.7 return string', function(done) { | ||
invoke('one', done); | ||
}); | ||
test('4.8 return number', function(done) { | ||
invoke(7, done); | ||
}); | ||
test('4.9 return number 0', function(done) { | ||
invoke(0, done); | ||
}); | ||
test('4.10 return NaN', function(done) { | ||
invoke(NaN, done); | ||
}); | ||
test('4.11 return empty Array', function(done) { | ||
invoke([], done); | ||
}); | ||
test('4.12 return function', function(done) { | ||
invoke(function(){}, done); | ||
}); | ||
test('4.13 return regex', function(done) { | ||
invoke(/a/, done); | ||
}); | ||
test('4.13 return Error instance', function(done) { | ||
invoke(new Error('inst'), done); | ||
}); | ||
}); | ||
suite('5. Failing middleware cases', function(){ | ||
@@ -193,28 +251,3 @@ var obj; | ||
}); | ||
test('5.2 a middleware calls next with an error', function(done){ | ||
obj.create.use(function(next){ | ||
next(new Error('an error')); | ||
}); | ||
obj.create().then(noop, function(err){ | ||
assert.instanceOf(err, Error, '"err" should be instanceOf Error'); | ||
assert.equal(err.message, 'an error', 'Error message should match'); | ||
done(); | ||
}).then(null, done); | ||
}); | ||
test('5.3 a failing middleware prevents rest of middleware from executing', function(done){ | ||
obj.create.use(function(next){ | ||
next(new Error('an error')); | ||
}); | ||
var middSpy = sinon.spy(); | ||
obj.create.use(middSpy); | ||
obj.create().then(null, function() { | ||
assert.notOk(middSpy.called, 'second middleware should not be called'); | ||
done(); | ||
}, done).then(null, done); | ||
}); | ||
}); | ||
@@ -24,4 +24,4 @@ /** | ||
function applyTests(num, middMethod, thing) { | ||
var middOpts = {}; | ||
setup(function() { | ||
var middOpts = {}; | ||
@@ -82,2 +82,47 @@ if (middMethod !== 'use') { | ||
}); | ||
test('7.' + num + '.5 async resolution', function(done) { | ||
var invoked = false; | ||
thing.create[middMethod](function() { | ||
return new Promise(function(resolve) { | ||
setTimeout(function(){ | ||
invoked = true; | ||
resolve(); | ||
}); | ||
}); | ||
}); | ||
thing.create().then(function(){ | ||
assert.ok(invoked); | ||
}).then(done, done); | ||
}); | ||
test('7.' + num + '.6 async rejection', function(done) { | ||
var invoked = false; | ||
thing.create[middMethod](function() { | ||
return new Promise(function(resolve, reject) { | ||
setTimeout(function(){ | ||
invoked = true; | ||
reject(); | ||
}); | ||
}); | ||
}); | ||
thing.create().then(null, function() { | ||
assert.ok(invoked); | ||
}).then(done, done); | ||
}); | ||
test('7.' + num + '.7 async resolution for final callback', function(done) { | ||
var invoked = false; | ||
thing = Object.create(null); | ||
midd.make(thing, 'create', function() { | ||
return new Promise(function(resolve) { | ||
setTimeout(function(){ | ||
invoked = true; | ||
resolve(); | ||
}); | ||
}); | ||
}, middOpts); | ||
thing.create().then(function() { | ||
assert.ok(invoked); | ||
}).then(done, done); | ||
}); | ||
} | ||
@@ -119,3 +164,4 @@ | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
715
36178
267