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>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set/Add a dependency
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {Object} value
|
||||
*/
|
||||
module.exports.set = function(key, value) {
|
||||
var path = require('path'),
|
||||
_ = require('lodash');
|
||||
|
||||
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