Skip to content

Instantly share code, notes, and snippets.

@ysndr

ysndr/Arrow.js

Last active Aug 29, 2015
Embed
What would you like to do?
arrowJS ( Minimal Middleware Manager (M3) )
/** ---IMPORTS {{{ */
var E3 = require('E3')
/** ---OUT --- */
var Arrow = module.exports = {}
Arrow.create = function(options){
options = options || {}
var stack = []
, api = {}
api.stack = inspectStack
api.flush = flushStack
Object.freeze(api)
stackManager.use = use
stackManager.api = api
return stackManager
function stackManager(){
var context = options.context || {}
, layerIndex = 0
, handlerIndex = 0
, args = [].slice.call(arguments)
, warnings = []
// calback ( if specified)
, final = ('function' === typeof args[args.length -1])
? args.pop() // shortens arguments by 1
: null
args.push(next)
next()
function next( err ){
var layer = stack[layerIndex]
/**
* next() will llot for handler at handlerIndex
* on the current layer which will be applied the arguments
* and call next(err).
* next() will then look for a handler at handlerIndex++
* If next() does not find any defined handler
* it will step over to the next layer
* if there is no further layer next() is done
* --------------------------------------------------------
* If an error occurs next() tests if err is an object
* which can (and will) be thrown
* --------------------------------------------------------
* If err is a string it's a warning
* thus it will be passed to the warning collection
* further the current layer will be aborded
* and it will be stepped over to the next layer.
*/
if (!layer || ( err && 'object' === typeof err )){
args.pop()
args.unshift(err
|| (warnings.length > 0)
? {warnings : warnings}
: null)
// handles callback before exiting
if (final){
final.apply(context /*proto*/, args/*args*/)
return
}
}
if (err && 'string' === typeof err){
warnings.push(err)
layerIndex++
handlerIndex = 0
return next()
}
var handler = layer[handlerIndex]
if (!handler){
layerIndex++
handlerIndex = 0 // prepare for next layer
return next()
}
handlerIndex++
return handler.apply(context, args)
}
}
function use(check){
if (!check) return stackManager
var args = [].slice.call(arguments)
, arg = 0
, layer = []
, err = null
// validates every parsed layer
for ( ; arg < args.length ; arg++){
if (Array.isArray( args[arg] )){
// v Is null if no error in current layer
err = validateLayer( layer )
|| validateLayer( args[arg] )
// ^ Is null if no error in nested layer
if (err) break
// adds current layer (if defined)
if ( layer.length > 0) { stack.push(layer); layer = [] }
stack.push(args[arg])
// and nested layer to stack
}else {
layer.push(args[arg])
}
}
err = err || (layer.length > 0)
? validateLayer(layer) || err //if no error yet, validate open layer
: err //if no error in open stack error is null
if (err) throw new Error(err)
if (layer.length > 0) stack.push(layer) // adds open layer to stack
return stackManager
function validateLayer(layer){
var index = 0
if ( layer.length < 1 ){
return ('Layer ( '
+ layer
+' ) might not be an empty array')
}
for ( ; index < layer.length ; index++ ){
if( typeof layer[index] !== 'function' ){
return ('Type of Argument ( '
+ layer[index]
+ ' ) is [ '
+ (typeof layer[index])
+ ' ] -- Must be [ function ]!')
}
}
return null // if there is no error
}
}
function flushStack(){
stack = []
console.warn('Stack wiped!!!')
}
function inspectStack(){
return stack
}
}
{
"name": "ArrowJS",
"version": "0.0.1",
"description": "Minimal Middleware framework for Node.js",
"main": "Arrow.js",
"repository": {
"type": "git",
"url": "https://gist.github.com/yangodev/e5fc125b6257e3a10f5f/"
},
"url": "git@gist.github.com:/e5fc125b6257e3a10f5f.git",
"keywords": [
"Minimal",
"Middleware",
"Manager",
"Framework",
"M3",
"express"
],
"author": {
"name": "y4ng0 @ yangodev"
},
"license": "MIT",
"bugs": {
"url": "https://gist.github.com/yangodev/e5fc125b6257e3a10f5f/"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment