merge-anything 4.0.1 → 4.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.cjs +92 -0
- package/dist/index.es.js +85 -0
- package/{types → dist/types}/extensions.d.ts +0 -0
- package/{types → dist/types}/index.d.ts +0 -0
- package/{types → dist/types}/merge.d.ts +0 -0
- package/package.json +40 -33
- package/.eslintignore +0 -9
- package/.github/FUNDING.yml +0 -12
- package/.github/typescript-support.png +0 -0
- package/.prettierrc +0 -9
- package/build/rollup.js +0 -57
- package/dist/index.cjs.js +0 -125
- package/dist/index.esm.js +0 -118
- package/src/extensions.ts +0 -10
- package/src/index.ts +0 -2
- package/src/merge.ts +0 -102
- package/test/index.ts +0 -299
- package/test/mergeAndCompare.ts +0 -62
- package/test/mergeAndConcat.ts +0 -15
- package/tsconfig.json +0 -16
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Merge anything 🥡
|
|
2
2
|
|
|
3
|
+
<a href="https://www.npmjs.com/package/merge-anything"><img src="https://img.shields.io/npm/v/merge-anything.svg" alt="Total Downloads"></a>
|
|
4
|
+
<a href="https://www.npmjs.com/package/merge-anything"><img src="https://img.shields.io/npm/dw/merge-anything.svg" alt="Latest Stable Version"></a>
|
|
5
|
+
|
|
3
6
|
```
|
|
4
7
|
npm i merge-anything
|
|
5
8
|
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var isWhat = require('is-what');
|
|
6
|
+
|
|
7
|
+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
8
|
+
function concatArrays(originVal, newVal) {
|
|
9
|
+
if (isWhat.isArray(originVal) && isWhat.isArray(newVal)) {
|
|
10
|
+
// concat logic
|
|
11
|
+
return originVal.concat(newVal);
|
|
12
|
+
}
|
|
13
|
+
return newVal; // always return newVal as fallback!!
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function assignProp(carry, key, newVal, originalObject) {
|
|
17
|
+
const propType = {}.propertyIsEnumerable.call(originalObject, key)
|
|
18
|
+
? 'enumerable'
|
|
19
|
+
: 'nonenumerable';
|
|
20
|
+
if (propType === 'enumerable')
|
|
21
|
+
carry[key] = newVal;
|
|
22
|
+
if (propType === 'nonenumerable') {
|
|
23
|
+
Object.defineProperty(carry, key, {
|
|
24
|
+
value: newVal,
|
|
25
|
+
enumerable: false,
|
|
26
|
+
writable: true,
|
|
27
|
+
configurable: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function mergeRecursively(origin, newComer, compareFn) {
|
|
32
|
+
// always return newComer if its not an object
|
|
33
|
+
if (!isWhat.isPlainObject(newComer))
|
|
34
|
+
return newComer;
|
|
35
|
+
// define newObject to merge all values upon
|
|
36
|
+
let newObject = {};
|
|
37
|
+
if (isWhat.isPlainObject(origin)) {
|
|
38
|
+
const props = Object.getOwnPropertyNames(origin);
|
|
39
|
+
const symbols = Object.getOwnPropertySymbols(origin);
|
|
40
|
+
newObject = [...props, ...symbols].reduce((carry, key) => {
|
|
41
|
+
const targetVal = origin[key];
|
|
42
|
+
if ((!isWhat.isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key)) ||
|
|
43
|
+
(isWhat.isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key))) {
|
|
44
|
+
assignProp(carry, key, targetVal, origin);
|
|
45
|
+
}
|
|
46
|
+
return carry;
|
|
47
|
+
}, {});
|
|
48
|
+
}
|
|
49
|
+
// newObject has all properties that newComer hasn't
|
|
50
|
+
const props = Object.getOwnPropertyNames(newComer);
|
|
51
|
+
const symbols = Object.getOwnPropertySymbols(newComer);
|
|
52
|
+
const result = [...props, ...symbols].reduce((carry, key) => {
|
|
53
|
+
// re-define the origin and newComer as targetVal and newVal
|
|
54
|
+
let newVal = newComer[key];
|
|
55
|
+
const targetVal = isWhat.isPlainObject(origin) ? origin[key] : undefined;
|
|
56
|
+
// When newVal is an object do the merge recursively
|
|
57
|
+
if (targetVal !== undefined && isWhat.isPlainObject(newVal)) {
|
|
58
|
+
newVal = mergeRecursively(targetVal, newVal, compareFn);
|
|
59
|
+
}
|
|
60
|
+
const propToAssign = compareFn ? compareFn(targetVal, newVal, key) : newVal;
|
|
61
|
+
assignProp(carry, key, propToAssign, newComer);
|
|
62
|
+
return carry;
|
|
63
|
+
}, newObject);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Merge anything recursively.
|
|
68
|
+
* Objects get merged, special objects (classes etc.) are re-assigned "as is".
|
|
69
|
+
* Basic types overwrite objects or other basic types.
|
|
70
|
+
* @param object
|
|
71
|
+
* @param otherObjects
|
|
72
|
+
*/
|
|
73
|
+
function merge(object, ...otherObjects) {
|
|
74
|
+
return otherObjects.reduce((result, newComer) => {
|
|
75
|
+
return mergeRecursively(result, newComer);
|
|
76
|
+
}, object);
|
|
77
|
+
}
|
|
78
|
+
function mergeAndCompare(compareFn, object, ...otherObjects) {
|
|
79
|
+
return otherObjects.reduce((result, newComer) => {
|
|
80
|
+
return mergeRecursively(result, newComer, compareFn);
|
|
81
|
+
}, object);
|
|
82
|
+
}
|
|
83
|
+
function mergeAndConcat(object, ...otherObjects) {
|
|
84
|
+
return otherObjects.reduce((result, newComer) => {
|
|
85
|
+
return mergeRecursively(result, newComer, concatArrays);
|
|
86
|
+
}, object);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
exports.concatArrays = concatArrays;
|
|
90
|
+
exports.merge = merge;
|
|
91
|
+
exports.mergeAndCompare = mergeAndCompare;
|
|
92
|
+
exports.mergeAndConcat = mergeAndConcat;
|
package/dist/index.es.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { isArray, isPlainObject, isSymbol } from 'is-what';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
4
|
+
function concatArrays(originVal, newVal) {
|
|
5
|
+
if (isArray(originVal) && isArray(newVal)) {
|
|
6
|
+
// concat logic
|
|
7
|
+
return originVal.concat(newVal);
|
|
8
|
+
}
|
|
9
|
+
return newVal; // always return newVal as fallback!!
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function assignProp(carry, key, newVal, originalObject) {
|
|
13
|
+
const propType = {}.propertyIsEnumerable.call(originalObject, key)
|
|
14
|
+
? 'enumerable'
|
|
15
|
+
: 'nonenumerable';
|
|
16
|
+
if (propType === 'enumerable')
|
|
17
|
+
carry[key] = newVal;
|
|
18
|
+
if (propType === 'nonenumerable') {
|
|
19
|
+
Object.defineProperty(carry, key, {
|
|
20
|
+
value: newVal,
|
|
21
|
+
enumerable: false,
|
|
22
|
+
writable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function mergeRecursively(origin, newComer, compareFn) {
|
|
28
|
+
// always return newComer if its not an object
|
|
29
|
+
if (!isPlainObject(newComer))
|
|
30
|
+
return newComer;
|
|
31
|
+
// define newObject to merge all values upon
|
|
32
|
+
let newObject = {};
|
|
33
|
+
if (isPlainObject(origin)) {
|
|
34
|
+
const props = Object.getOwnPropertyNames(origin);
|
|
35
|
+
const symbols = Object.getOwnPropertySymbols(origin);
|
|
36
|
+
newObject = [...props, ...symbols].reduce((carry, key) => {
|
|
37
|
+
const targetVal = origin[key];
|
|
38
|
+
if ((!isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key)) ||
|
|
39
|
+
(isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key))) {
|
|
40
|
+
assignProp(carry, key, targetVal, origin);
|
|
41
|
+
}
|
|
42
|
+
return carry;
|
|
43
|
+
}, {});
|
|
44
|
+
}
|
|
45
|
+
// newObject has all properties that newComer hasn't
|
|
46
|
+
const props = Object.getOwnPropertyNames(newComer);
|
|
47
|
+
const symbols = Object.getOwnPropertySymbols(newComer);
|
|
48
|
+
const result = [...props, ...symbols].reduce((carry, key) => {
|
|
49
|
+
// re-define the origin and newComer as targetVal and newVal
|
|
50
|
+
let newVal = newComer[key];
|
|
51
|
+
const targetVal = isPlainObject(origin) ? origin[key] : undefined;
|
|
52
|
+
// When newVal is an object do the merge recursively
|
|
53
|
+
if (targetVal !== undefined && isPlainObject(newVal)) {
|
|
54
|
+
newVal = mergeRecursively(targetVal, newVal, compareFn);
|
|
55
|
+
}
|
|
56
|
+
const propToAssign = compareFn ? compareFn(targetVal, newVal, key) : newVal;
|
|
57
|
+
assignProp(carry, key, propToAssign, newComer);
|
|
58
|
+
return carry;
|
|
59
|
+
}, newObject);
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Merge anything recursively.
|
|
64
|
+
* Objects get merged, special objects (classes etc.) are re-assigned "as is".
|
|
65
|
+
* Basic types overwrite objects or other basic types.
|
|
66
|
+
* @param object
|
|
67
|
+
* @param otherObjects
|
|
68
|
+
*/
|
|
69
|
+
function merge(object, ...otherObjects) {
|
|
70
|
+
return otherObjects.reduce((result, newComer) => {
|
|
71
|
+
return mergeRecursively(result, newComer);
|
|
72
|
+
}, object);
|
|
73
|
+
}
|
|
74
|
+
function mergeAndCompare(compareFn, object, ...otherObjects) {
|
|
75
|
+
return otherObjects.reduce((result, newComer) => {
|
|
76
|
+
return mergeRecursively(result, newComer, compareFn);
|
|
77
|
+
}, object);
|
|
78
|
+
}
|
|
79
|
+
function mergeAndConcat(object, ...otherObjects) {
|
|
80
|
+
return otherObjects.reduce((result, newComer) => {
|
|
81
|
+
return mergeRecursively(result, newComer, concatArrays);
|
|
82
|
+
}, object);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { concatArrays, merge, mergeAndCompare, mergeAndConcat };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "merge-anything",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.5",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"description": "Merge objects & other types recursively. A simple & small integration.",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
6
|
+
"module": "./dist/index.es.js",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"types": "./dist/types/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.es.js",
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/types/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
9
19
|
"scripts": {
|
|
10
|
-
"lint": "eslint src
|
|
11
|
-
"test": "
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"release": "npm run build && np"
|
|
20
|
+
"lint": "tsc --noEmit && eslint ./src --ext .ts",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"build": "rollup -c ./scripts/build.js",
|
|
23
|
+
"release": "npm run lint && del dist && npm run build && np"
|
|
15
24
|
},
|
|
16
25
|
"repository": {
|
|
17
26
|
"type": "git",
|
|
@@ -40,6 +49,7 @@
|
|
|
40
49
|
"nested-combine"
|
|
41
50
|
],
|
|
42
51
|
"author": "Luca Ban - Mesqueeb",
|
|
52
|
+
"funding": "https://github.com/sponsors/mesqueeb",
|
|
43
53
|
"license": "MIT",
|
|
44
54
|
"bugs": {
|
|
45
55
|
"url": "https://github.com/mesqueeb/merge-anything/issues"
|
|
@@ -47,37 +57,33 @@
|
|
|
47
57
|
"homepage": "https://github.com/mesqueeb/merge-anything#readme",
|
|
48
58
|
"dependencies": {
|
|
49
59
|
"is-what": "^3.14.1",
|
|
50
|
-
"ts-toolbelt": "^9.
|
|
60
|
+
"ts-toolbelt": "^9.6.0"
|
|
51
61
|
},
|
|
52
62
|
"devDependencies": {
|
|
53
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
54
|
-
"@typescript-eslint/parser": "^
|
|
55
|
-
"
|
|
56
|
-
"eslint": "^7.
|
|
57
|
-
"eslint-config-prettier": "^8.
|
|
58
|
-
"eslint-plugin-tree-shaking": "^1.
|
|
59
|
-
"np": "^7.
|
|
60
|
-
"prettier": "^2.
|
|
61
|
-
"rollup": "^2.
|
|
62
|
-
"rollup-plugin-typescript2": "^0.
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"typescript": "^4.2.2"
|
|
66
|
-
},
|
|
67
|
-
"ava": {
|
|
68
|
-
"extensions": [
|
|
69
|
-
"ts"
|
|
70
|
-
],
|
|
71
|
-
"require": [
|
|
72
|
-
"tsconfig-paths/register",
|
|
73
|
-
"ts-node/register"
|
|
74
|
-
]
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^5.10.1",
|
|
64
|
+
"@typescript-eslint/parser": "^5.10.1",
|
|
65
|
+
"del-cli": "^4.0.1",
|
|
66
|
+
"eslint": "^8.7.0",
|
|
67
|
+
"eslint-config-prettier": "^8.3.0",
|
|
68
|
+
"eslint-plugin-tree-shaking": "^1.10.0",
|
|
69
|
+
"np": "^7.6.0",
|
|
70
|
+
"prettier": "^2.5.1",
|
|
71
|
+
"rollup": "^2.66.0",
|
|
72
|
+
"rollup-plugin-typescript2": "^0.31.1",
|
|
73
|
+
"typescript": "^4.5.5",
|
|
74
|
+
"vitest": "^0.2.1"
|
|
75
75
|
},
|
|
76
76
|
"np": {
|
|
77
77
|
"yarn": false,
|
|
78
|
-
"branch": "
|
|
78
|
+
"branch": "legacy"
|
|
79
79
|
},
|
|
80
80
|
"eslintConfig": {
|
|
81
|
+
"ignorePatterns": [
|
|
82
|
+
"node_modules",
|
|
83
|
+
"dist",
|
|
84
|
+
"scripts",
|
|
85
|
+
"test"
|
|
86
|
+
],
|
|
81
87
|
"root": true,
|
|
82
88
|
"parser": "@typescript-eslint/parser",
|
|
83
89
|
"plugins": [
|
|
@@ -91,6 +97,7 @@
|
|
|
91
97
|
"prettier"
|
|
92
98
|
],
|
|
93
99
|
"rules": {
|
|
100
|
+
"@typescript-eslint/no-empty-function": "off",
|
|
94
101
|
"@typescript-eslint/no-explicit-any": "off",
|
|
95
102
|
"@typescript-eslint/ban-ts-ignore": "off",
|
|
96
103
|
"tree-shaking/no-side-effects-in-initialization": "error",
|
package/.eslintignore
DELETED
package/.github/FUNDING.yml
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# These are supported funding model platforms
|
|
2
|
-
|
|
3
|
-
github: mesqueeb
|
|
4
|
-
patreon: # Replace with a single Patreon username
|
|
5
|
-
open_collective: # Replace with a single Open Collective username
|
|
6
|
-
ko_fi: # Replace with a single Ko-fi username
|
|
7
|
-
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
8
|
-
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
-
liberapay: # Replace with a single Liberapay username
|
|
10
|
-
issuehunt: # Replace with a single IssueHunt username
|
|
11
|
-
otechie: # Replace with a single Otechie username
|
|
12
|
-
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
Binary file
|
package/.prettierrc
DELETED
package/build/rollup.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
|
|
3
|
-
// npm i -D rollup-plugin-typescript2 typescript
|
|
4
|
-
import typescript from 'rollup-plugin-typescript2'
|
|
5
|
-
|
|
6
|
-
// ------------------------------------------------------------------------------------------
|
|
7
|
-
// formats
|
|
8
|
-
// ------------------------------------------------------------------------------------------
|
|
9
|
-
// amd – Asynchronous Module Definition, used with module loaders like RequireJS
|
|
10
|
-
// cjs – CommonJS, suitable for Node and Browserify/Webpack
|
|
11
|
-
// esm – Keep the bundle as an ES module file
|
|
12
|
-
// iife – A self-executing function, suitable for inclusion as a <script> tag. (If you want to create a bundle for your application, you probably want to use this, because it leads to smaller file sizes.)
|
|
13
|
-
// umd – Universal Module Definition, works as amd, cjs and iife all in one
|
|
14
|
-
// system – Native format of the SystemJS loader
|
|
15
|
-
|
|
16
|
-
// ------------------------------------------------------------------------------------------
|
|
17
|
-
// setup
|
|
18
|
-
// ------------------------------------------------------------------------------------------
|
|
19
|
-
const pkg = require('../package.json')
|
|
20
|
-
const name = pkg.name
|
|
21
|
-
const className = name.replace(/(^\w|-\w)/g, c => c.replace('-', '').toUpperCase())
|
|
22
|
-
const external = Object.keys(pkg.dependencies || [])
|
|
23
|
-
const plugins = [
|
|
24
|
-
typescript({ useTsconfigDeclarationDir: true, tsconfigOverride: { exclude: ['test/**/*'] } }),
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
// ------------------------------------------------------------------------------------------
|
|
28
|
-
// Builds
|
|
29
|
-
// ------------------------------------------------------------------------------------------
|
|
30
|
-
function defaults (config) {
|
|
31
|
-
// defaults
|
|
32
|
-
const defaults = {
|
|
33
|
-
plugins,
|
|
34
|
-
external,
|
|
35
|
-
}
|
|
36
|
-
// defaults.output
|
|
37
|
-
config.output = config.output.map(output => {
|
|
38
|
-
return Object.assign(
|
|
39
|
-
{
|
|
40
|
-
sourcemap: false,
|
|
41
|
-
name: className,
|
|
42
|
-
},
|
|
43
|
-
output
|
|
44
|
-
)
|
|
45
|
-
})
|
|
46
|
-
return Object.assign(defaults, config)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export default [
|
|
50
|
-
defaults({
|
|
51
|
-
input: 'src/index.ts',
|
|
52
|
-
output: [
|
|
53
|
-
{ file: 'dist/index.cjs.js', format: 'cjs' },
|
|
54
|
-
{ file: 'dist/index.esm.js', format: 'esm' },
|
|
55
|
-
],
|
|
56
|
-
}),
|
|
57
|
-
]
|
package/dist/index.cjs.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var isWhat = require('is-what');
|
|
6
|
-
|
|
7
|
-
/*! *****************************************************************************
|
|
8
|
-
Copyright (c) Microsoft Corporation.
|
|
9
|
-
|
|
10
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
11
|
-
purpose with or without fee is hereby granted.
|
|
12
|
-
|
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
14
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
15
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
17
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
18
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
19
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
20
|
-
***************************************************************************** */
|
|
21
|
-
|
|
22
|
-
function __spreadArray(to, from) {
|
|
23
|
-
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
24
|
-
to[j] = from[i];
|
|
25
|
-
return to;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
29
|
-
function concatArrays(originVal, newVal) {
|
|
30
|
-
if (isWhat.isArray(originVal) && isWhat.isArray(newVal)) {
|
|
31
|
-
// concat logic
|
|
32
|
-
return originVal.concat(newVal);
|
|
33
|
-
}
|
|
34
|
-
return newVal; // always return newVal as fallback!!
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function assignProp(carry, key, newVal, originalObject) {
|
|
38
|
-
var propType = {}.propertyIsEnumerable.call(originalObject, key)
|
|
39
|
-
? 'enumerable'
|
|
40
|
-
: 'nonenumerable';
|
|
41
|
-
if (propType === 'enumerable')
|
|
42
|
-
carry[key] = newVal;
|
|
43
|
-
if (propType === 'nonenumerable') {
|
|
44
|
-
Object.defineProperty(carry, key, {
|
|
45
|
-
value: newVal,
|
|
46
|
-
enumerable: false,
|
|
47
|
-
writable: true,
|
|
48
|
-
configurable: true,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function mergeRecursively(origin, newComer, compareFn) {
|
|
53
|
-
// always return newComer if its not an object
|
|
54
|
-
if (!isWhat.isPlainObject(newComer))
|
|
55
|
-
return newComer;
|
|
56
|
-
// define newObject to merge all values upon
|
|
57
|
-
var newObject = {};
|
|
58
|
-
if (isWhat.isPlainObject(origin)) {
|
|
59
|
-
var props_1 = Object.getOwnPropertyNames(origin);
|
|
60
|
-
var symbols_1 = Object.getOwnPropertySymbols(origin);
|
|
61
|
-
newObject = __spreadArray(__spreadArray([], props_1), symbols_1).reduce(function (carry, key) {
|
|
62
|
-
var targetVal = origin[key];
|
|
63
|
-
if ((!isWhat.isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key)) ||
|
|
64
|
-
(isWhat.isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key))) {
|
|
65
|
-
assignProp(carry, key, targetVal, origin);
|
|
66
|
-
}
|
|
67
|
-
return carry;
|
|
68
|
-
}, {});
|
|
69
|
-
}
|
|
70
|
-
// newObject has all properties that newComer hasn't
|
|
71
|
-
var props = Object.getOwnPropertyNames(newComer);
|
|
72
|
-
var symbols = Object.getOwnPropertySymbols(newComer);
|
|
73
|
-
var result = __spreadArray(__spreadArray([], props), symbols).reduce(function (carry, key) {
|
|
74
|
-
// re-define the origin and newComer as targetVal and newVal
|
|
75
|
-
var newVal = newComer[key];
|
|
76
|
-
var targetVal = isWhat.isPlainObject(origin) ? origin[key] : undefined;
|
|
77
|
-
// When newVal is an object do the merge recursively
|
|
78
|
-
if (targetVal !== undefined && isWhat.isPlainObject(newVal)) {
|
|
79
|
-
newVal = mergeRecursively(targetVal, newVal, compareFn);
|
|
80
|
-
}
|
|
81
|
-
var propToAssign = compareFn ? compareFn(targetVal, newVal, key) : newVal;
|
|
82
|
-
assignProp(carry, key, propToAssign, newComer);
|
|
83
|
-
return carry;
|
|
84
|
-
}, newObject);
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Merge anything recursively.
|
|
89
|
-
* Objects get merged, special objects (classes etc.) are re-assigned "as is".
|
|
90
|
-
* Basic types overwrite objects or other basic types.
|
|
91
|
-
* @param object
|
|
92
|
-
* @param otherObjects
|
|
93
|
-
*/
|
|
94
|
-
function merge(object) {
|
|
95
|
-
var otherObjects = [];
|
|
96
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
97
|
-
otherObjects[_i - 1] = arguments[_i];
|
|
98
|
-
}
|
|
99
|
-
return otherObjects.reduce(function (result, newComer) {
|
|
100
|
-
return mergeRecursively(result, newComer);
|
|
101
|
-
}, object);
|
|
102
|
-
}
|
|
103
|
-
function mergeAndCompare(compareFn, object) {
|
|
104
|
-
var otherObjects = [];
|
|
105
|
-
for (var _i = 2; _i < arguments.length; _i++) {
|
|
106
|
-
otherObjects[_i - 2] = arguments[_i];
|
|
107
|
-
}
|
|
108
|
-
return otherObjects.reduce(function (result, newComer) {
|
|
109
|
-
return mergeRecursively(result, newComer, compareFn);
|
|
110
|
-
}, object);
|
|
111
|
-
}
|
|
112
|
-
function mergeAndConcat(object) {
|
|
113
|
-
var otherObjects = [];
|
|
114
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
115
|
-
otherObjects[_i - 1] = arguments[_i];
|
|
116
|
-
}
|
|
117
|
-
return otherObjects.reduce(function (result, newComer) {
|
|
118
|
-
return mergeRecursively(result, newComer, concatArrays);
|
|
119
|
-
}, object);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
exports.concatArrays = concatArrays;
|
|
123
|
-
exports.merge = merge;
|
|
124
|
-
exports.mergeAndCompare = mergeAndCompare;
|
|
125
|
-
exports.mergeAndConcat = mergeAndConcat;
|
package/dist/index.esm.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { isArray, isPlainObject, isSymbol } from 'is-what';
|
|
2
|
-
|
|
3
|
-
/*! *****************************************************************************
|
|
4
|
-
Copyright (c) Microsoft Corporation.
|
|
5
|
-
|
|
6
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
7
|
-
purpose with or without fee is hereby granted.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
-
***************************************************************************** */
|
|
17
|
-
|
|
18
|
-
function __spreadArray(to, from) {
|
|
19
|
-
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
20
|
-
to[j] = from[i];
|
|
21
|
-
return to;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
25
|
-
function concatArrays(originVal, newVal) {
|
|
26
|
-
if (isArray(originVal) && isArray(newVal)) {
|
|
27
|
-
// concat logic
|
|
28
|
-
return originVal.concat(newVal);
|
|
29
|
-
}
|
|
30
|
-
return newVal; // always return newVal as fallback!!
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function assignProp(carry, key, newVal, originalObject) {
|
|
34
|
-
var propType = {}.propertyIsEnumerable.call(originalObject, key)
|
|
35
|
-
? 'enumerable'
|
|
36
|
-
: 'nonenumerable';
|
|
37
|
-
if (propType === 'enumerable')
|
|
38
|
-
carry[key] = newVal;
|
|
39
|
-
if (propType === 'nonenumerable') {
|
|
40
|
-
Object.defineProperty(carry, key, {
|
|
41
|
-
value: newVal,
|
|
42
|
-
enumerable: false,
|
|
43
|
-
writable: true,
|
|
44
|
-
configurable: true,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function mergeRecursively(origin, newComer, compareFn) {
|
|
49
|
-
// always return newComer if its not an object
|
|
50
|
-
if (!isPlainObject(newComer))
|
|
51
|
-
return newComer;
|
|
52
|
-
// define newObject to merge all values upon
|
|
53
|
-
var newObject = {};
|
|
54
|
-
if (isPlainObject(origin)) {
|
|
55
|
-
var props_1 = Object.getOwnPropertyNames(origin);
|
|
56
|
-
var symbols_1 = Object.getOwnPropertySymbols(origin);
|
|
57
|
-
newObject = __spreadArray(__spreadArray([], props_1), symbols_1).reduce(function (carry, key) {
|
|
58
|
-
var targetVal = origin[key];
|
|
59
|
-
if ((!isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key)) ||
|
|
60
|
-
(isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key))) {
|
|
61
|
-
assignProp(carry, key, targetVal, origin);
|
|
62
|
-
}
|
|
63
|
-
return carry;
|
|
64
|
-
}, {});
|
|
65
|
-
}
|
|
66
|
-
// newObject has all properties that newComer hasn't
|
|
67
|
-
var props = Object.getOwnPropertyNames(newComer);
|
|
68
|
-
var symbols = Object.getOwnPropertySymbols(newComer);
|
|
69
|
-
var result = __spreadArray(__spreadArray([], props), symbols).reduce(function (carry, key) {
|
|
70
|
-
// re-define the origin and newComer as targetVal and newVal
|
|
71
|
-
var newVal = newComer[key];
|
|
72
|
-
var targetVal = isPlainObject(origin) ? origin[key] : undefined;
|
|
73
|
-
// When newVal is an object do the merge recursively
|
|
74
|
-
if (targetVal !== undefined && isPlainObject(newVal)) {
|
|
75
|
-
newVal = mergeRecursively(targetVal, newVal, compareFn);
|
|
76
|
-
}
|
|
77
|
-
var propToAssign = compareFn ? compareFn(targetVal, newVal, key) : newVal;
|
|
78
|
-
assignProp(carry, key, propToAssign, newComer);
|
|
79
|
-
return carry;
|
|
80
|
-
}, newObject);
|
|
81
|
-
return result;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Merge anything recursively.
|
|
85
|
-
* Objects get merged, special objects (classes etc.) are re-assigned "as is".
|
|
86
|
-
* Basic types overwrite objects or other basic types.
|
|
87
|
-
* @param object
|
|
88
|
-
* @param otherObjects
|
|
89
|
-
*/
|
|
90
|
-
function merge(object) {
|
|
91
|
-
var otherObjects = [];
|
|
92
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
93
|
-
otherObjects[_i - 1] = arguments[_i];
|
|
94
|
-
}
|
|
95
|
-
return otherObjects.reduce(function (result, newComer) {
|
|
96
|
-
return mergeRecursively(result, newComer);
|
|
97
|
-
}, object);
|
|
98
|
-
}
|
|
99
|
-
function mergeAndCompare(compareFn, object) {
|
|
100
|
-
var otherObjects = [];
|
|
101
|
-
for (var _i = 2; _i < arguments.length; _i++) {
|
|
102
|
-
otherObjects[_i - 2] = arguments[_i];
|
|
103
|
-
}
|
|
104
|
-
return otherObjects.reduce(function (result, newComer) {
|
|
105
|
-
return mergeRecursively(result, newComer, compareFn);
|
|
106
|
-
}, object);
|
|
107
|
-
}
|
|
108
|
-
function mergeAndConcat(object) {
|
|
109
|
-
var otherObjects = [];
|
|
110
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
111
|
-
otherObjects[_i - 1] = arguments[_i];
|
|
112
|
-
}
|
|
113
|
-
return otherObjects.reduce(function (result, newComer) {
|
|
114
|
-
return mergeRecursively(result, newComer, concatArrays);
|
|
115
|
-
}, object);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export { concatArrays, merge, mergeAndCompare, mergeAndConcat };
|
package/src/extensions.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
2
|
-
import { isArray } from 'is-what'
|
|
3
|
-
|
|
4
|
-
export function concatArrays (originVal: any, newVal: any): any | any[] {
|
|
5
|
-
if (isArray(originVal) && isArray(newVal)) {
|
|
6
|
-
// concat logic
|
|
7
|
-
return originVal.concat(newVal)
|
|
8
|
-
}
|
|
9
|
-
return newVal // always return newVal as fallback!!
|
|
10
|
-
}
|
package/src/index.ts
DELETED
package/src/merge.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { O } from 'ts-toolbelt'
|
|
2
|
-
import { isPlainObject, isSymbol } from 'is-what'
|
|
3
|
-
import { concatArrays } from './extensions'
|
|
4
|
-
|
|
5
|
-
function assignProp(
|
|
6
|
-
carry: Record<string, any>,
|
|
7
|
-
key: string,
|
|
8
|
-
newVal: any,
|
|
9
|
-
originalObject: Record<string, any>
|
|
10
|
-
): void {
|
|
11
|
-
const propType = {}.propertyIsEnumerable.call(originalObject, key)
|
|
12
|
-
? 'enumerable'
|
|
13
|
-
: 'nonenumerable'
|
|
14
|
-
if (propType === 'enumerable') carry[key] = newVal
|
|
15
|
-
if (propType === 'nonenumerable') {
|
|
16
|
-
Object.defineProperty(carry, key, {
|
|
17
|
-
value: newVal,
|
|
18
|
-
enumerable: false,
|
|
19
|
-
writable: true,
|
|
20
|
-
configurable: true,
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function mergeRecursively<
|
|
26
|
-
T1 extends Record<string, any> | any,
|
|
27
|
-
T2 extends Record<string, any> | any
|
|
28
|
-
>(
|
|
29
|
-
origin: T1,
|
|
30
|
-
newComer: T2,
|
|
31
|
-
compareFn?: (prop1: any, prop2: any, propName: string) => any
|
|
32
|
-
): (T1 & T2) | T2 {
|
|
33
|
-
// always return newComer if its not an object
|
|
34
|
-
if (!isPlainObject(newComer)) return newComer
|
|
35
|
-
// define newObject to merge all values upon
|
|
36
|
-
let newObject = {} as (T1 & T2) | T2
|
|
37
|
-
if (isPlainObject(origin)) {
|
|
38
|
-
const props = Object.getOwnPropertyNames(origin)
|
|
39
|
-
const symbols = Object.getOwnPropertySymbols(origin)
|
|
40
|
-
newObject = [...props, ...symbols].reduce((carry, key) => {
|
|
41
|
-
const targetVal = origin[key as string]
|
|
42
|
-
if (
|
|
43
|
-
(!isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key)) ||
|
|
44
|
-
(isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key))
|
|
45
|
-
) {
|
|
46
|
-
assignProp(carry as Record<string, any>, key as string, targetVal, origin)
|
|
47
|
-
}
|
|
48
|
-
return carry
|
|
49
|
-
}, {} as (T1 & T2) | T2)
|
|
50
|
-
}
|
|
51
|
-
// newObject has all properties that newComer hasn't
|
|
52
|
-
const props = Object.getOwnPropertyNames(newComer)
|
|
53
|
-
const symbols = Object.getOwnPropertySymbols(newComer)
|
|
54
|
-
const result = [...props, ...symbols].reduce((carry, key) => {
|
|
55
|
-
// re-define the origin and newComer as targetVal and newVal
|
|
56
|
-
let newVal = newComer[key as string]
|
|
57
|
-
const targetVal = isPlainObject(origin) ? origin[key as string] : undefined
|
|
58
|
-
// When newVal is an object do the merge recursively
|
|
59
|
-
if (targetVal !== undefined && isPlainObject(newVal)) {
|
|
60
|
-
newVal = mergeRecursively(targetVal, newVal, compareFn)
|
|
61
|
-
}
|
|
62
|
-
const propToAssign = compareFn ? compareFn(targetVal, newVal, key as string) : newVal
|
|
63
|
-
assignProp(carry as Record<string, any>, key as string, propToAssign, newComer)
|
|
64
|
-
return carry
|
|
65
|
-
}, newObject)
|
|
66
|
-
return result
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Merge anything recursively.
|
|
71
|
-
* Objects get merged, special objects (classes etc.) are re-assigned "as is".
|
|
72
|
-
* Basic types overwrite objects or other basic types.
|
|
73
|
-
* @param object
|
|
74
|
-
* @param otherObjects
|
|
75
|
-
*/
|
|
76
|
-
export function merge<T extends Record<string, any>, Tn extends Record<string, any>[]>(
|
|
77
|
-
object: T,
|
|
78
|
-
...otherObjects: Tn
|
|
79
|
-
): O.Assign<T, Tn, 'deep'> {
|
|
80
|
-
return otherObjects.reduce((result, newComer) => {
|
|
81
|
-
return mergeRecursively(result, newComer)
|
|
82
|
-
}, object) as any
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function mergeAndCompare<T extends Record<string, any>, Tn extends Record<string, any>[]>(
|
|
86
|
-
compareFn: (prop1: any, prop2: any, propName: string | symbol) => any,
|
|
87
|
-
object: T,
|
|
88
|
-
...otherObjects: Tn
|
|
89
|
-
): O.Assign<T, Tn, 'deep'> {
|
|
90
|
-
return otherObjects.reduce((result, newComer) => {
|
|
91
|
-
return mergeRecursively(result, newComer, compareFn)
|
|
92
|
-
}, object) as any
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function mergeAndConcat<T extends Record<string, any>, Tn extends Record<string, any>[]>(
|
|
96
|
-
object: T,
|
|
97
|
-
...otherObjects: Tn
|
|
98
|
-
): O.Assign<T, Tn, 'deep'> {
|
|
99
|
-
return otherObjects.reduce((result, newComer) => {
|
|
100
|
-
return mergeRecursively(result, newComer, concatArrays)
|
|
101
|
-
}, object) as any
|
|
102
|
-
}
|
package/test/index.ts
DELETED
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
import test from 'ava'
|
|
2
|
-
import { isDate } from 'is-what'
|
|
3
|
-
import { merge } from '../src/index'
|
|
4
|
-
|
|
5
|
-
function copy<T> (any: T): T {
|
|
6
|
-
return JSON.parse(JSON.stringify(any))
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
test('1. origin & target stays the same | 2. works with dates', t => {
|
|
10
|
-
const nd = new Date()
|
|
11
|
-
const origin = { body: 'a' }
|
|
12
|
-
const target = { dueDate: nd }
|
|
13
|
-
const res = merge(origin, target)
|
|
14
|
-
t.deepEqual(res, { body: 'a', dueDate: nd })
|
|
15
|
-
t.deepEqual(origin, { body: 'a' })
|
|
16
|
-
t.deepEqual(target, { dueDate: nd })
|
|
17
|
-
})
|
|
18
|
-
test('adding a prop on target1|target2|mergedObj', t => {
|
|
19
|
-
const origin = { nested: {} }
|
|
20
|
-
const target = { nested: {} }
|
|
21
|
-
const res = merge(origin, target)
|
|
22
|
-
t.deepEqual(res, { nested: {} })
|
|
23
|
-
const originAsAny: any = origin
|
|
24
|
-
const targetAsAny: any = target
|
|
25
|
-
const resAsAny: any = res
|
|
26
|
-
originAsAny.nested.a = ''
|
|
27
|
-
targetAsAny.nested.b = ''
|
|
28
|
-
resAsAny.nested.c = ''
|
|
29
|
-
t.deepEqual(originAsAny, { nested: { a: '' } })
|
|
30
|
-
t.deepEqual(targetAsAny, { nested: { b: '' } })
|
|
31
|
-
t.deepEqual(res, { nested: { c: '' } })
|
|
32
|
-
})
|
|
33
|
-
test('changing a prop on target1|target2|mergedObj: failing example', t => {
|
|
34
|
-
const origin = { nested: { a: 1 } }
|
|
35
|
-
const target = {}
|
|
36
|
-
const res = merge(origin, target)
|
|
37
|
-
t.deepEqual(res, { nested: { a: 1 } })
|
|
38
|
-
origin.nested.a = 2
|
|
39
|
-
t.deepEqual(origin, { nested: { a: 2 } }) // linked
|
|
40
|
-
t.deepEqual(target, {})
|
|
41
|
-
t.deepEqual(res, { nested: { a: 2 } }) // linked
|
|
42
|
-
const targetAsAny: any = target
|
|
43
|
-
targetAsAny.nested = { a: 3 }
|
|
44
|
-
t.deepEqual(origin, { nested: { a: 2 } }) // not changed
|
|
45
|
-
t.deepEqual(targetAsAny, { nested: { a: 3 } })
|
|
46
|
-
t.deepEqual(res, { nested: { a: 2 } }) // not changed
|
|
47
|
-
res.nested.a = 4
|
|
48
|
-
t.deepEqual(origin, { nested: { a: 4 } }) // linked
|
|
49
|
-
t.deepEqual(targetAsAny, { nested: { a: 3 } })
|
|
50
|
-
t.deepEqual(res, { nested: { a: 4 } }) // linked
|
|
51
|
-
})
|
|
52
|
-
test('changing a prop on target1|target2|mergedObj: working example', t => {
|
|
53
|
-
const origin = { nested: { a: 1 } }
|
|
54
|
-
const target = {}
|
|
55
|
-
const merged = merge(origin, target)
|
|
56
|
-
const res = copy(merged)
|
|
57
|
-
t.deepEqual(res, { nested: { a: 1 } })
|
|
58
|
-
origin.nested.a = 2
|
|
59
|
-
t.deepEqual(origin, { nested: { a: 2 } }) // not linked
|
|
60
|
-
t.deepEqual(target, {})
|
|
61
|
-
t.deepEqual(res, { nested: { a: 1 } }) // not linked
|
|
62
|
-
const targetAsAny: any = target
|
|
63
|
-
targetAsAny.nested = { a: 3 }
|
|
64
|
-
t.deepEqual(origin, { nested: { a: 2 } }) // not changed
|
|
65
|
-
t.deepEqual(targetAsAny, { nested: { a: 3 } })
|
|
66
|
-
t.deepEqual(res, { nested: { a: 1 } }) // not changed
|
|
67
|
-
res.nested.a = 4
|
|
68
|
-
t.deepEqual(origin, { nested: { a: 2 } }) // not linked
|
|
69
|
-
t.deepEqual(targetAsAny, { nested: { a: 3 } })
|
|
70
|
-
t.deepEqual(res, { nested: { a: 4 } }) // not linked
|
|
71
|
-
})
|
|
72
|
-
test('1. works with multiple levels | 2. overwrites entire object with null', t => {
|
|
73
|
-
const origin = { body: '', head: null, toes: { big: true }, fingers: { '12': false } }
|
|
74
|
-
const target = { body: {}, head: {}, toes: {}, fingers: null }
|
|
75
|
-
const res = merge(origin, target)
|
|
76
|
-
t.deepEqual(res, { body: {}, head: {}, toes: { big: true }, fingers: null })
|
|
77
|
-
})
|
|
78
|
-
test('origin and target are not AsAny', t => {
|
|
79
|
-
const origin = { body: '', head: null, toes: { big: true }, fingers: { '12': false } }
|
|
80
|
-
const target = { body: {}, head: {}, toes: {}, fingers: null }
|
|
81
|
-
const res = merge(origin, target)
|
|
82
|
-
t.deepEqual(res, { body: {}, head: {}, toes: { big: true }, fingers: null })
|
|
83
|
-
t.deepEqual(origin, { body: '', head: null, toes: { big: true }, fingers: { '12': false } })
|
|
84
|
-
t.deepEqual(target, { body: {}, head: {}, toes: {}, fingers: null })
|
|
85
|
-
origin.body = 'a'
|
|
86
|
-
const originAsAny: any = origin
|
|
87
|
-
const targetAsAny: any = target
|
|
88
|
-
originAsAny.head = 'a'
|
|
89
|
-
originAsAny.toes.big = 'a'
|
|
90
|
-
originAsAny.fingers['12'] = 'a'
|
|
91
|
-
targetAsAny.body = 'b'
|
|
92
|
-
targetAsAny.head = 'b'
|
|
93
|
-
targetAsAny.toes = 'b'
|
|
94
|
-
targetAsAny.fingers = 'b'
|
|
95
|
-
t.deepEqual(res, { body: {}, head: {}, toes: { big: true }, fingers: null })
|
|
96
|
-
t.deepEqual(originAsAny, { body: 'a', head: 'a', toes: { big: 'a' }, fingers: { '12': 'a' } })
|
|
97
|
-
t.deepEqual(targetAsAny, { body: 'b', head: 'b', toes: 'b', fingers: 'b' })
|
|
98
|
-
})
|
|
99
|
-
test('Overwrite arrays', t => {
|
|
100
|
-
const origin = { array: ['a'] }
|
|
101
|
-
const target = { array: ['b'] }
|
|
102
|
-
const res = merge(origin, target)
|
|
103
|
-
t.deepEqual(res, { array: ['b'] })
|
|
104
|
-
})
|
|
105
|
-
test('overwrites null with empty object', t => {
|
|
106
|
-
const origin = { body: null }
|
|
107
|
-
const target = { body: {} }
|
|
108
|
-
const res = merge(origin, target)
|
|
109
|
-
t.deepEqual(res, { body: {} })
|
|
110
|
-
})
|
|
111
|
-
test('overwrites null with object with props', t => {
|
|
112
|
-
const origin = { body: null }
|
|
113
|
-
const target = { body: { props: true } }
|
|
114
|
-
const res = merge(origin, target)
|
|
115
|
-
t.deepEqual(res, { body: { props: true } })
|
|
116
|
-
})
|
|
117
|
-
test('overwrites string values', t => {
|
|
118
|
-
const origin = { body: 'a' }
|
|
119
|
-
const target = { body: 'b' }
|
|
120
|
-
const res = merge(origin, target)
|
|
121
|
-
t.deepEqual(res, { body: 'b' })
|
|
122
|
-
t.deepEqual(origin, { body: 'a' })
|
|
123
|
-
t.deepEqual(target, { body: 'b' })
|
|
124
|
-
})
|
|
125
|
-
test('works with very deep props & dates', t => {
|
|
126
|
-
const newDate = new Date()
|
|
127
|
-
const origin = {
|
|
128
|
-
info: {
|
|
129
|
-
time: 'now',
|
|
130
|
-
newDate,
|
|
131
|
-
very: { deep: { prop: false } },
|
|
132
|
-
},
|
|
133
|
-
}
|
|
134
|
-
const target = {
|
|
135
|
-
info: {
|
|
136
|
-
date: 'tomorrow',
|
|
137
|
-
very: { deep: { prop: true } },
|
|
138
|
-
},
|
|
139
|
-
}
|
|
140
|
-
const res = merge(origin, target)
|
|
141
|
-
t.deepEqual(res, {
|
|
142
|
-
info: {
|
|
143
|
-
time: 'now',
|
|
144
|
-
newDate,
|
|
145
|
-
date: 'tomorrow',
|
|
146
|
-
very: { deep: { prop: true } },
|
|
147
|
-
},
|
|
148
|
-
})
|
|
149
|
-
t.deepEqual(origin, {
|
|
150
|
-
info: {
|
|
151
|
-
time: 'now',
|
|
152
|
-
newDate,
|
|
153
|
-
very: { deep: { prop: false } },
|
|
154
|
-
},
|
|
155
|
-
})
|
|
156
|
-
t.deepEqual(target, {
|
|
157
|
-
info: {
|
|
158
|
-
date: 'tomorrow',
|
|
159
|
-
very: { deep: { prop: true } },
|
|
160
|
-
},
|
|
161
|
-
})
|
|
162
|
-
t.true(isDate(res.info.newDate))
|
|
163
|
-
})
|
|
164
|
-
test('1. does not overwrite origin prop if target prop is an empty object | 2. properly merges deep props', t => {
|
|
165
|
-
const origin = {
|
|
166
|
-
info: {
|
|
167
|
-
time: { when: 'now' },
|
|
168
|
-
very: { deep: { prop: false } },
|
|
169
|
-
},
|
|
170
|
-
}
|
|
171
|
-
const target = {
|
|
172
|
-
info: {
|
|
173
|
-
time: {},
|
|
174
|
-
very: { whole: 1 },
|
|
175
|
-
},
|
|
176
|
-
}
|
|
177
|
-
const res = merge(origin, target)
|
|
178
|
-
t.deepEqual(res, {
|
|
179
|
-
info: {
|
|
180
|
-
time: { when: 'now' },
|
|
181
|
-
very: {
|
|
182
|
-
deep: { prop: false },
|
|
183
|
-
whole: 1,
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
})
|
|
187
|
-
})
|
|
188
|
-
test('overwrites any origin prop when target prop is an object with props', t => {
|
|
189
|
-
const origin = {
|
|
190
|
-
body: 'a',
|
|
191
|
-
body2: { head: false },
|
|
192
|
-
tail: {},
|
|
193
|
-
}
|
|
194
|
-
const target = {
|
|
195
|
-
body: { head: true },
|
|
196
|
-
body2: { head: { eyes: true } },
|
|
197
|
-
}
|
|
198
|
-
const res = merge(origin, target)
|
|
199
|
-
t.deepEqual(res, {
|
|
200
|
-
body: { head: true },
|
|
201
|
-
body2: { head: { eyes: true } },
|
|
202
|
-
tail: {},
|
|
203
|
-
})
|
|
204
|
-
t.deepEqual(origin, {
|
|
205
|
-
body: 'a',
|
|
206
|
-
body2: { head: false },
|
|
207
|
-
tail: {},
|
|
208
|
-
})
|
|
209
|
-
t.deepEqual(target, {
|
|
210
|
-
body: { head: true },
|
|
211
|
-
body2: { head: { eyes: true } },
|
|
212
|
-
})
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
test('works with unlimited depth', t => {
|
|
216
|
-
const date = new Date()
|
|
217
|
-
const origin = { origin: 'a', t2: false, t3: {}, t4: 'false' }
|
|
218
|
-
const t1 = { t1: date }
|
|
219
|
-
const t2 = { t2: 'new' }
|
|
220
|
-
const t3 = { t3: 'new' }
|
|
221
|
-
const t4 = { t4: 'new', t3: {} }
|
|
222
|
-
const res = merge(origin, t1, t2, t3, t4)
|
|
223
|
-
t.deepEqual(res, { origin: 'a', t1: date, t2: 'new', t3: {}, t4: 'new' })
|
|
224
|
-
t.deepEqual(origin, { origin: 'a', t2: false, t3: {}, t4: 'false' })
|
|
225
|
-
t.deepEqual(t1, { t1: date })
|
|
226
|
-
t.deepEqual(t2, { t2: 'new' })
|
|
227
|
-
t.deepEqual(t3, { t3: 'new' })
|
|
228
|
-
t.deepEqual(t4, { t4: 'new', t3: {} })
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
test('symbols as keys 1', t => {
|
|
232
|
-
const mySymbol = Symbol('mySymbol')
|
|
233
|
-
const x = { value: 42, [mySymbol]: 'hello' }
|
|
234
|
-
const y = { other: 33 }
|
|
235
|
-
const res = merge(x, y)
|
|
236
|
-
t.is(res.value, 42)
|
|
237
|
-
t.is(res.other, 33)
|
|
238
|
-
t.is(res[mySymbol], 'hello')
|
|
239
|
-
})
|
|
240
|
-
test('symbols as keys 2', t => {
|
|
241
|
-
const mySymbol = Symbol('mySymbol')
|
|
242
|
-
const x = { value: 42 }
|
|
243
|
-
const y = { other: 33, [mySymbol]: 'hello' }
|
|
244
|
-
const res = merge(x, y)
|
|
245
|
-
t.is(res.value, 42)
|
|
246
|
-
t.is(res.other, 33)
|
|
247
|
-
t.is(res[mySymbol], 'hello')
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
test('nonenumerable keys', t => {
|
|
251
|
-
const mySymbol = Symbol('mySymbol')
|
|
252
|
-
const x = { value: 42 }
|
|
253
|
-
const y = { other: 33 }
|
|
254
|
-
Object.defineProperty(x, 'xid', {
|
|
255
|
-
value: 1,
|
|
256
|
-
writable: true,
|
|
257
|
-
enumerable: false,
|
|
258
|
-
configurable: true,
|
|
259
|
-
})
|
|
260
|
-
Object.defineProperty(x, mySymbol, {
|
|
261
|
-
value: 'original',
|
|
262
|
-
writable: true,
|
|
263
|
-
enumerable: false,
|
|
264
|
-
configurable: true,
|
|
265
|
-
})
|
|
266
|
-
Object.defineProperty(y, 'yid', {
|
|
267
|
-
value: 2,
|
|
268
|
-
writable: true,
|
|
269
|
-
enumerable: false,
|
|
270
|
-
configurable: true,
|
|
271
|
-
})
|
|
272
|
-
Object.defineProperty(y, mySymbol, {
|
|
273
|
-
value: 'new',
|
|
274
|
-
writable: true,
|
|
275
|
-
enumerable: false,
|
|
276
|
-
configurable: true,
|
|
277
|
-
})
|
|
278
|
-
const res = merge(x, y)
|
|
279
|
-
t.is(res.value, 42)
|
|
280
|
-
t.is(res.other, 33)
|
|
281
|
-
t.is((res as any).xid, 1)
|
|
282
|
-
t.is((res as any).yid, 2)
|
|
283
|
-
t.is((res as any)[mySymbol], 'new')
|
|
284
|
-
t.is(Object.keys(res).length, 2)
|
|
285
|
-
t.true(Object.keys(res).includes('value'))
|
|
286
|
-
t.true(Object.keys(res).includes('other'))
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
test('readme', t => {
|
|
290
|
-
const starter = { name: 'Squirtle', types: { water: true } }
|
|
291
|
-
const newValues = { name: 'Wartortle', types: { fighting: true }, level: 16 }
|
|
292
|
-
const evolution = merge(starter, newValues, { is: 'cool' })
|
|
293
|
-
t.deepEqual(evolution, {
|
|
294
|
-
name: 'Wartortle',
|
|
295
|
-
types: { water: true, fighting: true },
|
|
296
|
-
level: 16,
|
|
297
|
-
is: 'cool',
|
|
298
|
-
})
|
|
299
|
-
})
|
package/test/mergeAndCompare.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import test from 'ava'
|
|
2
|
-
import { isDate, isString, isArray, isObject } from 'is-what'
|
|
3
|
-
import { mergeAndCompare } from '../src/index'
|
|
4
|
-
|
|
5
|
-
test('conversion based on original val', t => {
|
|
6
|
-
function convertTimestamps (originVal: any, targetVal: any) {
|
|
7
|
-
if (originVal === '%convertTimestamp%' && isString(targetVal) && isDate(new Date(targetVal))) {
|
|
8
|
-
return new Date(targetVal)
|
|
9
|
-
}
|
|
10
|
-
return targetVal
|
|
11
|
-
}
|
|
12
|
-
const origin = {
|
|
13
|
-
date: '%convertTimestamp%',
|
|
14
|
-
}
|
|
15
|
-
const target = {
|
|
16
|
-
date: '1990-06-22',
|
|
17
|
-
}
|
|
18
|
-
const res = mergeAndCompare(convertTimestamps, origin, target)
|
|
19
|
-
t.deepEqual(res as any, { date: new Date('1990-06-22') })
|
|
20
|
-
// doesn't work on base lvl anymore
|
|
21
|
-
// const res2 = mergeAndCompare(convertTimestamps, '%convertTimestamp%', '1990-06-22')
|
|
22
|
-
// t.deepEqual(res2, new Date('1990-06-22'))
|
|
23
|
-
})
|
|
24
|
-
test('conversion based on prop key', t => {
|
|
25
|
-
function convertTimestamps (originVal: any, targetVal: any, key: any) {
|
|
26
|
-
if (isString(targetVal) && key === 'date') {
|
|
27
|
-
return new Date(targetVal)
|
|
28
|
-
}
|
|
29
|
-
return targetVal
|
|
30
|
-
}
|
|
31
|
-
const origin = {
|
|
32
|
-
date: '%convertTimestamp%',
|
|
33
|
-
a: {},
|
|
34
|
-
}
|
|
35
|
-
const target = {
|
|
36
|
-
date: '1990-06-22',
|
|
37
|
-
a: { date: '1990-01-01' },
|
|
38
|
-
}
|
|
39
|
-
const res = mergeAndCompare(convertTimestamps, origin, target)
|
|
40
|
-
t.deepEqual(res as any, { date: new Date('1990-06-22'), a: { date: new Date('1990-01-01') } })
|
|
41
|
-
})
|
|
42
|
-
test('Extend with custom concat arrays', t => {
|
|
43
|
-
function concatArr (originVal: any, targetVal: any) {
|
|
44
|
-
if (isArray(originVal) && isArray(targetVal)) {
|
|
45
|
-
return originVal.concat(targetVal)
|
|
46
|
-
}
|
|
47
|
-
return targetVal
|
|
48
|
-
}
|
|
49
|
-
const origin = {
|
|
50
|
-
someArray: ['a'],
|
|
51
|
-
a: { b: { c: ['x'] } },
|
|
52
|
-
}
|
|
53
|
-
const target = {
|
|
54
|
-
someArray: ['b'],
|
|
55
|
-
a: { b: { c: ['y'] } },
|
|
56
|
-
}
|
|
57
|
-
const res = mergeAndCompare(concatArr, origin, target)
|
|
58
|
-
t.deepEqual(res, { someArray: ['a', 'b'], a: { b: { c: ['x', 'y'] } } })
|
|
59
|
-
// doesn't work on base lvl anymore
|
|
60
|
-
// const res2 = mergeAndCompare(concatArr, ['a'], ['b'])
|
|
61
|
-
// t.deepEqual(res2, ['a', 'b'])
|
|
62
|
-
})
|
package/test/mergeAndConcat.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import test from 'ava'
|
|
2
|
-
import { mergeAndConcat } from '../src/index'
|
|
3
|
-
|
|
4
|
-
test('mergeAndConcat', t => {
|
|
5
|
-
const origin = {
|
|
6
|
-
someArray: ['a'],
|
|
7
|
-
a: { b: { c: ['x'] } },
|
|
8
|
-
}
|
|
9
|
-
const target = {
|
|
10
|
-
someArray: ['b'],
|
|
11
|
-
a: { b: { c: ['y'] } },
|
|
12
|
-
}
|
|
13
|
-
const res = mergeAndConcat(origin, target)
|
|
14
|
-
t.deepEqual(res, { someArray: ['a', 'b'], a: { b: { c: ['x', 'y'] } } })
|
|
15
|
-
})
|
package/tsconfig.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"baseUrl": ".",
|
|
4
|
-
"lib": ["ES2015", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020"],
|
|
5
|
-
"strict": true,
|
|
6
|
-
"isolatedModules": true,
|
|
7
|
-
"esModuleInterop": true,
|
|
8
|
-
"moduleResolution": "node",
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"declarationDir": "./types/"
|
|
11
|
-
},
|
|
12
|
-
"include": [
|
|
13
|
-
"src/**/*",
|
|
14
|
-
"test/**/*"
|
|
15
|
-
]
|
|
16
|
-
}
|