UNPKG

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
"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;