pudge
Version:
simple node.js hook utility
135 lines (118 loc) • 3.52 kB
JavaScript
;
var extend = require('extend');
var store = require('./store');
var NORMAL = 'NORMAL';
var BEFORE = 'BEFORE';
var AFTER = 'AFTER';
var debug = require('debug')('pudge');
function addHook(type, name, key, fn) {
var attach = function() {
return addHook(type, name, key, fn);
};
if (typeof key === "function") {
fn = key;
key = undefined;
}
if (Array.isArray(name)) {
name.forEach(function(n) {
addHook(type, n, key, fn);
});
} else {
debug('adding hook', type, name);
store.add(type, name, {
fn: fn,
key: key
});
}
return {
key: key,
run: fn,
name: name,
type: type,
attach: attach
};
}
exports.on = exports.register = addHook.bind(this, NORMAL);
exports.before = addHook.bind(this, BEFORE);
exports.after = addHook.bind(this, AFTER);
function runHook(hooks, args) {
var current = Promise.resolve();
if (!hooks) {
hooks = [];
}
var results = {};
return Promise.all(hooks.map(function(hook){
var fn = hook.fn;
current = current.then(function() {
return fn.apply(this, args);
});
return current.then(function(result) {
if (hook.key) {
results[hook.key] = result;
}
return result;
});
})).then(function() {
return results;
});
}
function runHookParallel(hooks, args) {
if (!hooks) {
hooks = [];
}
return Promise.all(hooks.map(function(hook){
var fn = hook.fn;
return fn.apply(this, args);
})).then(function(results) {
var props = {};
results.forEach(function(result, index) {
var key = hooks[index].key;
if (key) {
props[key] = result;
}
});
return props;
});
}
exports.run = function(name) {
var result = {};
var args = Array.prototype.slice.call(arguments);
// remove first argument
args.shift();
debug('run BEFORE hooks', name);
return runHook(store.get(BEFORE, name), args).then(function(beforeResult) {
result = extend(result, beforeResult);
debug('run NORMAL hooks', name);
return runHook(store.get(NORMAL, name), args);
}).then(function(normalResult) {
result = extend(result, normalResult);
debug('run AFTER hooks', name);
return runHook(store.get(AFTER, name), args);
}).then(function(afterResult) {
result = extend(result, afterResult);
debug('hook', name, 'finished')
return result;
});
};
exports.parallel = function(name) {
var result = {};
var args = Array.prototype.slice.call(arguments);
// remove first argument
args.shift();
debug('parallel BEFORE hooks', name);
return runHookParallel(store.get(BEFORE, name), args).then(function(beforeResult) {
result = extend(result, beforeResult);
debug('parallel NORMAL hooks', name);
return runHookParallel(store.get(NORMAL, name), args);
}).then(function(normalResult) {
result = extend(result, normalResult);
debug('parallel AFTER hooks', name);
return runHookParallel(store.get(AFTER, name), args);
}).then(function(afterResult) {
result = extend(result, afterResult);
return result;
});
};
exports.clear = exports.___clearHooks = function(name) {
store.clear(name);
};