diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..87f8cd9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "0.10" \ No newline at end of file diff --git a/README.md b/README.md index 2133d8e..d4e38cf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,59 @@ -node-mware -========== +# mware -Module for creating middleware paradigms. +mware is a utility for creating middleware paradigms with any node or browser application. Inspired by the middleware pattern in [connect](https://github.com/senchalabs/connect). + +[![Build Status](https://travis-ci.org/tur-nr/node-mware?branch=master)](https://travis-ci.org/tur-nr/node-mware) + +### Example + +```js +var use = require('mware')(); +var message = {}; + +use(function(msg, next) { + // msg === message + next(); +}); + +use.run(message, function(err) { + if (err) return console.log(err); + // finished +}); +``` + +## Installation + +### Node + +To install mware in a Node application use npm. + +```bash +npm install mware +``` + +### Browser + +No tests available for the browser but you may try using it via [webpack](https://github.com/webpack/webpack). + +```bash +webpack index.js mware.js +``` + +## Test + +To run tests use the npm. + +```bash +npm install +npm test +``` + +## Documentation + +todo + +## License + +[MIT](LICENSE) + +Copyright (c) 2014 [Christopher Turner](https://github.com/tur-nr) \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..09570bb --- /dev/null +++ b/index.js @@ -0,0 +1,66 @@ +var slice = require('sliced'); + +module.exports = function mware(context) { + if (typeof context !== 'object') { + context = null; + } + + return (function() { + var calls = []; + + function use() { + var args = slice(arguments); + + while (args.length) { + var call = args.shift(); + + if (Array.isArray(call)) { + use.apply(this, call); + continue; + } + + if (typeof call !== 'function') { + throw new TypeError(); + } + + calls.push(call); + } + + return context; + } + + use.run = function run() { + var args = slice(arguments) + , stack = calls.concat() + , done; + + if (typeof args[args.length - 1] === 'function') { + done = args.pop(); + } + + if (!stack.length) { + return done(); + } + + args.push(next); + + function exec() { + stack.shift().apply(context, args); + } + + function next(err, fin) { + if (err || fin || !stack.length) { + stack = null; + if (done) { done(err) }; + return; + } + + exec(); + } + + exec(); + }; + + return use; + }()); +}; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..e243fd6 --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "name": "mware", + "version": "0.0.1", + "description": "Module for creating middleware paradigms.", + "main": "index.js", + "scripts": { + "test": "./node_modules/.bin/mocha" + }, + "repository": { + "type": "git", + "url": "https://github.com/tur-nr/node-mware" + }, + "keywords": [ + "middleware", + "middle-ware", + "use", + "custom" + ], + "author": "Christopher Turner ", + "license": "MIT", + "bugs": { + "url": "https://github.com/tur-nr/node-mware/issues" + }, + "homepage": "https://github.com/tur-nr/node-mware", + "dependencies": { + "sliced": "0.0.5" + }, + "devDependencies": { + "mocha": "^1.21.4" + } +} diff --git a/test/mware.tests.js b/test/mware.tests.js new file mode 100644 index 0000000..433522c --- /dev/null +++ b/test/mware.tests.js @@ -0,0 +1,127 @@ +var mware = require('../') + , assert = require('assert'); + +describe('mware', function() { + describe('#use()', function() { + it('should add middleware', function(done) { + var use = mware(); + + assert.equal(typeof use, 'function', 'use is a function'); + + use(function(next) { + assert.equal(typeof next, 'function'); + done(); + }); + use.run(); + }); + + it('should add with args', function(done) { + var use = mware(); + + use(function(arg1, arg2, next) { + assert.equal(arg1, 1); + assert.equal(arg2, 2); + assert.equal(typeof next, 'function'); + done(); + }); + use.run(1, 2); + }); + + it('should modify args', function(done) { + var use = mware() + , arg = { foo: 'bar' }; + + use(function(obj, next) { + assert.equal(obj, arg); + arg.baz = 'qux'; + next(); + }); + use(function(obj, next) { + assert.equal(obj, arg); + assert.equal(obj.baz, 'qux'); + done(); + }); + use.run(arg); + }); + + it('should add multiple', function(done) { + var use = mware(); + + use(function(next) { next(); } + , function(next) { done(); } + ); + use.run(); + }); + + it('should add array', function(done) { + var use = mware(); + + use([function(next) { next(); } + , function(next) { done(); } + ]); + use.run(); + }); + + it('should throw TypeError', function() { + var use = mware(); + + assert.throws(function() { + use({}); + }, TypeError); + }); + }); + + describe('#run()', function() { + it('should callback done', function(done) { + var use = mware(); + + use(function(next) { next(); }); + + use.run(function(err) { + assert.equal(err, null); + done(); + }); + }); + it('should callback done, with args', function(done) { + var use = mware(); + + use(function(arg1, arg2, next) { + assert.equal(arg1, 1); + assert.equal(arg2, 2); + assert.equal(typeof next, 'function'); + next(); + }); + + use.run(1, 2, function(err) { + assert.equal(err, null); + done(); + }); + }); + + it('should stop on error', function(done) { + var use = mware(); + + use(function(next) { next(new Error()); } + , function() { throw new Error('should never have thrown'); } + ); + + use.run(function(err) { + assert.ok(err instanceof Error); + done(); + }); + }); + + it('should finish early', function(done) { + var use = mware(); + + use(function(next) { next(null, true); } + , function() { throw new Error('should never have thrown'); } + ); + + use.run(function(err) { + assert.equal(err, null); + done(); + }); + }); + }); +}); \ No newline at end of file