UNPKG

@type-r/mixture

Version:

React-style mixins, Backbone-style events, logging router.

245 lines 9.3 kB
import { __extends as __extends_1, __rest } from "tslib"; import { __extends } from 'tslib'; import { assign, defaults, getBaseClass, hashMap, transform } from './tools'; var Mixable = (function () { function Mixable() { } Mixable.define = function (protoProps, staticProps) { if (protoProps === void 0) { protoProps = {}; } var BaseClass = getBaseClass(this); staticProps && assign(this, staticProps); var mixins = protoProps.mixins, defineMixin = __rest(protoProps, ["mixins"]); mixins && this.mixins.merge(mixins); this.mixins.mergeObject(this.prototype, defineMixin, true); this.mixins.mergeObject(this.prototype, this.mixins.getStaticDefinitions(BaseClass), true); this.onDefine && this.onDefine(this.mixins.definitions, BaseClass); this.mixins.mergeInheritedMembers(BaseClass); return this; }; Mixable.extend = function (spec, statics) { var TheSubclass; if (spec && spec.hasOwnProperty('constructor')) { TheSubclass = spec.constructor; __extends(TheSubclass, this); } else { TheSubclass = (function (_super) { __extends_1(Subclass, _super); function Subclass() { return _super !== null && _super.apply(this, arguments) || this; } return Subclass; }(this)); } predefine(TheSubclass); spec && TheSubclass.define(spec, statics); return TheSubclass; }; return Mixable; }()); export { Mixable }; export function predefine(Constructor) { var BaseClass = getBaseClass(Constructor); Constructor.__super__ = BaseClass.prototype; Constructor.define || MixinsState.get(Mixable).populate(Constructor); MixinsState.get(Constructor); Constructor.onExtend && Constructor.onExtend(BaseClass); } export function define(ClassOrDefinition) { if (typeof ClassOrDefinition === 'function') { predefine(ClassOrDefinition); ClassOrDefinition.define(); } else { return function (Ctor) { predefine(Ctor); Ctor.define(ClassOrDefinition); }; } } export function definitions(rules) { return function (Class) { var mixins = MixinsState.get(Class); mixins.definitionRules = defaults(hashMap(), rules, mixins.definitionRules); }; } export function propertyListDecorator(listName) { return function propList(proto, name) { var list = proto.hasOwnProperty(listName) ? proto[listName] : (proto[listName] = (proto[listName] || []).slice()); list.push(name); }; } export function definitionDecorator(definitionKey, value) { return function (proto, name) { var _a, _b; MixinsState .get(proto.constructor) .mergeObject(proto, (_a = {}, _a[definitionKey] = (_b = {}, _b[name] = value, _b), _a)); }; } var MixinsState = (function () { function MixinsState(Class) { this.Class = Class; this.definitions = {}; var mixins = getBaseClass(Class).mixins; this.mergeRules = (mixins && mixins.mergeRules) || hashMap(); this.definitionRules = (mixins && mixins.definitionRules) || hashMap(); this.appliedMixins = (mixins && mixins.appliedMixins) || []; } MixinsState.get = function (Class) { var mixins = Class.mixins; return mixins && Class === mixins.Class ? mixins : Class.mixins = new MixinsState(Class); }; MixinsState.prototype.getStaticDefinitions = function (BaseClass) { var definitions = hashMap(), Class = this.Class; return transform(definitions, this.definitionRules, function (rule, name) { if (BaseClass[name] !== Class[name]) { return Class[name]; } }); }; MixinsState.prototype.merge = function (mixins) { var proto = this.Class.prototype, mergeRules = this.mergeRules; var appliedMixins = this.appliedMixins = this.appliedMixins.slice(); for (var _i = 0, mixins_1 = mixins; _i < mixins_1.length; _i++) { var mixin = mixins_1[_i]; if (Array.isArray(mixin)) { this.merge(mixin); } else if (appliedMixins.indexOf(mixin) < 0) { appliedMixins.push(mixin); if (typeof mixin === 'function') { this.mergeObject(this.Class, mixin); var sourceMixins = mixin.mixins; if (sourceMixins) { this.mergeRules = defaults(hashMap(), this.mergeRules, sourceMixins.mergeRules); this.definitionRules = defaults(hashMap(), this.definitionRules, sourceMixins.definitionRules); this.appliedMixins = this.appliedMixins.concat(sourceMixins.appliedMixins); } this.mergeObject(proto, mixin.prototype); } else { this.mergeObject(proto, mixin); } } } }; MixinsState.prototype.populate = function () { var ctors = []; for (var _i = 0; _i < arguments.length; _i++) { ctors[_i] = arguments[_i]; } for (var _a = 0, ctors_1 = ctors; _a < ctors_1.length; _a++) { var Ctor = ctors_1[_a]; MixinsState.get(Ctor).merge([this.Class]); } }; MixinsState.prototype.mergeObject = function (dest, source, unshift) { var _this = this; forEachOwnProp(source, function (name) { var sourceProp = Object.getOwnPropertyDescriptor(source, name); var rule; if (rule = _this.definitionRules[name]) { assignProperty(_this.definitions, name, sourceProp, rule, unshift); } if (!rule || rule === mixinRules.protoValue) { assignProperty(dest, name, sourceProp, _this.mergeRules[name], unshift); } }); }; MixinsState.prototype.mergeInheritedMembers = function (BaseClass) { var _a = this, mergeRules = _a.mergeRules, Class = _a.Class; if (mergeRules) { var proto = Class.prototype, baseProto = BaseClass.prototype; for (var name_1 in mergeRules) { var rule = mergeRules[name_1]; if (proto.hasOwnProperty(name_1) && name_1 in baseProto) { proto[name_1] = resolveRule(proto[name_1], baseProto[name_1], rule); } } } }; return MixinsState; }()); export { MixinsState }; var dontMix = { function: hashMap({ length: true, prototype: true, caller: true, arguments: true, name: true, __super__: true }), object: hashMap({ constructor: true }) }; function forEachOwnProp(object, fun) { var ignore = dontMix[typeof object]; for (var _i = 0, _a = Object.getOwnPropertyNames(object); _i < _a.length; _i++) { var name_2 = _a[_i]; ignore[name_2] || fun(name_2); } } export var mixins = function () { var list = []; for (var _i = 0; _i < arguments.length; _i++) { list[_i] = arguments[_i]; } return (function (Class) { return MixinsState.get(Class).merge(list); }); }; export var mixinRules = (function (rules) { return (function (Class) { var mixins = MixinsState.get(Class); mixins.mergeRules = defaults(rules, mixins.mergeRules); }); }); mixinRules.value = function (a, b) { return a; }; mixinRules.protoValue = function (a, b) { return a; }; mixinRules.merge = function (a, b) { return defaults({}, a, b); }; mixinRules.pipe = function (a, b) { return (function (x) { return a.call(this, b.call(this, x)); }); }; mixinRules.defaults = function (a, b) { return (function () { return defaults(a.apply(this, arguments), b.apply(this, arguments)); }); }; mixinRules.classFirst = function (a, b) { return (function () { a.apply(this, arguments); b.apply(this, arguments); }); }; mixinRules.classLast = function (a, b) { return (function () { b.apply(this, arguments); a.apply(this, arguments); }); }; mixinRules.every = function (a, b) { return (function () { return a.apply(this, arguments) && b.apply(this, arguments); }); }; mixinRules.some = function (a, b) { return (function () { return a.apply(this, arguments) || b.apply(this, arguments); }); }; function assignProperty(dest, name, sourceProp, rule, unshift) { if (dest.hasOwnProperty(name)) { var destProp = Object.getOwnPropertyDescriptor(dest, name); if (destProp.configurable && 'value' in destProp) { dest[name] = unshift ? resolveRule(sourceProp.value, destProp.value, rule) : resolveRule(destProp.value, sourceProp.value, rule); } } else { Object.defineProperty(dest, name, sourceProp); } } function resolveRule(dest, source, rule) { if (dest === void 0) return source; if (!rule || source === void 0) return dest; return rule(dest, source); } //# sourceMappingURL=mixins.js.map