summonjs
v0.3.7
Published
Define Node.js module dependencies in JSON format, and be able to resolve them using angular inject style.
Readme
SummonJS
Define Node.js module dependencies in JSON format, and be able to resolve them using angular inject style. There is a tutorial introducing how to use SummonJS to create an Express App.
npm install summonjs
Define Dependency
Create a JSON file, define the mappings between dependency name and the source files.
"dependency": {
"ClassA": "./src/class_a",
"ClassB": "./src/class_b",
"_": {
path: "lodash",
shim: true
}
}Init the dependency manager
Pass in the dependency definition JSON file to the summonjs module, it will make all the dependencies defined available via summonjs:
var summon = require('summonjs')({
configs: require('./simple.json')
});Auto inject dependencies by argument names
Take below function from ./src/class_a for example, ClassB is a function argument, and it maps to the source file ./src/class_b. When ClassA is loaded from SummonJS, the ClassB will be injected automatically, available to the scope of ClassA.
./src/class_a:
module.exports = function(ClassB) {
this.name = "class_a";
this.classB = ClassB;
return this;
};./src/class_b:
module.exports = function() {
this.name = "class_b";
return this;
};shim the dependency without auto inject
If you don't want summon to auto inject dependencies, and want it to be initialized by a simple require operation, you can define the dependency to be shimmed:
"_": {
path: "lodash",
shim: true
}Internally it wrap the dependency with an anonymous function with empty argument list, and to be registered in the dependency manager:
function() {
return require('lodash');
}Register dependency in code
It can either register object or function.
var obj = {};
summon.register('Class', {});
var func = function(){
return 'test';
};
summon.register('Func', func);If it is a function, when it loads by summon the first time, it will execute the function and store the returned object in the summon's factory. So for next time it loads, the registered function won't be executed again. Instead it returns the object returned at the first time load.
Summon spirits by their names
var classA = summon.get('ClassA');
assert.equal(classA.name, 'class_a');
assert.equal(classA.classB.name, 'class_b');Invoke targeted modules
summon.invoke will call on the targeted modules. Internally it is call get on all the specified targets, while override the dependencies if the override param is defined.
summon.invoke({
override: {ClassB: {}},
targets: ['ClassA', 'ClassC']
})Hook Dependency Functions
In some scenarios, there might be needs to add integrate intercept logics for a object's function, such as manipulate input arguments before passing them to an existing function, or adding data caching logics in the function. SummonJS has a way to create a pre/post logic hook for a dependency's function, making it easier to plug in or plug out the custom logics to a function.
The SummonJS definition below define a dependency with a hook object.
{
"dependency": {
"ClassB": {
"path" : "./src/class_b",
"hook" : {
"main" : "./src/hook"
}
}
}
}The main key value under the hook property is the function needed to be hooked with the pre/post logics defined in the ./src/hook file. The hook object needs to have pre/post functions such as below:
module.exports = function(ClassA) {
this.pre = function(arg, next) {
next(arg + ' passed to pre hook;');
};
this.post = function(arg, next) {
next(arg + ' passed to post hook;');
};
return this;
};With the ClassB source code as below:
var classb = function() {
return this;
};
classb.prototype.main = function(arg, callback) {
callback(arg + ' passed to main func;');
};
module.exports = classb;Note that in order for a function to be hooked, it has be defined as a prototype function.
The callback result of the main will be as below:
var mainCallback = function(arg1) {
assert.equal(arg1, 'test passed to pre hook; passed to main func; passed to post hook;');
};
summon.get('ClassB').main('test', mainCallback);Here is how the hook works:
prehook function will be called first when themainfunction is called.nextfunction in the pre hook will call theClassB.mainwith the arguments.- The
callbackargument in themainfunction will call theposthook function with the arguments. - The original
mainCallbackwill be postponed to be thenextcallback function in the post hook. - Assume if
ClassAis defined in the dependency config json, it can be injected into the hook scope function and to be used by the pre/post hook functions.
Welcome Contributions
Feel free to fork and add features suit your needs.
Development Test
Run gulp, it should run all the unit tests and generate a coverage report.
