{"id":14969146,"url":"https://github.com/fastify/deepmerge","last_synced_at":"2026-01-21T00:15:11.755Z","repository":{"id":40665664,"uuid":"507868592","full_name":"fastify/deepmerge","owner":"fastify","description":"Merges the enumerable properties of two or more objects deeply. Fastest implementation of deepmerge","archived":false,"fork":false,"pushed_at":"2025-12-02T08:36:12.000Z","size":93,"stargazers_count":115,"open_issues_count":1,"forks_count":18,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-12-05T03:53:39.524Z","etag":null,"topics":["deepmerge","fastify-library","merge","nodejs"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@fastify/deepmerge","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fastify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"fastify","open_collective":"fastify"}},"created_at":"2022-06-27T10:47:21.000Z","updated_at":"2025-12-02T08:36:08.000Z","dependencies_parsed_at":"2023-02-06T06:30:33.358Z","dependency_job_id":"decece10-3e06-4810-9efa-f1766e341985","html_url":"https://github.com/fastify/deepmerge","commit_stats":{"total_commits":41,"total_committers":8,"mean_commits":5.125,"dds":0.6341463414634146,"last_synced_commit":"4a8bbd88c47af8bbd9ab41d03b9d2d09babefb6b"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":"fastify/skeleton","purl":"pkg:github/fastify/deepmerge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fdeepmerge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fdeepmerge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fdeepmerge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fdeepmerge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify","download_url":"https://codeload.github.com/fastify/deepmerge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fdeepmerge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28619256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T23:49:58.628Z","status":"ssl_error","status_checked_at":"2026-01-20T23:47:29.996Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deepmerge","fastify-library","merge","nodejs"],"created_at":"2024-09-24T13:41:12.441Z","updated_at":"2026-01-21T00:15:11.746Z","avatar_url":"https://github.com/fastify.png","language":"JavaScript","readme":"# @fastify/deepmerge\n\n[![CI](https://github.com/fastify/deepmerge/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/deepmerge/actions/workflows/ci.yml)\n[![NPM version](https://img.shields.io/npm/v/@fastify/deepmerge.svg?style=flat)](https://www.npmjs.com/package/@fastify/deepmerge)\n[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)\n\nMerges the enumerable properties of two or more objects deeply. Fastest implementation of deepmerge, see section 'Benchmarks'.\n\n### Install\n```\nnpm i @fastify/deepmerge\n```\n\n### Usage\n\nThe module exports a function, which provides a function to deepmerge Objects.\n\n`@fastify/deepmerge` does not mutate the input objects. It returns a new object, which is the result of the merge.\n\n```\ndeepmerge(options)\n```\n\n`options` is optional and can contain the following values:\n\n- `symbols` (`boolean`, optional) - should also merge object keys that are symbols, default is false\n- `all` (`boolean`, optional) - makes deepmerge accept and merge any number of passed objects, default is false\n- `mergeArray` (`function`, optional) - provide a function, which returns a function to add custom array merging function\n- `cloneProtoObject` (`function`, optional) - provide a function, which must return a clone of the object with the prototype of the object\n- `isMergeableObject` (`function`, optional) - provide a function, which must return true if the object should be merged, default is `isMergeableObject` from this module\n- `onlyDefinedProperties` (`boolean`, optional) - if `true`, properties with `undefined` in the source will not overwrite existing values from the target, default is `false`\n\n```js\nconst deepmerge = require('@fastify/deepmerge')()\nconst result = deepmerge({a: 'value'}, { b: 404 })\nconsole.log(result) // {a: 'value',  b: 404 }\n```\n\n```js\nconst deepmerge = require('@fastify/deepmerge')({ all: true })\nconst result = deepmerge({a: 'value'}, { b: 404 }, { a: 404 })\nconsole.log(result) // {a: 404,  b: 404 }\n```\n\nExample with `onlyDefinedProperties` option:\n\n```js\nconst deepmerge = require('@fastify/deepmerge')({ onlyDefinedProperties: true })\nconst result = deepmerge({ a: 1, b: null }, { a: undefined, b: undefined })\nconsole.log(result) // { a: 1, b: null }\n```\n\n#### mergeArray\n\nThe default mode to merge Arrays is to concat the source-Array to the target-Array.\n\n```js\nconst target = [1, 2, 3]\nconst source = [4, 5, 6]\nconst deepmerge = require('@fastify/deepmerge')()\nconst result = deepmerge(target, source)\nconsole.log(result) // [1, 2, 3, 4, 5, 6]\n```\n\nTo overwrite the default behavior regarding merging Arrays, you can provide a function to the\n`mergeArray` option of the deepmerge-function. The function provided to `mergeArray`\ngets an options-parameter passed, which is an Object containing the following keys and values.\n\n```typescript\nclone: (value: any) =\u003e any;\nisMergeableObject: (value: any) =\u003e any;\ndeepmerge: DeepMergeFn;\ngetKeys: (value: object) =\u003e string[];\n```\n\nThe `mergeArray`-Function needs to return the actual Array merging function, which accepts two parameters of type\nArray, and returns a value.\n\nExample 1: Replace the target-Array with a clone of the source-Array.\n\n```js\nfunction replaceByClonedSource(options) {\n  const clone = options.clone\n  return function (target, source) {\n    return clone(source)\n  }\n}\n\nconst deepmerge = require('@fastify/deepmerge')({ mergeArray: replaceByClonedSource })\nconst result = deepmerge([1, 2, 3], [4, 5, 6])\nconsole.log(result) // [4, 5, 6]\n```\n\nExample 2: Merge each element of the source-Array with the element at the same index-position of the target-Array.\n\n```js\nfunction deepmergeArray(options) {\n  const deepmerge = options.deepmerge\n  const clone = options.clone\n  return function (target, source) {\n    let i = 0\n    const tl = target.length\n    const sl = source.length\n    const il = Math.max(target.length, source.length)\n    const result = new Array(il)\n    for (i = 0; i \u003c il; ++i) {\n      if (i \u003c sl) {\n        result[i] = deepmerge(target[i], source[i])\n      } else {\n        result[i] = clone(target[i])\n      }\n    }\n    return result\n  }\n}\n\n// default behavior\nconst deepmergeConcatArray = require('@fastify/deepmerge')()\nconst resultConcatArray = deepmergeConcatArray([{ a: [1, 2, 3 ]}], [{b: [4, 5, 6]}])\nconsole.log(resultConcatArray) // [ { a: [ 1, 2, 3 ]}, { b: [ 4, 5, 6 ] } ]\n\n// modified behavior\nconst deepmergeDeepmergeArray = require('@fastify/deepmerge')({ mergeArray: deepmergeArray })\nconst resultDeepmergedArray = deepmergeDeepmergeArray([{ a: [1, 2, 3 ]}], [{b: [4, 5, 6]}])\nconsole.log(resultDeepmergedArray) // [ { a: [ 1, 2, 3 ], b: [ 4, 5, 6 ] } ]\n```\n\n#### cloneProtoObject\n\nMerging objects with prototypes, such as Streams or Buffers, are not supported by default.\nYou can provide a custom function to let this module deal with the object that has a `prototype` _(JSON object excluded)_.\n\n```js\nfunction cloneByReference (source) {\n  return source\n}\n\nconst deepmergeByReference = require('@fastify/deepmerge')({\n  cloneProtoObject: cloneByReference\n})\n\nconst result = deepmergeByReference({}, { stream: process.stdout })\nconsole.log(result) // { stream: \u003cref *1\u003e WriteStream }\n```\n\n#### isMergeableObject\n\nBy default, `@fastify/deepmerge` merges all objects except native `Date` and `RegExp` objects. To exclude certain objects from being merged, you can provide a custom function to the `isMergeableObject` option.\n\nThe default function is exported by this module as `isMergeableObject`.\n\nThe following example shows how to extend the default function to exclude globally defined `FormData` objects from being identified as mergeable objects.\n\n```js\nconst { isMergeableObject: defaultIsMergeableObject } = require('@fastify/deepmerge')\n\n\nfunction customIsMergeableObject (source) {\n  return defaultIsMergeableObject(source) \u0026\u0026 !(source instanceof FormData)\n}\n\nconst deepmergeWithCustomMergeableObject = require('@fastify/deepmerge')({\n  isMergeableObject: customIsMergeableObject\n})\n```\n\n## Benchmarks\n\nThe benchmarks are available in the benchmark folder.\n\n`npm run bench` - benchmark various use cases of deepmerge:\n```\n@fastify/deepmerge: merge regex with date x 1,256,523,040 ops/sec ±0.16% (92 runs sampled)\n@fastify/deepmerge: merge object with a primitive x 1,256,082,915 ops/sec ±0.25% (97 runs sampled)\n@fastify/deepmerge: merge two arrays containing strings x 25,392,605 ops/sec ±0.22% (97 runs sampled)\n@fastify/deepmerge: two merge arrays containing objects x 1,655,426 ops/sec ±0.65% (96 runs sampled)\n@fastify/deepmerge: merge two flat objects x 15,571,029 ops/sec ±0.45% (96 runs sampled)\n@fastify/deepmerge: merge nested objects x 7,601,328 ops/sec ±0.31% (96 runs sampled)\n```\n\n`npm run bench:compare` - comparison of @fastify/deepmerge with other popular deepmerge implementation:\n```\n@fastify/deepmerge x 605,343 ops/sec ±0.87% (96 runs sampled)\ndeepmerge x 20,312 ops/sec ±1.06% (92 runs sampled)\nmerge-deep x 83,167 ops/sec ±1.30% (94 runs sampled)\nts-deepmerge x 175,977 ops/sec ±0.57% (96 runs sampled)\ndeepmerge-ts x 174,973 ops/sec ±0.44% (93 runs sampled)\nlodash.merge x 89,213 ops/sec ±0.70% (98 runs sampled)\n```\n\n## License\n\nLicensed under [MIT](./LICENSE).\n","funding_links":["https://github.com/sponsors/fastify","https://opencollective.com/fastify"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Fdeepmerge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffastify%2Fdeepmerge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Fdeepmerge/lists"}