ProvenPin Install

microdiff object diff: working versions (tested 2026-10-16)

Diff nested objects and arrays with microdiff, asserting CREATE, REMOVE and CHANGE entries with their paths, and that identical inputs yield an empty diff offline.

passed7 passed · 0 failed2026-10-16 19:54 UTC
Status
passed
Last passed
2026-10-16 19:54 UTC
Tests
7 / 7
Language
TypeScript
Runtime
node v22.23.3
pinned versions3
microdiff@1.6.0@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38958328921

The code

Exactly the files that passed. Your agent can pull them with get_recipe("microdiff-object-diff") (install), or see them on GitHub.

package.json
{
  "name": "microdiff-object-diff",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --import tsx --test test/*.test.ts"
  },
  "dependencies": {
    "microdiff": "1.6.0"
  },
  "devDependencies": {
    "@types/node": "26.6.5",
    "tsx": "4.23.15"
  }
}
src/diff.ts
import diff from "microdiff";

export type DiffEntry = ReturnType<typeof diff>[number];
export type DiffType = DiffEntry["type"];
export type DiffPath = DiffEntry["path"];

export function diffObjects(before: unknown, after: unknown): DiffEntry[] {
  return diff(before, after);
}

export function entriesOfType(entries: DiffEntry[], type: DiffType): DiffEntry[] {
  return entries.filter((entry) => entry.type === type);
}

export function pathsOfType(entries: DiffEntry[], type: DiffType): DiffPath[] {
  return entriesOfType(entries, type).map((entry) => entry.path);
}
test/diff.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { diffObjects, entriesOfType, pathsOfType } from "../src/diff.ts";

test("identical nested objects produce an empty diff", () => {
  const before = { user: { id: "1", tags: ["a", "b"] }, active: true };
  const after = { user: { id: "1", tags: ["a", "b"] }, active: true };
  assert.deepEqual(diffObjects(before, after), []);
});

test("emits CREATE entries with paths for added keys", () => {
  const before = { user: { id: "1" } };
  const after = { user: { id: "1", email: "[email protected]" } };
  const result = diffObjects(before, after);
  assert.deepEqual(pathsOfType(result, "CREATE"), [["user", "email"]]);
  assert.equal(entriesOfType(result, "CREATE")[0].value, "[email protected]");
});

test("emits REMOVE entries with paths for deleted keys", () => {
  const before = { user: { id: "1", email: "[email protected]" } };
  const after = { user: { id: "1" } };
  const result = diffObjects(before, after);
  assert.deepEqual(pathsOfType(result, "REMOVE"), [["user", "email"]]);
});

test("emits CHANGE entries with paths for changed values", () => {
  const before = { total: 10, nested: { count: 1 } };
  const after = { total: 20, nested: { count: 2 } };
  const result = diffObjects(before, after);
  assert.deepEqual(pathsOfType(result, "CHANGE"), [["total"], ["nested", "count"]]);
  assert.deepEqual(entriesOfType(result, "CHANGE")[0], {
    type: "CHANGE",
    path: ["total"],
    value: 20,
    oldValue: 10,
  });
});

test("diffs arrays by index and reports the offending element", () => {
  const result = diffObjects({ list: [1, 2, 3] }, { list: [1, 9, 3] });
  assert.deepEqual(result, [
    { type: "CHANGE", path: ["list", 1], value: 9, oldValue: 2 },
  ]);
});

test("reports array growth as a CREATE at the appended index", () => {
  const result = diffObjects({ list: [1, 2] }, { list: [1, 2, 3] });
  assert.deepEqual(pathsOfType(result, "CREATE"), [["list", 2]]);
});

test("reports array shrink as a REMOVE at the dropped index", () => {
  const result = diffObjects({ list: [1, 2, 3] }, { list: [1, 2] });
  assert.deepEqual(pathsOfType(result, "REMOVE"), [["list", 2]]);
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.