merge-anything
Advanced tools
Comparing version 1.1.1 to 2.0.0
@@ -7,5 +7,16 @@ 'use strict'; | ||
function mergeRecursively(origin, newComer) { | ||
if (!isWhat.isObject(newComer)) return newComer; // define newObject to merge all values upon | ||
function mergeRecursively(origin, newComer, extensions) { | ||
// work directly on newComer if its not an object | ||
if (!isWhat.isObject(newComer)) { | ||
// extend merge rules | ||
if (extensions && isWhat.isArray(extensions)) { | ||
extensions.forEach(function (extend) { | ||
newComer = extend(origin, newComer); | ||
}); | ||
} | ||
return newComer; | ||
} // define newObject to merge all values upon | ||
var newObject = isWhat.isObject(origin) ? Object.keys(origin).reduce(function (carry, key) { | ||
@@ -17,5 +28,13 @@ var targetVal = origin[key]; | ||
return Object.keys(newComer).reduce(function (carry, key) { | ||
// re-define the origin and newComer as targetVal and newVal | ||
var newVal = newComer[key]; | ||
var targetVal = isWhat.isObject(origin) ? origin[key] : undefined; // early return when targetVal === undefined | ||
var targetVal = isWhat.isObject(origin) ? origin[key] : undefined; // extend merge rules | ||
if (extensions && isWhat.isArray(extensions)) { | ||
extensions.forEach(function (extend) { | ||
newVal = extend(targetVal, newVal); | ||
}); | ||
} // early return when targetVal === undefined | ||
if (targetVal === undefined) { | ||
@@ -36,9 +55,7 @@ carry[key] = newVal; | ||
}, newObject); | ||
} // let a = mergeRecursively(null, {}) | ||
// a | ||
} | ||
/** | ||
* Merge anything | ||
* | ||
* @param {object} origin the default values | ||
* @param {object} origin the default values, OR {extensions} to pass an array of functions with extentions | ||
* @param {object} newComer on which to set the default values | ||
@@ -49,2 +66,10 @@ */ | ||
function index (origin) { | ||
var extensions = null; | ||
var base = origin; | ||
if (origin['extensions'] && Object.keys(origin).length === 1) { | ||
base = {}; | ||
extensions = origin.extensions; | ||
} | ||
for (var _len = arguments.length, newComers = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
@@ -55,8 +80,6 @@ newComers[_key - 1] = arguments[_key]; | ||
return newComers.reduce(function (result, newComer) { | ||
if (!isWhat.isObject(result)) console.error('Trying to merge target:', newComer, 'onto a non-object:', result); | ||
if (!isWhat.isObject(newComer)) console.error('Trying to merge a non-object:', newComer, 'onto:', result); | ||
return mergeRecursively(result, newComer); | ||
}, origin); | ||
return mergeRecursively(result, newComer, extensions); | ||
}, base); | ||
} | ||
exports.default = index; |
@@ -1,6 +0,17 @@ | ||
import { isObject } from 'is-what'; | ||
import { isObject, isArray } from 'is-what'; | ||
function mergeRecursively(origin, newComer) { | ||
if (!isObject(newComer)) return newComer; // define newObject to merge all values upon | ||
function mergeRecursively(origin, newComer, extensions) { | ||
// work directly on newComer if its not an object | ||
if (!isObject(newComer)) { | ||
// extend merge rules | ||
if (extensions && isArray(extensions)) { | ||
extensions.forEach(function (extend) { | ||
newComer = extend(origin, newComer); | ||
}); | ||
} | ||
return newComer; | ||
} // define newObject to merge all values upon | ||
var newObject = isObject(origin) ? Object.keys(origin).reduce(function (carry, key) { | ||
@@ -12,5 +23,13 @@ var targetVal = origin[key]; | ||
return Object.keys(newComer).reduce(function (carry, key) { | ||
// re-define the origin and newComer as targetVal and newVal | ||
var newVal = newComer[key]; | ||
var targetVal = isObject(origin) ? origin[key] : undefined; // early return when targetVal === undefined | ||
var targetVal = isObject(origin) ? origin[key] : undefined; // extend merge rules | ||
if (extensions && isArray(extensions)) { | ||
extensions.forEach(function (extend) { | ||
newVal = extend(targetVal, newVal); | ||
}); | ||
} // early return when targetVal === undefined | ||
if (targetVal === undefined) { | ||
@@ -31,9 +50,7 @@ carry[key] = newVal; | ||
}, newObject); | ||
} // let a = mergeRecursively(null, {}) | ||
// a | ||
} | ||
/** | ||
* Merge anything | ||
* | ||
* @param {object} origin the default values | ||
* @param {object} origin the default values, OR {extensions} to pass an array of functions with extentions | ||
* @param {object} newComer on which to set the default values | ||
@@ -44,2 +61,10 @@ */ | ||
function index (origin) { | ||
var extensions = null; | ||
var base = origin; | ||
if (origin['extensions'] && Object.keys(origin).length === 1) { | ||
base = {}; | ||
extensions = origin.extensions; | ||
} | ||
for (var _len = arguments.length, newComers = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
@@ -50,8 +75,6 @@ newComers[_key - 1] = arguments[_key]; | ||
return newComers.reduce(function (result, newComer) { | ||
if (!isObject(result)) console.error('Trying to merge target:', newComer, 'onto a non-object:', result); | ||
if (!isObject(newComer)) console.error('Trying to merge a non-object:', newComer, 'onto:', result); | ||
return mergeRecursively(result, newComer); | ||
}, origin); | ||
return mergeRecursively(result, newComer, extensions); | ||
}, base); | ||
} | ||
export default index; |
{ | ||
"name": "merge-anything", | ||
"version": "1.1.1", | ||
"version": "2.0.0", | ||
"description": "Merge two objects recursively. A simple & small integration.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.cjs.js", |
@@ -59,5 +59,31 @@ # Merge anything 🥡 | ||
## Extend merge rules | ||
merge-anything can be really powerful because every step of the way **you can define rules to extend the overwrite logic.** | ||
Eg. merge-anything will overwrite arrays by default but you could change this logic to make it so it will concat the arrays. | ||
To do so your first parameter you pass has to be an object that looks like `{extensions: []}` and include an array of functions. In these functions you can change the value that will be overwriting the origin. See how to do this below: | ||
```js | ||
function concatArrays (originVal, newVal) { | ||
if (Array.isArray(originVal) && Array.isArray(newVal)) { | ||
// concat logic | ||
return originVal.concat(newVal) | ||
} | ||
return newVal // always return newVal as fallback!! | ||
} | ||
merge( | ||
{extensions: [concatArrays]}, // pass your extensions like so | ||
{array: ['a']}, | ||
{array: ['b']} | ||
) | ||
// results in {array: ['a', 'b']} | ||
``` | ||
Please note that each extension-function receives an `originVal` and `newVal` and **has** to return the `newVal` on fallback no matter what (in case your condition check fails or something)! | ||
## Source code | ||
It is literally just going through an object recursively and assigning the values to a new object like below. However, it's wrapped to allow extra params etc. | ||
It is literally just going through an object recursively and assigning the values to a new object like below. However, it's wrapped to allow extra params etc. The code below is the basic integration, that will make you understand the basics how it works. | ||
@@ -96,1 +122,3 @@ ```js | ||
``` | ||
\* Of course, there are small differences with the actual source code to cope with rare cases & extra features. The actual source code is [here](https://github.com/mesqueeb/merge-anything/blob/master/src/index.js). |
@@ -1,5 +0,14 @@ | ||
import { isObject } from 'is-what' | ||
import { isObject, isArray } from 'is-what' | ||
function mergeRecursively (origin, newComer) { | ||
if (!isObject(newComer)) return newComer | ||
function mergeRecursively (origin, newComer, extensions) { | ||
// work directly on newComer if its not an object | ||
if (!isObject(newComer)) { | ||
// extend merge rules | ||
if (extensions && isArray(extensions)) { | ||
extensions.forEach(extend => { | ||
newComer = extend(origin, newComer) | ||
}) | ||
} | ||
return newComer | ||
} | ||
// define newObject to merge all values upon | ||
@@ -16,6 +25,13 @@ const newObject = (isObject(origin)) | ||
.reduce((carry, key) => { | ||
const newVal = newComer[key] | ||
// re-define the origin and newComer as targetVal and newVal | ||
let newVal = newComer[key] | ||
const targetVal = (isObject(origin)) | ||
? origin[key] | ||
: undefined | ||
// extend merge rules | ||
if (extensions && isArray(extensions)) { | ||
extensions.forEach(extend => { | ||
newVal = extend(targetVal, newVal) | ||
}) | ||
} | ||
// early return when targetVal === undefined | ||
@@ -40,11 +56,15 @@ if (targetVal === undefined) { | ||
* | ||
* @param {object} origin the default values | ||
* @param {object} origin the default values, OR {extensions} to pass an array of functions with extentions | ||
* @param {object} newComer on which to set the default values | ||
*/ | ||
export default function (origin, ...newComers) { | ||
let extensions = null | ||
let base = origin | ||
if (origin['extensions'] && Object.keys(origin).length === 1) { | ||
base = {} | ||
extensions = origin.extensions | ||
} | ||
return newComers.reduce((result, newComer) => { | ||
if (!isObject(result)) console.error('Trying to merge target:', newComer, 'onto a non-object:', result) | ||
if (!isObject(newComer)) console.error('Trying to merge a non-object:', newComer, 'onto:', result) | ||
return mergeRecursively(result, newComer) | ||
}, origin) | ||
return mergeRecursively(result, newComer, extensions) | ||
}, base) | ||
} |
import test from 'ava' | ||
import merge from '../dist/index.cjs' | ||
import { isDate, isFunction } from 'is-what' | ||
import { isDate, isFunction, isString, isArray } from 'is-what' | ||
@@ -27,2 +27,57 @@ test('1. origin & target stays the same | 2. works with dates', t => { | ||
}) | ||
test('Overwrite arrays', t => { | ||
let res, origin, target | ||
origin = {array: ['a']} | ||
target = {array: ['b']} | ||
res = merge(origin, target) | ||
t.deepEqual(res, {array: ['b']}) | ||
}) | ||
test('Extend conversion', t => { | ||
let res, origin, target, extensions | ||
function convertTimestamps (originVal, targetVal) { | ||
if ( | ||
originVal === '%convertTimestamp%' && | ||
isString(targetVal) && | ||
isDate(new Date(targetVal)) | ||
) { | ||
return new Date(targetVal) | ||
} | ||
return targetVal | ||
} | ||
extensions = { | ||
extensions: [convertTimestamps] | ||
} | ||
origin = { | ||
date: '%convertTimestamp%' | ||
} | ||
target = { | ||
date: '1990-06-22' | ||
} | ||
res = merge(extensions, origin, target) | ||
t.deepEqual(res, {date: new Date('1990-06-22')}) | ||
res = merge(extensions, '%convertTimestamp%', '1990-06-22') | ||
t.deepEqual(res, new Date('1990-06-22')) | ||
}) | ||
test('Extend concat arrays', t => { | ||
let res, origin, target, extensions | ||
function concatArrays (originVal, targetVal) { | ||
if (isArray(originVal) && isArray(targetVal)) { | ||
return originVal.concat(targetVal) | ||
} | ||
return targetVal | ||
} | ||
extensions = { | ||
extensions: [concatArrays] | ||
} | ||
origin = { | ||
someArray: ['a'] | ||
} | ||
target = { | ||
someArray: ['b'] | ||
} | ||
res = merge(extensions, origin, target) | ||
t.deepEqual(res, {someArray: ['a', 'b']}) | ||
res = merge(extensions, ['a'], ['b']) | ||
t.deepEqual(res, ['a', 'b']) | ||
}) | ||
test('overwrites null with empty object', t => { | ||
@@ -29,0 +84,0 @@ let res, origin, target |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22689
572
123