Utility functions to apply and invert patches generated by Automerge document changes.
npm install @onsetsoftware/automerge-patcher
Used to take a single automerge patch and apply it to a document. It can also be used to apply an Automerge patch to a plain javascript object with the same shape as the relevant document
import { patch } from "@onsetsoftware/automerge-patcher";
import { from, change, type PutPatch } from "@automerge/automerge";
const doc = from({ foo: "bar" });
const toApply = {
action: "put",
path: ["foo"],
value: "baz",
};
const updated = change(doc, (d) => {
patch(d, toApply);
});
console.log(updated); // => { foo: 'baz' }
Provides the inverse of a patch, given the initial document (before the change) on which the patch applies.
import { unpatch } from "@onsetsoftware/automerge-patcher";
import { from } from "@automerge/automerge";
const doc = from({ foo: "bar" });
const patch = {
action: "put",
path: ["foo"],
value: "baz",
};
const inverse = unpatch(doc, patch);
console.log(inverse); // => { action: 'put', path: ["foo"], value: "bar"}
unpatchAll
can be used to reverse an array of patches relative to the initial (before changes) document which produced them.
It works by progressively updating a copy of the document after applying each patch, then reversing the next patch based on the new state.
Note
The best (and fastest) way to get the reverse of a change is to use the automerge diff
function, but it isn't ready quite yet.
In the meantime, the unpatchAll
function is provided to acheive this.
import { patch, unpatchAll } from "@onsetsoftware/automerge-patcher";
import { from, change, type Patch } from "@automerge/automerge";
const doc = from({ foo: "bar" });
let reverse: Patch[];
const doc2 = change(
doc,
{
patchCallback: (patches, { before }) => {
// capture reverse of the patches for undo
reverse = unpatchAll(before, patches);
},
},
(doc) => {
doc.foo = "baz";
},
);
console.log(reverse); // [{action: 'put', path: ['foo'], value: 'bar'}]
console.log(doc2.foo); // baz
const doc3 = change(doc2, (doc) => {
// apply the patch to revert the change
reverse.forEach((patch) => {
applyPatch(doc, patch);
});
});
console.log(doc3.foo); // bar