<br />
  <h1 align="center">ᯓ𝘁𝗿𝗮𝘃𝗲𝗿𝘀𝗮𝗯𝗹𝗲/𝘀𝗰𝗵𝗲𝗺𝗮-𝗱𝗲𝗲𝗽-𝗲𝗾𝘂𝗮𝗹</h1>
<br />

<p align="center">
Re-use your schema definitions to derive super fast, in-memory <b>deep equal</b> functions (with even faster <em>compiled</em> deep equal functions coming soon!)
</p>

<div align="center">
  <img alt="NPM Version" src="https://img.shields.io/npm/v/%40traversable%2Fschema-deep-equal?style=flat-square&logo=npm&label=npm&color=blue">
  &nbsp;
  <img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-5.5%2B-blue?style=flat-square&logo=TypeScript&logoColor=4a9cf6">
  &nbsp;
  <img alt="License" src="https://img.shields.io/static/v1?label=License&message=MIT&labelColor=59636e&color=838a93">
  &nbsp;
  <img alt="npm" src="https://img.shields.io/npm/dt/@traversable/schema-deep-equal?style=flat-square">
  &nbsp;
</div>

<div align="center">
  <!-- <img alt="npm bundle size (scoped)" src="https://img.shields.io/bundlephobia/minzip/%40traversable/schema-deep-equal?style=flat-square&label=size">
  &nbsp; -->
  <img alt="Static Badge" src="https://img.shields.io/badge/%F0%9F%8C%B2-tree--shakeable-brightgreen?labelColor=white">
  &nbsp;
  <img alt="Static Badge" src="https://img.shields.io/badge/ESM-supported-2d9574?style=flat-square&logo=JavaScript">
  &nbsp;
  <img alt="Static Badge" src="https://img.shields.io/badge/CJS-supported-2d9574?style=flat-square&logo=Node.JS">
  &nbsp;
</div>

<br />
<br />


## Overview

- An "deep equal" function" is a function that accepts 2 values, and returns a boolean indicating whether the values
are made up of the same component parts.

- The `@traversable/schema-deep-equal` package can be used in 2 ways: 

1. As a side-effect import, which will install a `.equals` method to all schemas. 

2. To derive a deep equal function from a schema recursively, by walking the schema's AST

## Notable features

### Portable

Derived deep equal functions are "isomorphic" -- JS-speak for "works on both the client and on the server".

That means you can use `@traversable/schema-deep-equal` anywhere: in the browser (they work great with state
libraries that use an equality function to determine when to re-render!), in a BFF-architecture, with
CloudFlare workers -- anywhere.

### Performance

Our deep equal functions are:

- **3-4x faster than `node:assert/deepStrictEqual`**, and 
- **4-6x faster than `lodash.deepEqual`**

If you'd like to check our math, the benchmarks are public and available [here](https://github.com/traversable/schema/tree/main/benchmarks).

### Drop-in replacement

- Deep equal functions generated by `@traversable/schema-deep-equal` have been thoroughly 
    **fuzz-tested against millions of randomly generated inputs** 
    (via [`fast-check`](https://github.com/dubzzz/fast-check)) to make the transition
    seamless for our users

### Quick Start

You can install `.equals` on all schemas with a single line:

#### Example

```typescript
import { t } from '@traversable/schema'
import '@traversable/schema-deep-equal/install'
//      ↑↑ importing `@traversable/schema-deep-equal/install` installs `.equal` on all schemas

const Schema = t.object({
  abc: t.boolean,
  def: t.optional(t.number.min(3)),
})

let x = { abc: true, def: 10 }
let y = { ...x }
let z = { ...x, abc: false }

console.log(Object.is(x, y))     // => false 😭

console.log(Schema.equals(x, y)) // => true  😌
console.log(Schema.equals(y, z)) // => false 😌
```

### Usage

If you'd prefer not to install `.equals` to all schemas, use `Eq.fromSchema` 
(or you can import `fromSchema` directly, if you're bundle-phobic).

#### Example

```typescript
import { t } from '@traversable/schema'
import { Eq } from '@traversable/schema-deep-equal'

const Schema = t.object({
  abc: t.boolean,
  def: t.optional(t.number.min(3)),
})

const equalsFn = Eq.fromSchema(Schema)

let x = { abc: true, def: 10 }
let y = { ...x }
let z = { ...x, abc: false }

console.log(Object.is(x, y))  // => false 😭

console.log(equalsFn(x, y))   // => true  😌
console.log(equalsFn(y, z))   // => false 😌
```
