/
applyDiff.js
60 lines (50 loc) · 1.69 KB
/
applyDiff.js
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
import {assocPath} from './assocPath'
import {path as pathModule} from './path'
const ALLOWED_OPERATIONS = ['remove', 'add', 'update']
export function removeAtPath(path, obj) {
const p = typeof path === 'string' ? path.split('.') : path
const len = p.length
if (len === 0) return
if (len === 1) return delete obj[p[0]]
if (len === 2) return delete obj[p[0]][p[1]]
if (len === 3) return delete obj[p[0]][p[1]][p[2]]
if (len === 4) return delete obj[p[0]][p[1]][p[2]][p[3]]
if (len === 5) return delete obj[p[0]][p[1]][p[2]][p[3]][p[4]]
if (len === 6) {
return delete obj[p[0]][p[1]][p[2]][p[3]][p[4]][p[5]]
}
if (len === 7) {
return delete obj[p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]]
}
if (len === 8) {
return delete obj[p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]][p[7]]
}
if (len === 9) {
return delete obj[p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]][p[7]][p[8]]
}
if (len === 10) {
return delete obj[p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]][p[7]][p[8]][
p[9]
]
}
}
export function applyDiff(rules, obj) {
if (arguments.length === 1) return _obj => applyDiff(rules, _obj)
let clone = {...obj}
rules.forEach(({op, path, value}) => {
if (!ALLOWED_OPERATIONS.includes(op)) return
if (op === 'add' && path && value !== undefined) {
if (pathModule(path, obj)) return
return (clone = assocPath(path, value, clone))
}
if (op === 'remove') {
if (pathModule(path, obj) === undefined) return
return removeAtPath(path, clone)
}
if (op === 'update' && path && value !== undefined) {
if (pathModule(path, obj) === undefined) return
return (clone = assocPath(path, value, clone))
}
})
return clone
}