mirror of
https://gitlab.com/upRootNutrition/zookeeper.git
synced 2025-06-17 02:45:12 -05:00
feat: init
This commit is contained in:
parent
8379d09058
commit
2cfa016090
2929 changed files with 299087 additions and 3 deletions
109
node_modules/ts-mixer/dist/cjs/decorator.js
generated
vendored
Normal file
109
node_modules/ts-mixer/dist/cjs/decorator.js
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.decorate = exports.getDecoratorsForClass = exports.directDecoratorSearch = exports.deepDecoratorSearch = void 0;
|
||||
const util_1 = require("./util");
|
||||
const mixin_tracking_1 = require("./mixin-tracking");
|
||||
const mergeObjectsOfDecorators = (o1, o2) => {
|
||||
var _a, _b;
|
||||
const allKeys = (0, util_1.unique)([...Object.getOwnPropertyNames(o1), ...Object.getOwnPropertyNames(o2)]);
|
||||
const mergedObject = {};
|
||||
for (let key of allKeys)
|
||||
mergedObject[key] = (0, util_1.unique)([...((_a = o1 === null || o1 === void 0 ? void 0 : o1[key]) !== null && _a !== void 0 ? _a : []), ...((_b = o2 === null || o2 === void 0 ? void 0 : o2[key]) !== null && _b !== void 0 ? _b : [])]);
|
||||
return mergedObject;
|
||||
};
|
||||
const mergePropertyAndMethodDecorators = (d1, d2) => {
|
||||
var _a, _b, _c, _d;
|
||||
return ({
|
||||
property: mergeObjectsOfDecorators((_a = d1 === null || d1 === void 0 ? void 0 : d1.property) !== null && _a !== void 0 ? _a : {}, (_b = d2 === null || d2 === void 0 ? void 0 : d2.property) !== null && _b !== void 0 ? _b : {}),
|
||||
method: mergeObjectsOfDecorators((_c = d1 === null || d1 === void 0 ? void 0 : d1.method) !== null && _c !== void 0 ? _c : {}, (_d = d2 === null || d2 === void 0 ? void 0 : d2.method) !== null && _d !== void 0 ? _d : {}),
|
||||
});
|
||||
};
|
||||
const mergeDecorators = (d1, d2) => {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
return ({
|
||||
class: (0, util_1.unique)([...(_a = d1 === null || d1 === void 0 ? void 0 : d1.class) !== null && _a !== void 0 ? _a : [], ...(_b = d2 === null || d2 === void 0 ? void 0 : d2.class) !== null && _b !== void 0 ? _b : []]),
|
||||
static: mergePropertyAndMethodDecorators((_c = d1 === null || d1 === void 0 ? void 0 : d1.static) !== null && _c !== void 0 ? _c : {}, (_d = d2 === null || d2 === void 0 ? void 0 : d2.static) !== null && _d !== void 0 ? _d : {}),
|
||||
instance: mergePropertyAndMethodDecorators((_e = d1 === null || d1 === void 0 ? void 0 : d1.instance) !== null && _e !== void 0 ? _e : {}, (_f = d2 === null || d2 === void 0 ? void 0 : d2.instance) !== null && _f !== void 0 ? _f : {}),
|
||||
});
|
||||
};
|
||||
const decorators = new Map();
|
||||
const findAllConstituentClasses = (...classes) => {
|
||||
var _a;
|
||||
const allClasses = new Set();
|
||||
const frontier = new Set([...classes]);
|
||||
while (frontier.size > 0) {
|
||||
for (let clazz of frontier) {
|
||||
const protoChainClasses = (0, util_1.protoChain)(clazz.prototype).map(proto => proto.constructor);
|
||||
const mixinClasses = (_a = (0, mixin_tracking_1.getMixinsForClass)(clazz)) !== null && _a !== void 0 ? _a : [];
|
||||
const potentiallyNewClasses = [...protoChainClasses, ...mixinClasses];
|
||||
const newClasses = potentiallyNewClasses.filter(c => !allClasses.has(c));
|
||||
for (let newClass of newClasses)
|
||||
frontier.add(newClass);
|
||||
allClasses.add(clazz);
|
||||
frontier.delete(clazz);
|
||||
}
|
||||
}
|
||||
return [...allClasses];
|
||||
};
|
||||
const deepDecoratorSearch = (...classes) => {
|
||||
const decoratorsForClassChain = findAllConstituentClasses(...classes)
|
||||
.map(clazz => decorators.get(clazz))
|
||||
.filter(decorators => !!decorators);
|
||||
if (decoratorsForClassChain.length == 0)
|
||||
return {};
|
||||
if (decoratorsForClassChain.length == 1)
|
||||
return decoratorsForClassChain[0];
|
||||
return decoratorsForClassChain.reduce((d1, d2) => mergeDecorators(d1, d2));
|
||||
};
|
||||
exports.deepDecoratorSearch = deepDecoratorSearch;
|
||||
const directDecoratorSearch = (...classes) => {
|
||||
const classDecorators = classes.map(clazz => (0, exports.getDecoratorsForClass)(clazz));
|
||||
if (classDecorators.length === 0)
|
||||
return {};
|
||||
if (classDecorators.length === 1)
|
||||
return classDecorators[0];
|
||||
return classDecorators.reduce((d1, d2) => mergeDecorators(d1, d2));
|
||||
};
|
||||
exports.directDecoratorSearch = directDecoratorSearch;
|
||||
const getDecoratorsForClass = (clazz) => {
|
||||
let decoratorsForClass = decorators.get(clazz);
|
||||
if (!decoratorsForClass) {
|
||||
decoratorsForClass = {};
|
||||
decorators.set(clazz, decoratorsForClass);
|
||||
}
|
||||
return decoratorsForClass;
|
||||
};
|
||||
exports.getDecoratorsForClass = getDecoratorsForClass;
|
||||
const decorateClass = (decorator) => ((clazz) => {
|
||||
const decoratorsForClass = (0, exports.getDecoratorsForClass)(clazz);
|
||||
let classDecorators = decoratorsForClass.class;
|
||||
if (!classDecorators) {
|
||||
classDecorators = [];
|
||||
decoratorsForClass.class = classDecorators;
|
||||
}
|
||||
classDecorators.push(decorator);
|
||||
return decorator(clazz);
|
||||
});
|
||||
const decorateMember = (decorator) => ((object, key, ...otherArgs) => {
|
||||
var _a, _b, _c;
|
||||
const decoratorTargetType = typeof object === 'function' ? 'static' : 'instance';
|
||||
const decoratorType = typeof object[key] === 'function' ? 'method' : 'property';
|
||||
const clazz = decoratorTargetType === 'static' ? object : object.constructor;
|
||||
const decoratorsForClass = (0, exports.getDecoratorsForClass)(clazz);
|
||||
const decoratorsForTargetType = (_a = decoratorsForClass === null || decoratorsForClass === void 0 ? void 0 : decoratorsForClass[decoratorTargetType]) !== null && _a !== void 0 ? _a : {};
|
||||
decoratorsForClass[decoratorTargetType] = decoratorsForTargetType;
|
||||
let decoratorsForType = (_b = decoratorsForTargetType === null || decoratorsForTargetType === void 0 ? void 0 : decoratorsForTargetType[decoratorType]) !== null && _b !== void 0 ? _b : {};
|
||||
decoratorsForTargetType[decoratorType] = decoratorsForType;
|
||||
let decoratorsForKey = (_c = decoratorsForType === null || decoratorsForType === void 0 ? void 0 : decoratorsForType[key]) !== null && _c !== void 0 ? _c : [];
|
||||
decoratorsForType[key] = decoratorsForKey;
|
||||
// @ts-ignore: array is type `A[] | B[]` and item is type `A | B`, so technically a type error, but it's fine
|
||||
decoratorsForKey.push(decorator);
|
||||
// @ts-ignore
|
||||
return decorator(object, key, ...otherArgs);
|
||||
});
|
||||
const decorate = (decorator) => ((...args) => {
|
||||
if (args.length === 1)
|
||||
return decorateClass(decorator)(args[0]);
|
||||
return decorateMember(decorator)(...args);
|
||||
});
|
||||
exports.decorate = decorate;
|
12
node_modules/ts-mixer/dist/cjs/index.js
generated
vendored
Normal file
12
node_modules/ts-mixer/dist/cjs/index.js
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.hasMixin = exports.decorate = exports.settings = exports.mix = exports.Mixin = void 0;
|
||||
var mixins_1 = require("./mixins");
|
||||
Object.defineProperty(exports, "Mixin", { enumerable: true, get: function () { return mixins_1.Mixin; } });
|
||||
Object.defineProperty(exports, "mix", { enumerable: true, get: function () { return mixins_1.mix; } });
|
||||
var settings_1 = require("./settings");
|
||||
Object.defineProperty(exports, "settings", { enumerable: true, get: function () { return settings_1.settings; } });
|
||||
var decorator_1 = require("./decorator");
|
||||
Object.defineProperty(exports, "decorate", { enumerable: true, get: function () { return decorator_1.decorate; } });
|
||||
var mixin_tracking_1 = require("./mixin-tracking");
|
||||
Object.defineProperty(exports, "hasMixin", { enumerable: true, get: function () { return mixin_tracking_1.hasMixin; } });
|
42
node_modules/ts-mixer/dist/cjs/mixin-tracking.js
generated
vendored
Normal file
42
node_modules/ts-mixer/dist/cjs/mixin-tracking.js
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.hasMixin = exports.registerMixins = exports.getMixinsForClass = void 0;
|
||||
const util_1 = require("./util");
|
||||
// Keeps track of constituent classes for every mixin class created by ts-mixer.
|
||||
const mixins = new WeakMap();
|
||||
const getMixinsForClass = (clazz) => mixins.get(clazz);
|
||||
exports.getMixinsForClass = getMixinsForClass;
|
||||
const registerMixins = (mixedClass, constituents) => mixins.set(mixedClass, constituents);
|
||||
exports.registerMixins = registerMixins;
|
||||
const hasMixin = (instance, mixin) => {
|
||||
if (instance instanceof mixin)
|
||||
return true;
|
||||
const constructor = instance.constructor;
|
||||
const visited = new Set();
|
||||
let frontier = new Set();
|
||||
frontier.add(constructor);
|
||||
while (frontier.size > 0) {
|
||||
// check if the frontier has the mixin we're looking for. if not, we can say we visited every item in the frontier
|
||||
if (frontier.has(mixin))
|
||||
return true;
|
||||
frontier.forEach((item) => visited.add(item));
|
||||
// build a new frontier based on the associated mixin classes and prototype chains of each frontier item
|
||||
const newFrontier = new Set();
|
||||
frontier.forEach((item) => {
|
||||
var _a;
|
||||
const itemConstituents = (_a = mixins.get(item)) !== null && _a !== void 0 ? _a : (0, util_1.protoChain)(item.prototype)
|
||||
.map((proto) => proto.constructor)
|
||||
.filter((item) => item !== null);
|
||||
if (itemConstituents)
|
||||
itemConstituents.forEach((constituent) => {
|
||||
if (!visited.has(constituent) && !frontier.has(constituent))
|
||||
newFrontier.add(constituent);
|
||||
});
|
||||
});
|
||||
// we have a new frontier, now search again
|
||||
frontier = newFrontier;
|
||||
}
|
||||
// if we get here, we couldn't find the mixin anywhere in the prototype chain or associated mixin classes
|
||||
return false;
|
||||
};
|
||||
exports.hasMixin = hasMixin;
|
82
node_modules/ts-mixer/dist/cjs/mixins.js
generated
vendored
Normal file
82
node_modules/ts-mixer/dist/cjs/mixins.js
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.mix = exports.Mixin = void 0;
|
||||
const proxy_1 = require("./proxy");
|
||||
const settings_1 = require("./settings");
|
||||
const util_1 = require("./util");
|
||||
const decorator_1 = require("./decorator");
|
||||
const mixin_tracking_1 = require("./mixin-tracking");
|
||||
function Mixin(...constructors) {
|
||||
var _a, _b, _c;
|
||||
const prototypes = constructors.map(constructor => constructor.prototype);
|
||||
// Here we gather up the init functions of the ingredient prototypes, combine them into one init function, and
|
||||
// attach it to the mixed class prototype. The reason we do this is because we want the init functions to mix
|
||||
// similarly to constructors -- not methods, which simply override each other.
|
||||
const initFunctionName = settings_1.settings.initFunction;
|
||||
if (initFunctionName !== null) {
|
||||
const initFunctions = prototypes
|
||||
.map(proto => proto[initFunctionName])
|
||||
.filter(func => typeof func === 'function');
|
||||
const combinedInitFunction = function (...args) {
|
||||
for (let initFunction of initFunctions)
|
||||
initFunction.apply(this, args);
|
||||
};
|
||||
const extraProto = { [initFunctionName]: combinedInitFunction };
|
||||
prototypes.push(extraProto);
|
||||
}
|
||||
function MixedClass(...args) {
|
||||
for (const constructor of constructors)
|
||||
// @ts-ignore: potentially abstract class
|
||||
(0, util_1.copyProps)(this, new constructor(...args));
|
||||
if (initFunctionName !== null && typeof this[initFunctionName] === 'function')
|
||||
this[initFunctionName].apply(this, args);
|
||||
}
|
||||
MixedClass.prototype = settings_1.settings.prototypeStrategy === 'copy'
|
||||
? (0, util_1.hardMixProtos)(prototypes, MixedClass)
|
||||
: (0, proxy_1.softMixProtos)(prototypes, MixedClass);
|
||||
Object.setPrototypeOf(MixedClass, settings_1.settings.staticsStrategy === 'copy'
|
||||
? (0, util_1.hardMixProtos)(constructors, null, ['prototype'])
|
||||
: (0, proxy_1.proxyMix)(constructors, Function.prototype));
|
||||
let DecoratedMixedClass = MixedClass;
|
||||
if (settings_1.settings.decoratorInheritance !== 'none') {
|
||||
const classDecorators = settings_1.settings.decoratorInheritance === 'deep'
|
||||
? (0, decorator_1.deepDecoratorSearch)(...constructors)
|
||||
: (0, decorator_1.directDecoratorSearch)(...constructors);
|
||||
for (let decorator of (_a = classDecorators === null || classDecorators === void 0 ? void 0 : classDecorators.class) !== null && _a !== void 0 ? _a : []) {
|
||||
const result = decorator(DecoratedMixedClass);
|
||||
if (result) {
|
||||
DecoratedMixedClass = result;
|
||||
}
|
||||
}
|
||||
applyPropAndMethodDecorators((_b = classDecorators === null || classDecorators === void 0 ? void 0 : classDecorators.static) !== null && _b !== void 0 ? _b : {}, DecoratedMixedClass);
|
||||
applyPropAndMethodDecorators((_c = classDecorators === null || classDecorators === void 0 ? void 0 : classDecorators.instance) !== null && _c !== void 0 ? _c : {}, DecoratedMixedClass.prototype);
|
||||
}
|
||||
(0, mixin_tracking_1.registerMixins)(DecoratedMixedClass, constructors);
|
||||
return DecoratedMixedClass;
|
||||
}
|
||||
exports.Mixin = Mixin;
|
||||
const applyPropAndMethodDecorators = (propAndMethodDecorators, target) => {
|
||||
const propDecorators = propAndMethodDecorators.property;
|
||||
const methodDecorators = propAndMethodDecorators.method;
|
||||
if (propDecorators)
|
||||
for (let key in propDecorators)
|
||||
for (let decorator of propDecorators[key])
|
||||
decorator(target, key);
|
||||
if (methodDecorators)
|
||||
for (let key in methodDecorators)
|
||||
for (let decorator of methodDecorators[key])
|
||||
decorator(target, key, Object.getOwnPropertyDescriptor(target, key));
|
||||
};
|
||||
/**
|
||||
* A decorator version of the `Mixin` function. You'll want to use this instead of `Mixin` for mixing generic classes.
|
||||
*/
|
||||
const mix = (...ingredients) => decoratedClass => {
|
||||
// @ts-ignore
|
||||
const mixedClass = Mixin(...ingredients.concat([decoratedClass]));
|
||||
Object.defineProperty(mixedClass, 'name', {
|
||||
value: decoratedClass.name,
|
||||
writable: false,
|
||||
});
|
||||
return mixedClass;
|
||||
};
|
||||
exports.mix = mix;
|
82
node_modules/ts-mixer/dist/cjs/proxy.js
generated
vendored
Normal file
82
node_modules/ts-mixer/dist/cjs/proxy.js
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.softMixProtos = exports.proxyMix = exports.getIngredientWithProp = void 0;
|
||||
const util_1 = require("./util");
|
||||
/**
|
||||
* Finds the ingredient with the given prop, searching in reverse order and breadth-first if searching ingredient
|
||||
* prototypes is required.
|
||||
*/
|
||||
const getIngredientWithProp = (prop, ingredients) => {
|
||||
const protoChains = ingredients.map(ingredient => (0, util_1.protoChain)(ingredient));
|
||||
// since we search breadth-first, we need to keep track of our depth in the prototype chains
|
||||
let protoDepth = 0;
|
||||
// not all prototype chains are the same depth, so this remains true as long as at least one of the ingredients'
|
||||
// prototype chains has an object at this depth
|
||||
let protosAreLeftToSearch = true;
|
||||
while (protosAreLeftToSearch) {
|
||||
// with the start of each horizontal slice, we assume this is the one that's deeper than any of the proto chains
|
||||
protosAreLeftToSearch = false;
|
||||
// scan through the ingredients right to left
|
||||
for (let i = ingredients.length - 1; i >= 0; i--) {
|
||||
const searchTarget = protoChains[i][protoDepth];
|
||||
if (searchTarget !== undefined && searchTarget !== null) {
|
||||
// if we find something, this is proof that this horizontal slice potentially more objects to search
|
||||
protosAreLeftToSearch = true;
|
||||
// eureka, we found it
|
||||
if (Object.getOwnPropertyDescriptor(searchTarget, prop) != undefined) {
|
||||
return protoChains[i][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
protoDepth++;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
exports.getIngredientWithProp = getIngredientWithProp;
|
||||
/**
|
||||
* "Mixes" ingredients by wrapping them in a Proxy. The optional prototype argument allows the mixed object to sit
|
||||
* downstream of an existing prototype chain. Note that "properties" cannot be added, deleted, or modified.
|
||||
*/
|
||||
const proxyMix = (ingredients, prototype = Object.prototype) => new Proxy({}, {
|
||||
getPrototypeOf() {
|
||||
return prototype;
|
||||
},
|
||||
setPrototypeOf() {
|
||||
throw Error('Cannot set prototype of Proxies created by ts-mixer');
|
||||
},
|
||||
getOwnPropertyDescriptor(_, prop) {
|
||||
return Object.getOwnPropertyDescriptor((0, exports.getIngredientWithProp)(prop, ingredients) || {}, prop);
|
||||
},
|
||||
defineProperty() {
|
||||
throw new Error('Cannot define new properties on Proxies created by ts-mixer');
|
||||
},
|
||||
has(_, prop) {
|
||||
return (0, exports.getIngredientWithProp)(prop, ingredients) !== undefined || prototype[prop] !== undefined;
|
||||
},
|
||||
get(_, prop) {
|
||||
return ((0, exports.getIngredientWithProp)(prop, ingredients) || prototype)[prop];
|
||||
},
|
||||
set(_, prop, val) {
|
||||
const ingredientWithProp = (0, exports.getIngredientWithProp)(prop, ingredients);
|
||||
if (ingredientWithProp === undefined)
|
||||
throw new Error('Cannot set new properties on Proxies created by ts-mixer');
|
||||
ingredientWithProp[prop] = val;
|
||||
return true;
|
||||
},
|
||||
deleteProperty() {
|
||||
throw new Error('Cannot delete properties on Proxies created by ts-mixer');
|
||||
},
|
||||
ownKeys() {
|
||||
return ingredients
|
||||
.map(Object.getOwnPropertyNames)
|
||||
.reduce((prev, curr) => curr.concat(prev.filter(key => curr.indexOf(key) < 0)));
|
||||
},
|
||||
});
|
||||
exports.proxyMix = proxyMix;
|
||||
/**
|
||||
* Creates a new proxy-prototype object that is a "soft" mixture of the given prototypes. The mixing is achieved by
|
||||
* proxying all property access to the ingredients. This is not ES5 compatible and less performant. However, any
|
||||
* changes made to the source prototypes will be reflected in the proxy-prototype, which may be desirable.
|
||||
*/
|
||||
const softMixProtos = (ingredients, constructor) => (0, exports.proxyMix)([...ingredients, { constructor }]);
|
||||
exports.softMixProtos = softMixProtos;
|
9
node_modules/ts-mixer/dist/cjs/settings.js
generated
vendored
Normal file
9
node_modules/ts-mixer/dist/cjs/settings.js
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.settings = void 0;
|
||||
exports.settings = {
|
||||
initFunction: null,
|
||||
staticsStrategy: 'copy',
|
||||
prototypeStrategy: 'copy',
|
||||
decoratorInheritance: 'deep',
|
||||
};
|
2
node_modules/ts-mixer/dist/cjs/types.js
generated
vendored
Normal file
2
node_modules/ts-mixer/dist/cjs/types.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
85
node_modules/ts-mixer/dist/cjs/util.js
generated
vendored
Normal file
85
node_modules/ts-mixer/dist/cjs/util.js
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.flatten = exports.unique = exports.hardMixProtos = exports.nearestCommonProto = exports.protoChain = exports.copyProps = void 0;
|
||||
/**
|
||||
* Utility function that works like `Object.apply`, but copies getters and setters properly as well. Additionally gives
|
||||
* the option to exclude properties by name.
|
||||
*/
|
||||
const copyProps = (dest, src, exclude = []) => {
|
||||
const props = Object.getOwnPropertyDescriptors(src);
|
||||
for (let prop of exclude)
|
||||
delete props[prop];
|
||||
Object.defineProperties(dest, props);
|
||||
};
|
||||
exports.copyProps = copyProps;
|
||||
/**
|
||||
* Returns the full chain of prototypes up until Object.prototype given a starting object. The order of prototypes will
|
||||
* be closest to farthest in the chain.
|
||||
*/
|
||||
const protoChain = (obj, currentChain = [obj]) => {
|
||||
const proto = Object.getPrototypeOf(obj);
|
||||
if (proto === null)
|
||||
return currentChain;
|
||||
return (0, exports.protoChain)(proto, [...currentChain, proto]);
|
||||
};
|
||||
exports.protoChain = protoChain;
|
||||
/**
|
||||
* Identifies the nearest ancestor common to all the given objects in their prototype chains. For most unrelated
|
||||
* objects, this function should return Object.prototype.
|
||||
*/
|
||||
const nearestCommonProto = (...objs) => {
|
||||
if (objs.length === 0)
|
||||
return undefined;
|
||||
let commonProto = undefined;
|
||||
const protoChains = objs.map(obj => (0, exports.protoChain)(obj));
|
||||
while (protoChains.every(protoChain => protoChain.length > 0)) {
|
||||
const protos = protoChains.map(protoChain => protoChain.pop());
|
||||
const potentialCommonProto = protos[0];
|
||||
if (protos.every(proto => proto === potentialCommonProto))
|
||||
commonProto = potentialCommonProto;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return commonProto;
|
||||
};
|
||||
exports.nearestCommonProto = nearestCommonProto;
|
||||
/**
|
||||
* Creates a new prototype object that is a mixture of the given prototypes. The mixing is achieved by first
|
||||
* identifying the nearest common ancestor and using it as the prototype for a new object. Then all properties/methods
|
||||
* downstream of this prototype (ONLY downstream) are copied into the new object.
|
||||
*
|
||||
* The resulting prototype is more performant than softMixProtos(...), as well as ES5 compatible. However, it's not as
|
||||
* flexible as updates to the source prototypes aren't captured by the mixed result. See softMixProtos for why you may
|
||||
* want to use that instead.
|
||||
*/
|
||||
const hardMixProtos = (ingredients, constructor, exclude = []) => {
|
||||
var _a;
|
||||
const base = (_a = (0, exports.nearestCommonProto)(...ingredients)) !== null && _a !== void 0 ? _a : Object.prototype;
|
||||
const mixedProto = Object.create(base);
|
||||
// Keeps track of prototypes we've already visited to avoid copying the same properties multiple times. We init the
|
||||
// list with the proto chain below the nearest common ancestor because we don't want any of those methods mixed in
|
||||
// when they will already be accessible via prototype access.
|
||||
const visitedProtos = (0, exports.protoChain)(base);
|
||||
for (let prototype of ingredients) {
|
||||
let protos = (0, exports.protoChain)(prototype);
|
||||
// Apply the prototype chain in reverse order so that old methods don't override newer ones.
|
||||
for (let i = protos.length - 1; i >= 0; i--) {
|
||||
let newProto = protos[i];
|
||||
if (visitedProtos.indexOf(newProto) === -1) {
|
||||
(0, exports.copyProps)(mixedProto, newProto, ['constructor', ...exclude]);
|
||||
visitedProtos.push(newProto);
|
||||
}
|
||||
}
|
||||
}
|
||||
mixedProto.constructor = constructor;
|
||||
return mixedProto;
|
||||
};
|
||||
exports.hardMixProtos = hardMixProtos;
|
||||
const unique = (arr) => arr.filter((e, i) => arr.indexOf(e) == i);
|
||||
exports.unique = unique;
|
||||
const flatten = (arr) => arr.length === 0
|
||||
? []
|
||||
: arr.length === 1
|
||||
? arr[0]
|
||||
: arr.reduce((a1, a2) => [...a1, ...a2]);
|
||||
exports.flatten = flatten;
|
Loading…
Add table
Add a link
Reference in a new issue