UNPKG

mmlpx

Version:

mobx model layer paradigm

110 lines 4.51 kB
import * as tslib_1 from "tslib"; /** * @author Kuitos * @homepage https://github.com/kuitos/ * @since 2018-06-26 17:06 */ import { action, observable, ObservableMap, runInAction } from 'mobx'; import Injector from '../core/dependency-inject/Injector'; import { isMap } from '../utils/types'; var reactiveInjectorSymbol = Symbol('reactiveInjector'); function getLRUCacheSymbol(container) { return Object.getOwnPropertySymbols(container).find(function (symbol) { return isMap(container[symbol]); }); } function makeLRUCacheReactive(container, cacheSymbol) { var originalDump = container.dump, originalSet = container.set; var originalMap = container[cacheSymbol]; var observableMap = originalMap instanceof ObservableMap ? originalMap : new ObservableMap(); // hijack the map assignment to replace it by a ObservableMap // @see https://github.com/isaacs/node-lru-cache/blob/master/index.js#L201 Object.defineProperty(container, cacheSymbol, { set: function () { // should clear the map rather than reassign it to a new one, what will lose the reactive observation runInAction(function () { return observableMap.clear(); }); }, get: function () { return observableMap; } }); // wrap observable map setting into action container.set = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var result = false; runInAction(function () { return result = originalSet.apply(container, args); }); return result; }; container.dump = function () { // :dark magic: access container map size thus snapshot will reactive with ObservableMap when its setting(via getSnapshot invocation) // tslint:disable-next-line container[cacheSymbol].size; return originalDump.apply(container); }; } var ReactiveContainer = /** @class */function () { function ReactiveContainer() { this.container = new Map(); } ReactiveContainer.prototype.set = function (key, value) { try { this.container.set(key, value); return true; } catch (e) { /* istanbul ignore next */ console.error(e); /* istanbul ignore next */ return false; } }; ReactiveContainer.prototype.get = function (key) { return this.container.get(key); }; ReactiveContainer.prototype.dump = function () { return Array.from(this.container.entries()).map(function (entry) { return { k: entry[0], v: entry[1] }; }); }; ReactiveContainer.prototype.load = function (cacheEntries) { var _this = this; this.container.clear(); cacheEntries.forEach(function (entry) { _this.container.set(entry.k, entry.v); }); }; tslib_1.__decorate([observable, tslib_1.__metadata("design:type", Object)], ReactiveContainer.prototype, "container", void 0); tslib_1.__decorate([action, tslib_1.__metadata("design:type", Function), tslib_1.__metadata("design:paramtypes", [String, Object]), tslib_1.__metadata("design:returntype", void 0)], ReactiveContainer.prototype, "set", null); tslib_1.__decorate([action, tslib_1.__metadata("design:type", Function), tslib_1.__metadata("design:paramtypes", [Object]), tslib_1.__metadata("design:returntype", void 0)], ReactiveContainer.prototype, "load", null); return ReactiveContainer; }(); export default function genReactiveInjector(prevInjector) { if (prevInjector[reactiveInjectorSymbol]) { return prevInjector; } var newInjector = prevInjector; /* * if the injector has an LRUCache based container, we can hijack it and made the underlying map to be a reactive map, * and keep the lru features * otherwise we need to construct a simple-ObservableMap-based reactive container */ var container = prevInjector._getContainer(); var cacheSymbol = getLRUCacheSymbol(container); if (cacheSymbol) { makeLRUCacheReactive(container, cacheSymbol); } else { var reactiveContainer = new ReactiveContainer(); newInjector = Injector.newInstance(reactiveContainer); } var snapshot = prevInjector.dump(); newInjector.load(snapshot); newInjector[reactiveInjectorSymbol] = true; return newInjector; }