ts-comply
Version:
TypeTools is a Typescript library for providing extensible tooling runtime validations and type helpers.
262 lines • 11.1 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClassLineage = exports.ClassLineageExtensionData = exports.ClassLineageSettings = void 0;
var context_1 = require("./context");
var type_tools_1 = require("./type-tools");
var common_iface_1 = require("./upstream/common.iface");
var lcaCache = {};
var lineageCache = {};
var ClassLineageSettings = exports.ClassLineageSettings = (function (_super) {
__extends(ClassLineageSettings, _super);
function ClassLineageSettings(init) {
var _this = _super.call(this, init) || this;
_this.extensionEphemerals = ClassLineageSettings.extensionClassLineage;
if (init) {
Object.assign(_this, init);
}
return _this;
}
ClassLineageSettings.extensionClassLineage = 'ClassLineage';
return ClassLineageSettings;
}(type_tools_1.TypeToolsSettings));
var ClassLineageExtensionData = (function () {
function ClassLineageExtensionData() {
this.lineage = [];
}
return ClassLineageExtensionData;
}());
exports.ClassLineageExtensionData = ClassLineageExtensionData;
var ClassLineage = exports.ClassLineage = (function () {
function ClassLineage(settings) {
this.settings = (0, type_tools_1.settingsInitialize)(ClassLineageSettings, settings);
}
ClassLineage.getExtensionData = function (target, settings) {
if (settings === void 0) { settings = ClassLineageSettings; }
return type_tools_1.TypeToolsBase.getExtension(target, settings.extensionClassLineage, settings);
};
ClassLineage.typeCheck = function (target, settings) {
if (settings === void 0) { settings = ClassLineageSettings; }
return target && !!ClassLineage.getExtensionData(target, settings);
};
ClassLineage.implementOn = function (target, settings) {
if (settings === void 0) { settings = ClassLineageSettings; }
if (!type_tools_1.TypeToolsBase.checkContext(ClassLineage)) {
return false;
}
if (!ClassLineage.getExtensionData(target, settings)) {
var extension = new ClassLineageExtensionData();
type_tools_1.TypeToolsBase.addExtension(target, ClassLineageSettings.extensionClassLineage, extension);
}
return true;
};
ClassLineage.mapOut = function (target, settings) {
if (settings === void 0) { settings = ClassLineageSettings; }
if (!ClassLineage.implementOn(target, settings)) {
return;
}
var lineage = ClassLineage.of(target);
ClassLineage.getExtensionData(target, settings).lineage = lineage;
return lineage;
};
ClassLineage.mapOf = function (target) {
return ClassLineage.of(target, null, null, true);
};
ClassLineage.of = function (target, topDown, getAsNames, getAsMap) {
if (topDown === void 0) { topDown = true; }
if (getAsNames === void 0) { getAsNames = false; }
if (getAsMap === void 0) { getAsMap = false; }
var useCache = !ClassLineage.noCache;
var lineage = [];
var targetIsClass = !!target.prototype && !!target.constructor.name;
if (targetIsClass) {
if (useCache) {
var cached = lineageCache[(0, common_iface_1.typeLocalName)(target)];
if (cached) {
if (getAsMap) {
return cached.mapped;
}
if (getAsNames) {
return topDown ? cached.topDownNames : cached.bottomUpNames;
}
else {
return topDown ? cached.topDown : cached.bottomUp;
}
}
}
target = type_tools_1.TypeToolsBase.getSampleInstance(target);
}
var node = Object.getPrototypeOf(target);
var topType = node.constructor;
if (useCache) {
var cached2 = lineageCache[(0, common_iface_1.typeLocalName)(topType)];
if (cached2) {
if (getAsMap) {
return cached2.mapped;
}
if (getAsNames) {
return topDown ? cached2.topDownNames : cached2.bottomUpNames;
}
else {
return topDown ? cached2.topDown : cached2.bottomUp;
}
}
}
while (node && node.constructor.name !== 'Object') {
lineage.push(node.constructor);
node = Object.getPrototypeOf(node);
}
var mapped = {};
for (var _i = 0, lineage_1 = lineage; _i < lineage_1.length; _i++) {
var cls = lineage_1[_i];
mapped[(0, common_iface_1.typeLocalName)(cls)] = cls;
}
var result = {
topDown: lineage.reverse(),
bottomUp: lineage,
topDownNames: lineage.reverse().map(function (a) { return (0, common_iface_1.typeLocalName)(a); }),
bottomUpNames: lineage.map(function (a) { return (0, common_iface_1.typeLocalName)(a); }),
mapped: mapped
};
if (useCache) {
lineageCache[(0, common_iface_1.typeLocalName)(topType)] = result;
}
if (getAsMap) {
return result.mapped;
}
if (getAsNames) {
return topDown ? result.topDownNames : result.bottomUpNames;
}
else {
return topDown ? result.topDown : result.bottomUp;
}
};
ClassLineage.typeOf = function (target) {
return ClassLineage.of(target, false)[0];
};
ClassLineage.parentOf = function (target) {
var parentClass = ClassLineage.of(target, false)[1];
return parentClass ? parentClass : null;
};
ClassLineage.parentNameOf = function (target) {
var parentClass = ClassLineage.of(target, false)[1];
return parentClass ? parentClass.name : null;
};
ClassLineage.namesOf = function (target, topDown) {
if (topDown === void 0) { topDown = true; }
return ClassLineage.of(target, topDown, true);
};
ClassLineage.commonAncestorsInfo = function (target1, target2) {
var lineage1 = ClassLineage.of(target1, true);
var lineage2 = ClassLineage.of(target2, true);
var key = (0, common_iface_1.typeLocalName)(lineage1[0]) + ':' + (0, common_iface_1.typeLocalName)(lineage2[0]);
if (!ClassLineage.noCache) {
var cache = lcaCache[key];
if (cache) {
return cache;
}
}
var travel = 0;
var closestMatch;
for (var i = 0; i < lineage1.length; ++i) {
var parent1 = lineage1[i];
for (var j = 0; j < lineage2.length; ++j) {
var parent2 = lineage2[j];
if (parent1 === parent2) {
var commonAncestors = lineage2.slice(j);
var levelCompare = j - i;
var levelDifference = Math.abs(levelCompare);
var distance = i + j;
var senior = (levelDifference === 0) ? null : (i > j) ? target2 : target1;
var junior = (levelDifference === 0) ? null : (i < j) ? target2 : target1;
if (!closestMatch || closestMatch.travel > travel) {
closestMatch = {
commonAncestors: commonAncestors,
lastCommonAncestor: parent1,
senior: senior,
junior: junior,
distance: distance,
travel: travel,
levelCompare: levelCompare,
levelDifference: levelDifference,
};
}
}
}
++travel;
}
if (!closestMatch) {
closestMatch = {
commonAncestors: [],
lastCommonAncestor: null,
senior: null,
junior: null,
distance: Infinity,
travel: Infinity,
levelCompare: NaN,
levelDifference: NaN,
};
}
if (!ClassLineage.noCache) {
lcaCache[key] = closestMatch;
}
return closestMatch;
};
ClassLineage.lastCommonAncestor = function (target1, target2) {
return ClassLineage.commonAncestorsInfo(target1, target2).lastCommonAncestor;
};
ClassLineage.areRelated = function (target1, target2) {
return ClassLineage.commonAncestorsInfo(target1, target2).lastCommonAncestor !== null;
};
ClassLineage.recentConstructorName = function () {
try {
return new Error().stack.split('\n')
.filter(function (line) { return line.indexOf('at new ') >= 0; })[0]
.trim().split(' ')[2];
}
catch (e) {
return null;
}
};
ClassLineage.getContextSlow = function (target) {
var name = ClassLineage.recentConstructorName();
var lineage = ClassLineage.of(target);
for (var _i = 0, lineage_2 = lineage; _i < lineage_2.length; _i++) {
var parent_1 = lineage_2[_i];
if (name === parent_1.name) {
return parent_1;
}
}
return null;
};
ClassLineage.prototype.getExtensionData = function (target) { return ClassLineage.getExtensionData(target, this.settings); };
ClassLineage.prototype.typeCheck = function (target) { return ClassLineage.typeCheck(target, this.settings); };
ClassLineage.prototype.implementOn = function (target) { return ClassLineage.implementOn(target, this.settings); };
ClassLineage.prototype.mapOut = function (target) {
return ClassLineage.mapOut(target, this.settings);
};
ClassLineage.noCache = false;
return ClassLineage;
}());
context_1.Context.lineageMap = function (a) {
return ClassLineage.of(a, null, null, true);
};
context_1.Context.lineageHas = function (a, type) {
var map = ClassLineage.of(a, null, null, true);
return (map && map[(0, common_iface_1.typeLocalName)(type)]) ? true : false;
};
//# sourceMappingURL=class-lineage.js.map
;