overmind
Version:
Frictionless state management
88 lines • 3.68 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Derived = exports.IS_DERIVED_CONSTRUCTOR = exports.IS_DERIVED = void 0;
const proxy_state_tree_1 = require("proxy-state-tree");
const internalTypes_1 = require("./internalTypes");
exports.IS_DERIVED = Symbol('IS_DERIVED');
exports.IS_DERIVED_CONSTRUCTOR = Symbol('IS_DERIVED_CONSTRUCTOR');
class Derived {
constructor(cb) {
this.cb = cb;
this.isDirty = true;
this.updateCount = 0;
const boundEvaluate = this.evaluate.bind(this);
if (process.env.NODE_ENV === 'development') {
boundEvaluate.dispose = () => {
this.disposeOnMutation();
};
}
boundEvaluate[exports.IS_DERIVED] = true;
return boundEvaluate;
}
runScope(tree, path) {
const parent = path
.slice(0, path.length - 1)
.reduce((curr, key) => curr[key], tree.state);
return this.cb(parent, tree.state);
}
evaluate(eventHub, tree, proxyStateTree, path) {
if (!this.disposeOnMutation) {
this.disposeOnMutation = proxyStateTree.onMutation((_, paths, flushId) => {
if (typeof path.reduce((aggr, key) => aggr && aggr[key], proxyStateTree.sourceState) !== 'function') {
this.disposeOnMutation();
return;
}
if (this.isDirty) {
return;
}
for (const mutationPath of paths) {
if (this.paths.has(mutationPath)) {
this.isDirty = true;
eventHub.emitAsync(internalTypes_1.EventType.DERIVED_DIRTY, {
derivedPath: path,
path: mutationPath,
flushId,
});
return;
}
}
});
}
// During development we need to move the ownership of whatever state is returned from
// the derived to track it correctly. In production we only have one proxifier, so no worries
if (this.isDirty || this.previousProxifier !== tree.proxifier) {
const getPaths = tree.trackPaths();
this.value = this.runScope(tree, path);
this.isDirty = false;
this.paths = getPaths();
if (process.env.NODE_ENV === 'development') {
eventHub.emitAsync(internalTypes_1.EventType.DERIVED, {
path,
paths: Array.from(this.paths),
updateCount: this.updateCount,
value: this.value,
});
this.updateCount++;
}
}
if (tree instanceof proxy_state_tree_1.TrackStateTree) {
// If we access a cached value we have to make sure that we move
// the tracked paths into the tree looking at it, where
// addTrackingPath is for initial tree and "trackPathListeners"
// is for nested derived
for (const path of this.paths) {
tree.addTrackingPath(path);
tree.trackPathListeners.forEach((cb) => cb(path));
}
}
this.previousProxifier = tree.proxifier;
// This value might be a proxy, we need to rescope
// it to the current tree looking
if (this.value && this.value[proxy_state_tree_1.IS_PROXY]) {
return proxyStateTree.rescope(this.value, tree);
}
return this.value;
}
}
exports.Derived = Derived;
//# sourceMappingURL=derived.js.map