fluxtuate
Version:
a javascript ES7 library for handling complex data transactions
253 lines (190 loc) • 11.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _class;
var _coreDecorators = require("core-decorators");
var _getOwnPropertyDescriptors = require("../utils/getOwnPropertyDescriptors");
var _getOwnPropertyDescriptors2 = _interopRequireDefault(_getOwnPropertyDescriptors);
var _internals = require("./_internals");
var _lang = require("lodash/lang");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var reservedWords = ["view", "payload"];
var injectionPropertyMap = Symbol("fluxtuateInjector_injectionPropertyMap");
var injectionClassMap = Symbol("fluxtuateInjector_injectionClassMap");
var hasInjection = Symbol("fluxtuateInjector_hasInjection");
var Injector = (0, _coreDecorators.autobind)(_class = function () {
function Injector() {
var _this = this;
_classCallCheck(this, Injector);
this[_internals.injectionValueMap] = {};
this[injectionPropertyMap] = {};
this[injectionClassMap] = {};
this[_internals.defaultValues] = {};
this[_internals.globalValues] = [];
this[_internals.getInjectValue] = function (iKey) {
var defaultInjection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var value = void 0;
if (_this[_internals.injectionValueMap][iKey] !== undefined) value = _this[_internals.injectionValueMap][iKey];else if (_this[injectionPropertyMap][iKey] !== undefined) value = _this[injectionPropertyMap][iKey];else if (_this[injectionClassMap][iKey] !== undefined) value = _this[injectionClassMap][iKey];else if (defaultInjection[iKey] !== undefined) value = defaultInjection[iKey];
if (value[_internals.isPropertyInjection]) {
_this.inject(value.object[value.property]);
} else {
_this.inject(value);
}
return value;
};
this[_internals.applyInjectionSignature] = function (instance, signature) {
instance[hasInjection] = signature;
};
this[_internals.getInjectionSignature] = function (instance) {
return instance[hasInjection];
};
}
_createClass(Injector, [{
key: "hasInjection",
value: function hasInjection(iKey) {
return this[_internals.injectionValueMap][iKey] !== undefined || this[injectionPropertyMap][iKey] !== undefined || this[injectionClassMap][iKey] !== undefined;
}
}, {
key: "mapKey",
value: function mapKey(key) {
if (reservedWords.indexOf(key) !== -1) throw new Error("\"" + key + "\" is a reserved word, use a different mapping for this value!");
if (Object.keys(this[_internals.defaultValues]).indexOf(key) !== -1) throw new Error("\"" + key + "\" is a reserved value in the injector! " + this[_internals.defaultValues][key] + ".");
if (this[_internals.injectionValueMap][key]) throw new Error("The key " + key + " is already injected to value: " + this[_internals.injectionValueMap][key]);
if (this[injectionPropertyMap][key]) throw new Error("The key " + key + " is already injected to value: " + this[injectionPropertyMap][key]);
var self = this;
return {
toValue: function toValue(value) {
if (self[injectionClassMap][key]) delete self[injectionClassMap][key];
if (self[injectionPropertyMap][key]) delete self[injectionPropertyMap][key];
self[_internals.injectionValueMap][key] = value;
return self;
},
toProperty: function toProperty(object, property) {
if (self[_internals.injectionValueMap][key]) delete self[_internals.injectionValueMap][key];
if (self[injectionClassMap][key]) delete self[injectionClassMap][key];
self[injectionPropertyMap][key] = { object: object, property: property };
self[injectionPropertyMap][key][_internals.isPropertyInjection] = true;
return self;
},
toClass: function toClass(Class) {
if (self[injectionClassMap][key]) {
if (!(self[injectionClassMap][key] instanceof Class)) throw new Error("You are trying to inject a new class on a existing injection of " + key);
return;
}
if (self[_internals.injectionValueMap][key]) delete self[_internals.injectionValueMap][key];
if (self[injectionPropertyMap][key]) delete self[injectionPropertyMap][key];
self[injectionClassMap][key] = new Class();
return self;
}
};
}
}, {
key: "removeKey",
value: function removeKey(key) {
if (reservedWords.indexOf(key) !== -1) throw new Error("\"" + key + "\" is a reserved word and can't be removed!");
if (Object.keys(this[_internals.defaultValues]).indexOf(key) !== -1) throw new Error("\"" + key + "\" is a reserved value in the context, and can't be removed! " + this[_internals.defaultValues][key] + ".");
var keyMap = void 0;
if (this[_internals.injectionValueMap][key]) {
keyMap = this[_internals.injectionValueMap];
} else if (this[injectionPropertyMap][key]) {
keyMap = this[injectionPropertyMap];
} else if (this[injectionClassMap][key]) {
keyMap = this[injectionClassMap];
}
if (!keyMap) return;
delete keyMap[key];
}
}, {
key: "inherit",
value: function inherit(injector) {
for (var key in injector[_internals.injectionValueMap]) {
if (reservedWords.indexOf(key) !== -1) continue;
this[_internals.injectionValueMap][key] = injector[_internals.injectionValueMap][key];
}
for (var _key in injector[injectionPropertyMap]) {
if (reservedWords.indexOf(_key) !== -1) continue;
this[injectionPropertyMap][_key] = injector[injectionPropertyMap][_key];
}
for (var _key2 in injector[injectionClassMap]) {
if (reservedWords.indexOf(_key2) !== -1) continue;
this[injectionClassMap][_key2] = injector[injectionClassMap][_key2];
}
}
}, {
key: "inject",
value: function inject(instance) {
var _this2 = this;
var defaultInjection = {};
for (var _len = arguments.length, injections = Array(_len > 1 ? _len - 1 : 0), _key3 = 1; _key3 < _len; _key3++) {
injections[_key3 - 1] = arguments[_key3];
}
injections.forEach(function (injection) {
if (!injection) return;
if (injection instanceof Injector) {
var parentInjector = injection;
injection = Object.assign({}, injection[_internals.injectionValueMap], injection[injectionPropertyMap], injection[injectionClassMap], { parentInjector: parentInjector });
}
if (!(0, _lang.isObject)(injection)) throw new Error("Injection defaults can only be a object literal!");
defaultInjection = Object.assign(defaultInjection, injection);
});
var possibleInjections = Object.assign({}, defaultInjection, this[_internals.injectionValueMap], this[injectionPropertyMap], this[injectionClassMap]);
var injectionSignature = JSON.stringify(Object.keys(possibleInjections));
if (this[_internals.getInjectionSignature](instance) === injectionSignature) return;
var descriptorsInstance = instance;
var descriptors = {};
while (descriptorsInstance && descriptorsInstance !== Object.prototype) {
var newDescriptors = (0, _getOwnPropertyDescriptors2.default)(descriptorsInstance);
for (var key in newDescriptors) {
if (key === "constructor" || key === "__proto__" || key === "prototype") {
continue;
}
if (!descriptors[key] || descriptors[key].configurable) {
descriptors[key] = newDescriptors[key];
}
}
if (descriptorsInstance.prototype) {
descriptorsInstance = descriptorsInstance.prototype;
} else if (descriptorsInstance.__proto__) {
descriptorsInstance = descriptorsInstance.__proto__;
} else if (descriptorsInstance.constructor) {
descriptorsInstance = descriptorsInstance.constructor.prototype;
} else {
descriptorsInstance = null;
}
}
var _loop = function _loop(_key4) {
var desc = descriptors[_key4];
if (!desc || !desc.value) return "continue";
var iKey = desc.value[_internals.injectionKey];
if (typeof desc.value === "function" || !iKey || possibleInjections[iKey] === undefined) {
return "continue";
}
if (!desc.configurable) return "continue";
var value = _this2[_internals.getInjectValue](iKey, defaultInjection);
Object.defineProperty(instance, _key4, {
get: function get() {
if (value[_internals.isPropertyInjection]) {
return value.object[value.property];
} else {
return value;
}
},
enumerable: true,
configurable: false
});
};
for (var _key4 in descriptors) {
var _ret = _loop(_key4);
if (_ret === "continue") continue;
}
this[_internals.applyInjectionSignature](instance, injectionSignature);
return instance;
}
}]);
return Injector;
}()) || _class;
exports.default = Injector;