diff options
author | sowgro <tpoke.ferrari@gmail.com> | 2023-09-02 19:12:47 -0400 |
---|---|---|
committer | sowgro <tpoke.ferrari@gmail.com> | 2023-09-02 19:12:47 -0400 |
commit | e4450c8417624b71d779cb4f41692538f9165e10 (patch) | |
tree | b70826542223ecdf8a7a259f61b0a1abb8a217d8 /node_modules/ts-mixer/dist | |
download | sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.tar.gz sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.tar.bz2 sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.zip |
first commit
Diffstat (limited to 'node_modules/ts-mixer/dist')
26 files changed, 996 insertions, 0 deletions
diff --git a/node_modules/ts-mixer/dist/cjs/decorator.js b/node_modules/ts-mixer/dist/cjs/decorator.js new file mode 100644 index 0000000..45d6dba --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/decorator.js @@ -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; diff --git a/node_modules/ts-mixer/dist/cjs/index.js b/node_modules/ts-mixer/dist/cjs/index.js new file mode 100644 index 0000000..5702401 --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/index.js @@ -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; } }); diff --git a/node_modules/ts-mixer/dist/cjs/mixin-tracking.js b/node_modules/ts-mixer/dist/cjs/mixin-tracking.js new file mode 100644 index 0000000..33ac2e7 --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/mixin-tracking.js @@ -0,0 +1,40 @@ +"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 Map(); +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; diff --git a/node_modules/ts-mixer/dist/cjs/mixins.js b/node_modules/ts-mixer/dist/cjs/mixins.js new file mode 100644 index 0000000..925e90a --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/mixins.js @@ -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; diff --git a/node_modules/ts-mixer/dist/cjs/proxy.js b/node_modules/ts-mixer/dist/cjs/proxy.js new file mode 100644 index 0000000..f7974c3 --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/proxy.js @@ -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; diff --git a/node_modules/ts-mixer/dist/cjs/settings.js b/node_modules/ts-mixer/dist/cjs/settings.js new file mode 100644 index 0000000..dabb6d3 --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/settings.js @@ -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', +}; diff --git a/node_modules/ts-mixer/dist/cjs/types.js b/node_modules/ts-mixer/dist/cjs/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/ts-mixer/dist/cjs/util.js b/node_modules/ts-mixer/dist/cjs/util.js new file mode 100644 index 0000000..5151696 --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/util.js @@ -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; diff --git a/node_modules/ts-mixer/dist/esm/decorator.d.ts b/node_modules/ts-mixer/dist/esm/decorator.d.ts new file mode 100644 index 0000000..dde5df2 --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/decorator.d.ts @@ -0,0 +1,18 @@ +import { Class } from './types'; +type ObjectOfDecorators<T extends PropertyDecorator | MethodDecorator> = { + [key: string]: T[]; +}; +export type PropertyAndMethodDecorators = { + property?: ObjectOfDecorators<PropertyDecorator>; + method?: ObjectOfDecorators<MethodDecorator>; +}; +type Decorators = { + class?: ClassDecorator[]; + static?: PropertyAndMethodDecorators; + instance?: PropertyAndMethodDecorators; +}; +export declare const deepDecoratorSearch: (...classes: Class[]) => Decorators; +export declare const directDecoratorSearch: (...classes: Class[]) => Decorators; +export declare const getDecoratorsForClass: (clazz: Class) => Decorators; +export declare const decorate: <T extends PropertyDecorator | MethodDecorator | ClassDecorator>(decorator: T) => T; +export {}; diff --git a/node_modules/ts-mixer/dist/esm/index.d.ts b/node_modules/ts-mixer/dist/esm/index.d.ts new file mode 100644 index 0000000..2a16080 --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/index.d.ts @@ -0,0 +1,4 @@ +export { Mixin, mix } from './mixins'; +export { settings } from './settings'; +export { decorate } from './decorator'; +export { hasMixin } from './mixin-tracking'; diff --git a/node_modules/ts-mixer/dist/esm/index.js b/node_modules/ts-mixer/dist/esm/index.js new file mode 100644 index 0000000..991d21b --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/index.js @@ -0,0 +1,364 @@ +/** + * 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); +}; +/** + * 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 protoChain(proto, [...currentChain, proto]); +}; +/** + * 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 => 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; +}; +/** + * 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 = 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 = protoChain(base); + for (let prototype of ingredients) { + let protos = 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) { + copyProps(mixedProto, newProto, ['constructor', ...exclude]); + visitedProtos.push(newProto); + } + } + } + mixedProto.constructor = constructor; + return mixedProto; +}; +const unique = (arr) => arr.filter((e, i) => arr.indexOf(e) == i); + +/** + * 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 => 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; +}; +/** + * "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(getIngredientWithProp(prop, ingredients) || {}, prop); + }, + defineProperty() { + throw new Error('Cannot define new properties on Proxies created by ts-mixer'); + }, + has(_, prop) { + return getIngredientWithProp(prop, ingredients) !== undefined || prototype[prop] !== undefined; + }, + get(_, prop) { + return (getIngredientWithProp(prop, ingredients) || prototype)[prop]; + }, + set(_, prop, val) { + const ingredientWithProp = 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))); + }, +}); +/** + * 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) => proxyMix([...ingredients, { constructor }]); + +const settings = { + initFunction: null, + staticsStrategy: 'copy', + prototypeStrategy: 'copy', + decoratorInheritance: 'deep', +}; + +// Keeps track of constituent classes for every mixin class created by ts-mixer. +const mixins = new Map(); +const getMixinsForClass = (clazz) => mixins.get(clazz); +const registerMixins = (mixedClass, constituents) => mixins.set(mixedClass, constituents); +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 : 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; +}; + +const mergeObjectsOfDecorators = (o1, o2) => { + var _a, _b; + const allKeys = unique([...Object.getOwnPropertyNames(o1), ...Object.getOwnPropertyNames(o2)]); + const mergedObject = {}; + for (let key of allKeys) + mergedObject[key] = 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: 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 = protoChain(clazz.prototype).map(proto => proto.constructor); + const mixinClasses = (_a = 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)); +}; +const directDecoratorSearch = (...classes) => { + const classDecorators = classes.map(clazz => getDecoratorsForClass(clazz)); + if (classDecorators.length === 0) + return {}; + if (classDecorators.length === 1) + return classDecorators[0]; + return classDecorators.reduce((d1, d2) => mergeDecorators(d1, d2)); +}; +const getDecoratorsForClass = (clazz) => { + let decoratorsForClass = decorators.get(clazz); + if (!decoratorsForClass) { + decoratorsForClass = {}; + decorators.set(clazz, decoratorsForClass); + } + return decoratorsForClass; +}; +const decorateClass = (decorator) => ((clazz) => { + const decoratorsForClass = 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 = 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); +}); + +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.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 + copyProps(this, new constructor(...args)); + if (initFunctionName !== null && typeof this[initFunctionName] === 'function') + this[initFunctionName].apply(this, args); + } + MixedClass.prototype = settings.prototypeStrategy === 'copy' + ? hardMixProtos(prototypes, MixedClass) + : softMixProtos(prototypes, MixedClass); + Object.setPrototypeOf(MixedClass, settings.staticsStrategy === 'copy' + ? hardMixProtos(constructors, null, ['prototype']) + : proxyMix(constructors, Function.prototype)); + let DecoratedMixedClass = MixedClass; + if (settings.decoratorInheritance !== 'none') { + const classDecorators = settings.decoratorInheritance === 'deep' + ? deepDecoratorSearch(...constructors) + : 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); + } + registerMixins(DecoratedMixedClass, constructors); + return DecoratedMixedClass; +} +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; +}; + +export { Mixin, decorate, hasMixin, mix, settings }; diff --git a/node_modules/ts-mixer/dist/esm/index.min.js b/node_modules/ts-mixer/dist/esm/index.min.js new file mode 100644 index 0000000..04ab5ba --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/index.min.js @@ -0,0 +1 @@ +const t=(t,e,o=[])=>{const r=Object.getOwnPropertyDescriptors(e);for(let t of o)delete r[t];Object.defineProperties(t,r)},e=(t,o=[t])=>{const r=Object.getPrototypeOf(t);return null===r?o:e(r,[...o,r])},o=(o,r,n=[])=>{var l;const i=null!==(l=((...t)=>{if(0===t.length)return;let o;const r=t.map((t=>e(t)));for(;r.every((t=>t.length>0));){const t=r.map((t=>t.pop())),e=t[0];if(!t.every((t=>t===e)))break;o=e}return o})(...o))&&void 0!==l?l:Object.prototype,c=Object.create(i),s=e(i);for(let r of o){let o=e(r);for(let e=o.length-1;e>=0;e--){let r=o[e];-1===s.indexOf(r)&&(t(c,r,["constructor",...n]),s.push(r))}}return c.constructor=r,c},r=t=>t.filter(((e,o)=>t.indexOf(e)==o)),n=(t,o)=>{const r=o.map((t=>e(t)));let n=0,l=!0;for(;l;){l=!1;for(let e=o.length-1;e>=0;e--){const o=r[e][n];if(null!=o&&(l=!0,null!=Object.getOwnPropertyDescriptor(o,t)))return r[e][0]}n++}},l=(t,e=Object.prototype)=>new Proxy({},{getPrototypeOf:()=>e,setPrototypeOf(){throw Error("Cannot set prototype of Proxies created by ts-mixer")},getOwnPropertyDescriptor:(e,o)=>Object.getOwnPropertyDescriptor(n(o,t)||{},o),defineProperty(){throw new Error("Cannot define new properties on Proxies created by ts-mixer")},has:(o,r)=>void 0!==n(r,t)||void 0!==e[r],get:(o,r)=>(n(r,t)||e)[r],set(e,o,r){const l=n(o,t);if(void 0===l)throw new Error("Cannot set new properties on Proxies created by ts-mixer");return l[o]=r,!0},deleteProperty(){throw new Error("Cannot delete properties on Proxies created by ts-mixer")},ownKeys:()=>t.map(Object.getOwnPropertyNames).reduce(((t,e)=>e.concat(t.filter((t=>e.indexOf(t)<0)))))}),i={initFunction:null,staticsStrategy:"copy",prototypeStrategy:"copy",decoratorInheritance:"deep"},c=new Map,s=t=>c.get(t),p=(t,o)=>{if(t instanceof o)return!0;const r=t.constructor,n=new Set;let l=new Set;for(l.add(r);l.size>0;){if(l.has(o))return!0;l.forEach((t=>n.add(t)));const t=new Set;l.forEach((o=>{var r;const i=null!==(r=c.get(o))&&void 0!==r?r:e(o.prototype).map((t=>t.constructor)).filter((t=>null!==t));i&&i.forEach((e=>{n.has(e)||l.has(e)||t.add(e)}))})),l=t}return!1},u=(t,e)=>{var o,n;const l=r([...Object.getOwnPropertyNames(t),...Object.getOwnPropertyNames(e)]),i={};for(let c of l)i[c]=r([...null!==(o=null==t?void 0:t[c])&&void 0!==o?o:[],...null!==(n=null==e?void 0:e[c])&&void 0!==n?n:[]]);return i},a=(t,e)=>{var o,r,n,l;return{property:u(null!==(o=null==t?void 0:t.property)&&void 0!==o?o:{},null!==(r=null==e?void 0:e.property)&&void 0!==r?r:{}),method:u(null!==(n=null==t?void 0:t.method)&&void 0!==n?n:{},null!==(l=null==e?void 0:e.method)&&void 0!==l?l:{})}},d=(t,e)=>{var o,n,l,i,c,s;return{class:r([...null!==(o=null==t?void 0:t.class)&&void 0!==o?o:[],...null!==(n=null==e?void 0:e.class)&&void 0!==n?n:[]]),static:a(null!==(l=null==t?void 0:t.static)&&void 0!==l?l:{},null!==(i=null==e?void 0:e.static)&&void 0!==i?i:{}),instance:a(null!==(c=null==t?void 0:t.instance)&&void 0!==c?c:{},null!==(s=null==e?void 0:e.instance)&&void 0!==s?s:{})}},f=new Map,v=(...t)=>{const o=((...t)=>{var o;const r=new Set,n=new Set([...t]);for(;n.size>0;)for(let t of n){const l=[...e(t.prototype).map((t=>t.constructor)),...null!==(o=s(t))&&void 0!==o?o:[]].filter((t=>!r.has(t)));for(let t of l)n.add(t);r.add(t),n.delete(t)}return[...r]})(...t).map((t=>f.get(t))).filter((t=>!!t));return 0==o.length?{}:1==o.length?o[0]:o.reduce(((t,e)=>d(t,e)))},y=t=>{let e=f.get(t);return e||(e={},f.set(t,e)),e},h=t=>(...e)=>1===e.length?(t=>e=>{const o=y(e);let r=o.class;return r||(r=[],o.class=r),r.push(t),t(e)})(t)(e[0]):(t=>(e,o,...r)=>{var n,l,i;const c="function"==typeof e?"static":"instance",s="function"==typeof e[o]?"method":"property",p="static"===c?e:e.constructor,u=y(p),a=null!==(n=null==u?void 0:u[c])&&void 0!==n?n:{};u[c]=a;let d=null!==(l=null==a?void 0:a[s])&&void 0!==l?l:{};a[s]=d;let f=null!==(i=null==d?void 0:d[o])&&void 0!==i?i:[];return d[o]=f,f.push(t),t(e,o,...r)})(t)(...e);function O(...e){var r,n,s;const p=e.map((t=>t.prototype)),u=i.initFunction;if(null!==u){const t=p.map((t=>t[u])).filter((t=>"function"==typeof t)),e={[u]:function(...e){for(let o of t)o.apply(this,e)}};p.push(e)}function a(...o){for(const r of e)t(this,new r(...o));null!==u&&"function"==typeof this[u]&&this[u].apply(this,o)}var f,h;a.prototype="copy"===i.prototypeStrategy?o(p,a):(f=p,h=a,l([...f,{constructor:h}])),Object.setPrototypeOf(a,"copy"===i.staticsStrategy?o(e,null,["prototype"]):l(e,Function.prototype));let O=a;if("none"!==i.decoratorInheritance){const t="deep"===i.decoratorInheritance?v(...e):((...t)=>{const e=t.map((t=>y(t)));return 0===e.length?{}:1===e.length?e[0]:e.reduce(((t,e)=>d(t,e)))})(...e);for(let e of null!==(r=null==t?void 0:t.class)&&void 0!==r?r:[]){const t=e(O);t&&(O=t)}g(null!==(n=null==t?void 0:t.static)&&void 0!==n?n:{},O),g(null!==(s=null==t?void 0:t.instance)&&void 0!==s?s:{},O.prototype)}var w,m;return w=O,m=e,c.set(w,m),O}const g=(t,e)=>{const o=t.property,r=t.method;if(o)for(let t in o)for(let r of o[t])r(e,t);if(r)for(let t in r)for(let o of r[t])o(e,t,Object.getOwnPropertyDescriptor(e,t))},w=(...t)=>e=>{const o=O(...t.concat([e]));return Object.defineProperty(o,"name",{value:e.name,writable:!1}),o};export{O as Mixin,h as decorate,p as hasMixin,w as mix,i as settings}; diff --git a/node_modules/ts-mixer/dist/esm/mixin-tracking.d.ts b/node_modules/ts-mixer/dist/esm/mixin-tracking.d.ts new file mode 100644 index 0000000..1beaf87 --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/mixin-tracking.d.ts @@ -0,0 +1,4 @@ +import { Class } from './types'; +export declare const getMixinsForClass: (clazz: Class) => Function[] | undefined; +export declare const registerMixins: (mixedClass: any, constituents: Function[]) => Map<any, Function[]>; +export declare const hasMixin: <M>(instance: any, mixin: abstract new (...args: any[]) => M) => instance is M; diff --git a/node_modules/ts-mixer/dist/esm/mixins.d.ts b/node_modules/ts-mixer/dist/esm/mixins.d.ts new file mode 100644 index 0000000..a4f65be --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/mixins.d.ts @@ -0,0 +1,16 @@ +import { Class, Longest } from './types'; +declare function Mixin<A extends any[], I1, S1>(c1: Class<A, I1, S1>): Class<A, I1, S1>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>): Class<Longest<A1, A2>, I1 & I2, S1 & S2>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>): Class<Longest<A1, A2, A3>, I1 & I2 & I3, S1 & S2 & S3>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>): Class<Longest<A1, A2, A3, A4>, I1 & I2 & I3 & I4, S1 & S2 & S3 & S4>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>): Class<Longest<A1, A2, A3, A4, A5>, I1 & I2 & I3 & I4 & I5, S1 & S2 & S3 & S4 & S5>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>): Class<Longest<A1, A2, A3, A4, A5, A6>, I1 & I2 & I3 & I4 & I5 & I6, S1 & S2 & S3 & S4 & S5 & S6>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>): Class<Longest<A1, A2, A3, A4, A5, A6, A7>, I1 & I2 & I3 & I4 & I5 & I6 & I7, S1 & S2 & S3 & S4 & S5 & S6 & S7>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7, A8 extends any[], I8, S8>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>, c8: Class<A8, I8, S8>): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7, A8 extends any[], I8, S8, A9 extends any[], I9, S9>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>, c8: Class<A8, I8, S8>, c9: Class<A9, I9, S9>): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8, A9>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7, A8 extends any[], I8, S8, A9 extends any[], I9, S9, A10 extends any[], I10, S10>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>, c8: Class<A8, I8, S8>, c9: Class<A9, I9, S9>, c10: Class<A10, I10, S10>): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9 & I10, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9 & S10>; +/** + * A decorator version of the `Mixin` function. You'll want to use this instead of `Mixin` for mixing generic classes. + */ +declare const mix: (...ingredients: Class[]) => (decoratedClass: any) => any; +export { Mixin, mix }; diff --git a/node_modules/ts-mixer/dist/esm/proxy.d.ts b/node_modules/ts-mixer/dist/esm/proxy.d.ts new file mode 100644 index 0000000..fafe399 --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/proxy.d.ts @@ -0,0 +1,16 @@ +/** + * Finds the ingredient with the given prop, searching in reverse order and breadth-first if searching ingredient + * prototypes is required. + */ +export declare const getIngredientWithProp: (prop: string | number | symbol, ingredients: any[]) => object | undefined; +/** + * "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. + */ +export declare const proxyMix: (ingredients: any[], prototype?: Object) => {}; +/** + * 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. + */ +export declare const softMixProtos: (ingredients: any[], constructor: Function) => object; diff --git a/node_modules/ts-mixer/dist/esm/settings.d.ts b/node_modules/ts-mixer/dist/esm/settings.d.ts new file mode 100644 index 0000000..d34d2b4 --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/settings.d.ts @@ -0,0 +1,7 @@ +export type Settings = { + initFunction: string | null; + staticsStrategy: 'copy' | 'proxy'; + prototypeStrategy: 'copy' | 'proxy'; + decoratorInheritance: 'deep' | 'direct' | 'none'; +}; +export declare const settings: Settings; diff --git a/node_modules/ts-mixer/dist/esm/types.d.ts b/node_modules/ts-mixer/dist/esm/types.d.ts new file mode 100644 index 0000000..cb25fc1 --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/types.d.ts @@ -0,0 +1,13 @@ +/** + * Returns the longer of the two tuples. Indefinite tuples will always be considered longest. + */ +type _Longest<T1 extends any[], T2 extends any[]> = any[] extends T1 ? T1 : any[] extends T2 ? T2 : Exclude<keyof T1, keyof T2> extends never ? T2 : T1; +/** + * Returns the longest of up to 10 different tuples. + */ +export type Longest<T1 extends any[], T2 extends any[] = [], T3 extends any[] = [], T4 extends any[] = [], T5 extends any[] = [], T6 extends any[] = [], T7 extends any[] = [], T8 extends any[] = [], T9 extends any[] = [], T10 extends any[] = []> = _Longest<_Longest<_Longest<_Longest<T1, T2>, _Longest<T3, T4>>, _Longest<_Longest<T5, T6>, _Longest<T7, T8>>>, _Longest<T9, T10>>; +/** + * A rigorous type alias for a class. + */ +export type Class<CtorArgs extends any[] = any[], InstanceType = {}, StaticType = {}, IsAbstract = false> = (abstract new (...args: any[]) => InstanceType) & StaticType; +export {}; diff --git a/node_modules/ts-mixer/dist/esm/util.d.ts b/node_modules/ts-mixer/dist/esm/util.d.ts new file mode 100644 index 0000000..4797ef4 --- /dev/null +++ b/node_modules/ts-mixer/dist/esm/util.d.ts @@ -0,0 +1,27 @@ +/** + * Utility function that works like `Object.apply`, but copies getters and setters properly as well. Additionally gives + * the option to exclude properties by name. + */ +export declare const copyProps: (dest: object, src: object, exclude?: string[]) => void; +/** + * 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. + */ +export declare const protoChain: (obj: object, currentChain?: object[]) => object[]; +/** + * Identifies the nearest ancestor common to all the given objects in their prototype chains. For most unrelated + * objects, this function should return Object.prototype. + */ +export declare const nearestCommonProto: (...objs: object[]) => object | undefined; +/** + * 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. + */ +export declare const hardMixProtos: (ingredients: any[], constructor: Function | null, exclude?: string[]) => object; +export declare const unique: <T>(arr: T[]) => T[]; +export declare const flatten: <T>(arr: T[][]) => T[]; diff --git a/node_modules/ts-mixer/dist/types/decorator.d.ts b/node_modules/ts-mixer/dist/types/decorator.d.ts new file mode 100644 index 0000000..dde5df2 --- /dev/null +++ b/node_modules/ts-mixer/dist/types/decorator.d.ts @@ -0,0 +1,18 @@ +import { Class } from './types'; +type ObjectOfDecorators<T extends PropertyDecorator | MethodDecorator> = { + [key: string]: T[]; +}; +export type PropertyAndMethodDecorators = { + property?: ObjectOfDecorators<PropertyDecorator>; + method?: ObjectOfDecorators<MethodDecorator>; +}; +type Decorators = { + class?: ClassDecorator[]; + static?: PropertyAndMethodDecorators; + instance?: PropertyAndMethodDecorators; +}; +export declare const deepDecoratorSearch: (...classes: Class[]) => Decorators; +export declare const directDecoratorSearch: (...classes: Class[]) => Decorators; +export declare const getDecoratorsForClass: (clazz: Class) => Decorators; +export declare const decorate: <T extends PropertyDecorator | MethodDecorator | ClassDecorator>(decorator: T) => T; +export {}; diff --git a/node_modules/ts-mixer/dist/types/index.d.ts b/node_modules/ts-mixer/dist/types/index.d.ts new file mode 100644 index 0000000..2a16080 --- /dev/null +++ b/node_modules/ts-mixer/dist/types/index.d.ts @@ -0,0 +1,4 @@ +export { Mixin, mix } from './mixins'; +export { settings } from './settings'; +export { decorate } from './decorator'; +export { hasMixin } from './mixin-tracking'; diff --git a/node_modules/ts-mixer/dist/types/mixin-tracking.d.ts b/node_modules/ts-mixer/dist/types/mixin-tracking.d.ts new file mode 100644 index 0000000..1beaf87 --- /dev/null +++ b/node_modules/ts-mixer/dist/types/mixin-tracking.d.ts @@ -0,0 +1,4 @@ +import { Class } from './types'; +export declare const getMixinsForClass: (clazz: Class) => Function[] | undefined; +export declare const registerMixins: (mixedClass: any, constituents: Function[]) => Map<any, Function[]>; +export declare const hasMixin: <M>(instance: any, mixin: abstract new (...args: any[]) => M) => instance is M; diff --git a/node_modules/ts-mixer/dist/types/mixins.d.ts b/node_modules/ts-mixer/dist/types/mixins.d.ts new file mode 100644 index 0000000..a4f65be --- /dev/null +++ b/node_modules/ts-mixer/dist/types/mixins.d.ts @@ -0,0 +1,16 @@ +import { Class, Longest } from './types'; +declare function Mixin<A extends any[], I1, S1>(c1: Class<A, I1, S1>): Class<A, I1, S1>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>): Class<Longest<A1, A2>, I1 & I2, S1 & S2>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>): Class<Longest<A1, A2, A3>, I1 & I2 & I3, S1 & S2 & S3>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>): Class<Longest<A1, A2, A3, A4>, I1 & I2 & I3 & I4, S1 & S2 & S3 & S4>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>): Class<Longest<A1, A2, A3, A4, A5>, I1 & I2 & I3 & I4 & I5, S1 & S2 & S3 & S4 & S5>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>): Class<Longest<A1, A2, A3, A4, A5, A6>, I1 & I2 & I3 & I4 & I5 & I6, S1 & S2 & S3 & S4 & S5 & S6>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>): Class<Longest<A1, A2, A3, A4, A5, A6, A7>, I1 & I2 & I3 & I4 & I5 & I6 & I7, S1 & S2 & S3 & S4 & S5 & S6 & S7>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7, A8 extends any[], I8, S8>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>, c8: Class<A8, I8, S8>): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7, A8 extends any[], I8, S8, A9 extends any[], I9, S9>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>, c8: Class<A8, I8, S8>, c9: Class<A9, I9, S9>): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8, A9>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9>; +declare function Mixin<A1 extends any[], I1, S1, A2 extends any[], I2, S2, A3 extends any[], I3, S3, A4 extends any[], I4, S4, A5 extends any[], I5, S5, A6 extends any[], I6, S6, A7 extends any[], I7, S7, A8 extends any[], I8, S8, A9 extends any[], I9, S9, A10 extends any[], I10, S10>(c1: Class<A1, I1, S1>, c2: Class<A2, I2, S2>, c3: Class<A3, I3, S3>, c4: Class<A4, I4, S4>, c5: Class<A5, I5, S5>, c6: Class<A6, I6, S6>, c7: Class<A7, I7, S7>, c8: Class<A8, I8, S8>, c9: Class<A9, I9, S9>, c10: Class<A10, I10, S10>): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9 & I10, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9 & S10>; +/** + * A decorator version of the `Mixin` function. You'll want to use this instead of `Mixin` for mixing generic classes. + */ +declare const mix: (...ingredients: Class[]) => (decoratedClass: any) => any; +export { Mixin, mix }; diff --git a/node_modules/ts-mixer/dist/types/proxy.d.ts b/node_modules/ts-mixer/dist/types/proxy.d.ts new file mode 100644 index 0000000..fafe399 --- /dev/null +++ b/node_modules/ts-mixer/dist/types/proxy.d.ts @@ -0,0 +1,16 @@ +/** + * Finds the ingredient with the given prop, searching in reverse order and breadth-first if searching ingredient + * prototypes is required. + */ +export declare const getIngredientWithProp: (prop: string | number | symbol, ingredients: any[]) => object | undefined; +/** + * "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. + */ +export declare const proxyMix: (ingredients: any[], prototype?: Object) => {}; +/** + * 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. + */ +export declare const softMixProtos: (ingredients: any[], constructor: Function) => object; diff --git a/node_modules/ts-mixer/dist/types/settings.d.ts b/node_modules/ts-mixer/dist/types/settings.d.ts new file mode 100644 index 0000000..d34d2b4 --- /dev/null +++ b/node_modules/ts-mixer/dist/types/settings.d.ts @@ -0,0 +1,7 @@ +export type Settings = { + initFunction: string | null; + staticsStrategy: 'copy' | 'proxy'; + prototypeStrategy: 'copy' | 'proxy'; + decoratorInheritance: 'deep' | 'direct' | 'none'; +}; +export declare const settings: Settings; diff --git a/node_modules/ts-mixer/dist/types/types.d.ts b/node_modules/ts-mixer/dist/types/types.d.ts new file mode 100644 index 0000000..cb25fc1 --- /dev/null +++ b/node_modules/ts-mixer/dist/types/types.d.ts @@ -0,0 +1,13 @@ +/** + * Returns the longer of the two tuples. Indefinite tuples will always be considered longest. + */ +type _Longest<T1 extends any[], T2 extends any[]> = any[] extends T1 ? T1 : any[] extends T2 ? T2 : Exclude<keyof T1, keyof T2> extends never ? T2 : T1; +/** + * Returns the longest of up to 10 different tuples. + */ +export type Longest<T1 extends any[], T2 extends any[] = [], T3 extends any[] = [], T4 extends any[] = [], T5 extends any[] = [], T6 extends any[] = [], T7 extends any[] = [], T8 extends any[] = [], T9 extends any[] = [], T10 extends any[] = []> = _Longest<_Longest<_Longest<_Longest<T1, T2>, _Longest<T3, T4>>, _Longest<_Longest<T5, T6>, _Longest<T7, T8>>>, _Longest<T9, T10>>; +/** + * A rigorous type alias for a class. + */ +export type Class<CtorArgs extends any[] = any[], InstanceType = {}, StaticType = {}, IsAbstract = false> = (abstract new (...args: any[]) => InstanceType) & StaticType; +export {}; diff --git a/node_modules/ts-mixer/dist/types/util.d.ts b/node_modules/ts-mixer/dist/types/util.d.ts new file mode 100644 index 0000000..4797ef4 --- /dev/null +++ b/node_modules/ts-mixer/dist/types/util.d.ts @@ -0,0 +1,27 @@ +/** + * Utility function that works like `Object.apply`, but copies getters and setters properly as well. Additionally gives + * the option to exclude properties by name. + */ +export declare const copyProps: (dest: object, src: object, exclude?: string[]) => void; +/** + * 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. + */ +export declare const protoChain: (obj: object, currentChain?: object[]) => object[]; +/** + * Identifies the nearest ancestor common to all the given objects in their prototype chains. For most unrelated + * objects, this function should return Object.prototype. + */ +export declare const nearestCommonProto: (...objs: object[]) => object | undefined; +/** + * 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. + */ +export declare const hardMixProtos: (ingredients: any[], constructor: Function | null, exclude?: string[]) => object; +export declare const unique: <T>(arr: T[]) => T[]; +export declare const flatten: <T>(arr: T[][]) => T[]; |