Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sebamar88/bytekit/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The DiffUtils class provides utilities for deep comparison, change detection, and patch generation. Perfect for tracking object changes, implementing undo/redo, synchronizing data, and detecting differences in complex data structures.

Import

import { DiffUtils } from 'bytekit';

Usage

Deep Comparison

const obj1 = { name: 'John', age: 30, meta: { role: 'admin' } };
const obj2 = { name: 'John', age: 30, meta: { role: 'admin' } };
const obj3 = { name: 'John', age: 31, meta: { role: 'admin' } };

DiffUtils.deepEqual(obj1, obj2); // true
DiffUtils.deepEqual(obj1, obj3); // false

Detect Changes

const oldState = {
  name: 'John',
  age: 30,
  role: 'user'
};

const newState = {
  name: 'John',
  age: 31,
  role: 'admin',
  verified: true
};

const diff = DiffUtils.diff(oldState, newState);
console.log(diff);
// {
//   changed: ['age', 'role'],
//   added: ['verified'],
//   removed: []
// }

Generate and Apply Patches

const original = { count: 0, status: 'idle' };
const updated = { count: 5, status: 'active', timestamp: 1234567890 };

// Generate patches
const patches = DiffUtils.createPatch(original, updated);
console.log(patches);
// [
//   { op: 'replace', path: 'count', value: 5, oldValue: 0 },
//   { op: 'replace', path: 'status', value: 'active', oldValue: 'idle' },
//   { op: 'add', path: 'timestamp', value: 1234567890 }
// ]

// Apply patches
const result = DiffUtils.applyPatch(original, patches);
console.log(result);
// { count: 5, status: 'active', timestamp: 1234567890 }

Undo/Redo Implementation

const original = { count: 0 };
const updated = { count: 5 };

// Create forward patches
const patches = DiffUtils.createPatch(original, updated);

// Apply changes
let state = DiffUtils.applyPatch(original, patches);

// Undo - reverse patches
const undoPatches = DiffUtils.reversePatch(patches);
state = DiffUtils.applyPatch(state, undoPatches);
console.log(state); // { count: 0 }

Deep Diff with Nested Paths

const oldObj = {
  user: {
    profile: { name: 'John', age: 30 },
    settings: { theme: 'dark' }
  }
};

const newObj = {
  user: {
    profile: { name: 'John', age: 31 },
    settings: { theme: 'light', notifications: true }
  }
};

const deepDiff = DiffUtils.deepDiff(oldObj, newObj);
console.log(deepDiff);
// {
//   changed: ['user.profile.age', 'user.settings.theme'],
//   added: ['user.settings.notifications'],
//   removed: []
// }

Merge Objects

const obj1 = { name: 'John', age: 30, meta: { role: 'user' } };
const obj2 = { age: 31, meta: { verified: true }, email: 'john@example.com' };

// Deep merge
const merged = DiffUtils.merge(obj1, obj2);
console.log(merged);
// {
//   name: 'John',
//   age: 31,
//   meta: { role: 'user', verified: true },
//   email: 'john@example.com'
// }

// Use first object's values
const first = DiffUtils.merge(obj1, obj2, 'first');

// Use second object's values
const second = DiffUtils.merge(obj1, obj2, 'second');

API Reference

deepEqual

Deep compare two values for equality.
a
unknown
required
First value to compare
b
unknown
required
Second value to compare
return
boolean
Returns true if values are deeply equal
DiffUtils.deepEqual({ a: 1 }, { a: 1 }); // true
DiffUtils.deepEqual({ a: 1 }, { a: 2 }); // false

diff

Compare two objects and return changed, added, and removed keys.
oldObj
Record<string, unknown>
required
Original object
newObj
Record<string, unknown>
required
New object to compare
return
DiffResult
Object containing arrays of changed, added, and removed keys
interface DiffResult {
  changed: string[];
  added: string[];
  removed: string[];
}

deepDiff

Perform deep diff with nested paths using dot notation.
oldObj
unknown
required
Original object
newObj
unknown
required
New object to compare
prefix
string
default:"''"
Path prefix for nested keys
return
DiffResult
Object with nested paths (e.g., ‘user.profile.age’)

createPatch

Generate patches to transform one object into another.
oldObj
Record<string, unknown>
required
Original object
newObj
Record<string, unknown>
required
Target object
return
Patch[]
Array of patch operations
interface Patch {
  op: 'add' | 'remove' | 'replace';
  path: string;
  value?: unknown;
  oldValue?: unknown;
}

applyPatch

Apply patches to an object.
obj
Record<string, unknown>
required
Object to patch
patches
Patch[]
required
Array of patches to apply
return
Record<string, unknown>
New object with patches applied (does not mutate original)

reversePatch

Reverse patches to create undo operations.
patches
Patch[]
required
Patches to reverse
return
Patch[]
Reversed patches for undo
const patches = DiffUtils.createPatch(oldObj, newObj);
const undoPatches = DiffUtils.reversePatch(patches);

merge

Merge two objects with conflict resolution strategy.
obj1
Record<string, unknown>
required
First object
obj2
Record<string, unknown>
required
Second object
strategy
'first' | 'second' | 'merge'
default:"'merge'"
Conflict resolution strategy:
  • 'first': Use values from obj1
  • 'second': Use values from obj2
  • 'merge': Deep merge (default)
return
Record<string, unknown>
Merged object

getSummary

Get a human-readable summary of changes.
diff
DiffResult
required
Diff result from diff() or deepDiff()
return
string
Summary string (e.g., “2 changed, 1 added, 0 removed”)
const diff = DiffUtils.diff(oldObj, newObj);
const summary = DiffUtils.getSummary(diff);
console.log(summary); // "2 changed, 1 added"

Types

DiffResult

interface DiffResult {
  changed: string[];
  added: string[];
  removed: string[];
}

Patch

interface Patch {
  op: 'add' | 'remove' | 'replace';
  path: string;
  value?: unknown;
  oldValue?: unknown;
}

Use Cases

State Management

class StateManager {
  private history: Patch[][] = [];
  private state: any;
  
  update(newState: any) {
    const patches = DiffUtils.createPatch(this.state, newState);
    this.history.push(patches);
    this.state = newState;
  }
  
  undo() {
    const patches = this.history.pop();
    if (patches) {
      const undoPatches = DiffUtils.reversePatch(patches);
      this.state = DiffUtils.applyPatch(this.state, undoPatches);
    }
  }
}

Data Sync

const localData = await fetchLocal();
const serverData = await fetchServer();

const diff = DiffUtils.diff(localData, serverData);

if (diff.changed.length > 0 || diff.added.length > 0) {
  const patches = DiffUtils.createPatch(localData, serverData);
  await syncToServer(patches);
}

Change Tracking

const observer = {
  original: data,
  
  check(current: any) {
    const diff = DiffUtils.deepDiff(this.original, current);
    const summary = DiffUtils.getSummary(diff);
    
    if (diff.changed.length > 0) {
      console.log(`Changes detected: ${summary}`);
      console.log('Modified fields:', diff.changed);
    }
  }
};

Build docs developers (and LLMs) love