Duplex functionality for observing JavaScript objects and automatically generating JSON patches when changes are detected. This enables reactive programming patterns and efficient change tracking.
Starts observing an object or array for changes and automatically generates patches.
/**
* Observes changes made to an object, which can then be retrieved using generate
* @param obj Object or array to observe for changes
* @param callback Optional callback function called when changes are detected
* @returns Observer object with patches array and unobserve method
*/
function observe<T>(
obj: Object | Array<T>,
callback?: (patches: Operation[]) => void
): Observer<T>;Usage Examples:
import { observe } from "fast-json-patch";
// Basic observation
const data = { name: "Alice", age: 25 };
const observer = observe(data);
// Make changes
data.name = "Bob";
data.age = 26;
// Generate patches manually
const patches = generate(observer);
console.log(patches);
// [
// { op: "replace", path: "/name", value: "Bob" },
// { op: "replace", path: "/age", value: 26 }
// ]
// Stop observing
observer.unobserve();
// With callback for automatic patch generation
const liveData = { counter: 0 };
const liveObserver = observe(liveData, (patches) => {
console.log("Changes detected:", patches);
// Could send patches to server, store in history, etc.
});
liveData.counter++; // Automatically triggers callback with patchesStops observing an object and cleans up event listeners.
/**
* Detach an observer from an object
* @param root The root object being observed
* @param observer The observer to detach
*/
function unobserve<T>(root: T, observer: Observer<T>): void;Usage Examples:
import { observe, unobserve } from "fast-json-patch";
const obj = { status: "active" };
const observer = observe(obj);
// Later, stop observing
unobserve(obj, observer);
// Or use the observer's built-in method
observer.unobserve();Generates an array of patches from an observer, capturing all changes since the last generation.
/**
* Generate an array of patches from an observer
* @param observer The observer to generate patches from
* @param invertible Whether to generate invertible patches (with test operations)
* @returns Array of patch operations describing the changes
*/
function generate<T>(
observer: Observer<Object>,
invertible?: boolean
): Operation[];Usage Examples:
import { observe, generate } from "fast-json-patch";
const document = { users: ["Alice"] };
const observer = observe(document);
// Make changes
document.users.push("Bob");
document.users[0] = "Alice Smith";
// Generate regular patches
const patches = generate(observer);
console.log(patches);
// [
// { op: "replace", path: "/users/0", value: "Alice Smith" },
// { op: "add", path: "/users/1", value: "Bob" }
// ]
// Generate invertible patches (with test operations)
document.users.push("Charlie");
const invertiblePatches = generate(observer, true);
console.log(invertiblePatches);
// [
// { op: "test", path: "/users/2", value: undefined },
// { op: "add", path: "/users/2", value: "Charlie" }
// ]Compares two objects and generates patches representing the differences.
/**
* Create an array of patches from the differences in two objects
* @param tree1 The original object
* @param tree2 The target object
* @param invertible Whether to generate invertible patches (with test operations)
* @returns Array of patch operations to transform tree1 into tree2
*/
function compare(
tree1: Object | Array<any>,
tree2: Object | Array<any>,
invertible?: boolean
): Operation[];Usage Examples:
import { compare } from "fast-json-patch";
const original = {
name: "John",
age: 30,
hobbies: ["reading", "gaming"]
};
const updated = {
name: "John Smith",
age: 31,
hobbies: ["reading", "swimming"],
email: "john@example.com"
};
// Generate patches to transform original into updated
const patches = compare(original, updated);
console.log(patches);
// [
// { op: "replace", path: "/name", value: "John Smith" },
// { op: "replace", path: "/age", value: 31 },
// { op: "replace", path: "/hobbies/1", value: "swimming" },
// { op: "add", path: "/email", value: "john@example.com" }
// ]
// Generate invertible patches
const invertiblePatches = compare(original, updated, true);
// Includes test operations to verify the original stateThe observer object returned by the observe function:
interface Observer<T> {
/** The observed object */
object: T;
/** Array of accumulated patches since last generation */
patches: Operation[];
/** Function to stop observing and clean up */
unobserve: () => void;
/** Optional callback function for automatic patch generation */
callback: (patches: Operation[]) => void;
}In browser environments, the observer automatically sets up event listeners for user interactions:
mouseup, mousedown - Mouse interactionskeyup, keydown - Keyboard interactionschange - Form element changesThese listeners trigger automatic patch generation through a debounced mechanism, making the observer perfect for tracking user-driven changes in web applications.
generate() is called or when changes are detectedunobserve() to prevent memory leaksThe duplex observation system provides a powerful foundation for reactive programming patterns while maintaining compatibility with the JSON Patch standard.