Skip to main content

@genetik/patches

Structured mutations over content: add node, remove node, update config, reorder slot. Apply a patch to get new content without mutating the input. Used by revisions (drafts/published, history), undo/redo, and LLM edit-in-place.

Installation​

pnpm add @genetik/patches

Concepts​

  • Patch: A single operation (PatchOp) or an array of operations applied in order.
  • Operations: addNode, removeNode, updateConfig, reorderSlot.
  • Immutable: applyPatch(content, patch) returns new content; the input is not modified. The result is not validated (e.g. use @genetik/content’s validateContent if needed).

Usage​

import { applyPatch } from "@genetik/patches";
import type { GenetikContent } from "@genetik/content";

const content: GenetikContent = {
entryId: "root",
nodes: {
root: { id: "root", block: "card", config: { title: "Root" }, children: ["a", "b"] },
a: { id: "a", block: "text", config: { content: "A" } },
b: { id: "b", block: "text", config: { content: "B" } },
},
};

// Add a node
const withC = applyPatch(content, {
type: "addNode",
id: "c",
node: { id: "c", block: "text", config: { content: "C" } },
});

// Update config
const updated = applyPatch(content, {
type: "updateConfig",
id: "root",
config: { title: "Updated" },
});

// Reorder a slot
const reordered = applyPatch(content, {
type: "reorderSlot",
id: "root",
slotName: "children",
order: ["b", "a"],
});

// Remove a node (also removes its id from any slot that references it)
const withoutA = applyPatch(content, { type: "removeNode", id: "a" });

// Multiple operations
const result = applyPatch(content, [
{ type: "addNode", id: "c", node: { id: "c", block: "text", config: { content: "C" } } },
{ type: "reorderSlot", id: "root", slotName: "children", order: ["a", "b", "c"] },
]);

Operations​

OperationDescription
addNodeAdd a node to the map. If the id already exists, the node is overwritten.
removeNodeRemove the node and remove its id from every slot that references it.
updateConfigReplace a node’s config. No-op if the node does not exist.
reorderSlotSet a node’s slot to an ordered list of ids. No-op if the node does not exist.

API summary​

ExportDescription
applyPatch(content, patch)Apply one or more operations; returns new content.
AddNodeOp, RemoveNodeOp, UpdateConfigOp, ReorderSlotOpOperation types.
PatchOp, PatchSingle op or array of ops.
ContentNode, GenetikContentRe-exported from @genetik/content.

Package location and build​

Source: packages/patches in the monorepo. Built with tsdown. Run pnpm --filter @genetik/patches build from the repo root.