-
Notifications
You must be signed in to change notification settings - Fork 2
/
apply-overlay.js
64 lines (55 loc) · 2.41 KB
/
apply-overlay.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
61
62
63
64
const set = require('./set')
const get = require('./get')
const remove = require('./remove')
const jsonPath = require('./json-path')
const jsonPointerToArray = require('./json-pointer-to-array')
module.exports = async function applyOverlay(overlay, resolver) {
let source = overlay.extends ? await resolver(overlay.extends) : {}
const {actions} = overlay
actions.forEach(action => {
jsonPath(source, action.target).forEach(jsonPointer => {
const path = jsonPointerToArray(jsonPointer)
let targetValue = get(source, path)
let parentValue = get(source, path.slice(0, -1))
if(typeof action.where === 'object' && action.where) {
let whereClausSucceeded = true
if(typeof action.where.target === 'string') {
const wherePaths = jsonPath(targetValue, action.where.target)
whereClausSucceeded = wherePaths && wherePaths.length > 0
}
if(typeof action.where.empty === 'boolean') {
// null | {} | [] | ''
const isNull = targetValue === null
const isEmptyStr = targetValue === ''
const isEmptyObject = typeof targetValue === 'object' && targetValue && !Object.keys(targetValue).length
const isEmptyArray = Array.isArray(targetValue) && !targetValue.length
const isEmpty = (isNull || isEmptyStr || isEmptyObject || isEmptyArray)
whereClausSucceeded = action.where.empty == isEmpty
}
if(action.where.not === true) {
whereClausSucceeded = !whereClausSucceeded
}
// If the where clause failed, bail.
if(!whereClausSucceeded) {
return
}
}
if(action.remove === true) {
source = remove(source, path)
} else if(typeof action.replace !== 'undefined') {
source = set(source, path, action.replace)
} else if(action.update && typeof action.update === 'object') {
if(Array.isArray(targetValue)) {
let merged = [...targetValue, action.update]
source = set(source, path, merged)
} else {
let merged = Object.assign({}, targetValue, action.update)
source = set(source, path, merged)
}
} else if(typeof action.update !== 'undefined') {
source = set(source, path, action.update)
}
})
})
return source
}