Revamp DI module
This commit is contained in:
parent
5422892066
commit
2cc0601ed0
155
di.js
155
di.js
|
@ -1,17 +1,154 @@
|
||||||
/**
|
/**
|
||||||
* Dependency Injection
|
* Dependency injection
|
||||||
*
|
*
|
||||||
* @author Mohammad Fares <faressoft.com@gmail.com>
|
* @author Mohammad Fares <faressoft.com@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
var path = require('path'),
|
||||||
* Set/Add a dependency
|
_ = require('lodash');
|
||||||
*
|
|
||||||
* @param {String} key
|
|
||||||
* @param {Object} value
|
|
||||||
*/
|
|
||||||
module.exports.set = function(key, value) {
|
|
||||||
|
|
||||||
module.exports[key] = value;
|
/**
|
||||||
|
* Dependency injection
|
||||||
|
*/
|
||||||
|
function DI() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injected dependecies
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
this._dependencies = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper proxy object to set traps
|
||||||
|
* @type {Proxy}
|
||||||
|
*/
|
||||||
|
this._proxy = new Proxy(this, {
|
||||||
|
get: this.getHandler,
|
||||||
|
set: this.setHandler
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._proxy;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trap for getting a property value
|
||||||
|
*
|
||||||
|
* @param {Object} target
|
||||||
|
* @param {String} key
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
DI.prototype.getHandler = function(target, key) {
|
||||||
|
|
||||||
|
if (key in target) {
|
||||||
|
return target[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key in target._dependencies) {
|
||||||
|
return target._dependencies[key];
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trap for setting a property value
|
||||||
|
*
|
||||||
|
* @param {Object} target
|
||||||
|
* @param {String} key
|
||||||
|
* @param {*} value
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
DI.prototype.setHandler = function(target, key, value) {
|
||||||
|
|
||||||
|
if (key in target) {
|
||||||
|
throw new Error(`It is not allowed to set '${key}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
target._dependencies[key] = value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require and set a package
|
||||||
|
*
|
||||||
|
* - Require the module
|
||||||
|
* - Add the module as depndency
|
||||||
|
* - Format the key as
|
||||||
|
* - Convert the moduleName to camelCase
|
||||||
|
* - Remove the extension
|
||||||
|
* - Resolve third party packages as the native `require`.
|
||||||
|
* - Resolve our own scripts with paths relative to
|
||||||
|
* the app's root path `require`.
|
||||||
|
*
|
||||||
|
* @param {String} moduleName
|
||||||
|
* @param {String} key (Optional) (Default: the moduleName camel cased)
|
||||||
|
*/
|
||||||
|
DI.prototype.require = function(moduleName, key) {
|
||||||
|
|
||||||
|
var parsedModuleName = path.parse(moduleName);
|
||||||
|
|
||||||
|
// Default value for key
|
||||||
|
if (typeof key == 'undefined') {
|
||||||
|
key = _.camelCase(parsedModuleName.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is not a third party package
|
||||||
|
if (parsedModuleName.dir != '') {
|
||||||
|
|
||||||
|
// Resolve the path to an absolute path
|
||||||
|
moduleName = path.resolve(this._getAppRootPath(), moduleName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this._dependencies[key] = require(moduleName);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject a dependency
|
||||||
|
*
|
||||||
|
* @param {String} key
|
||||||
|
* @param {*} value
|
||||||
|
*/
|
||||||
|
DI.prototype.set = function(key, value) {
|
||||||
|
|
||||||
|
this[key] = value;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an injected dependency
|
||||||
|
*
|
||||||
|
* @param {String} key
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
DI.prototype.get = function(key) {
|
||||||
|
|
||||||
|
return this[key];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the root path of the app
|
||||||
|
*
|
||||||
|
* - Follow the module.parent.parent... etc until null
|
||||||
|
*
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
DI.prototype._getAppRootPath = function() {
|
||||||
|
|
||||||
|
var parent = module.parent;
|
||||||
|
|
||||||
|
while (parent.parent) {
|
||||||
|
|
||||||
|
parent = parent.parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.dirname(parent.filename);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = DI;
|
||||||
|
|
Loading…
Reference in New Issue