-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
68 lines (57 loc) · 1.77 KB
/
index.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
const getReducer = (options = {}) => {
const { overwriteArrays, overwriteObjects } = options;
return (sum, val) => {
// Get all keys, including any Symbols.
const keys = Reflect.ownKeys(val);
for (const key of keys) {
const both = [val[key], sum[key]];
const bothArrays = both.every(Array.isArray);
const bothObjects = both.every(isObject);
if (bothArrays && !overwriteArrays) {
// Merge both arrays together.
sum[key] = [...sum[key], ...val[key]];
} else if (bothObjects && !overwriteObjects) {
// Recursively merge both objects together.
sum[key] = deepAssignOptions(options, {}, sum[key], val[key]);
} else {
// Fallthrough: overwrite previously-set value.
sum[key] = val[key];
}
}
return sum;
};
};
const isObject = val => {
return (
typeof val === "object" &&
!Array.isArray(val) &&
!(val instanceof Date) &&
!(val instanceof RegExp) &&
val !== null
);
};
// Makes sure inputs to reduce() are valid.
const isValidType = obj => typeof obj !== "undefined" && obj !== null;
/**
* Allows for customizing array and object merging behavior.
*/
export const deepAssignOptions = (
options = {},
receiverObject,
...sourceObjects
) => {
const reducer = getReducer(options);
return sourceObjects.filter(isValidType).reduce(reducer, receiverObject);
};
/**
* With default options, merging arrays and objects.
*/
export const deepAssign = (receiverObject, ...sourceObjects) => {
const defaultOptions = {
overwriteArrays: false,
overwriteObjects: false
};
// Note: intentionally mutates receiverObject, just like Object.assign().
return deepAssignOptions(defaultOptions, receiverObject, ...sourceObjects);
};
export default deepAssign;