Skip to main content

Version History

@oh-just-another/versioning provides git-like version control for scenes: named snapshots, a branch tree, and diff/merge utilities. This is distinct from undo/redo โ€” that is @oh-just-another/history, an ephemeral linear stack of edits. Versioning is about durable, named snapshots that branch and merge.

Snapshot storeโ€‹

SnapshotStore is the system-of-record for the version tree. It starts on the "main" branch (DEFAULT_BRANCH_ID). capture() takes a CaptureRequest (scene, author, message, optional branchId) and returns an immutable Snapshot; the store generates id, parent, and timestamp. branch() takes a BranchRequest (name, fromVersion) and forks a new Branch from any snapshot. Ids are branded VersionId / BranchId, constructed via versionId() / branchId().

import {
SnapshotStore,
diffScenes,
isEmptyDiff,
serializeStore,
} from "@oh-just-another/versioning";

const store = new SnapshotStore(); // starts on "main"

const v1 = store.capture({
scene,
author: { id: "u1", name: "Ada" },
message: "init",
});
const feature = store.branch({ name: "feature", fromVersion: v1.id });

const diff = diffScenes(sceneA, sceneB);
if (!isEmptyDiff(diff)) console.log(diff.elements.added);

const json = serializeStore(store); // persist with the host's storage of choice

Diffโ€‹

diffScenes(before, after) returns a SceneDiff that splits each part of the scene (elements, links, layers, annotations) into added, removed, and modified id lists via DiffCategory. isEmptyDiff(diff) reports whether anything changed.

Mergeโ€‹

For divergent branch heads the package exposes findCommonAncestor, threeWayMerge, mergeBranchHeads, and resolveConflict, plus the Conflict, SceneConflict, MergeReport, and ConflictResolution types.

Editor bridge and serializationโ€‹

captureFromEditor and restoreSnapshot (with EditorLike and CaptureOptions) connect a live editor to the store. Persistence helpers include serializeStore / stringifyStore / importStoreJson / importIntoStore for the whole tree, and serializeSnapshot / deserializeSnapshot for a single snapshot. The store is in-memory; wrap these helpers with localStorage, IndexedDB, or a server API of your choice.