merge-anything 4.0.2 → 4.0.3

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 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;
@@ -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,31 @@
1
1
  {
2
2
  "name": "merge-anything",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "sideEffects": false,
5
+ "type": "module",
5
6
  "description": "Merge objects & other types recursively. A simple & small integration.",
6
- "main": "dist/index.cjs.js",
7
- "module": "dist/index.esm.js",
8
- "types": "types/index.d.ts",
7
+ "module": "./dist/index.es.js",
8
+ "main": "./dist/index.cjs",
9
+ "types": "./dist/types/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.es.js",
13
+ "require": "./dist/index.cjs",
14
+ "types": "./dist/types/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "engines": {
21
+ "node": ">=12.13",
22
+ "npm": ">=7"
23
+ },
9
24
  "scripts": {
10
- "lint": "eslint src/ --ext .js,.jsx,.ts,.tsx",
11
- "test": "ava",
12
- "rollup": "rollup -c build/rollup.js",
13
- "build": "npm run lint && npm run test && npm run rollup",
14
- "release": "npm run build && np"
25
+ "lint": "tsc --noEmit && eslint ./src --ext .ts",
26
+ "test": "vitest run",
27
+ "build": "rollup -c ./scripts/build.js",
28
+ "release": "npm run lint && del dist && npm run build && np"
15
29
  },
16
30
  "repository": {
17
31
  "type": "git",
@@ -40,44 +54,41 @@
40
54
  "nested-combine"
41
55
  ],
42
56
  "author": "Luca Ban - Mesqueeb",
57
+ "funding": "https://github.com/sponsors/mesqueeb",
43
58
  "license": "MIT",
44
59
  "bugs": {
45
60
  "url": "https://github.com/mesqueeb/merge-anything/issues"
46
61
  },
47
62
  "homepage": "https://github.com/mesqueeb/merge-anything#readme",
48
63
  "dependencies": {
49
- "is-what": "^3.14.1",
64
+ "is-what": "^4.1.1",
50
65
  "ts-toolbelt": "^9.6.0"
51
66
  },
52
67
  "devDependencies": {
53
- "@typescript-eslint/eslint-plugin": "^5.3.1",
54
- "@typescript-eslint/parser": "^5.3.1",
55
- "ava": "^3.15.0",
56
- "eslint": "^8.2.0",
68
+ "@typescript-eslint/eslint-plugin": "^5.10.1",
69
+ "@typescript-eslint/parser": "^5.10.1",
70
+ "del-cli": "^4.0.1",
71
+ "eslint": "^8.7.0",
57
72
  "eslint-config-prettier": "^8.3.0",
58
- "eslint-plugin-tree-shaking": "^1.9.2",
59
- "np": "^7.5.0",
60
- "prettier": "^2.4.1",
61
- "rollup": "^2.59.0",
62
- "rollup-plugin-typescript2": "^0.30.0",
63
- "ts-node": "^10.4.0",
64
- "tsconfig-paths": "^3.11.0",
65
- "typescript": "^4.4.4"
66
- },
67
- "ava": {
68
- "extensions": [
69
- "ts"
70
- ],
71
- "require": [
72
- "tsconfig-paths/register",
73
- "ts-node/register"
74
- ]
73
+ "eslint-plugin-tree-shaking": "^1.10.0",
74
+ "np": "^7.6.0",
75
+ "prettier": "^2.5.1",
76
+ "rollup": "^2.66.0",
77
+ "rollup-plugin-typescript2": "^0.31.1",
78
+ "typescript": "^4.5.5",
79
+ "vitest": "^0.2.1"
75
80
  },
76
81
  "np": {
77
82
  "yarn": false,
78
83
  "branch": "production"
79
84
  },
80
85
  "eslintConfig": {
86
+ "ignorePatterns": [
87
+ "node_modules",
88
+ "dist",
89
+ "scripts",
90
+ "test"
91
+ ],
81
92
  "root": true,
82
93
  "parser": "@typescript-eslint/parser",
83
94
  "plugins": [
@@ -91,6 +102,7 @@
91
102
  "prettier"
92
103
  ],
93
104
  "rules": {
105
+ "@typescript-eslint/no-empty-function": "off",
94
106
  "@typescript-eslint/no-explicit-any": "off",
95
107
  "@typescript-eslint/ban-ts-ignore": "off",
96
108
  "tree-shaking/no-side-effects-in-initialization": "error",
package/.eslintignore DELETED
@@ -1,9 +0,0 @@
1
- # don't ever lint node_modules
2
- node_modules
3
- # don't lint build output (make sure it's set to your correct build folder name)
4
- dist
5
- # don't lint nyc coverage output
6
- coverage
7
-
8
- test
9
- .eslintrc.js
@@ -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
@@ -1,9 +0,0 @@
1
- {
2
- "printWidth": 100,
3
- "tabWidth": 2,
4
- "singleQuote": true,
5
- "trailingComma": "es5",
6
- "semi": false,
7
- "bracketSpacing": true,
8
- "quoteProps": "consistent"
9
- }
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
@@ -1,2 +0,0 @@
1
- export { merge, mergeAndCompare, mergeAndConcat } from './merge'
2
- export { concatArrays } from './extensions'
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
- })
@@ -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
- })
@@ -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
- }