Comparing version 0.0.1 to 0.1.0
220
index.js
@@ -16,3 +16,4 @@ (function (name, context, definition) { | ||
} | ||
})('ginga', this, function () { | ||
})('ginga', this, function() { | ||
var is = { | ||
@@ -42,4 +43,3 @@ 'string': function(val){ | ||
function emptyFn(cb){ | ||
if(is.function(cb)) cb(null, null); | ||
function dummy(){ | ||
return true; | ||
@@ -77,3 +77,3 @@ } | ||
}else | ||
obj.check = emptyFn; | ||
obj.check = dummy; | ||
spec.push(obj); | ||
@@ -114,47 +114,51 @@ } | ||
//ginga use method | ||
function use(){ | ||
//init hooks | ||
if(!this._hooks){ | ||
this._hooks = {}; | ||
}else{ | ||
//prototype instance | ||
if(!this.hasOwnProperty('_hooks')){ | ||
var _hooks = this._hooks; | ||
this._hooks = {}; | ||
for(var _name in _hooks) | ||
this._hooks[_name] = [ _hooks[_name] ]; | ||
} | ||
} | ||
var args = Array.prototype.slice.call(arguments); | ||
//this refers to scope instance | ||
//self refers to driver instance | ||
var name = null, i, j, l, m; | ||
if(is.array(args[0])){ | ||
//use(['a','b','c'], fn) | ||
//use(['a','b','c'], ...) | ||
var arr = args.shift(); | ||
for(i = 0, l = arr.length; i<l; i++) | ||
this.use.apply(this, [arr[i]].concat(args)); | ||
use.apply(this, [arr[i]].concat(args)); | ||
return this; | ||
}else if(is.object(args[0])){ | ||
//use({ a: fn1, b: fn2, c: fn3 }) | ||
var obj = args.shift(); | ||
for(i in obj) | ||
this.use.call(this, i, obj[i]); | ||
}else if(is.object(args[0]) && args[0]._hooks){ | ||
//use(ginga) | ||
for(var _name in args[0]._hooks) | ||
use.call(this, _name, args[0]._hooks[_name]); | ||
return this; | ||
} | ||
//single method name | ||
//method name | ||
if(is.string(args[0])) | ||
name = args.shift(); | ||
if(!name) | ||
throw new Error('Need to specify method name for instance middleware.'); | ||
throw new Error('Method name is not defined.'); | ||
if(!this._hooks[name]) | ||
this._hooks[name] = []; | ||
//scope var init | ||
if(!this._middleware) | ||
this._middleware = {}; | ||
if(!this._middleware[name]) | ||
this._middleware[name] = []; | ||
for(i = 0, l = args.length; i<l; i++){ | ||
if(is.function(args[i])){ | ||
this._middleware[name].push(args[i]); | ||
this._hooks[name].push(args[i]); | ||
}else if(is.array(args[i])){ | ||
//use('a', [fn1, fn2, fn3]) | ||
for(j = 0, m = args[i].length; j<m; j++) | ||
this.use.call(this, name, args[i][j]); | ||
use.call(this, name, args[i][j]); | ||
return this; | ||
}else | ||
throw new Error('invalid function'); | ||
throw new Error('Middleware must be a function'); | ||
} | ||
@@ -165,61 +169,27 @@ | ||
//Ginga constructor | ||
function Ginga(scope){ | ||
if(!(this instanceof Ginga)) | ||
return new Ginga(scope); | ||
this._middleware = []; | ||
this.scope = scope || {}; | ||
this.scope.use = use; | ||
} | ||
Ginga.prototype.use = function(){ | ||
var args = Array.prototype.slice.call(arguments); | ||
var name = null, i, j, l, m; | ||
if(is.array(args[0])){ | ||
//use(['a','b','c'], fn) | ||
var arr = args.shift(); | ||
for(i = 0, l = arr.length; i<l; i++) | ||
this.use.apply(this, [arr[i]].concat(args)); | ||
return this; | ||
}else if(is.object(args[0])){ | ||
//use({ a: fn1, b: fn2, c: fn3 }) | ||
var obj = args.shift(); | ||
for(i in obj) | ||
this.use.call(this, i, obj[i]); | ||
return this; | ||
//util: flatten array | ||
function flatten(arr, res){ | ||
if(!res){ | ||
res = []; | ||
} | ||
if(is.string(args[0])) | ||
name = args.shift(); | ||
for(i = 0, l = args.length; i<l; i++){ | ||
if(is.function(args[i])){ | ||
this._middleware.push({ | ||
name: name, | ||
fn: args[i] | ||
}); | ||
}else if(is.array(args[i])){ | ||
//use('a', [fn1, fn2, fn3]) | ||
for(j = 0, m = args[i].length; j<m; j++) | ||
this.use.call(this, name, args[i][j]); | ||
return this; | ||
for(var i = 0, l = arr.length; i < l; i++){ | ||
if(arr[i] && arr[i].constructor == Array){ | ||
flatten(arr[i], res); | ||
}else{ | ||
throw new Error('invalid function'); | ||
res.push(arr[i]); | ||
} | ||
} | ||
return this; | ||
}; | ||
return res; | ||
} | ||
Ginga.prototype.define = function(){ | ||
//ginga define method | ||
function define(){ | ||
var args = Array.prototype.slice.call(arguments); | ||
var i, l; | ||
var name = args[0]; | ||
var name = args.shift(); | ||
if(is.array(name)) { | ||
name = args.shift(); | ||
for(i = 0, l = name.length; i<l; i++) | ||
this.define.apply(this, [name[i]].concat(args)); | ||
define.apply(this, [name[i]].concat(args)); | ||
return this; | ||
@@ -233,39 +203,24 @@ } | ||
if (!is.function(invoke)) | ||
invoke = emptyFn; | ||
invoke = null; | ||
this.use.apply(this, args); | ||
var pre = args; | ||
//filter local middleware | ||
var middleware = []; | ||
for(i = 0, l = this._middleware.length; i<l; i++){ | ||
var _name = this._middleware[i].name; | ||
if(!_name || _name === name) | ||
middleware.push(this._middleware[i].fn); | ||
} | ||
//pipe with local middleware | ||
var _pipe = [].concat( | ||
middleware, | ||
invoke | ||
); | ||
//define scope method | ||
this.scope[name] = function(){ | ||
this[name] = function(){ | ||
var args = Array.prototype.slice.call(arguments); | ||
//this refers to scope instance, not driver instance | ||
var self = this; | ||
var callback = emptyFn; | ||
var callbacks = []; | ||
if (is.function(args[args.length - 1])) | ||
callback = args.pop(); | ||
callbacks.push(args.pop()); | ||
var pipe = _pipe; | ||
//pipe scope middleware if exists | ||
if(this._middleware && this._middleware[name]) | ||
pipe = [].concat( | ||
middleware, | ||
this._middleware[name], | ||
invoke | ||
); | ||
//define pipeline; | ||
var pipe = [pre]; | ||
if(this._hooks && this._hooks[name]) | ||
pipe.push(this._hooks[name]); | ||
if(invoke) | ||
pipe.push(invoke); | ||
pipe = flatten(pipe); | ||
//context object and next triggerer | ||
@@ -276,43 +231,33 @@ var ctx = { | ||
}; | ||
var callbacks = [callback]; | ||
var index = 0; | ||
var size = pipe.length; | ||
function trigger(){ | ||
var fn = pipe[index]; | ||
var len = fn.length; | ||
if(len >= 2) | ||
fn.call(self, ctx, next, onEnd); | ||
else if(len === 1) | ||
fn.call(self, next); | ||
else if(len === 0){ | ||
throw new Error('Missing callback function.'); | ||
} | ||
} | ||
function onEnd(fn){ | ||
if(!fn) return; | ||
if(!is.function(fn)) | ||
throw new Error('end callback must be function'); | ||
callbacks.push(fn); | ||
if(is.function(fn)) | ||
callbacks.push(fn); | ||
} | ||
function next(){ | ||
//trigger callback if args exist | ||
if(arguments.length > 0){ | ||
var args = Array.prototype.slice.call(arguments); | ||
for(i = 0, l = callbacks.length; i<l; i++){ | ||
callbacks[i].apply(self, args); | ||
} | ||
for(var i = 0, l = callbacks.length; i<l; i++) | ||
callbacks[i].apply(self, arguments); | ||
return; | ||
} | ||
index++; | ||
if(pipe[index]){ | ||
//trigger pipe | ||
trigger(); | ||
if(index < size){ | ||
var fn = pipe[index]; | ||
var len = fn.length; | ||
index++; | ||
if(len >= 2) | ||
fn.call(self, ctx, next, onEnd); | ||
else if(len === 1) | ||
fn.call(self, next); | ||
else if(len === 0){ | ||
throw new Error('Missing callback function.'); | ||
} | ||
}else{ | ||
//trigger empty callback if no more pipe | ||
for(i = 0, l = callbacks.length; i<l; i++){ | ||
callbacks[i].apply(self); | ||
} | ||
next(null); | ||
} | ||
} | ||
trigger(); | ||
next(); | ||
@@ -322,4 +267,13 @@ return this; | ||
return this; | ||
}; | ||
} | ||
function Ginga(scope){ | ||
scope = scope || {}; | ||
scope.use = use; | ||
scope.define = define; | ||
return scope; | ||
} | ||
Ginga.use = use; | ||
Ginga.define = define; | ||
Ginga.params = params; | ||
@@ -326,0 +280,0 @@ |
{ | ||
"name": "ginga", | ||
"version": "0.0.1", | ||
"description": "", | ||
"version": "0.1.0", | ||
"description": "Ginga modularises asynchronous control flow of Javascript functions.", | ||
"scripts": { | ||
@@ -6,0 +6,0 @@ "test": "set -e; for t in test/*.js; do node $t; done" |
# Ginga | ||
Ginga modularises asynchronous control flow of Javascript functions. | ||
```bash | ||
@@ -7,50 +9,4 @@ $ npm install ginga | ||
##Example | ||
Middleware | ||
```js | ||
var ginga = require('ginga'); | ||
function Clock(){ | ||
this._tick = 'tick'; | ||
this._tock = 'tock'; | ||
} | ||
ginga(Clock.prototype) | ||
.use(function(ctx, next){ | ||
ctx.logs = ['clock',this._tick]; | ||
next(); | ||
}) | ||
.use('tock',function(ctx, next){ | ||
ctx.logs.push(this._tock); | ||
next(); | ||
}) | ||
.define(['tick','tock'],function(ctx, done){ | ||
ctx.logs.push('done'); | ||
done(null, ctx.logs); | ||
}); | ||
var clock1 = new Clock(); | ||
var clock2 = new Clock(); | ||
//middleware on prototypal instance | ||
clock2.use('tick',function(ctx, next){ | ||
ctx.logs.push('tick2'); | ||
next(); | ||
}); | ||
clock2.use('tock',function(ctx, next){ | ||
next('booooom'); //error | ||
}); | ||
//Results | ||
clock1.tick(console.log.bind(console)); //null [ 'clock', 'tick', 'done' ] | ||
clock1.tock(console.log.bind(console)); //null ['clock','tick','tock','done'] | ||
clock2.tick(console.log.bind(console)); //null ['clock','tick','tick2','done'] | ||
clock2.tock(console.log.bind(console)); //'booooom' | ||
``` | ||
## Changelog | ||
## License | ||
MIT |
@@ -5,9 +5,8 @@ var tape = require('tape'); | ||
function invoke(ctx, done){ | ||
return done(null, ctx.params); | ||
} | ||
var obj = ginga() | ||
.use('f1', params('a:string','b:string?','c:function?') ) | ||
.use('f2', params('a','b:string')) | ||
.define(['f1','f2'], function(ctx, done){ | ||
return done(null, ctx.params); | ||
}) | ||
.scope; | ||
.define('f1', params('a:string','b:string?','c:function?'), invoke) | ||
.define('f2', params('a','b:string'), invoke); | ||
@@ -14,0 +13,0 @@ function fn(){} |
@@ -8,21 +8,22 @@ var tape = require('tape'); | ||
} | ||
function base(ctx, next){ | ||
ctx.logs = ['clock']; | ||
next(); | ||
} | ||
function tick(ctx, next){ | ||
ctx.logs.push(this._tick); | ||
next(); | ||
} | ||
function tock(ctx, next){ | ||
ctx.logs.push(this._tock); | ||
next(); | ||
} | ||
function end(ctx, done){ | ||
ctx.logs.push('done'); | ||
done(null, ctx.logs); | ||
} | ||
ginga(Clock.prototype) | ||
.use([ | ||
function(ctx, next){ | ||
ctx.logs = ['clock']; | ||
next(); | ||
}, | ||
function(ctx, next){ | ||
ctx.logs.push(this._tick); | ||
next(); | ||
} | ||
]) | ||
.use('tock',function(ctx, next){ | ||
ctx.logs.push(this._tock); | ||
next(); | ||
}) | ||
.define(['tick','tock'],function(ctx, done){ | ||
ctx.logs.push('done'); | ||
done(null, ctx.logs); | ||
}); | ||
.define('tick', base, tick, end) | ||
.define('tock', base, tick, tock, end); | ||
@@ -32,17 +33,19 @@ var clock1 = new Clock(); | ||
clock2.use({ | ||
'tick': [ | ||
function(ctx, next){ | ||
ctx.logs.push('more'); | ||
next(); | ||
}, | ||
function(ctx, next){ | ||
ctx.logs.push('and more tick'); | ||
next(); | ||
} | ||
], | ||
'tock': function(next){ | ||
clock2.use( | ||
'tick', | ||
function(ctx, next){ | ||
ctx.logs.push('more'); | ||
next(); | ||
}, | ||
function(ctx, next){ | ||
ctx.logs.push('and more tick'); | ||
next(); | ||
} | ||
); | ||
clock2.use( | ||
'tock', | ||
function(ctx, next){ | ||
next('booooom'); | ||
} | ||
}); | ||
); | ||
@@ -49,0 +52,0 @@ tape('ginga middleware', function (t) { |
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
10451
330
12