deep-equal

A standalone port of Node's own assert.deepEqual algorithm, giving spec-accurate deep equality checks in Node and the browser alike.

Library
npm
v2.2.3
791stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
37/100Needs Attention
Development Activity4
Maintenance0
Community64
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
68/100Good
Architecture78
Code Quality80
Innovation58
Learning Curve55

deep-equal extracts the exact recursive comparison algorithm behind Node’s assert.deepEqual() into a standalone, dependency-injectable module that runs anywhere JavaScript runs, including browsers. Rather than reimplementing a simplified equality check, it mirrors the real internal semantics Node uses, tracking cyclic references through a side-channel, distinguishing boxed primitives, typed arrays, ArrayBuffers, SharedArrayBuffers, Dates, RegExps, and Map/Set collections, and offering both loose (==) and opts.strict (===) comparison modes.

It’s maintained as part of the inspect-js / ljharb ecosystem of small, spec-correct utility packages, and leans on sibling packages like is-array-buffer, which-typed-array, which-collection, and side-channel instead of hand-rolled type checks. That composition keeps each individual concern narrow and independently tested while the top-level deepEqual(a, b, opts) API stays a single function call with one option.

What You Get

  • A single deepEqual(a, b, opts) function that recursively compares objects, arrays, Maps, Sets, typed arrays, ArrayBuffers, Dates, RegExps, and boxed primitives
  • An opts.strict flag to switch between coercive (==) and strict (===) leaf comparisons, matching assert.deepEqual vs assert.deepStrictEqual
  • Cycle-safe comparison via an internal side-channel, so circular references in a or b don’t cause infinite recursion
  • Cross-realm and cross-engine correctness checks (boxed primitives, typed arrays, SharedArrayBuffer) built on dedicated is-*/which-* shim packages rather than ad hoc typeof/instanceof logic
  • Browser compatibility out of the box, with no Node-only APIs required at the call site

Common Use Cases

  • Powering assertion logic inside custom test helpers or matcher libraries that need Node-parity deep equality without requiring Node’s assert module
  • Comparing parsed configuration objects, API response payloads, or Redux/state-store snapshots for equality checks in application code
  • Deduplicating or diffing collections of objects (arrays, Maps, Sets) where reference equality is insufficient
  • Providing the underlying equality algorithm for other polyfill/shim packages (e.g. commonjs-assert) that need to match Node’s exact comparison semantics

Under The Hood

Architecture deep-equal is a single flat CommonJS module (index.js) built around one recursive internalDeepEqual function that layers comparisons by type: identical-value fast path, boxed-primitive check, primitive ==/=== fallback, then a full objEquiv pass for objects that checks Object.prototype.toString tags, arguments/Error/RegExp/Date special cases, typed arrays, Buffers, ArrayBuffers, SharedArrayBuffers, plain-object keys, and finally Map/Set collection equivalence via dedicated setEquiv/mapEquiv helpers. Cyclic references are handled through a side-channel-based “channel” object that records sentinel values for already-visited pairs before recursing, a pattern explicitly ported from Node’s own internal util/comparisons.js (the source comments cite the exact upstream commits). There’s no class hierarchy or dependency injection here — it’s a pure function library where an opts.strict flag threads through every recursive call to switch between loose and strict semantics.

Tech Stack The library is plain ES5-compatible CommonJS with no build step and an engines field down to Node >= 0.4. Rather than hand-rolling type detection, it composes a set of small, single-purpose shim packages by the same maintainer group (is-arguments, is-array-buffer, is-date-object, is-regex, is-shared-array-buffer, which-boxed-primitive, which-collection, which-typed-array, object-keys, object.assign, get-intrinsic, call-bound, side-channel, es-get-iterator), each providing a spec-accurate, cross-realm-safe check. Testing runs on tape with nyc coverage; linting uses eslint with @ljharb/eslint-config; publishing is gated by safe-publish-latest and npmignore; CI spans several GitHub Actions workflows testing across many Node major versions plus a post-test npm audit.

