@schoolbelle/common
Version:
1,031 lines (1,021 loc) • 32.3 kB
JavaScript
import { Subject } from 'rxjs';
import { forEach, isArray, isPlainObject, get as get$1, set as set$1, unset, isEqual, cloneDeep, orderBy, isEmpty, values, defaults } from 'lodash-es';
import { __extends, __assign, __read } from 'tslib';
import { get, set, cloneDeep as cloneDeep$1, defaults as defaults$1, isEmpty as isEmpty$1 } from 'lodash';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} ob
* @param {?=} delimiter
* @param {?=} current_key_path
* @param {?=} paths
* @return {?}
*/
function getAllLeafPaths(ob, delimiter, current_key_path, paths) {
if (delimiter === void 0) { delimiter = '.'; }
if (current_key_path === void 0) { current_key_path = []; }
if (paths === void 0) { paths = []; }
forEach(ob, (/**
* @param {?} val
* @param {?} key
* @return {?}
*/
function (val, key) {
key = isArray(ob) ? "" + key : key;
// an instance of Class such as a File instance is not a plain object.
if (isPlainObject(val) || isArray(val)) {
paths = getAllLeafPaths(val, delimiter, current_key_path.concat([key]), paths);
}
else {
paths.push(current_key_path.concat([key]).join(delimiter));
}
}));
return paths;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* calculate the difference btwn two objects
* and return object with key being path and value being an object of to and from ;
* ex> say before is {a:{b:{c:1}}} and current is {a:{b:{c:2}}}
* returned value will be {'a.b.c':{to:2, from:1}}
*
* @param {?} current
* @param {?} before
* @return {?}
*/
function getAllLeafChanges(current, before) {
/** @type {?} */
var diff = {};
/** @type {?} */
var allLeafPathsOfCurrent = getAllLeafPaths(current);
/** @type {?} */
var allLeafPathsOfBefore = getAllLeafPaths(before);
allLeafPathsOfCurrent.forEach((/**
* @param {?} path
* @return {?}
*/
function (path) {
/** @type {?} */
var v_from_origin = get(before, path);
/** @type {?} */
var v_from_current = get(current, path);
if (isEmptyStringOrNullOrUndefined(v_from_current) === true && isEmptyStringOrNullOrUndefined(v_from_origin) === true)
return;
if (v_from_current !== v_from_origin) {
set(diff, [path, 'to'], v_from_current);
}
}));
allLeafPathsOfBefore.forEach((/**
* @param {?} path
* @return {?}
*/
function (path) {
/** @type {?} */
var v_from_origin = get(before, path);
/** @type {?} */
var v_from_current = get(current, path);
if (isEmptyStringOrNullOrUndefined(v_from_current) === true && isEmptyStringOrNullOrUndefined(v_from_origin) === true)
return;
if (v_from_current !== v_from_origin) {
set(diff, [path, 'from'], v_from_origin);
}
}));
/**
* [START file type usage extension]
*
*
* class Foo {
* a = "a"
* b = "b"
* }
* const before = {branch1:{a:"a", b:"b"}, branch2:"c"}; // getAllLeafPaths will return ["branch1.a", "branch1.b", "branch2"]
* const current = {branch1:new Foo(), , branch2:"c"} // getAllLeafPaths will return ["branch1", "branch2"]
*
* result will be :
* 1. missing to or from in the "diff"
* 2. sub-paths of a class instance in the "diff"
*
* We have to :
* 1. Fill in the missing part of data
* 2. Remove all sub-paths of a class instance
*
* @type {?}
*/
var paths = Object.keys(diff);
Object.entries(diff)
.forEach((/**
* @param {?} __0
* @return {?}
*/
function (_a) {
var _b = __read(_a, 2), path = _b[0], update = _b[1];
if (update.to !== null && typeof update.to === 'object') {
// fill the missing data, from.
update.from = get(before, path);
// delete sub-paths of a class instance such as "branch1.a", "branch1.b"
paths.filter((/**
* @param {?} p
* @return {?}
*/
function (p) { return p.startsWith(path) && p !== path; })).forEach((/**
* @param {?} p
* @return {?}
*/
function (p) { delete diff[p]; }));
}
else if (update.from !== null && typeof update.from === 'object') {
// fill the missing data, to.
update.to = get(current, path);
// delete sub-paths of a class instance such as "branch1.a", "branch1.b"
paths.filter((/**
* @param {?} p
* @return {?}
*/
function (p) { return p.startsWith(path) && p !== path; })).forEach((/**
* @param {?} p
* @return {?}
*/
function (p) { delete diff[p]; }));
}
}));
// [END file type usage extension]
return diff;
}
/**
* @param {?} v
* @return {?}
*/
function isEmptyStringOrNullOrUndefined(v) {
return v === '' || v === null || v === undefined;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} val
* @return {?}
*/
function shakeDeadLeaves(val) {
if (val === null)
return null;
if (val === undefined)
return null;
// if (val instanceof File || val instanceof Blob) return val; // instance of File or Blob
if (val && typeof val === 'object' && !isPlainObject(val))
return val; // instance of a class including File, Blob, and many other
if (val && typeof val === 'object' && Object.keys(val).length === 0)
return null; // {}
if (typeof val !== 'object')
return val;
else {
for (var key in val) {
val[key] = shakeDeadLeaves(val[key]);
if (val[key] === null)
delete val[key];
}
if (Object.keys(val).length === 0)
return null;
else
return val;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ObjectChangeTracker = /** @class */ (function () {
function ObjectChangeTracker(root, pathFromRoot) {
if (root === void 0) { root = undefined; }
if (pathFromRoot === void 0) { pathFromRoot = []; }
this.contentUpdateEvent = new Subject();
/**
* this is where it keep its model.
* The only root tracker keeps it.
* Child trackers send all changes to their root tracker and the root tracker writes all changes to this property.
*
*/
this._value = {};
this._origin = {};
this._to = {};
this._from = {};
this._trackers = new Map();
this._root = root || this;
this._pathFromRoot = pathFromRoot;
if (this.root !== this) {
this.trackers.set(this.pathFromRoot.join('.'), this);
}
}
Object.defineProperty(ObjectChangeTracker.prototype, "root", {
get: /**
* @return {?}
*/
function () {
if (this._root === this)
return this;
else
return this._root.root;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "pathFromRoot", {
get: /**
* @return {?}
*/
function () {
if (this._root === this)
return [];
else {
return this._root.pathFromRoot.concat(this._pathFromRoot);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "onContentUpdate", {
get: /**
* @return {?}
*/
function () {
return this.contentUpdateEvent.asObservable();
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "value", {
/**
* return the whole model if root or else "branch" of model.
* Watch out for modifying this data cause it may return reference to the model itself.
*/
get: /**
* return the whole model if root or else "branch" of model.
* Watch out for modifying this data cause it may return reference to the model itself.
* @return {?}
*/
function () {
if (this._root === this)
return this._value;
else
return get$1(this.root._value, this.pathFromRoot);
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "isChanged", {
get: /**
* @return {?}
*/
function () {
/** @type {?} */
var to = this.to;
/** @type {?} */
var from = this.from;
return ((to && (typeof to === 'object' && Object.keys(to).length !== 0))
|| (from && (typeof from === 'object' && Object.keys(from).length !== 0))
|| !isEqual(to, from));
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "origin", {
get: /**
* @return {?}
*/
function () {
if (this.root === this)
return this._origin;
else
return get$1(this.root.origin, this.pathFromRoot);
},
set: /**
* @param {?} v
* @return {?}
*/
function (v) {
if (typeof v === 'undefined')
v = null;
if (this.root === this)
this._origin = v;
else
set$1(this.root.origin, this.pathFromRoot, v);
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "to", {
get: /**
* @return {?}
*/
function () {
if (this.root === this)
return this._to;
else
return get$1(this.root.to, this.pathFromRoot);
},
set: /**
* @param {?} v
* @return {?}
*/
function (v) {
if (this.root === this)
this._to = v || {};
else {
if (v === null) {
unset(this.root.to, this.pathFromRoot);
this.root.to = shakeDeadLeaves(this.root.to);
}
else
set$1(this.root.to, this.pathFromRoot, v);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "from", {
get: /**
* @return {?}
*/
function () {
if (this.root === this)
return this._from;
else
return get$1(this.root.from, this.pathFromRoot);
},
set: /**
* @param {?} v
* @return {?}
*/
function (v) {
if (this.root === this)
this._from = v || {};
else {
if (v === null) {
unset(this.root.from, this.pathFromRoot);
this.root.from = shakeDeadLeaves(this.root.from);
}
else
set$1(this.root.from, this.pathFromRoot, v);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "parent", {
get: /**
* @return {?}
*/
function () {
if (this.root === this)
return this;
else
return this.root.getChildTracker(this.pathFromRoot.slice(0, -1));
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTracker.prototype, "trackers", {
get: /**
* @return {?}
*/
function () {
if (this.root === this)
return this._trackers;
else
return this.root.trackers;
},
enumerable: true,
configurable: true
});
/**
* @param {?} path
* @return {?}
*/
ObjectChangeTracker.prototype.get = /**
* @param {?} path
* @return {?}
*/
function (path) {
if (typeof path === 'string')
path = path.split('.').filter((/**
* @param {?} step
* @return {?}
*/
function (step) { return step; }));
path = this.pathFromRoot.concat(path);
/** @type {?} */
var value;
if (path.length === 0)
value = this.root._value;
else {
value = get$1(this.root._value, path);
}
// array data type handling
if (!isEmpty(value) && typeof value === 'object' && !Array.isArray(value)) {
/** @type {?} */
var keys = Object.keys(value);
if (typeof value["" + 0] !== "undefined" && typeof value["" + (keys.length - 1)] !== "undefined" && !keys.find((/**
* @param {?} key
* @return {?}
*/
function (key) { return parseInt("" + key) === NaN; }))) {
return values(value);
}
else {
return value;
}
}
return value;
// if (path.length === 0) return cloneDeep(this.root._value);
// else {
// return cloneDeep(get(this.root._value, path));
// }
};
/**
* @param {?} path
* @param {?} value
* @param {?=} options
* @return {?}
*/
ObjectChangeTracker.prototype.set = /**
* @param {?} path
* @param {?} value
* @param {?=} options
* @return {?}
*/
function (path, value, options) {
if (options === void 0) { options = undefined; }
options = defaults(options, { push: 'up', updateDiff: true });
if (typeof value === 'undefined')
value = null;
if (typeof path === 'string')
path = path.split('.').filter((/**
* @param {?} step
* @return {?}
*/
function (step) { return step; }));
path = this.pathFromRoot.concat(path);
this.updateData(path, value);
if (options.updateOrigin)
this.updateOrigin(path, value);
if (options.updateDiff)
this.updateDiff();
if (options.push !== 'none')
this.notifyChangeThruTree(path, options);
};
/**
* @param {?=} origin
* @param {?=} options
* @return {?}
*/
ObjectChangeTracker.prototype.load = /**
* @param {?=} origin
* @param {?=} options
* @return {?}
*/
function (origin, options) {
if (origin === void 0) { origin = {}; }
if (options === void 0) { options = undefined; }
if (this.root !== this)
throw new Error('load is only allowed for root');
options = defaults(options, { push: 'up', updateDiff: true });
this.origin = cloneDeep(origin);
this.updateData([], origin);
if (options.updateDiff)
this.updateDiff();
if (options.push !== 'none')
this.notifyChangeThruTree([], options);
};
/**
* @protected
* @return {?}
*/
ObjectChangeTracker.prototype.updateDiff = /**
* @protected
* @return {?}
*/
function () {
/** @type {?} */
var origin = this.origin;
/** @type {?} */
var current = this.value;
/** @type {?} */
var to = {};
/** @type {?} */
var from = {};
/** @type {?} */
var changes = getAllLeafChanges(current, origin);
for (var path in changes) {
set$1(to, path, changes[path].to);
set$1(from, path, changes[path].from);
}
shakeDeadLeaves(to);
shakeDeadLeaves(from);
this.to = isEmpty(to) ? null : to;
this.from = isEmpty(from) ? null : from;
};
/**
*
* @param path
* @param v_n
* set 'null' means unset
* unset value will return as 'undefined'
*
*/
/**
*
* @protected
* @param {?} path
* @param {?} v_n
* set 'null' means unset
* unset value will return as 'undefined'
*
* @return {?}
*/
ObjectChangeTracker.prototype.updateData = /**
*
* @protected
* @param {?} path
* @param {?} v_n
* set 'null' means unset
* unset value will return as 'undefined'
*
* @return {?}
*/
function (path, v_n) {
/** @type {?} */
var v_o = get$1(this._value, path);
if (isEqual(v_n, v_o))
return;
if (v_n === null) {
if (path.length === 0)
this.root._value = v_n;
else
unset(this.root._value, path);
}
else {
if (path.length === 0)
this.root._value = cloneDeep(v_n);
else
set$1(this.root._value, path, cloneDeep(v_n));
}
};
/**
* @protected
* @param {?} path
* @param {?} v_n
* @return {?}
*/
ObjectChangeTracker.prototype.updateOrigin = /**
* @protected
* @param {?} path
* @param {?} v_n
* @return {?}
*/
function (path, v_n) {
/** @type {?} */
var v_o = get$1(this._origin, path);
if (isEqual(v_n, v_o))
return;
if (v_n === null) {
if (path.length === 0)
this.root._origin = v_n;
else
unset(this.root._origin, path);
}
else {
if (path.length === 0)
this.root._origin = v_n instanceof File ? v_n : cloneDeep(v_n);
else
set$1(this.root._origin, path, v_n instanceof File ? v_n : cloneDeep(v_n));
}
};
/**
* @param {?=} paths
* @param {?=} options
* @return {?}
*/
ObjectChangeTracker.prototype.notifyChangeThruTree = /**
* @param {?=} paths
* @param {?=} options
* @return {?}
*/
function (paths, options) {
var _this = this;
if (paths === void 0) { paths = []; }
if (options === void 0) { options = undefined; }
options = __assign({ push: 'up' }, options);
/** @type {?} */
var tracker = paths.length === 0 ? this : this.trackers.get(paths.join('.'));
if (['down', 'both'].includes(options.push)) {
orderBy(Array.from(this.trackers.keys()), (/**
* @param {?} key
* @return {?}
*/
function (key) { return key.split('.').length; }), 'desc')
.filter((/**
* @param {?} key
* @return {?}
*/
function (key) { return key.match(paths.join('.')); }))
.map((/**
* @param {?} key
* @return {?}
*/
function (key) { return _this.trackers.get(key); }))
.filter((/**
* @param {?} childTracker
* @return {?}
*/
function (childTracker) { return childTracker; }))
.forEach((/**
* @param {?} childTracker
* @return {?}
*/
function (childTracker) { return childTracker.contentUpdateEvent.next({ to: childTracker.to, from: childTracker.from }); }));
}
if (!['none'].includes(options.push) && tracker)
tracker.contentUpdateEvent.next({ to: tracker.to, from: tracker.from });
if (['up', 'both'].includes(options.push)) {
paths.map((/**
* @param {?} path
* @param {?} index
* @return {?}
*/
function (path, index) { return paths.slice(0, paths.length - index).join('.'); }))
.map((/**
* @param {?} subpaths
* @return {?}
*/
function (subpaths) { return _this.trackers.get(subpaths); }))
.filter((/**
* @param {?} childTracker
* @return {?}
*/
function (childTracker) { return childTracker; }))
.forEach((/**
* @param {?} childTracker
* @return {?}
*/
function (childTracker) {
childTracker.contentUpdateEvent.next({ to: childTracker.to, from: childTracker.from });
}));
this.root.contentUpdateEvent.next({ to: this.root.to, from: this.root.from });
}
};
/**
* @param {?} path
* @return {?}
*/
ObjectChangeTracker.prototype.getChildTracker = /**
* @param {?} path
* @return {?}
*/
function (path) {
if (typeof path === 'string')
path = path.split('.').filter((/**
* @param {?} step
* @return {?}
*/
function (step) { return step; }));
/** @type {?} */
var fullpath = this.pathFromRoot.concat(path);
if (fullpath.length === 0) {
return this;
}
else {
/** @type {?} */
var childRef = this.trackers.get(fullpath.join('.'));
if (!childRef) {
childRef = new ObjectChangeTracker(this, path);
this.trackers.set(fullpath.join('/'), childRef);
}
return childRef;
}
};
/**
* @param {?=} path
* @return {?}
*/
ObjectChangeTracker.prototype.destroyTracker = /**
* @param {?=} path
* @return {?}
*/
function (path) {
if (path === void 0) { path = []; }
if (typeof path === 'string')
path = path.split('.').filter((/**
* @param {?} step
* @return {?}
*/
function (step) { return step; }));
path = this.pathFromRoot.concat(path);
/** @type {?} */
var tracker;
if (path.length === 0)
tracker = this;
else
tracker = this.trackers.get(path.join('.'));
if (tracker) {
tracker.contentUpdateEvent.complete();
this.trackers.delete(path.join('.'));
}
};
return ObjectChangeTracker;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
var DEFAULT_MAX_SIZE = 100;
var ObjectChangeTrackerWithHistory = /** @class */ (function (_super) {
__extends(ObjectChangeTrackerWithHistory, _super);
function ObjectChangeTrackerWithHistory(root, pathFromRoot) {
if (root === void 0) { root = undefined; }
if (pathFromRoot === void 0) { pathFromRoot = []; }
var _this = _super.call(this, root, pathFromRoot) || this;
_this._trackers = new Map();
/**
* maximum length of history stack
*/
_this.MAX_SIZE = DEFAULT_MAX_SIZE;
/**
* current position in the history stack
*/
_this.position = 0;
/**
* history stack
*/
_this.stack = [];
return _this;
}
Object.defineProperty(ObjectChangeTrackerWithHistory.prototype, "root", {
get: /**
* @return {?}
*/
function () {
if (this._root === this)
return this;
else
return this._root.root;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTrackerWithHistory.prototype, "parent", {
get: /**
* @return {?}
*/
function () {
if (this.root === this)
return this;
else
return this.root.getChildTracker(this.pathFromRoot.slice(0, -1));
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectChangeTrackerWithHistory.prototype, "trackers", {
get: /**
* @return {?}
*/
function () {
if (this.root === this)
return this._trackers;
else
return this.root.trackers;
},
enumerable: true,
configurable: true
});
/**
* @param {?} path
* @return {?}
*/
ObjectChangeTrackerWithHistory.prototype.getChildTracker = /**
* @param {?} path
* @return {?}
*/
function (path) {
if (typeof path === 'string')
path = path.split('.').filter((/**
* @param {?} step
* @return {?}
*/
function (step) { return step; }));
/** @type {?} */
var fullpath = this.pathFromRoot.concat(path);
if (fullpath.length === 0) {
return this;
}
else {
/** @type {?} */
var childRef = this.trackers.get(fullpath.join('.'));
if (!childRef) {
childRef = new ObjectChangeTrackerWithHistory(this, path);
this.trackers.set(fullpath.join('/'), childRef);
}
return childRef;
}
};
/**
*
* @param data
* @param MAX_SIZE
*
* let's say you make 3 changes, undo 2 times, and enter then another change.
* v denotes the current position in history stack.
* [d1 d2 d3 v] // 3 changes (pos is 3)
* [d1 v d2 d3] // 2 undo's (pos is 1)
* [d1 d4 v] // a new change (pos is 2)
*/
/**
*
* @return {?}
*/
ObjectChangeTrackerWithHistory.prototype.save = /**
*
* @return {?}
*/
function () {
if (this.root !== this)
throw new Error('save is only allowed for root');
// 0. get diff
/** @type {?} */
var before = this.before;
/** @type {?} */
var current = this.value;
/** @type {?} */
var diff = getAllLeafChanges(current, before)
// 1. Pushing a new item should remove the history items that stand after the current position, if there is(are).
;
// 1. Pushing a new item should remove the history items that stand after the current position, if there is(are).
if (this.stack.length > this.position)
this.stack.splice(this.position);
// 2. Push to the stack.
this.stack.push(diff);
// 3. Rotate the list if it grows too big.
if (this.stack.length > this.MAX_SIZE)
this.stack.splice(0, this.stack.length - this.MAX_SIZE);
// 4. move up the position if possible.
if (this.position < this.MAX_SIZE)
this.position++;
// 5. update before
for (var path in diff) {
set(this.before, path, diff[path].to);
}
this.updateDiff();
};
/**
* @param {?} path
* @param {?} value
* @param {?=} options
* @return {?}
*/
ObjectChangeTrackerWithHistory.prototype.set = /**
* @param {?} path
* @param {?} value
* @param {?=} options
* @return {?}
*/
function (path, value, options) {
if (options === void 0) { options = undefined; }
options = defaults$1(options, { saveToHistory: true });
_super.prototype.set.call(this, path, value, options);
if (options.saveToHistory)
this.root.save();
};
/**
* reset history related properties.
*/
/**
* reset history related properties.
* @protected
* @return {?}
*/
ObjectChangeTrackerWithHistory.prototype.reset = /**
* reset history related properties.
* @protected
* @return {?}
*/
function () {
this.before = null;
this.position = 0;
this.stack.splice(0, this.stack.length);
};
/**
* @param {?=} origin
* @param {?=} options
* @return {?}
*/
ObjectChangeTrackerWithHistory.prototype.load = /**
* @param {?=} origin
* @param {?=} options
* @return {?}
*/
function (origin, options) {
if (origin === void 0) { origin = {}; }
if (options === void 0) { options = undefined; }
_super.prototype.load.call(this, origin, options);
this.reset();
this.before = cloneDeep$1(origin);
};
/**
* @return {?}
*/
ObjectChangeTrackerWithHistory.prototype.undo = /**
* @return {?}
*/
function () {
if (this.root !== this)
throw new Error('undo is only allowed for root');
if (this.position <= 0)
return false;
// decrement position
this.position--;
// get the target history snapshot
/** @type {?} */
var diff = this.stack[this.position];
// update current and before value
/** @type {?} */
var current = this._value || {};
/** @type {?} */
var before = this.before || {};
// recalculate current and before
for (var path in diff) {
set(current, path, diff[path].from); // go back, model!
set(before, path, diff[path].from); // update before
}
shakeDeadLeaves(current);
shakeDeadLeaves(before);
// store current and before
this._value = isEmpty$1(current) ? null : current;
this.before = isEmpty$1(before) ? null : before;
// update diff
this.updateDiff();
// notify
for (var path in diff) {
this.notifyChangeThruTree(path.split('.'), { push: 'up' });
}
return true;
};
/**
* @return {?}
*/
ObjectChangeTrackerWithHistory.prototype.redo = /**
* @return {?}
*/
function () {
if (this.root !== this)
throw new Error('redo is only allowed for root');
if (this.position >= this.stack.length)
return false;
// increment position
this.position++;
// get the target history snapshot
/** @type {?} */
var diff = this.stack[this.position - 1];
// recalculate current and before
/** @type {?} */
var current = this._value || {};
/** @type {?} */
var before = this.before || {};
for (var path in diff) {
set(current, path, diff[path].to); // go forward, model!
set(before, path, diff[path].to); // update before
}
shakeDeadLeaves(current);
shakeDeadLeaves(before);
// store current and before
this._value = isEmpty$1(current) ? null : current;
this.before = isEmpty$1(before) ? null : before;
// update diff
this.updateDiff();
// notify
for (var path in diff) {
this.notifyChangeThruTree(path.split('.'));
}
return true;
};
return ObjectChangeTrackerWithHistory;
}(ObjectChangeTracker));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { ObjectChangeTracker, ObjectChangeTrackerWithHistory, getAllLeafPaths, shakeDeadLeaves };
//# sourceMappingURL=schoolbelle-common-object-change-tracker.js.map