deep-equal
A standalone port of Node's own assert.deepEqual algorithm, giving spec-accurate deep equality checks in Node and the browser alike.
Repository Health
Technical Analysis
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.strictflag to switch between coercive (==) and strict (===) leaf comparisons, matchingassert.deepEqualvsassert.deepStrictEqual - Cycle-safe comparison via an internal side-channel, so circular references in
aorbdon’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 hoctypeof/instanceoflogic - 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
assertmodule - 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
Activepieces
Automation · AI Assistants
Open-source AI automation platform that converts 280+ workflow integrations into MCP servers for LLMs, with no-code builders and TypeScript extensibility.
Authgear
Authentication
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.
Convex Backend
Developer Tools · Databases
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.
Karakeep
Bookmarks Archiving
Self-hosted bookmark manager that captures links, notes, images, and PDFs with AI tagging, full-text search, and automatic archiving.
Label Studio
AI Development · Data Engineering
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.
OpenHands
AI Code Assistants · AI Development
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.
Tabby
AI Code Assistants
Self-hosted AI coding assistant — run GitHub Copilot-grade code completion on your own hardware with no cloud dependency.
twenty
CRM
The open-source CRM you build, ship, and version like the rest of your stack — with customizable objects, AI agents, and a TypeScript SDK.
Webiny JS
Ecommerce · Blogging · CMS
Open-source, self-hosted CMS on AWS serverless — a TypeScript framework you extend with code, not a product you configure through a UI.