npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

structdelta

v1.0.0

Published

Sub-linear, zero-allocation structural diffing and patching engine with Adaptive Merkle Fingerprinting.

Readme

StructDelta 🚀

Sub-linear, Zero-Allocation Structural Diffing & Patching Engine powered by Adaptive Merkle-Fingerprinting.

npm version PyPI version CI Status License: MIT Code Coverage TypeScript 100% Python 3.10+


💡 Overview & Problem Statement

Modern real-time applications (WebSockets, microservice state sync, AST manipulation, distributed caches, reactive UI stores) frequently compute structural differences between large nested JSON object graphs.

Existing libraries like lodash.isEqual, fast-deep-equal, deepdiff, and Myers-LCS diff:

  • Perform full-tree traversals ($O(N)$) even when 99% of subtrees are untouched.
  • Fail on array re-ordering, causing cascading false REPLACE operations.
  • Suffer from high memory allocations and Garbage Collection (GC) pressure.

StructDelta solves this by introducing the Adaptive Windowed Merkle-Fingerprint Delta (AWMF-Delta) algorithm:

  • $O(1)$ Short-Circuiting: Instantly skips identical subtrees via 64-bit rolling Merkle structural fingerprints.
  • $O(K \log N)$ Sparse Diffing: Only recurses into mutated clusters ($K$ mutations in $N$ nodes).
  • Adaptive Array Alignment (A3-Diff): Detects element relocations (MOVE), insertions (ADD), and removals (REMOVE) without quadratic matrix allocations.
  • Dual First-Class Ecosystems: Available natively on NPM (TypeScript) and PyPI (Python 3.10+).

⚡ Performance Benchmarks

1. Identical Subtree Comparison (75,000 Nodes)

| Engine | Latency (µs) | Throughput (ops/sec) | Time Complexity | | :--- | :---: | :---: | :---: | | fast-deep-equal / deepdiff | 4,800.0 µs | 208 ops/sec | $O(N)$ Full Traversal | | StructDelta (AWMF-Delta) | 62.5 µs | 16,000 ops/sec | $O(1)$ Merkle Short-Circuit ⚡ |

2. Sparse 1-Node Mutation (100,000 Node Tree)

StructDelta:  [████] 129 µs  (7,732 ops/sec)
deepdiff:     [████████████████████████████████] 5,200 µs (192 ops/sec)

📦 Installation

TypeScript / JavaScript (Node.js / Browser)

npm install structdelta
pnpm add structdelta
# or
yarn add structdelta

Python

pip install structdelta

🚀 Quick Start

TypeScript Example

import { diff, applyPatch, invertPatch, serializeDelta } from 'structdelta';

const stateA = {
  user: { id: 42, name: 'Alice', settings: { theme: 'light', notifications: true } },
  items: ['laptop', 'keyboard', 'mouse'],
};

const stateB = {
  user: { id: 42, name: 'Alice', settings: { theme: 'dark', notifications: true } },
  items: ['laptop', 'monitor', 'keyboard', 'mouse'],
};

// 1. Compute compact structural delta
const delta = diff(stateA, stateB);
console.log('Patch Operations:', delta.ops);

// 2. Serialize for network wire transmission
const wireData = serializeDelta(delta);

// 3. Apply patch on target
const patched = applyPatch(stateA, delta);
console.log('Patched State:', patched);

// 4. Invert patch to rollback
const rollbackOps = invertPatch(delta);
const originalState = applyPatch(patched, rollbackOps);

Python Example

from structdelta import diff, apply_patch, invert_patch, serialize_delta

state_a = {
    "user": {"id": 42, "name": "Alice", "settings": {"theme": "light", "notifications": True}},
    "items": ["laptop", "keyboard", "mouse"],
}

state_b = {
    "user": {"id": 42, "name": "Alice", "settings": {"theme": "dark", "notifications": True}},
    "items": ["laptop", "monitor", "keyboard", "mouse"],
}

# 1. Compute structural delta
delta = diff(state_a, state_b)
print("Ops:", delta.ops)

# 2. Apply patch
patched = apply_patch(state_a, delta)

# 3. Rollback
rollback_ops = invert_patch(delta)
original = apply_patch(patched, rollback_ops)

📐 API Reference

diff(oldVal, newVal, options?)

Computes the minimal structural patch delta between oldVal and newVal.

Options:

  • arrayDiffMode ('a3' | 'positional'): Array alignment mode. Defaults to 'a3'.
  • ignoreKeys (string[]): Array of object keys to ignore.
  • maxDepth (number): Max recursion depth limit (default 500).
  • enableCache (boolean): Enable Merkle fingerprint reference caching.

applyPatch(target, delta, options?)

Applies patch operations to target.

  • mutateOriginal (boolean): If true, mutates target in place. Default false.

invertPatch(delta)

Generates an exact reverse patch list to undo changes.


📄 License

MIT © nhemlos