You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
5.5 KiB
160 lines
5.5 KiB
3 years ago
|
# @fastify/deepmerge
|
||
|
|
||
|

|
||
|
[](https://www.npmjs.com/package/@fastify/deepmerge)
|
||
|
[](https://standardjs.com/)
|
||
|
|
||
|
Merges the enumerable properties of two or more objects deeply. Fastest implementation of deepmerge, see section 'Benchmarks'.
|
||
|
|
||
|
### Install
|
||
|
```
|
||
|
npm i @fastify/deepmerge
|
||
|
```
|
||
|
|
||
|
### Usage
|
||
|
|
||
|
The module exports a function, which provides a function to deepmerge Objects.
|
||
|
|
||
|
```
|
||
|
deepmerge(options)
|
||
|
```
|
||
|
|
||
|
`options` is optional and can contain following values
|
||
|
|
||
|
- `symbols` (`boolean`, optional) - should also merge object-keys which are symbols, default is false
|
||
|
- `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
|
||
|
- `cloneProtoObject` (`function`, optional) - provide a function, which must return a clone of the object with the prototype of the object
|
||
|
|
||
|
```js
|
||
|
const deepmerge = require('@fastify/deepmerge')()
|
||
|
const result = deepmerge({a: 'value'}, { b: 404 })
|
||
|
console.log(result) // {a: 'value', b: 404 }
|
||
|
```
|
||
|
|
||
|
```js
|
||
|
const deepmerge = require('@fastify/deepmerge')({ all: true })
|
||
|
const result = deepmerge({a: 'value'}, { b: 404 }, { a: 404 })
|
||
|
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 ] } ]
|
||
|
```
|
||
|
|
||
|
#### cloneProtoObject
|
||
|
|
||
|
Merging objects with prototypes, such as Streams or Buffers, are not supported by default.
|
||
|
You can provide a custom function to let this module deal with the object that has a `prototype` _(JSON object excluded)_.
|
||
|
|
||
|
```js
|
||
|
function cloneByReference (source) {
|
||
|
return source
|
||
|
}
|
||
|
|
||
|
const deepmergeByReference = require('@fastify/deepmerge')({
|
||
|
cloneProtoObject: cloneByReference
|
||
|
})
|
||
|
|
||
|
const result = deepmergeByReference({}, { stream: process.stdout })
|
||
|
console.log(result) // { stream: <ref *1> WriteStream }
|
||
|
```
|
||
|
|
||
|
## Benchmarks
|
||
|
|
||
|
The benchmarks are available in the benchmark-folder.
|
||
|
|
||
|
`npm run bench` - benchmark various use cases of deepmerge:
|
||
|
```
|
||
|
@@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)
|
||
|
```
|
||
|
|
||
|
`npm run bench:compare` - comparison of @fastify/deepmerge with other popular deepmerge implementation:
|
||
|
```
|
||
|
@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)
|
||
|
```
|
||
|
|
||
|
## License
|
||
|
|
||
|
Licensed under [MIT](./LICENSE).
|