@fastify/deepmerge
Advanced tools
Comparing version 1.0.0 to 1.1.0
28
index.js
@@ -8,6 +8,8 @@ 'use strict' | ||
function deepmergeConstructor (options) { | ||
const prototypeKeys = ['constructor', '__proto__', 'prototype'] | ||
function isNotPrototypeKey (value) { | ||
return prototypeKeys.indexOf(value) === -1 | ||
return ( | ||
value !== 'constructor' && | ||
value !== 'prototype' && | ||
value !== '__proto__' | ||
) | ||
} | ||
@@ -25,2 +27,14 @@ | ||
function cloneObject (target) { | ||
const result = {} | ||
const targetKeys = getKeys(target) | ||
let i, il, key | ||
for (i = 0, il = targetKeys.length; i < il; ++i) { | ||
isNotPrototypeKey(key = targetKeys[i]) && | ||
(result[key] = clone(target[key])) | ||
} | ||
return result | ||
} | ||
function concatArrays (target, source) { | ||
@@ -66,2 +80,6 @@ const tl = target.length | ||
const mergeArray = options && typeof options.mergeArray === 'function' | ||
? options.mergeArray({ clone, deepmerge: _deepmerge, getKeys, isMergeableObject }) | ||
: concatArrays | ||
function clone (entry) { | ||
@@ -71,3 +89,3 @@ return isMergeableObject(entry) | ||
? cloneArray(entry) | ||
: mergeObject({}, entry) | ||
: cloneObject(entry) | ||
: entry | ||
@@ -106,3 +124,3 @@ } | ||
} else if (sourceIsArray && targetIsArray) { | ||
return concatArrays(target, source) | ||
return mergeArray(target, source) | ||
} else if (sourceIsArray !== targetIsArray) { | ||
@@ -109,0 +127,0 @@ return clone(source) |
{ | ||
"name": "@fastify/deepmerge", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Merges the enumerable properties of two or more objects deeply.", | ||
@@ -27,3 +27,3 @@ "main": "index.js", | ||
"tap": "^16.3.0", | ||
"tsd": "^0.21.0" | ||
"tsd": "^0.22.0" | ||
}, | ||
@@ -30,0 +30,0 @@ "files": [ |
104
README.md
@@ -26,5 +26,6 @@ # @fastify/deepmerge | ||
- `all` (`boolean`, optional) - merges all parameters, default is false | ||
- `mergeArray` (`function`, optional) - provide a function, which returns a function to add custom array merging function | ||
```js | ||
const deepmerge = require('@fastify/deepmegre')() | ||
const deepmerge = require('@fastify/deepmerge')() | ||
const result = deepmerge({a: 'value'}, { b: 404 }) | ||
@@ -35,3 +36,3 @@ console.log(result) // {a: 'value', b: 404 } | ||
```js | ||
const deepmerge = require('@fastify/deepmegre')({ all: true }) | ||
const deepmerge = require('@fastify/deepmerge')({ all: true }) | ||
const result = deepmerge({a: 'value'}, { b: 404 }, { a: 404 }) | ||
@@ -41,2 +42,77 @@ console.log(result) // {a: 404, b: 404 } | ||
#### mergeArray | ||
The default mode to merge Arrays is to concat the source-Array to the target-Array. | ||
```js | ||
const target = [1, 2, 3] | ||
const source = [4, 5, 6] | ||
const deepmerge = require('@fastify/deepmerge')() | ||
const result = deepmerge(target, source) | ||
console.log(result) // [1, 2, 3, 4, 5, 6] | ||
``` | ||
To overwrite the default behaviour regarding merging Arrays, you can provide a function to the | ||
`mergeArray` option of the deepmerge-function. The function provided to `mergeArray` | ||
gets an options-parameter passed, which is an Object containing the following keys and values. | ||
```typescript | ||
clone: (value: any) => any; | ||
isMergeableObject: (value: any) => any; | ||
deepmerge: DeepMergeFn; | ||
getKeys: (value: object) => string[]; | ||
``` | ||
The `mergeAray`-Function needs to return the actual Array merging function, which accepts two parameters of type | ||
Array, and returns a value. | ||
Example 1: Replace the target-Array with a clone of the source-Array. | ||
```js | ||
function replaceByClonedSource(options) { | ||
const clone = options.clone | ||
return function (target, source) { | ||
return clone(source) | ||
} | ||
} | ||
const deepmerge = require('@fastify/deepmerge')({ mergeArray: replaceByClonedSource }) | ||
const result = deepmerge([1, 2, 3], [4, 5, 6]) | ||
console.log(result) // [4, 5, 6] | ||
``` | ||
Example 2: Merge each element of the source-Array with the element at the same index-position of the target-Array. | ||
```js | ||
function deepmergeArray(options) { | ||
const deepmerge = options.deepmerge | ||
const clone = options.clone | ||
return function (target, source) { | ||
let i = 0 | ||
const tl = target.length | ||
const sl = source.length | ||
const il = Math.max(target.length, source.length) | ||
const result = new Array(il) | ||
for (i = 0; i < il; ++i) { | ||
if (i < sl) { | ||
result[i] = deepmerge(target[i], source[i]) | ||
} else { | ||
result[i] = clone(target[i]) | ||
} | ||
} | ||
return result | ||
} | ||
} | ||
// default behaviour | ||
const deepmergeConcatArray = require('@fastify/deepmerge')() | ||
const resultConcatArray = deepmergeConcatArray([{ a: [1, 2, 3 ]}], [{b: [4, 5, 6]}]) | ||
console.log(resultConcatArray) // [ { a: [ 1, 2, 3 ]}, { b: [ 4, 5, 6 ] } ] | ||
// modified behaviour | ||
const deepmergeDeepmergeArray = require('@fastify/deepmerge')({ mergeArray: deepmergeArray }) | ||
const resultDeepmergedArray = deepmergeDeepmergeArray([{ a: [1, 2, 3 ]}], [{b: [4, 5, 6]}]) | ||
console.log(resultDeepmergedArray) // [ { a: [ 1, 2, 3 ], b: [ 4, 5, 6 ] } ] | ||
``` | ||
## Benchmarks | ||
@@ -48,8 +124,8 @@ | ||
``` | ||
@fastify/deepmerge: merge regex with date x 1,266,447,885 ops/sec ±0.14% (97 runs sampled) | ||
@fastify/deepmerge: merge object with a primitive x 1,266,435,016 ops/sec ±0.33% (97 runs sampled) | ||
@fastify/deepmerge: merge two arrays containing strings x 25,591,739 ops/sec ±0.24% (98 runs sampled) | ||
@fastify/deepmerge: two merge arrays containing objects x 976,182 ops/sec ±0.46% (98 runs sampled) | ||
@fastify/deepmerge: merge two flat objects x 10,027,879 ops/sec ±0.36% (94 runs sampled) | ||
@fastify/deepmerge: merge nested objects x 5,341,227 ops/sec ±0.67% (94 runs sampled) | ||
@@fastify/deepmerge: merge regex with date x 1,256,523,040 ops/sec ±0.16% (92 runs sampled) | ||
@fastify/deepmerge: merge object with a primitive x 1,256,082,915 ops/sec ±0.25% (97 runs sampled) | ||
@fastify/deepmerge: merge two arrays containing strings x 25,392,605 ops/sec ±0.22% (97 runs sampled) | ||
@fastify/deepmerge: two merge arrays containing objects x 1,655,426 ops/sec ±0.65% (96 runs sampled) | ||
@fastify/deepmerge: merge two flat objects x 15,571,029 ops/sec ±0.45% (96 runs sampled) | ||
@fastify/deepmerge: merge nested objects x 7,601,328 ops/sec ±0.31% (96 runs sampled) | ||
``` | ||
@@ -59,8 +135,8 @@ | ||
``` | ||
@fastify/deepmerge x 403,777 ops/sec ±0.22% (98 runs sampled) | ||
deepmerge x 21,143 ops/sec ±0.83% (93 runs sampled) | ||
merge-deep x 89,447 ops/sec ±0.59% (95 runs sampled) | ||
ts-deepmerge x 185,601 ops/sec ±0.59% (96 runs sampled) | ||
deepmerge-ts x 185,310 ops/sec ±0.50% (92 runs sampled) | ||
lodash.merge x 89,053 ops/sec ±0.37% (99 runs sampled) | ||
@fastify/deepmerge x 605,343 ops/sec ±0.87% (96 runs sampled) | ||
deepmerge x 20,312 ops/sec ±1.06% (92 runs sampled) | ||
merge-deep x 83,167 ops/sec ±1.30% (94 runs sampled) | ||
ts-deepmerge x 175,977 ops/sec ±0.57% (96 runs sampled) | ||
deepmerge-ts x 174,973 ops/sec ±0.44% (93 runs sampled) | ||
lodash.merge x 89,213 ops/sec ±0.70% (98 runs sampled) | ||
``` | ||
@@ -67,0 +143,0 @@ |
@@ -57,3 +57,13 @@ declare function deepmerge(options: Options & { all: true }): DeepMergeAllFn; | ||
type MergeArrayFnOptions = { | ||
clone: (value: any) => any; | ||
isMergeableObject: (value: any) => boolean; | ||
deepmerge: DeepMergeFn; | ||
getKeys: (value: object) => string[]; | ||
} | ||
type MergeArrayFn = (options: MergeArrayFnOptions) => (target: any[], source: any[]) => any[] | ||
interface Options { | ||
mergeArray?: MergeArrayFn; | ||
symbols?: boolean; | ||
@@ -60,0 +70,0 @@ all?: boolean; |
13015
192
141