JSON diff & patch library with support for objects, arrays, text diffs, and multiple output formats
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Object-oriented interface providing full control over diff and patch operations with customizable options and processing pipeline access.
Creates a new DiffPatcher instance with optional configuration.
/**
* Create DiffPatcher instance with custom options
* @param options - Configuration options for diff/patch behavior
*/
class DiffPatcher {
constructor(options?: Options);
}Usage Examples:
import { DiffPatcher } from "jsondiffpatch";
// Default instance
const patcher = new DiffPatcher();
// Custom configuration
const customPatcher = new DiffPatcher({
objectHash: (obj) => obj.id || obj.name,
arrays: {
detectMove: true,
includeValueOnMove: false
},
textDiff: {
minLength: 60
},
cloneDiffValues: true
});Generates a delta representing the differences between two values.
/**
* Generate diff between two values
* @param left - Original value
* @param right - Target value
* @returns Delta representing changes needed to transform left into right
*/
diff(left: unknown, right: unknown): Delta;Usage Examples:
const patcher = new DiffPatcher();
// Object diff
const objectDelta = patcher.diff(
{ name: "Alice", age: 25, tags: ["user"] },
{ name: "Alice", age: 26, tags: ["user", "admin"], active: true }
);
// Result: { age: [25, 26], tags: { _t: "a", 1: ["admin"] }, active: [true] }
// Array diff with move detection
const arrayDelta = patcher.diff(
[{ id: 1, name: "A" }, { id: 2, name: "B" }, { id: 3, name: "C" }],
[{ id: 2, name: "B" }, { id: 3, name: "C" }, { id: 1, name: "A" }]
);Applies a delta to a value to produce the target value.
/**
* Apply patch to transform a value
* @param left - Original value to patch
* @param delta - Delta to apply
* @returns Transformed value
*/
patch(left: unknown, delta: Delta): unknown;Usage Examples:
const patcher = new DiffPatcher();
const original = { name: "Alice", age: 25, tags: ["user"] };
const delta = { age: [25, 26], tags: { _t: "a", 1: ["admin"] }, active: [true] };
const result = patcher.patch(original, delta);
// Result: { name: "Alice", age: 26, tags: ["user", "admin"], active: true }
// Patch preserves original by default (unless cloneDiffValues is false)
console.log(original); // Still { name: "Alice", age: 25, tags: ["user"] }Applies the reverse of a delta to revert changes.
/**
* Apply reverse patch to revert changes
* @param right - Target value to unpatch
* @param delta - Original delta to reverse
* @returns Original value before patch was applied
*/
unpatch(right: unknown, delta: Delta): unknown;Usage Examples:
const patcher = new DiffPatcher();
const target = { name: "Alice", age: 26, tags: ["user", "admin"], active: true };
const delta = { age: [25, 26], tags: { _t: "a", 1: ["admin"] }, active: [true] };
const original = patcher.unpatch(target, delta);
// Result: { name: "Alice", age: 25, tags: ["user"] }Creates a reversed delta that can undo the original delta's changes.
/**
* Reverse a delta to create undo operation
* @param delta - Delta to reverse
* @returns Reversed delta
*/
reverse(delta: Delta): Delta;Usage Examples:
const patcher = new DiffPatcher();
const originalDelta = { age: [25, 26], role: ["admin"] };
const reversedDelta = patcher.reverse(originalDelta);
// Result: { age: [26, 25], role: [undefined, 0, 0] }
// Use reversed delta for undo functionality
const target = { name: "Alice", age: 26, role: "admin" };
const undone = patcher.patch(target, reversedDelta);
// Result: { name: "Alice", age: 25 }Creates a deep clone of any value using the same cloning logic as internal operations.
/**
* Create deep clone of a value
* @param value - Value to clone
* @returns Deep cloned copy
*/
clone(value: unknown): unknown;Usage Examples:
const patcher = new DiffPatcher();
const original = {
user: { name: "Alice", permissions: ["read", "write"] },
metadata: { created: new Date(), version: 1 }
};
const cloned = patcher.clone(original);
// Modify clone without affecting original
cloned.user.name = "Bob";
cloned.user.permissions.push("admin");
console.log(original.user.name); // "Alice"
console.log(original.user.permissions); // ["read", "write"]Gets or sets the DiffPatcher instance options.
/**
* Get or set DiffPatcher options
* @param options - New options to set (optional)
* @returns Current options object
*/
options(options?: Options): Options;Usage Examples:
const patcher = new DiffPatcher();
// Get current options
const currentOptions = patcher.options();
console.log(currentOptions.arrays?.detectMove); // true (default)
// Update options
patcher.options({
arrays: {
detectMove: false,
includeValueOnMove: true
},
objectHash: (obj) => obj.id
});
// Options are merged with existing options
const updatedOptions = patcher.options();
console.log(updatedOptions.cloneDiffValues); // true (preserved from defaults)const patcher = new DiffPatcher({
objectHash: (item, index) => {
// Use id field for object matching
if (item && typeof item === 'object' && 'id' in item) {
return String(item.id);
}
// Use name field as fallback
if (item && typeof item === 'object' && 'name' in item) {
return String(item.name);
}
// Default to position-based matching
return undefined;
}
});
const delta = patcher.diff(
[{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }],
[{ id: 2, name: "Bob" }, { id: 1, name: "Alice", role: "admin" }]
);
// Detects move and modification based on id matchingconst patcher = new DiffPatcher({
propertyFilter: (name, context) => {
// Skip private properties
if (name.startsWith('_')) return false;
// Skip computed properties in certain contexts
if (name === 'computed' && context.left && context.left.type === 'temp') {
return false;
}
return true;
}
});
const delta = patcher.diff(
{ name: "Alice", _private: "secret", computed: "temp" },
{ name: "Bob", _private: "changed", computed: "updated" }
);
// Only includes changes to 'name' property// Using with-text-diffs module
import { DiffPatcher } from "jsondiffpatch/with-text-diffs";
const textPatcher = new DiffPatcher({
textDiff: {
minLength: 40 // Only diff strings longer than 40 characters
}
});
const delta = textPatcher.diff(
"The quick brown fox jumps over the lazy dog",
"The quick brown fox jumped over the lazy cat"
);
// Creates text diff instead of simple replacement/**
* Access to internal processor for advanced pipeline customization
*/
readonly processor: Processor;The processor property provides access to the internal processing pipeline for advanced customization of diff, patch, and reverse operations through filter manipulation.