A zero dependency, high-performance, security-conscious JavaScript diffing library for comparing complex data structures with ease.
- ⚡️ Zero dependencies – lightweight and no external libraries required
- 📝 Detects additions, deletions, and modifications
- 💡 Supports Primitives, Objects, Arrays, Maps, and Sets
- 🔄 Handles circular references safely
- 🛠️ Highly configurable to fit different use cases
- 🚨 Built with security in mind to prevent prototype pollution and other risks
- 💻 Works in both Node.js and browser environments
npm install @sandboxed/diff
yarn add @sandboxed/diff
Works with both ESM (import) and CJS (require). Use the syntax that matches your environment:
// ESM
import diff, { ChangeType } from '@sandboxed/diff';
// CJS option 1
const diff = require('@sandboxed/diff').default;
const { ChangeType } = require('@sandboxed/diff');
// CJS option 2
const { default: diff, ChangeType } = require('@sandboxed/diff');import diff, { ChangeType } from '@sandboxed/diff';
const a = { name: "Alice", age: 25 };
const b = { name: "Alice", age: 26, city: "New York" };
const result = diff(a, b);
console.log(result);
console.log(result.toDiffString());
console.log(result.equal); // falseOutput:
[
  { type: 'noop', str: '{', depth: 0, path: [] },
  {
    type: 'noop',
    str: '"name": "Alice",',
    depth: 1,
    path: [ 'name', { deleted: false, value: 'Alice' } ]
  },
  {
    type: 'remove',
    str: '"age": 25,',
    depth: 1,
    path: [ 'age', { deleted: true, value: 25 } ]
  },
  {
    type: 'update',
    str: '"age": 26,',
    depth: 1,
    path: [ 'age', { deleted: false, value: 26 } ]
  },
  {
    type: 'add',
    str: '"city": "New York",',
    depth: 1,
    path: [ 'city', { deleted: false, value: 'New York' } ]
  },
  { type: 'noop', str: '}', depth: 0, path: [] }
]
// ---
{
   "name": "Alice",
-  "age": 25,
!  "age": 26,
+  "city": "New York",
}| option | Description | 
|---|---|
| config.include | Include only these change types from the diff result. Can be combined with exclude. | 
| config.exclude | Excludes the change types from the diff result. Can be combined with include. | 
| config.strict | Performs loose type check if disabled. | 
| config.showUpdatedOnly | @sandboxed/diffcreates aChangeType.REMOVEentry for everyChangeType.UPDATE. This flags prevents this behavior. | 
| config.pathHints | Hashmap of mapandsetpath hints. These strings will be used in thepatharray to provide a hit about the object's type. | 
| config.redactKeys | List of keys that should be redacted from the output. Works with stringbased keys and serializedSymbol. | 
| config.maxDepth | Max depth that the diffing function can traverse. | 
| config.maxKeys | Max keys the diffing function can traverse. | 
| config.timeout | Milliseconds before throwing a timeout error. | 
| util | Description | 
|---|---|
| toDiffString | Generates the diff string representation of the diff result. | 
| equal | Determines whether the inputs are structurally equal based on the diff result. | 
Many diffing libraries are optimized for either structured output or human-readable text, but rarely both. @sandboxed/diff is designed to provide a structured diff result along with a utility to generate a string representation, making it easy to use in both programmatic logic and UI rendering.
Trade-off: It may be slower than other libraries, but if you prioritize structured diffs with a built-in string representation, @sandboxed/diff is a great fit.