@itrocks/uses
Version:
Apply reusable mixins to your classes effortlessly with the @Uses decorator
52 lines • 1.82 kB
JavaScript
import { baseType } from '@itrocks/class-type';
import { decorate, ownDecoratorOf } from '@itrocks/decorator/class';
export function Super(self) {
return Object.getPrototypeOf(Object.getPrototypeOf(self));
}
function uses(target, mixins) {
const builtTarget = (() => class extends target {
constructor(...args) {
super(...args);
for (const mixin of mixins)
this[mixin.name](...args);
}
})();
for (const mixin of mixins) {
const already = ['constructor'];
let proto = mixin.prototype;
while (proto.constructor !== Object) {
for (const [name, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(proto))) {
if (already.includes(name))
continue;
already.push(name);
Object.defineProperty(builtTarget.prototype, name, descriptor);
}
proto = Object.getPrototypeOf(proto);
}
}
for (const mixin of mixins) {
Object.defineProperty(builtTarget.prototype, mixin.name, {
configurable: true,
enumerable: false,
value: function (...args) { Object.assign(this, new mixin(...args)); },
writable: true
});
}
return builtTarget;
}
const USES = Symbol('uses');
export function Uses(...mixins) {
return (target) => {
mixins = mixins.concat(usesOf(target));
const builtTarget = uses(target, mixins);
decorate(USES, mixins)(builtTarget);
return builtTarget;
};
}
export function usesOf(target, resolveBuiltClass = false) {
const usesOf = ownDecoratorOf(target, USES, []);
return resolveBuiltClass
? usesOf.map(type => baseType(type))
: usesOf;
}
//# sourceMappingURL=uses.js.map