-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathutils.js
More file actions
95 lines (80 loc) · 1.92 KB
/
utils.js
File metadata and controls
95 lines (80 loc) · 1.92 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
import dot from '@eivifj/dot';
import typeOf from 'component-type';
/**
* Assign given key and value (or object) to given object
*
* @private
*/
export function assign(key, val, obj) {
if (typeof key == 'string') {
obj[key] = val;
return;
}
Object.keys(key).forEach(k => obj[k] = key[k]);
}
/**
* Enumerate all permutations of `path`, replacing $ with array indices
*
* @private
*/
export function enumerate(path, obj, callback) {
const parts = path.split(/\.[$*](?=\.|$|\*)/);
const first = parts.shift();
const arr = dot.get(obj, first);
if (!parts.length) {
return callback(first, arr);
}
if (!Array.isArray(arr)) {
if (typeOf(arr) === 'object') {
const keys = Object.keys(arr);
for (let i = 0; i < keys.length; i++) {
const current = join(keys[i], first);
const next = current + parts.join('.*');
enumerate(next, obj, callback);
}
}
return;
}
for (let i = 0; i < arr.length; i++) {
const current = join(i, first);
const next = current + parts.join('.$');
enumerate(next, obj, callback);
}
}
/**
* Walk object and call `callback` with path and prop name
*
* @private
*/
export function walk(obj, callback, path, prop) {
const type = typeOf(obj);
if (type === 'array') {
obj.forEach((v, i) =>
walk(v, callback, join(i, path), join('$', prop))
);
return;
}
if (type !== 'object') {
return;
}
for (const [key, val] of Object.entries(obj)) {
const newPath = join(key, path);
const newProp = join(key, prop);
const newCatchProp = join('*', prop);
if (callback(newPath, newCatchProp, true)) {
walk(val, callback, newPath, newCatchProp);
} else if (callback(newPath, newProp)) {
walk(val, callback, newPath, newProp);
}
}
}
/**
* Join `path` with `prefix`
*
* @private
*/
export function join(path, prefix) {
return prefix
? `${prefix}.${path}`
: path;
}