// reverse changes to an object
const proxyobserver = require("@createvibe/proxyobserver")
const data = {initializing: true};
const reverse = [];
const proxy = proxyobserver(data, function() {
const chain = Array.prototype.slice.call(arguments);
const root = chain[0];
const leaf = chain[chain.length - 1];
const path = chain.map(link => link.prop);
const link = {chain: chain.slice(), root, leaf, path};
leaf.value = leaf.value && JSON.parse(JSON.stringify(leaf.value)) || leaf.value;
leaf.oldValue = leaf.oldValue && JSON.parse(JSON.stringify(leaf.oldValue)) || leaf.oldValue;
reverse.push(() => {
if (leaf.oldValue === undefined) {
return Reflect.deleteProperty(leaf.target, leaf.prop);
}
let node;
let reference = data;
const chain = link.chain.slice(0, -1);
while (node = chain.shift()) {
const { prop, oldValue } = node;
if (!(prop in reference)) {
Reflect.defineProperty(reference, prop, {
value: oldValue,
enumerable: true,
configurable: true,
writable: true
});
}
reference = reference[prop];
}
if (leaf.prop in reference) {
return Reflect.set(reference, leaf.prop, leaf.oldValue, leaf.receiver);
}
Reflect.defineProperty(reference, leaf.prop, {
value: leaf.oldValue,
enumerable: true,
configurable: true,
writable: true
});
});
});
// remove the initializing flag
delete proxy.initializing;
// add data to the object
proxy.one = 'test';
proxy.two = [1,2,3];
proxy.two.splice(0,1,5,8,9);
proxy.three = {
nested: [4,5,6],
data: {value: 'test'}
};
// modify data in the object
proxy.one = 'modified';
proxy.two[1] = 'test';
proxy.two = ['array', 'change'];
proxy.two.push('stuff');
proxy.two = null;
proxy.two = undefined;
proxy.two = 'test';
proxy.two = undefined;
proxy.two = undefined;
proxy.two = 'foo';
proxy.two = undefined;
delete proxy.two;
proxy.three.data.value = 'modified';
proxy.three.nested.push(7);
proxy.three.nested.splice(0,0,3);
// delete data
delete proxy.one;
console.log('the updated data', JSON.stringify(data));
// now reverse the last change
reverse.pop().call(null);
// now reverse the rest of the changes!
while (reverse.length !== 0) {
reverse.pop().call(null);
}
// notice the object is exactly how it was when we initialized it
console.log('the reset data', JSON.stringify(data));