@webfactoryde/merge-objects 1.0.0
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/.babelrc +3 -0
- package/.github/workflows/tests.yml +29 -0
- package/.idea/merge-objects.iml +8 -0
- package/.idea/modules.xml +8 -0
- package/.idea/php.xml +19 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +30 -0
- package/jest.config.js +7 -0
- package/package.json +16 -0
- package/src/merge-objects.js +49 -0
- package/tests/mergeObjects.test.js +52 -0
package/.babelrc
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
pull_request_target:
|
|
8
|
+
|
|
9
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
JSUnit:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
node-version: [ 20.x ]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
24
|
+
uses: actions/setup-node@v3
|
|
25
|
+
with:
|
|
26
|
+
node-version: ${{ matrix.node-version }}
|
|
27
|
+
cache: 'npm'
|
|
28
|
+
- run: yarn install --immutable --immutable-cache --check-cache
|
|
29
|
+
- run: yarn test
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="WEB_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager">
|
|
4
|
+
<content url="file://$MODULE_DIR$" />
|
|
5
|
+
<orderEntry type="inheritedJdk" />
|
|
6
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
7
|
+
</component>
|
|
8
|
+
</module>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectModuleManager">
|
|
4
|
+
<modules>
|
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/merge-objects.iml" filepath="$PROJECT_DIR$/.idea/merge-objects.iml" />
|
|
6
|
+
</modules>
|
|
7
|
+
</component>
|
|
8
|
+
</project>
|
package/.idea/php.xml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="MessDetectorOptionsConfiguration">
|
|
4
|
+
<option name="transferred" value="true" />
|
|
5
|
+
</component>
|
|
6
|
+
<component name="PHPCSFixerOptionsConfiguration">
|
|
7
|
+
<option name="transferred" value="true" />
|
|
8
|
+
</component>
|
|
9
|
+
<component name="PHPCodeSnifferOptionsConfiguration">
|
|
10
|
+
<option name="highlightLevel" value="WARNING" />
|
|
11
|
+
<option name="transferred" value="true" />
|
|
12
|
+
</component>
|
|
13
|
+
<component name="PhpStanOptionsConfiguration">
|
|
14
|
+
<option name="transferred" value="true" />
|
|
15
|
+
</component>
|
|
16
|
+
<component name="PsalmOptionsConfiguration">
|
|
17
|
+
<option name="transferred" value="true" />
|
|
18
|
+
</component>
|
|
19
|
+
</project>
|
package/.idea/vcs.xml
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# mergeObjects Utility
|
|
2
|
+
|
|
3
|
+
The `mergeObjects` function is a utility for merging multiple objects into a single object, with an option to perform a deep merge. This function is particularly useful for combining configuration settings, state management, or any scenario where you need to consolidate multiple objects while preserving their properties.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install @webfactoryde/merge-objects
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Import the `mergeObjects` function in your module(s) and pass any number of objects:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
// your module
|
|
17
|
+
import mergeObjects from '@webfactoryde/merge-objects';
|
|
18
|
+
|
|
19
|
+
// Shallow merge:
|
|
20
|
+
const obj1 = { a: 1, b: 2 };
|
|
21
|
+
const obj2 = { b: 3, c: 4 };
|
|
22
|
+
const result = mergeObjects(obj1, obj2);
|
|
23
|
+
console.log(result); // Output: { a: 1, b: 3, c: 4 }
|
|
24
|
+
|
|
25
|
+
// Deep merge
|
|
26
|
+
const obj1 = { a: 1, b: { x: 10, y: 20 } };
|
|
27
|
+
const obj2 = { b: { y: 30, z: 40 }, c: 4 };
|
|
28
|
+
const result = mergeObjects(true, obj1, obj2);
|
|
29
|
+
console.log(result); // Output: { a: 1, b: { x: 10, y: 30, z: 40 }, c: 4 }
|
|
30
|
+
```
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webfactoryde/merge-objects",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "JS Utility that merges multiple objects into one, with an option for deep merging",
|
|
5
|
+
"main": "src/merge-objects.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"@babel/core": "^7.28.3",
|
|
9
|
+
"@babel/preset-env": "^7.28.3",
|
|
10
|
+
"babel-jest": "^30.1.1",
|
|
11
|
+
"jest": "^30.1.0"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "jest"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges multiple objects into one, with an option for deep merging.
|
|
3
|
+
*
|
|
4
|
+
* Accepts either:
|
|
5
|
+
* - mergeObjects(true, obj1, obj2, ...) // deep merge
|
|
6
|
+
* - mergeObjects(obj1, obj2, ...) // shallow merge
|
|
7
|
+
*
|
|
8
|
+
* @param {...(boolean|Object)} args Boolean deep flag optionally first, then source objects.
|
|
9
|
+
* @returns {Object} New merged object.
|
|
10
|
+
* @throws {TypeError} If any provided source (after optional boolean) is not an object.
|
|
11
|
+
* @see https://gomakethings.com/merging-objects-with-vanilla-javascript/#adding-a-deep-merge
|
|
12
|
+
*/
|
|
13
|
+
export default function mergeObjects(...args) {
|
|
14
|
+
// Determine whether caller passed (deep, ...objects) or just (...objects)
|
|
15
|
+
let deep = false;
|
|
16
|
+
let objects = args;
|
|
17
|
+
|
|
18
|
+
if (typeof args[0] === 'boolean') {
|
|
19
|
+
deep = args[0];
|
|
20
|
+
objects = args.slice(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const extended = {};
|
|
24
|
+
|
|
25
|
+
// Validate
|
|
26
|
+
for (const obj of objects) {
|
|
27
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
28
|
+
throw new TypeError('All arguments after the deep parameter must be objects.');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const merge = (obj) => {
|
|
33
|
+
for (const prop in obj) {
|
|
34
|
+
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
|
|
35
|
+
if (deep && typeof obj[prop] === 'object' && obj[prop] !== null) {
|
|
36
|
+
extended[prop] = mergeObjects(true, extended[prop] || {}, obj[prop]);
|
|
37
|
+
} else {
|
|
38
|
+
extended[prop] = obj[prop];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
for (const obj of objects) {
|
|
45
|
+
merge(obj);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return extended;
|
|
49
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import mergeObjects from '../src/merge-objects'; // Adjust the import path accordingly
|
|
2
|
+
|
|
3
|
+
describe('mergeObjects', () => {
|
|
4
|
+
test('should perform a shallow merge', () => {
|
|
5
|
+
const obj1 = { a: 1, b: 2 };
|
|
6
|
+
const obj2 = { b: 3, c: 4 };
|
|
7
|
+
const result = mergeObjects(false, obj1, obj2);
|
|
8
|
+
expect(result).toEqual({ a: 1, b: 3, c: 4 });
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('should perform a deep merge', () => {
|
|
12
|
+
const obj1 = { a: 1, b: { x: 10, y: 20 } };
|
|
13
|
+
const obj2 = { b: { y: 30, z: 40 }, c: 4 };
|
|
14
|
+
const result = mergeObjects(true, obj1, obj2);
|
|
15
|
+
expect(result).toEqual({ a: 1, b: { x: 10, y: 30, z: 40 }, c: 4 });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('should perform a shallow merge when no deep arg is passed', () => {
|
|
19
|
+
const obj1 = { a: 1, b: 2 };
|
|
20
|
+
const obj2 = { b: 3, c: 4 };
|
|
21
|
+
const result = mergeObjects(obj1, obj2); // No deep argument passed
|
|
22
|
+
expect(result).toEqual({ a: 1, b: 3, c: 4 });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('should throw an error if a non-object is passed', () => {
|
|
26
|
+
expect(() => mergeObjects(true, { a: 1 }, 'not an object')).toThrow(TypeError);
|
|
27
|
+
expect(() => mergeObjects(false, { a: 1 }, null)).toThrow(TypeError);
|
|
28
|
+
expect(() => mergeObjects(false, { a: 1 }, 42)).toThrow(TypeError);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('should handle more than two objects', () => {
|
|
32
|
+
const obj1 = { a: 1 };
|
|
33
|
+
const obj2 = { b: 2 };
|
|
34
|
+
const obj3 = { c: 3 };
|
|
35
|
+
const result = mergeObjects(false, obj1, obj2, obj3);
|
|
36
|
+
expect(result).toEqual({ a: 1, b: 2, c: 3 });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('should handle empty objects', () => {
|
|
40
|
+
const obj1 = {};
|
|
41
|
+
const obj2 = {};
|
|
42
|
+
const result = mergeObjects(false, obj1, obj2);
|
|
43
|
+
expect(result).toEqual({});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('should handle deep merge with empty objects', () => {
|
|
47
|
+
const obj1 = { a: 1, b: {} };
|
|
48
|
+
const obj2 = { b: { y: 30 }, c: 4 };
|
|
49
|
+
const result = mergeObjects(true, obj1, obj2);
|
|
50
|
+
expect(result).toEqual({ a: 1, b: { y: 30 }, c: 4 });
|
|
51
|
+
});
|
|
52
|
+
});
|