README.md
# middleware-decorator
Decorates functions with middleware super-powers.
[![Build Status](https://travis-ci.org/lifenautjoe/middleware-decorator.svg?branch=master)](https://travis-ci.org/lifenautjoe/middleware-decorator)
[![Code Climate](https://codeclimate.com/github/thefabulousdev/middleware-decorator/badges/gpa.svg)](https://codeclimate.com/github/thefabulousdev/middleware-decorator)
[![Test Coverage](https://codeclimate.com/github/thefabulousdev/middleware-decorator/badges/coverage.svg)](https://codeclimate.com/github/thefabulousdev/middleware-decorator)
[![Dependency Status](https://david-dm.org/thefabulousdev/middleware-decorator.svg)](https://david-dm.org/thefabulousdev/middleware-decorator)
[![devDependency Status](https://david-dm.org/thefabulousdev/middleware-decorator/dev-status.svg)](https://david-dm.org/thefabulousdev/middleware-decorator#info=devDependencies)
## Table of contents
* [Features](#features)
* [Installation](#installation)
+ [npm](#npm)
+ [bower](#bower)
* [Sample usage](#sample-usage)
* [Prerequisites](#prerequisites)
- [Decorate with a synchronous middleware runner](#decorate-with-a-synchronous-middleware-runner)
- [Decorate with an asynchronous middleware runner](#decorate-with-an-asynchronous-middleware-runner)
- [Decorate with a promised middleware runner](#decorate-with-a-promised-middleware-runner)
* [API](#api)
+ [Module](#module)
- [(anyFunction) : SynchronousMiddlewareRunner](#anyfunction--synchronousmiddlewarerunner)
- [promised(anyFunction) : PromisedMiddlewareRunner](#promisedanyfunction--promisedmiddlewarerunner)
- [async(anyFunction) : AsynchronousMiddlewareRunner](#asyncanyfunction--asynchronousmiddlewarerunner)
+ [SynchronousMiddlewareRunner](#synchronousmiddlewarerunner)
- [synchronousMiddlewareRunner.use(synchronousMiddleware: Function)](#synchronousmiddlewarerunnerusesynchronousmiddleware-function)
- [synchronousMiddlewareRunner.has(synchronousMiddleware: Function):boolean](#synchronousmiddlewarerunnerhassynchronousmiddleware-functionboolean)
- [synchronousMiddlewareRunner(...args);](#synchronousmiddlewarerunnerargs)
+ [AsynchronousMiddlewareRunner](#asynchronousmiddlewarerunner)
- [asynchronousMiddlewareRunner.use(asynchronousMiddleware: Function)](#asynchronousmiddlewarerunneruseasynchronousmiddleware-function)
- [asynchronousMiddlewareRunner.has(asynchronousMiddleware: Function):boolean](#asynchronousmiddlewarerunnerhasasynchronousmiddleware-functionboolean)
- [asynchronousMiddlewareRunner(...args).cb(callback: Function);](#asynchronousmiddlewarerunnerargscbcallback-function)
+ [PromisedMiddlewareRunner](#promisedmiddlewarerunner)
- [promisedMiddlewareRunner.use(promisedMiddleware: Function)](#promisedmiddlewarerunnerusepromisedmiddleware-function)
- [promisedMiddlewareRunner.has(promisedMiddleware: Function):boolean](#promisedmiddlewarerunnerhaspromisedmiddleware-functionboolean)
- [promisedMiddlewareRunner(...args).then(promiseHandler: Function);](#promisedmiddlewarerunnerargsthenpromisehandler-function)
* [Contributing](#contributing)
- [Clone the repository](#clone-the-repository)
- [Install dependencies](#install-dependencies)
- [Use npm scripts](#use-npm-scripts)
## Features
- Synchronous, asynchronous and promised middleware support
- Zero dependencies
- UMD Module
- Tiny(5KB)
## Installation
### npm
```sh
npm install middleware-decorator
```
### bower
```sh
bower install middleware-decorator
```
## Sample usage
#### Prerequisites
The module has been imported with your favorite loader as `middlewareDecorator` and the following function is available
```js
function getPrice(){
return 10;
}
```
#### Decorate with a synchronous middleware runner
```js
getPrice = middlewareDecorator(getPrice);
function halfPriceMiddleware(price){
return price / 2;
}
getPrice.use(halfPriceMiddleware);
console.log(getPrice()); // 5
```
#### Decorate with an asynchronous middleware runner
```js
getPrice = middlewareDecorator.async(getPrice);
function halfPriceMiddleware(price, done){
setTimeout(()=>{
done(price / 2);
}, 2000);
}
getPrice.use(halfPriceMiddleware);
getPrice().cb((price)=>{
console.log(price()); // 5
});
```
#### Decorate with a promised middleware runner
```js
getPrice = middlewareDecorator.promised(getPrice);
// Can return any value, if it's a promise, next middleware won't get executed till resolved
function halfPriceMiddleware(price){
return hasHalfPriceDiscount().then((hasHalfPriceDiscount)=>{
return hasHalfPriceDiscount ? price / 2 : price;
});
}
getPrice.use(halfPriceMiddleware);
getPrice().then((price)=>{
console.log(price()); // 5
});
```
## API
### Module
#### (anyFunction) : SynchronousMiddlewareRunner
Takes a function as argument and returns a synchronous middleware runner
```js
synchronousMiddlewareRunner = middlewareDecorator(anyFunction);
```
#### promised(anyFunction) : PromisedMiddlewareRunner
Takes a function as argument and returns a promised middleware runner
```js
promisedMiddlewareRunner = middlewareDecorator(anyFunction);
```
#### async(anyFunction) : AsynchronousMiddlewareRunner
Takes a function as argument and returns an asynchronous middleware runner
```js
asynchronousMiddlewareRunner = middlewareDecorator(anyFunction);
```
### SynchronousMiddlewareRunner
#### synchronousMiddlewareRunner.use(synchronousMiddleware: Function)
Adds a synchronous middleware
```js
synchronousMiddlewareRunner.use((middlewareOutput) => {
return middlewareOutput;
});
```
#### synchronousMiddlewareRunner.has(synchronousMiddleware: Function):boolean
Checks if has the given middleware
```js
synchronousMiddlewareRunner.has(aMiddleware); // true || false
```
#### synchronousMiddlewareRunner(...args);
Calls the original function with the given arguments and runs it's output through the registered synchronous middleware
```js
synchronousMiddlewareRunner(arg1, arg2);
```
### AsynchronousMiddlewareRunner
#### asynchronousMiddlewareRunner.use(asynchronousMiddleware: Function)
Adds an asynchronous middleware
```js
asynchronousMiddlewareRunner.use((middlewareOutput, done) => {
done(middlewareOutput);
});
```
#### asynchronousMiddlewareRunner.has(asynchronousMiddleware: Function):boolean
Checks if has the given middleware
```js
asynchronousMiddlewareRunner.has(aMiddleware); // true || false
```
#### asynchronousMiddlewareRunner(...args).cb(callback: Function);
Calls the original function with the given arguments and runs it's output through the registered middleware, when done, calls the provided callback
```js
asynchronousMiddlewareRunner(arg1, arg2).cb((middlewareOutput)=>{
console.log(`Done with ${middlewareOutput}`);
});
```
### PromisedMiddlewareRunner
#### promisedMiddlewareRunner.use(promisedMiddleware: Function)
Adds a promised middleware
```js
promisedMiddlewareRunner.use((middlewareOutput) => {
return new Promise((resolve, reject) => {
resolve(middlewareOutput);
});
});
```
#### promisedMiddlewareRunner.has(promisedMiddleware: Function):boolean
Checks if has the given middleware
```js
promisedMiddlewareRunner.has(aMiddleware); // true || false
```
#### promisedMiddlewareRunner(...args).then(promiseHandler: Function);
Calls the original function with the given arguments and runs it's output through the registered middleware, when done, calls the provided callback
```js
promisedMiddlewareRunner(arg1, arg2).then((middlewareOutput)=>{
console.log(`Done with ${middlewareOutput}`);
});
```
## Contributing
#### Clone the repository
``` sh
git clone git@github.com:thefabulousdev/middleware-decorator.git
```
#### Install dependencies
``` sh
npm install
```
#### Use npm scripts
- `npm test` - Lint the library and tests, then run the unit tests
- `npm run lint` - Lint the source and unit tests
- `npm run watch` - Continuously run the unit tests as you make changes to the source
and test files themselves
- `npm run test-browser` - Build the library for use with the browser spec runner.
Changes to the source will cause the runner to automatically refresh.
- `npm run build` - Lint then build the library
- `npm run coverage` - Generate a coverage report
#### Author: [Joel Hernández](https://github.com/thefabulousdev)