Code Quality The test suite (test/cmp.js, over 1,500 lines) exercises primitives, boxed types, arrays, typed arrays, Dates, RegExps, Buffers, ArrayBuffers, Maps, Sets, and cyclic-reference cases extensively, run through tape with an _tape.js harness. Intrinsics are accessed through cached callBound references rather than direct prototype method calls, a defensive style typical of the es-shims ecosystem that guards against prototype pollution. There are no TypeScript types or JSDoc annotations — this is intentionally plain, dependency-shimmed JavaScript — but linting is enforced as a pretest hook and CI runs the suite across a wide matrix of Node versions. Because the library performs no I/O, there’s no error-handling layer to speak of; correctness is enforced through defensive type checks rather than exceptions.

API Design The public surface is deliberately minimal: one function, deepEqual(a, b, opts), returning a boolean, with a single option (strict). There’s no configuration to learn beyond that flag, and the mental model maps directly onto what most JavaScript developers already know from Node’s assert.deepEqual/assert.deepStrictEqual. Its differentiator isn’t a richer feature set — unlike general-purpose “isEqual” utilities that add customizer callbacks — but spec-fidelity: it reproduces Node’s actual internal comparison algorithm rather than a simplified reimplementation, which is why other polyfill packages (such as commonjs-assert) reference this repo as their algorithmic source of truth.

Used by 9 apps in this directory

TypeScript
99%
Other

Activepieces

Automation · AI Assistants

24,298

Open-source AI automation platform that converts 280+ workflow integrations into MCP servers for LLMs, with no-code builders and TypeScript extensibility.

View details
92
Repo Health
85
Technical
64
Dependency
Built with
TypeScript99%
Updated today
Go
54%
Apache 2.0

Authgear

Authentication

2,028

Open-source, self-hostable authentication platform with passkeys, biometric login, SSO, MFA, and GraphQL admin API — a full Auth0/Clerk/Firebase alternative for SaaS and mobile apps.

View details
88
Repo Health
81
Technical
68
Dependency
Built with
Go54%
HTML25%
TypeScript18%
Updated 3 days ago
TypeScript
45%
Other

Convex Backend

Developer Tools · Databases

12,494

Open-source reactive database that lets developers build live-updating apps with pure TypeScript, strong consistency, and real-time subscriptions—no separate API layer required.

View details
87
Repo Health
82
Technical
68
Dependency
Built with
TypeScript45%
Rust43%
Updated 2 days ago
TypeScript
99%
AGPL 3.0

Karakeep

Bookmarks Archiving

28,871

Self-hosted bookmark manager that captures links, notes, images, and PDFs with AI tagging, full-text search, and automatic archiving.

View details
88
Repo Health
76
Technical
66
Dependency
Built with
TypeScript99%
Updated 1 weeks ago
TypeScript
38%
Apache 2.0

Label Studio

AI Development · Data Engineering

28,222

Label Studio is an open-source, multi-type data labeling platform that lets teams annotate images, text, audio, video, and time series data with a configurable XML-based UI and export annotations in formats ready for any ML framework.

View details
93
Repo Health
87
Technical
67
Dependency
Built with
TypeScript38%
JavaScript27%
Python25%
Updated today
TypeScript
94%
Other

OpenHands

AI Code Assistants · AI Development

86,377

The self-hosted developer control center for running AI coding agents — locally, in Docker, on VMs, or across cloud backends — with automation workflows for GitHub, Slack, and more.

View details
91
Repo Health
82
Technical
70
Dependency
Built with
TypeScript94%
Updated today
Rust
93%
Other

Tabby

AI Code Assistants

33,868

Self-hosted AI coding assistant — run GitHub Copilot-grade code completion on your own hardware with no cloud dependency.

View details
60
Repo Health
78
Technical
61
Dependency
Built with
Rust93%
Updated 2 months ago
TypeScript
80%
Other

twenty

CRM

56,361

The open-source CRM you build, ship, and version like the rest of your stack — with customizable objects, AI agents, and a TypeScript SDK.

View details
92
Repo Health
82
Technical
64
Dependency
Built with
TypeScript80%
MDX17%
Updated yesterday
TypeScript
85%
Other

Webiny JS

Ecommerce · Blogging · CMS

8,032

Open-source, self-hosted CMS on AWS serverless — a TypeScript framework you extend with code, not a product you configure through a UI.

View details
90
Repo Health
86
Technical
62
Dependency
Built with
TypeScript85%
JavaScript14%
Updated yesterday

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search