inversify
Version:
A powerful and lightweight inversion of control container for JavaScript and Node.js apps powered by TypeScript.
251 lines (250 loc) • 10.7 kB
JavaScript
"use strict";
var binding_count_1 = require("../bindings/binding_count");
var binding_1 = require("../bindings/binding");
var lookup_1 = require("./lookup");
var planner_1 = require("../planning/planner");
var resolver_1 = require("../resolution/resolver");
var ERROR_MSGS = require("../constants/error_msgs");
var METADATA_KEY = require("../constants/metadata_keys");
var binding_to_syntax_1 = require("../syntax/binding_to_syntax");
var metadata_1 = require("../planning/metadata");
var target_1 = require("../planning/target");
var target_type_1 = require("../planning/target_type");
var request_1 = require("../planning/request");
var kernel_snapshot_1 = require("./kernel_snapshot");
var guid_1 = require("../utils/guid");
var utils_1 = require("../utils/utils");
var Kernel = (function () {
function Kernel() {
this.guid = guid_1.default();
this._planner = new planner_1.default();
this._resolver = new resolver_1.default();
this._bindingDictionary = new lookup_1.default();
this._middleware = null;
this._snapshots = [];
}
Kernel.prototype.load = function () {
var _this = this;
var modules = [];
for (var _i = 0; _i < arguments.length; _i++) {
modules[_i - 0] = arguments[_i];
}
var getBindFunction = function (moduleId) {
return function (serviceIdentifier) {
var _bind = _this.bind.bind(_this);
var bindingToSyntax = _bind(serviceIdentifier);
bindingToSyntax._binding.moduleId = moduleId;
return bindingToSyntax;
};
};
modules.forEach(function (module) {
var bindFunction = getBindFunction(module.guid);
module.registry(bindFunction);
});
};
Kernel.prototype.unload = function () {
var _this = this;
var modules = [];
for (var _i = 0; _i < arguments.length; _i++) {
modules[_i - 0] = arguments[_i];
}
modules.forEach(function (module) {
_this._bindingDictionary.removeByModuleId(module.guid);
});
};
Kernel.prototype.bind = function (serviceIdentifier) {
var binding = new binding_1.default(serviceIdentifier);
this._bindingDictionary.add(serviceIdentifier, binding);
return new binding_to_syntax_1.default(binding);
};
Kernel.prototype.unbind = function (serviceIdentifier) {
try {
this._bindingDictionary.remove(serviceIdentifier);
}
catch (e) {
throw new Error(ERROR_MSGS.CANNOT_UNBIND + " " + this.getServiceIdentifierAsString(serviceIdentifier));
}
};
Kernel.prototype.unbindAll = function () {
this._bindingDictionary = new lookup_1.default();
};
Kernel.prototype.isBound = function (serviceIdentifier) {
var bindings = this._planner.getBindings(this, serviceIdentifier);
return bindings.length > 0;
};
Kernel.prototype.get = function (serviceIdentifier) {
return this._get({
contextInterceptor: function (context) { return context; },
multiInject: false,
serviceIdentifier: serviceIdentifier,
target: null
})[0];
};
Kernel.prototype.getNamed = function (serviceIdentifier, named) {
return this.getTagged(serviceIdentifier, METADATA_KEY.NAMED_TAG, named);
};
Kernel.prototype.getTagged = function (serviceIdentifier, key, value) {
var metadata = new metadata_1.default(key, value);
var target = new target_1.default(target_type_1.default.ConstructorArgument, null, serviceIdentifier, metadata);
return this._get({
contextInterceptor: function (context) { return context; },
multiInject: false,
serviceIdentifier: serviceIdentifier,
target: target
})[0];
};
Kernel.prototype.snapshot = function () {
this._snapshots.push(kernel_snapshot_1.default.of(this._bindingDictionary.clone(), this._middleware));
};
Kernel.prototype.restore = function () {
if (this._snapshots.length === 0) {
throw new Error(ERROR_MSGS.NO_MORE_SNAPSHOTS_AVAILABLE);
}
var snapshot = this._snapshots.pop();
this._bindingDictionary = snapshot.bindings;
this._middleware = snapshot.middleware;
};
Kernel.prototype.getServiceIdentifierAsString = function (serviceIdentifier) {
var type = typeof serviceIdentifier;
if (type === "function") {
var _serviceIdentifier = serviceIdentifier;
return _serviceIdentifier.name;
}
else if (type === "symbol") {
return serviceIdentifier.toString();
}
else {
var _serviceIdentifier = serviceIdentifier;
return _serviceIdentifier;
}
};
Kernel.prototype.applyMiddleware = function () {
var middlewares = [];
for (var _i = 0; _i < arguments.length; _i++) {
middlewares[_i - 0] = arguments[_i];
}
var previous = (this._middleware) ? this._middleware : this._planAndResolve.bind(this);
this._middleware = middlewares.reduce(function (prev, curr) {
return curr(prev);
}, previous);
};
Kernel.prototype.getAll = function (serviceIdentifier) {
return this._get({
contextInterceptor: function (context) { return context; },
multiInject: true,
serviceIdentifier: serviceIdentifier,
target: null
});
};
Kernel.prototype.getAllNamed = function (serviceIdentifier, named) {
return this.getAllTagged(serviceIdentifier, METADATA_KEY.NAMED_TAG, named);
};
Kernel.prototype.getAllTagged = function (serviceIdentifier, key, value) {
var metadata = new metadata_1.default(key, value);
var target = new target_1.default(null, null, serviceIdentifier, metadata);
return this._get({
contextInterceptor: function (context) { return context; },
multiInject: true,
serviceIdentifier: serviceIdentifier,
target: target
});
};
Object.defineProperty(Kernel.prototype, "parent", {
set: function (kernel) {
this._parentKernel = kernel;
},
enumerable: true,
configurable: true
});
Kernel.prototype._get = function (args) {
var result = null;
if (this._middleware) {
result = this._middleware(args);
}
else {
result = this._planAndResolve(args);
}
if (Array.isArray(result) === false) {
throw new Error(ERROR_MSGS.INVALID_MIDDLEWARE_RETURN);
}
return result;
};
Kernel.prototype._planAndResolve = function (args) {
var contexts = this._plan(args.multiInject, args.serviceIdentifier, args.target);
var results = this._resolve(contexts, args.contextInterceptor);
return results;
};
Kernel.prototype._getActiveBindings = function (multiInject, serviceIdentifier, target) {
var bindings = this._planner.getBindings(this, serviceIdentifier);
if (target !== null) {
var request = new request_1.default(serviceIdentifier, this._planner.createContext(this), null, bindings, target);
bindings = this._planner.getActiveBindings(request, target);
}
switch (bindings.length) {
case binding_count_1.default.NoBindingsAvailable:
var serviceIdentifierString = this.getServiceIdentifierAsString(serviceIdentifier), msg = ERROR_MSGS.NOT_REGISTERED;
if (target !== null) {
msg = msg + " " + serviceIdentifierString + "\n " + serviceIdentifierString + " - " + target.metadata[0].toString();
msg += this._listRegisteredBindingsForServiceIdentifier(serviceIdentifierString);
}
else {
msg = msg + " " + serviceIdentifierString;
}
throw new Error(msg);
case binding_count_1.default.OnlyOneBindingAvailable:
if (multiInject === false) {
return bindings;
}
case binding_count_1.default.MultipleBindingsAvailable:
default:
if (multiInject === false) {
var serviceIdentifierString_1 = this.getServiceIdentifierAsString(serviceIdentifier), msg_1 = ERROR_MSGS.AMBIGUOUS_MATCH + " " + serviceIdentifierString_1;
msg_1 += this._listRegisteredBindingsForServiceIdentifier(serviceIdentifierString_1);
throw new Error(msg_1);
}
else {
return bindings;
}
}
};
Kernel.prototype._plan = function (multiInject, serviceIdentifier, target) {
var _this = this;
var bindings = this._getActiveBindings(multiInject, serviceIdentifier, target);
var contexts = bindings.map(function (binding) {
return _this._createContext(binding, target);
});
return contexts;
};
Kernel.prototype._createContext = function (binding, target) {
var context = this._planner.createContext(this);
this._planner.createPlan(context, binding, target);
return context;
};
Kernel.prototype._resolve = function (contexts, contextInterceptor) {
var _this = this;
var results = contexts.map(function (context) {
return _this._resolver.resolve(contextInterceptor(context));
});
return results;
};
Kernel.prototype._listRegisteredBindingsForServiceIdentifier = function (serviceIdentifier) {
var registeredBindingsList = "", registeredBindings = this._planner.getBindings(this, serviceIdentifier);
if (registeredBindings.length !== 0) {
registeredBindingsList = "\nRegistered bindings:";
registeredBindings.forEach(function (binding) {
var name = "Object";
if (binding.implementationType !== null) {
name = utils_1.getFunctionName(binding.implementationType);
}
registeredBindingsList = registeredBindingsList + "\n " + name;
if (binding.constraint.metaData) {
registeredBindingsList = registeredBindingsList + " - " + binding.constraint.metaData;
}
});
}
return registeredBindingsList;
};
return Kernel;
}());
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Kernel;