-
Notifications
You must be signed in to change notification settings - Fork 0
/
Object.js
76 lines (69 loc) · 2.39 KB
/
Object.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
65
66
67
68
69
70
71
72
73
74
75
76
import { typeNameOf } from '@dr-js/core/module/common/format.js'
import { isBasicObject, isString } from '@dr-js/core/module/common/check.js'
import { dupJSON } from '@dr-js/core/module/common/data/function.js'
import { createTreeDepthFirstSearch } from '@dr-js/core/module/common/data/Tree.js'
import { objectMergeDeep } from '@dr-js/core/module/common/mutable/Object.js'
const FLAVOR_SEPARATOR = '|'
const pickFlavor = (
object = {},
flavorConfig = {},
flavorKey = '',
flavorSet = new Set() // to collect flavorKey in flavorConfig, for later check
) => {
const objectList = [ dupJSON(object) ]
for (const [ keyOrCombo, flavorValue ] of Object.entries(flavorConfig)) {
const keyList = keyOrCombo.split(FLAVOR_SEPARATOR)
keyList.forEach((key) => flavorSet.add(key))
if (!keyList.includes(flavorKey)) continue
if (!isBasicObject(flavorValue)) throw new Error(`invalid flavorValue of ${keyOrCombo}`)
objectList.push(flavorValue)
}
return objectList
}
const mergeFlavor = (objectList) => objectList.reduce((o, object) => objectMergeDeep(o, object), {})
const useFlavor = (
object = {},
flavorConfig = {},
flavorKey = '',
flavorSet = new Set() // to collect flavorKey in flavorConfig, for later check
) => mergeFlavor(pickFlavor(
object,
flavorConfig,
flavorKey,
flavorSet
))
const SECRET_PREFIX = '@@.'
const useSecret = (
object = {},
secretConfig = {},
onSecret = (secretPath, valueType) => {} // for log
) => {
object = dupJSON(object)
objectDFS(
[ null, '', object ],
([ upValue, key, value ]) => {
if (!isString(value) || !value.startsWith(SECRET_PREFIX)) return
const secretValue = getPathValue(secretConfig, value.split('.').slice(1))
if (secretValue === undefined) throw new Error(`expect secret: ${value}`) // NOTE: can't use undefined as secret value
onSecret(value, typeNameOf(secretValue))
upValue[ key ] = secretValue
}
)
return object
}
const objectDFS = createTreeDepthFirstSearch(([ upValue, key, value ]) => {
if (!isBasicObject(value)) return
return Object.entries(value).map(([ subKey, subValue ]) => [ value, subKey, subValue ])
})
const getPathValue = (object, keyPath) => {
let index = 0
while (isBasicObject(object) && keyPath[ index ]) {
object = object[ keyPath[ index ] ]
index++
}
return object
}
export {
FLAVOR_SEPARATOR, pickFlavor, mergeFlavor, useFlavor,
SECRET_PREFIX, useSecret
}