UNPKG

tiny-di

Version:

A tini tiny dependency injection container for node/io.js applications

241 lines (207 loc) 7.12 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _generic = require("./binder/generic"); var _path = require("./binder/path"); var _provider = require("./binder/provider"); var _abstract = require("./binding/abstract"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } /** * tiny-di * @module tiny-di * @copyright Dennis Saenger <tiny-di-15@mail.ds82.de> */ var path = require('path'); var _require = require('../package.json'), version = _require.version; // https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } var TinyDi = /*#__PURE__*/ function () { function TinyDi() { (0, _classCallCheck2["default"])(this, TinyDi); this.version = version; this.logger = console.log; this.resolving = []; this.bindings = {}; this.nsBindings = []; this.resolverFn = this.getDefaultResolver(); } // // PUBLIC DI API // (0, _createClass2["default"])(TinyDi, [{ key: "setLogger", value: function setLogger(logger) { this.logger = logger; } }, { key: "bind", value: function bind(key) { return new _generic.GenericBinder(this, key); } }, { key: "ns", value: function ns(space) { return new _path.PathBinder(this, space); } }, { key: "get", value: function get(key, env) { var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var _bindings = opts.bindings || {}; var bindings = _objectSpread({}, this.bindings, {}, _bindings); if (Array.isArray(key)) { return key.map(function (_key) { return this.get(_key, env, opts); }, this); } return bindings[key] !== undefined ? this.getBinding(key, env, bindings) : this.lazy(key); } }, { key: "provide", value: function provide(key) { return new _provider.ProviderBinder(this, key); } }, { key: "setResolver", value: function setResolver(resolverFn) { this.resolverFn = resolverFn; } }, { key: "set", value: function set(key, object) { this.bindings[key] = object; return object; } // // HELPER // }, { key: "getDefaultResolver", value: function getDefaultResolver(req) { req = req || require; var APP_ROOT = path.dirname(require.main.filename); return function (file) { var filePath = path.join(APP_ROOT, file); try { return req(filePath); } catch (error1) { try { return req(file); } catch (error2) { this.logger('ERROR: Cannot load module', file); this.logger('tried to require `' + filePath + '` and `' + file + '`'); this.logger(error1, error2, error1.stack.split('\n'), error2.stack.split('\n')); } } }; } }, { key: "resolveKey", value: function resolveKey(key) { if (this.hasBinding(key)) { return key; } var prefix = this.nsBindings.find(function (prefix) { var re = new RegExp('^' + escapeRegExp(prefix.ns) + '/'); return key === prefix.ns || !!key.match(re); }); if (prefix) { var re = new RegExp('^' + escapeRegExp(prefix.ns)); return key.replace(re, prefix.path); } return key; } }, { key: "hasBinding", value: function hasBinding(key) { return !!this.bindings[key]; } }, { key: "setNsBinding", value: function setNsBinding(ns, dir) { this.nsBindings.push({ ns: ns, path: dir }); } }, { key: "load", value: function load(key, what, opts) { what = what || key; what = this.resolveKey(what); var resolved = typeof what === 'function' ? what : this.resolverFn(what); if (resolved) { this.markResolving(key); var object = this.apply(resolved, { key: key, binding: what }, null, opts); this.set(key, object); this.markResolved(key); return object; } } }, { key: "lazy", value: function lazy(key, opts) { if (this.isCircularDep(key)) { throw new Error('Circular dependency found; abort loading'); } return this.load(key, key, opts); } }, { key: "getBinding", value: function getBinding(key, env) { var bindings = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.bindings; var binding = bindings[key]; if (binding instanceof _abstract.AbstractBinding) { return binding.$get(env); } return binding; } }, { key: "apply", value: function apply(fn, env, that, opts) { var self = this; // support es6 default exports fn = fn["default"] ? fn["default"] : fn; if (fn && fn.$inject && typeof fn === 'function') { var isArray = Array.isArray(fn.$inject); var rawArgs = isArray ? fn.$inject : fn.$inject.deps || []; var returnAsClass = !isArray && fn.$inject.callAs === 'class'; var argumentList = rawArgs.map(function (arg) { return self.get(arg, env, opts); }, this); return returnAsClass ? new (Function.prototype.bind.apply(fn, [null].concat(argumentList)))() : fn.apply(that, argumentList); } return fn; } }, { key: "markResolving", value: function markResolving(key) { this.resolving.push(key); } }, { key: "markResolved", value: function markResolved(key) { var index = this.resolving.indexOf(key); if (index > -1) { this.resolving.splice(index, 1); } } }, { key: "isCircularDep", value: function isCircularDep(key) { return this.resolving.indexOf(key) > -1; } }]); return TinyDi; }(); module.exports = function () { return new TinyDi(); };