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

compact-delta

v1.0.0

Published

Generic optimal binary delta compression - auto-picks the smallest encoding (copy/insert, Myers LCS, or raw). Zero dependencies, works in Node and the browser.

Readme

compact-delta

The only JS delta library that auto-picks the smallest encoding. Given an old base and a new target, it produces the smallest possible binary delta to send to a peer who already has the base — by trying several methods and emitting the winner. Zero dependencies. Works in Node (ESM + CJS) and the browser.

npm install compact-delta

Why

There is no single delta algorithm that wins for every kind of edit:

  • in-place substitutions → an LCS/Myers diff is smallest
  • block moves, copy/paste, repeats → a copy/insert (rsync-style) delta wins
  • a brand-new payload → no delta helps; sending it raw is best

Other libraries pick one algorithm. compact-delta runs every applicable method, measures the result, and emits the smallest — with a 1-byte tag so the decoder always knows how to read it. The choice is made by the numbers at runtime, not by the caller. Cheap short-circuits (identical / empty base) skip work up front.

This is optimal-in-practice: the smallest delta among proven methods, independent of the kind of edit.

Usage

All operations are callback-based (Node-style (err, result)), so the API is ready for an async backend (e.g. a future WebAssembly codec) without changing any call sites. The callback always fires asynchronously, exactly once.

ESM / TypeScript

import { encode, decode } from 'compact-delta';

encode(oldText, newText, (err, delta) => {
  if (err) throw err;
  // delta is a Uint8Array, ready to send
  decode(oldText, delta, (err2, restored) => {
    // restored === newText (as bytes)
  });
});

CommonJS

const { encode, decode } = require('compact-delta');

Browser (no bundler, opens over file://)

<script src="./dist/compact-delta.umd.js"></script>
<script>
  compactDelta.encodeString('hello world', 'hello brave world', (err, delta) => {
    compactDelta.decodeString('hello world', delta, (err2, text) => console.log(text));
  });
</script>

API

encode(base, target, [optionsOrMethod], callback)        // cb(err, Uint8Array)
decode(base, delta, callback)                            // cb(err, Uint8Array)
encodeString(base, target, [optionsOrMethod], callback)  // cb(err, Uint8Array)
decodeString(base, delta, callback)                      // cb(err, string)
tryEncode(base, target, [optionsOrMethod], callback)     // cb(err, { method, delta, worthwhile, size, raw, ratio })
inspect(base, target, callback)                          // cb(err, { method, size, raw, ratio, candidates })

isRaw(deltaBytes)   // → boolean  (synchronous — reads only the method tag)
METHODS             // { RAW: 0, BYTEDIFF: 1, LCS: 2 }

base/target accept Uint8Array | string. The callback is always the last argument and always fires asynchronously. Full TypeScript declarations bundled.

Forcing a method

By default the encoder runs every method and picks the smallest. If you know one method always wins for your data, force it (skipping the others). Pass a method name or options object before the callback:

encode(base, target, cb)                              // auto — try all
encode(base, target, 'bytediff', cb)                  // force bytediff
encode(base, target, { method: 'lcs' }, cb)           // object form
encode(base, target, { method: 'bytediff', strict: true }, cb)

A forced method still falls back to RAW if its delta would be larger than the full target (cheap length check). strict: true sends it verbatim regardless. The method tag travels in the delta, so a forced delta decodes like any other.

Deciding whether a delta is worth sending

tryEncode(oldText, newText, (err, r) => {
  if (r.worthwhile) send(r.delta);     // a delta method beat the full target
  else sendFullViaGzip(newText);       // RAW won — delta didn't help
});

Inspecting the decision

inspect(offerSdp, answerSdp, (err, info) => {
  // info = { method: 'bytediff', size: 104, raw: 439, ratio: 0.237,
  //          candidates: { raw: 440, bytediff: 104, lcs: 128 } }
});

Wire format

Every delta is [ 1-byte method tag ][ payload ]:

| tag | method | payload | strong at | | ---- | -------- | --------------------------- | -------------------------------- | | 0x00 | RAW | the target, verbatim | brand-new content (safety floor) | | 0x01 | BYTEDIFF | COPY/INSERT op stream | moves, copy/paste, repeats | | 0x02 | LCS | Myers diff, binary-encoded | in-place substitutions |

Because the method is self-describing, adding a method later does not break old deltas — old decoders still read old tags.

Guarantees

  • Reversible: decode(base, encode(base, target)) reproduces target, for any bytes.
  • Bounded: a delta is never larger than target.length + 1 (the RAW floor).
  • Content-agnostic: no assumptions about the data (SDP, JSON, anything).
  • Cross-realm safe: accepts Uint8Array from any realm (worker, iframe).

Algorithms

  • BYTEDIFF — Rabin-Karp rolling hash builds an anchor map of the base; the target is scanned in linear time, matches are verified byte-for-byte and extended greedily. Output is a varint-encoded COPY/INSERT stream.
  • LCS — Myers' O(ND) diff over the byte sequences, then a compact binary encoding (EQUAL/INSERT/DELETE with varint lengths) — not the verbose unified-diff text format.

Development

npm run build   # regenerate dist/ from src/compact-delta.js
npm test        # core suite + format-interop suite

Single source of truth: src/compact-delta.js (ESM). build.cjs derives the UMD build. Tests cover correctness, binary/unicode, 500 randomized fuzz cases across all edit types, a per-edit-type benchmark proving the selector picks the right winner, and cross-format byte-identity.

License

Apache-2.0