diff --git a/index.js b/index.js index 1cf0f79..832d600 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,9 @@ const diff = require('./diff'); const patch = require('./patch'); +const reverse = require('./reverse'); module.exports = { diff, patch, + reverse, }; diff --git a/reverse.js b/reverse.js new file mode 100644 index 0000000..80e4a20 --- /dev/null +++ b/reverse.js @@ -0,0 +1,47 @@ +const { _clone, _objId } = require('./helpers'); + +function reverse(changes) { + + const reversed = _clone(changes).reverse(); + + for (const change of reversed) { + + if (change.op == 'add') { + change.op = 'remove'; + const id = _objId(change.value); + if (id) { + change._index = change.path.split('/').pop(); + change.path = change.path.replace(/\d+$/, `[${id}]`); + } + + } else if (change.op == 'remove') { + change.op = 'add'; + } + + if ('_prev' in change) { + var _prev = change._prev; + } + + if ('value' in change) { + var _value = change.value; + } + + if (_prev === undefined) { + delete change.value; + } else { + change.value = _prev; + } + + if (_value === undefined) { + delete change._prev; + } else { + change._prev = _value; + } + + } + + return reversed; + +} + +module.exports = reverse; diff --git a/test.js b/test.js index 7f71991..419e662 100644 --- a/test.js +++ b/test.js @@ -2,6 +2,7 @@ const assert = require('assert'); const diff = require('./diff'); const patch = require('./patch'); +const reverse = require('./reverse'); /* DIFF */ @@ -26,7 +27,7 @@ assert.deepEqual( [ { op: 'remove', path: '/title', _prev: 'hello' } ] ); -// object property remove +// object property replace assert.deepEqual( diff({ id: 1, title: 'hello' }, { id: 1, title: 'salut' }), [ { op: 'replace', path: '/title', value: 'salut', _prev: 'hello' } ] @@ -147,6 +148,19 @@ assert.deepEqual( ); +/* REVERSE */ +assert.deepEqual( + reverse( + [ { op: 'replace', path: '/name', value: 'henry', _prev: 'hank' } ] + ), + [ { op: 'replace', path: '/name', value: 'hank', _prev: 'henry' } ] +); +assert.deepEqual( + reverse( + [ { op: 'add', path: '/names/0', value: { id: 38, name: 'henry' } } ] + ), + [ { op: 'remove', path: '/names/[38]', _index: 0, _prev: { id: 38, name: 'henry' } } ] +);