{"id":24206362,"url":"https://github.com/open-tech-foundation/obj-diff","last_synced_at":"2025-09-22T04:33:28.420Z","repository":{"id":235568646,"uuid":"790922076","full_name":"Open-Tech-Foundation/obj-diff","owner":"Open-Tech-Foundation","description":"🚀 The Fast, Accurate, JavaScript Objects Diffing \u0026 Patching Library.","archived":false,"fork":false,"pushed_at":"2024-05-09T09:37:57.000Z","size":209,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-04T11:42:28.831Z","etag":null,"topics":["deep","diff","javascript","library","objects","patching","typescript"],"latest_commit_sha":null,"homepage":"https://obj-diff.pages.dev/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Open-Tech-Foundation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":["Open-Tech-Foundation"]}},"created_at":"2024-04-23T19:12:52.000Z","updated_at":"2025-03-18T18:25:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"704c1e8c-e954-4bec-a064-3e1e5d1b69ee","html_url":"https://github.com/Open-Tech-Foundation/obj-diff","commit_stats":null,"previous_names":["open-tech-foundation/obj-diff"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/Open-Tech-Foundation/obj-diff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Tech-Foundation%2Fobj-diff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Tech-Foundation%2Fobj-diff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Tech-Foundation%2Fobj-diff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Tech-Foundation%2Fobj-diff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Open-Tech-Foundation","download_url":"https://codeload.github.com/Open-Tech-Foundation/obj-diff/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Tech-Foundation%2Fobj-diff/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276347148,"owners_count":25626597,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-22T02:00:08.972Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["deep","diff","javascript","library","objects","patching","typescript"],"created_at":"2025-01-14T00:20:17.143Z","updated_at":"2025-09-22T04:33:28.030Z","avatar_url":"https://github.com/Open-Tech-Foundation.png","language":"TypeScript","readme":"\u003cimg align=\"left\" src=\"https://open-tech-foundation.pages.dev/img/Logo.svg\" width=\"50\" height=\"50\"\u003e\n\n\u0026nbsp;[OPEN TECH FOUNDATION](https://open-tech-foundation.pages.dev/)\n\n\u003cdiv align=\"center\"\u003e\n\n# obj-diff\n\n[![Build](https://github.com/Open-Tech-Foundation/obj-diff/actions/workflows/build.yml/badge.svg)](https://github.com/Open-Tech-Foundation/obj-diff/actions/workflows/build.yml) \u0026nbsp; [![JSR Score](https://jsr.io/badges/@opentf/obj-diff/score)](https://jsr.io/@opentf/obj-diff)\n\n![Demo image](./demo.png)\n\n\u003c/div\u003e\n\n\u003e The Fast, Accurate, JavaScript Objects Diffing \u0026 Patching Library.\n\n**[LIVE DEMO](https://obj-diff.pages.dev/)**\n\n## Features\n\n- Deep Objects Diffing\n\n- Patching\n\n- Supports comparing custom object types\n\n- TypeScript Support\n\n- Cross-Platform\n\n## Supported Types\n\n- Primitives\n\n  - Undefined\n  - Null\n  - Number\n  - String\n  - Boolean\n  - BigInt\n\n- Objects\n  - Plain Objects, eg: `{}`\n  - Array\n  - Date\n  - Map\n  - Set\n\n## Installation\n\nInstall it using your favourite package manager.\n\n```sh\nnpm install @opentf/obj-diff\n```\n\n```sh\nyarn add @opentf/obj-diff\n```\n\n```sh\npnpm add @opentf/obj-diff\n```\n\n```sh\nbun add @opentf/obj-diff\n```\n\n```sh\ndeno add @opentf/obj-diff\n```\n\n## Usage\n\n```js\nimport { diff } from '@opentf/obj-diff';\n\ndiff(obj1: object, obj2: object): Array\u003cDiffResult\u003e\n```\n\n```ts\ntype DiffResult = {\n  t: 0 | 1 | 2; // The type of diff, 0 - Deleted, 1 - Created, 2 - Updated\n  p: Array\u003cstring | number\u003e; // The object path\n  v?: unknown; // The current value\n};\n```\n\n## Examples\n\n1. Diff two simple objects.\n\n```js\nconst a = { a: 1, b: 2 };\nconst b = { a: 2, c: 3 };\n\ndiff(a, b);\n/*\n[\n  {\n    t: 2,\n    p: [\"a\"],\n    v: 2,\n  },\n  {\n    t: 0,\n    p: [\"b\"],\n  },\n  {\n    t: 1,\n    p: [\"c\"],\n    v: 5,\n  },\n]\n*/\n```\n\n2. Diff two arrays.\n\n```js\nconst a = [1, 2, 3, 4, 5];\nconst b = [1, 3, 5];\n\ndiff(a, b);\n/* \n[\n  {\n    t: 2,\n    p: [1],\n    v: 3,\n  },\n  {\n    t: 2,\n    p: [2],\n    v: 5,\n  },\n  {\n    t: 0,\n    p: [3],\n  },\n  {\n    t: 0,\n    p: [4],\n  },\n]\n*/\n```\n\n3. Deep diff two objects.\n\n```js\nconst a = {\n  foo: {\n    bar: {\n      a: [\"a\", \"b\"],\n      b: 2,\n      c: [\"x\", \"y\"],\n      e: 100,\n    },\n  },\n  buzz: \"world\",\n};\n\nconst b = {\n  foo: {\n    bar: {\n      a: [\"a\"],\n      b: 2,\n      c: [\"x\", \"y\", \"z\"],\n      d: \"Hello, world!\",\n    },\n  },\n  buzz: \"fizz\",\n};\n\ndiff(a, b);\n/*\n[\n  {\n    t: 0,\n    p: [\"foo\", \"bar\", \"a\", 1],\n  },\n  {\n    t: 1,\n    p: [\"foo\", \"bar\", \"c\", 2],\n    v: \"z\",\n  },\n  {\n    t: 0,\n    p: [\"foo\", \"bar\", \"e\"],\n  },\n  {\n    t: 1,\n    p: [\"foo\", \"bar\", \"d\"],\n    v: \"Hello, world!\",\n  },\n  {\n    t: 2,\n    p: [\"buzz\"],\n    v: \"fizz\",\n  },\n]\n*/\n```\n\n## Patching\n\nYou can apply the diff result onto the original object to get the modified object.\n\n```js\nimport { diff, patch } from \"@opentf/obj-diff\";\n\nconst a = { a: 1, b: 2 };\nconst b = { a: 2, c: 3 };\n\nconst out = patch(a, diff(a, b));\n\nassert.deepStrictEqual(out, b); // ok\n```\n\n## Comparing Custom Types\n\nBy default, the `diff` function cannot compare every object types other than the supported list above.\n\nYou can extend the default `diff` function using the `diffWith` function.\n\nNow you can compare any object types of your own.\n\n### Usage - diffWith()\n\n```js\nimport { diffWith } from '@opentf/obj-diff';\n\ndiffWith(\n  obj1: object,\n  obj2: object,\n  fn: (a: object, b: object) =\u003e boolean | undefined\n): Array\u003cDiffResult\u003e\n```\n\n### Examples\n\nLet us compare the `MongoDB` bson `ObjectId` objects.\n\n```js\nimport { ObjectId } from \"bson\";\nimport { diffWith } from \"@opentf/obj-diff\";\n\nconst record1 = {\n  _id: new ObjectId(),\n  title: \"Article 1\",\n  desc: \"The article description.\",\n};\n\nconst record2 = {\n  _id: new ObjectId(),\n  title: \"Article 1\",\n  desc: \"The new article description.\",\n};\n\nconst result = diffWith(record1, record2, (a, b) =\u003e {\n  if (a instanceof ObjectId \u0026\u0026 b instanceof ObjectId) {\n    return a.toString() !== b.toString();\n  }\n});\n\nconsole.log(result);\n/*\n[\n  {\n    t: 2,\n    p: [ \"_id\" ],\n    v: new ObjectId('663088b877dd3c9aaec482d4'),\n  }, \n  {\n    t: 2,\n    p: [ \"desc\" ],\n    v: \"The new article description.\",\n  }\n]\n*/\n```\n\n## FAQs\n\n### 1. **Why the standard JSON Patch protocol is not supported?**\n\nThe `JSON Patch` protocol is complicated in nature. And simply we don't want use it as our existing solution works for most of the projects.\n\n### 2. What is the meaning of empty array `{p: []}` in path property?\n\nThe empty path denotes `Root` path, and it simply means the entire object was replaced.\n\nFor Eg:\n\n```js\ndiff({}, null); //=\u003e [{t: 2, p: [], v: null}]\n```\n\n## Benchmark\n\n```diff\n┌───┬──────────────────┬─────────┬───────────────────┬────────┬─────────┐\n│   │ Task Name        │ ops/sec │ Average Time (ns) │ Margin │ Samples │\n├───┼──────────────────┼─────────┼───────────────────┼────────┼─────────┤\n+ 0 │ diff             │ 252,694 │ 3957.346814404028 │ ±1.60% │ 25270   │\n│ 1 │ microdiff        │ 218,441 │ 4577.892286564301 │ ±0.92% │ 21845   │\n│ 2 │ deep-object-diff │ 121,385 │ 8238.188318642591 │ ±1.66% │ 12139   │\n│ 3 │ just-diff        │ 105,292 │ 9497.35384615396  │ ±1.66% │ 10530   │\n│ 4 │ deep-diff        │ 160,802 │ 6218.820533549017 │ ±1.59% │ 16081   │\n└───┴──────────────────┴─────────┴───────────────────┴────────┴─────────┘\n```\n\n### Running benchmarks\n\n```sh\n$ bun run build\n$ bun benchmark.js\n```\n\n## Articles\n\nPlease read our important articles:\n\n- [Introducing Our New JavaScript Standard Library](https://ganapathy.hashnode.dev/introducing-our-new-javascript-standard-library)\n\n- [You Don’t Need JavaScript Native Methods](https://ganapathy.hashnode.dev/you-dont-need-javascript-native-methods)\n\n## License\n\nCopyright (c) [Thanga Ganapathy](https://github.com/Thanga-Ganapathy) ([MIT License](./LICENSE)).\n","funding_links":["https://github.com/sponsors/Open-Tech-Foundation"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-tech-foundation%2Fobj-diff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopen-tech-foundation%2Fobj-diff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-tech-foundation%2Fobj-diff/lists"}