PitchHut logo
Effortless journaling of file changes with deterministic replay and rollback.
Pitch

diff-journal is a lightweight Node.js library that enables append-only, diff-based journaling of file changes. It allows for deterministic replay, rollback to previous states, and unmatched auditability. Aimed at developers needing precise control over file versioning, it simplifies change tracking with immutable journal entries.

Description

diff-journal is a lightweight Node.js library designed to provide append-only, diff-based journaling of file changes, complete with features for deterministic replay, rollback, and robust auditability. This tool captures every change as an immutable journal entry, ensuring that all modifications are logged efficiently and audibly.

Key Features

  • Append-only: Every change is recorded as a permanent journal entry, ensuring the integrity of the change history.
  • Deterministic Replay: State can be rebuilt by strictly applying journal entries in the correct order, eliminating ambiguity in the reconstruction process.
  • Rollback Functionality: Users can revert files to any specified point in the change sequence, ensuring a reliable and straightforward rollback mechanism.
  • Auditable Changes: Each change is not only documented with its context (who made the change and why) but also stored as a unified diff, making it easier to review modifications.

Quickstart Example

To illustrate its usage, here’s a brief example that showcases how to implement diff-journal in an ESM JavaScript environment:

import { readFile } from "node:fs/promises";
import { join as pathJoin } from "node:path";
import { openDiffJournal } from "diff-journal";

const WORKSPACE_DIR = ".";
const JOURNAL_DIR = ".journal";
const FILE = "example.txt";
const ACTOR = "quickstart";

const journal = openDiffJournal({
  rootDir: WORKSPACE_DIR,
  journalDir: JOURNAL_DIR,
  strictReplay: true,
  snapshots: true
});

async function appendChange(current, intent, computeNext) {
  const before = current;
  const after = computeNext(before);

  await journal.append({
    file: FILE,
    actor: ACTOR,
    intent,
    before,
    after
  });

  return after;
}

let current = "";
current = await appendChange(current, "initial content", () => "Hello world\n");
current = await appendChange(current, "add a second line", (t) => `${t}Nice to meet you.\n`);

await journal.materialize(FILE);

console.log("=== CURRENT ===");
console.log(await readFile(pathJoin(WORKSPACE_DIR, FILE), "utf8"));

await journal.rollback(FILE, { seq: 1 });

console.log("=== ROLLBACK (seq=1) ===");
console.log(await readFile(pathJoin(WORKSPACE_DIR, FILE), "utf8"));

console.log("=== INSPECT ===");
console.log(await journal.inspect(FILE));

Running this sample will produce a materialized file (example.txt) reflecting the updates logged in the append-only journal (.journal).

Motivation and Use Cases

diff-journal addresses challenges faced with automatic file changes created by tools, pipelines, or AI systems. It emphasizes the need for automatic logging of changes, which should be auditable and reconstructable, along with a deterministic rollback mechanism. Intended use cases include automated file transformations, AI-assisted code generation, and audit-sensitive workflows, making it an invaluable tool across various development scenarios.

Built with strong guarantees for append-only semantics and deterministic behavior, diff-journal serves as a reliable solution for managing state changes effectively, without replacing existing filesystem operations or version control systems like Git.

0 comments

No comments yet.

Sign in to be the first to comment.