Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

middlewarify

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

middlewarify - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

36

middlewarify.js

@@ -15,7 +15,9 @@ /**

*
* @param {Object} obj An Object.
* @param {string} prop The property to apply the middleware pattern on.
* @param {Function=} optFinalCb Last middleware to call.
* @param {Object} obj An Object.
* @param {string} prop The property to apply the middleware pattern on.
* @param {Function=} optFinalCb Last middleware to call.
* @param {Object=} optParams Optional parameters.
* @param {boolean=} throwErrors default is true.
*/
middlewarify.make = function(obj, prop, optFinalCb) {
middlewarify.make = function(obj, prop, optFinalCb, optParams) {

@@ -25,5 +27,15 @@ var middObj = Object.create(null);

middObj.finalMidd = noopMidd;
middObj.params = {
throwErrors: true,
};
if (__.isFunction(optFinalCb)) {
middObj.finalMidd = optFinalCb;
}
if (__.isObject(optFinalCb)) {
__.extend(middObj.params, optFinalCb);
}
if (__.isObject(optParams)) {
__.extend(middObj.params, optParams);
}

@@ -57,3 +69,3 @@ obj[prop] = middlewarify._runAll.bind(null, middObj);

middlewarify._fetchAndInvoke(midds, args, done);
middlewarify._fetchAndInvoke(midds, args, middObj.params, done);

@@ -74,2 +86,3 @@ return {done: function(fn) {

* @param {Array} args An array of arbitrary arguments, can be empty.
* @param {Object} params Parameters passed by the user.
* @param {Function} done Callback.

@@ -79,3 +92,3 @@ * @param {...*} optMiddArgs Arguments passed from the last middleware.

*/
middlewarify._fetchAndInvoke = function(midds, args, done, optMiddArgs) {
middlewarify._fetchAndInvoke = function(midds, args, params, done, optMiddArgs) {
var lastMiddArgs = optMiddArgs || [];

@@ -87,4 +100,5 @@

}
var midd = midds.shift();
try {
var midd = midds.shift();
midd.apply(null, args.concat(function(err){

@@ -95,7 +109,11 @@ if (err) {

var middArgs = Array.prototype.slice.call(arguments, 1);
middlewarify._fetchAndInvoke(midds, args, done, middArgs);
middlewarify._fetchAndInvoke(midds, args, params, done, middArgs);
}
}));
} catch(ex) {
done(ex);
if (params.throwErrors) {
throw ex;
} else {
done(ex);
}
}

@@ -102,0 +120,0 @@ };

{
"name": "middlewarify",
"description": "Apply the middleware pattern to any function.",
"version": "0.0.3",
"version": "0.0.4",
"homepage": "https://github.com/thanpolas/middlewarify",

@@ -6,0 +6,0 @@ "author": {

@@ -15,4 +15,7 @@ # Middlewarify

Apply the middleware pattern:
### Quick Start Examples
Creating a middleware:
```js

@@ -24,7 +27,8 @@ var midd = require('middlewarify');

// this will be the last callback to be invoked
tasks._create = function() {
console.log('tasks._create');
tasks._create = function(done) {
console.log('tasks._create Final Fn to be invoked');
done();
};
// Make the 'create' prop a middleware function.
// Make the'create' Middleware Container.
midd.make(tasks, 'create', tasks._create);

@@ -40,12 +44,13 @@ ```

// add a middleware to the 'create' operation
tasks.create.use(function(done){
// add middleware to the 'create' operation
tasks.create.use(function(next){
console.log('middleware 1');
done();
next();
});
// add another middleware to the 'create' operation
tasks.create.use(function(done){
tasks.create.use(function(next){
console.log('middleware 2');
done();
next();
});

@@ -72,38 +77,94 @@

#### make(object, property, optFinalCallback)
#### make(object, property, optFinalCallback, optOptions)
The `middlewarify.make()` method will apply the middleware pattern to an Object's property.
The `middlewarify.make()` method will apply the middleware pattern to an Object's property, this property will be called the *Middleware Container*.
```js
// create a Middleware Container
var crud = {};
middlewarify.make(crud, 'create');
middlewarify.make(crud, 'read');
middlewarify.make(crud, 'update');
middlewarify.make(crud, 'delete');
```
Each time `make()` is used two new functions are added to the `crud` Object:
This example has created the Middleware Container `create` in the object `crud`. `create.crud` is a function that will invoke all the middleware.
* `crud.create([, ...], optCallback)` This method will invoke all added middleware in the sequence they were defined. If the final argument is a Function, it will be treated as a callback after all middleware have finished. `crud.create( function( err ){ /* check err */ } )`
* `crud.create.use(middleware [, ...])` This method will add middleware Functions to the `crud.create` container.
You can add a third argument, the `optFinalCallback`. As the name suggests this will be the final callback to be invoked in the chain of middleware execution. This callback gets the same arguments as any other middleware.
##### make() Options
`make()` accepts the following options:
* `throwErrors` type: **Boolean**, default: `true` If set to false all thrown errors will be suppressed and available only through the `.done()` method.
```js
// don't throw errors
var crud = {};
middlewarify.make(crud, 'create', {throwErrors: false});
crud.create.use(function(){
throw new Error('an error');
});
// executing the middleware will not throw an error, the exception
// will be available only through the .done() callback
crud.create().done(function(err) {
err.message === 'an error'; // true
});
```
#### The use(fn) Method
The middleware container exposes a `use` method to add middleware. `use()` accepts any number of parameters as long they are type Function or Arrays of Functions.
The Middleware Container exposes a `use` method so you can add any number of middleware. `use()` accepts any number of parameters as long they are of type Function or Arrays of Functions.
```js
// create the Middleware Container
var crud = {};
middlewarify.make(crud, 'create');
middlewarify.make(crud, 'create', fnFinal);
// add middleware
// add 3 middleware functions
crud.create.use([fn1, fn2], fn3);
// then add another one
crud.create.use(fn4);
```
#### Invoking the callbacks
In the above example we added 4 middleware before the final method `fnFinal` will be invoked. A FIFO queue is implemented so the order of execution will be:
The middleware container is a function that accepts any number of arguments and an optional callback.
1. `fn1()`
2. `fn2()`
3. `fn3()`
4. `fn4()`
5. `fnFinal()`
Any argument passed to the middleware container will also be passed to all middleware.
#### Middleware Arguments
All middleware gets invoked with a callback so it can pass control to the next middleware.
following up on the previous examples:
```js
crud.create.use(function(next) {
// do stuff
next();
});
```
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
The Middleware Container is nothing but a function that accepts any number of arguments.
Any argument passed to the Middleware Container will also be passed to all middleware.
```js
var crud = {};

@@ -113,19 +174,47 @@ middlewarify.make(crud, 'create');

// run all middleware
crud.create(userDataObject);
crud.create({a: 1, b:2}, 'bar');
```
The optional callback should always be defined last, it gets invoked when all middleware have finished. It provides at least one argument, `err` which if has a truthy value (typically an instance of `Error`) meas that something did not go well.
Arguments middleware will get:
**The last middleware** to be invoked can pass arguments to the *Create Callback* like so:
```js
crud.create.use(function(arg1, arg2, next) {
arg1 === {a:1, b:2}; // true
arg2 === 'bar'; // true
next();
});
```
#### Getting the Middleware Results and Error Handling
Because any argument passed to the Middleware Container (`crud.create(arg1, arg2, fn1);`) will get piped to the middleware, we cannot add a callback within these arguments. Thus the function `.done()` is provided, so you can check for errors or results.
```js
crud.create(arg1, arg2, fn1).done(function(err) {
if (err) {
return console.error(err);
}
// all cool...
});
```
The only way to pass arguments back to the callback of the `.done()` method is through the *Final Callback* that is defined in the `make()` method.
```js
var crud = {};
var lastMiddlware = function(next) {
/* ... */
next(null, 'one', 'two');
var lastMiddlware = function(done) {
// since this is the final middleware, we name the
// callback "done" instead of "next"
// and we invoke it with a null value as the first
// argument to indicate there were no errors.
done(null, 'one', 'two');
});
// now create the Middleware Container
middlewarify.make(crud, 'create', lastMiddlware);
// run all middleware
crud.create(userDataObject).done(function(err, arg1, arg2) {
// Invoke the Middleware Container
crud.create().done(function(err, arg1, arg2) {
if (err) { /* tough love */ }

@@ -138,18 +227,7 @@

#### The Middleware Callback
> **Beware of Error Handling** Middlewarify will catch all thrown errors from your middleware. They will be piped to the `.done()` method. So if any of your middleware functions throws an error, it will not be visible unless you setup the `.done()` callback.
When adding a `middleware` Function (i.e. `crud.create.use(middleware)`) by default it will be invoked with only one argument, the `next` callback. If you add arguments when calling the middleware container `crud.create(arg1, arg2)`, all middleware callbacks will be invoked with these arguments first. The `next` callback will always be last.
> Invoking next() with a truthy argument (i.e. `next(err)`) will stop invoking more middleware. The flow is passed to the `optFinalCallback` if defined in the `make()` method or silently dismissed.
```js
crud.create.use(function(arg1, arg2, next) {
if (arg1 !== arg2) { return next(new Error('not a match'))}
next();
});
crud.create(foo, bar);
```
## Release History
- **v0.0.4**, *10 Oct 2013*
- Added option to not throw errors
- **v0.0.3**, *02 Aug 2013*

@@ -156,0 +234,0 @@ - Added a more explicit way to declare callbacks when invoking the middleware.

@@ -130,3 +130,3 @@ /**

suite('5. Failing cases', function(){
suite('5. Failing middleware cases', function(){
var obj;

@@ -136,9 +136,18 @@ setup(function(){

midd.make(obj, 'create');
});
test('5.1 a middleware throws an error', function(){
test('5.1.1 middleware throws an error', function(){
obj.create.use(function(){
throw new Error('an error');
});
obj.create().done(function(err){
assert.throws(obj.create, Error);
});
test('5.1.2 middleware throws an error when param is not throw', function(){
var custObj = Object.create(null);
midd.make(custObj, 'create', {throwErrors: false});
custObj.create.use(function(){
throw new Error('an error');
});
custObj.create().done(function(err){
assert.instanceOf(err, Error, '"err" should be instanceOf Error');

@@ -171,4 +180,3 @@ assert.equal(err.message, 'an error', 'Error message should match');

});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc