This repository was archived by the owner on Mar 6, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpatch.js
More file actions
135 lines (114 loc) · 3.63 KB
/
Copy pathpatch.js
File metadata and controls
135 lines (114 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
'use strict'
var JSON8Pointer = require('json8-pointer')
var parse = JSON8Pointer.parse
var serialize = JSON8Pointer.serialize
var operations = require('./operations')
/**
* Apply a single JSON Patch operation object to a JSON document
* @param {Object|Array} doc - JSON document to apply the patch to
* @param {Object} patch - JSON Patch operation object
* @return {void}
*/
var run = function(doc, patch) {
if (typeof patch.path === 'string')
var pathTokens = parse(patch.path)
if (typeof patch.from === 'string')
var fromTokens = parse(patch.from)
switch (patch.op) {
case 'add':
case 'replace':
case 'test':
if (patch.value === undefined)
throw new Error('Missing value parameter')
return operations[patch.op](doc, pathTokens, patch.value)
case 'move':
case 'copy':
return operations[patch.op](doc, fromTokens, pathTokens)
case 'remove':
return operations[patch.op](doc, pathTokens)
}
throw new Error(patch.op + ' isn\'t a valid operation')
}
/**
* Return the reverse operation to a JSON Patch operation
* @param {Object} patch - JSON Patch operation object
* @param {Any} previous - previous value for add and replace operations
* @param {Number} idx - index of the item for array
* @return {void}
*/
var reverse = function(patch, previous, idx) {
var op = patch.op
var path = patch.path
if (op === 'copy' || (op === 'add' && previous === undefined)) {
if (idx === undefined)
return {"op": "remove", "path": path}
// for item pushed to array with -
var tokens = parse(path)
tokens[tokens.length - 1] = idx.toString()
return {"op": "remove", "path": serialize(tokens)}
}
if (op === 'replace')
return {"op": "replace", "path": path, "value": previous}
if (op === 'move')
return {"op": "move", "path": patch.from, "from": path}
if (op === 'add' || op === 'remove')
return {"op": "add", "path": path, "value": previous}
if (op === 'test')
return {"op": "test", "path": path, "value": patch.value}
}
/**
* Apply a JSON Patch to a JSON document
* @param {Object|Array} doc - JSON document to apply the patch to
* @param {Array} patch - JSON Patch array
* @param {Object} options - options
* @param {Boolean} options.reversible - return an array to revert
* @return {void}
*/
var apply = function(doc, patch, options) {
if (!Array.isArray(patch))
throw new Error('Invalid argument, patch must be an array')
var done = []
for (var i = 0, len = patch.length; i < len; i++) {
var p = patch[i]
var r
try {
r = run(doc, p)
}
catch (err) {
revert(doc, done)
throw err
}
doc = r[0]
done.push([p, r[1], r[2]])
}
if (!options || !options.reversible)
return doc
return [doc, done]
}
/**
* Return an object that can be use with revert
* @param {Array} items - array of [patch, previous, idx] items
* @return {Array} patches - JSON Patch array
*/
var foo = function(items) {
var patches = []
for (var i = 0, len = items.length; i < len; i++) {
var item = items[i]
patches.unshift(reverse(item[0], item[1], item[2]))
}
return patches
}
/**
* Revert apply a JSON Patch
* @param {Object|Array} doc - JSON document to which the patch was applied to
* @param {Array} items - array of [patch, previous, idx] items
* @return {void}
*/
var revert = function(doc, items) {
var patches = foo(items)
return apply(doc, patches)
}
module.exports.foo = foo
module.exports.apply = apply
module.exports.revert = revert
module.exports.reverse = reverse