vv-di
Version:
Simple IoC Container
163 lines (139 loc) • 3.18 kB
JavaScript
/**
*
* @type {Promise|bluebird}
*/
var Promise = require('bluebird');
/**
* @name Container
* @constructor
*/
var Container = function () {
this.singletons = {};
this.bindings = {};
this.asyncs = [];
};
/**
* Binds a dependency with given factory
*
* @param {string} alias
* @param {Container~FactoryCallback} factory
*/
Container.prototype.bind = function (alias, factory) {
this.bindings[alias] = factory;
};
/**
* Instantiate a dependency
*
* @param alias
* @returns {*}
*/
Container.prototype.make = function (alias) {
if (!this.bindings.hasOwnProperty(alias)) {
throw new Error('Could not instantiate [' + alias + ']');
}
var factory = this.bindings[alias];
if (!this.singletons.hasOwnProperty(alias)) {
return factory.apply(factory, [this]);
}
if(!this.singletons[alias]) {
this.singletons[alias] = true;
this.bindings[alias] = factory.apply(factory, [this]);
}
return this.bindings[alias];
};
/**
* Binds a dependency as singleton (sharedService)
*
* @param {string} alias
* @param {Container~FactoryCallback} factory
*/
Container.prototype.singleton = function (alias, factory) {
this.bindings[alias] = factory;
this.singletons[alias] = false;
};
/**
*
* @param {string} alias
* @param {Container~AsyncFactoryCallback} asyncFactory
*/
Container.prototype.bindAsync = function (alias, asyncFactory) {
var self = this;
this.asyncs.push(new Promise(function (resolve, reject) {
asyncFactory(self, {
done: function (result) {
self.singleton(alias, function () {
return result;
});
resolve();
},
error: reject});
}
));
};
Container.prototype.boot = function () {
var self = this;
return Promise.all(this.asyncs).then(function () {
return self;
});
};
/**
* Register a service provider
*
* @param {Container~ServiceProviderInterface} serviceProvider
*/
Container.prototype.use = function (serviceProvider) {
serviceProvider.register(this);
};
/**
* Load and register service provider
*
* @param {string} serviceProviderLocation
*/
Container.prototype.load = function (serviceProviderLocation) {
this.use(require(this.root + "/" + serviceProviderLocation));
};
/**
*
* @param {string} root
*/
Container.prototype.setRoot = function (root) {
this.root = root;
return this;
};
module.exports = Container;
/**
*
* @type {Container}
*/
var singletonContainer = null;
/**
*
* @returns {Container}
*/
module.exports.instance = function () {
if (!singletonContainer) {
singletonContainer = new Container();
}
return singletonContainer;
};
/**
* @callback
* @name Container~FactoryCallback
* @param {Container=} container
* @return {*}
*/
/**
* @callback
* @name Container~AsyncFactoryCallback
* @param {Container} container
* @param {{done, error}} call
*/
/**
* @interface
* @name Container~ServiceProviderInterface
*/
/**
* @method
* @name Container~ServiceProviderInterface#register
* @param {Container} container
*/