Skip to content

refactor: cut the hand-rolled deepEqual and dead scaffolding - #67

Merged
btravers merged 1 commit into
mainfrom
chore/ponytail-audit-cuts
Aug 12, 2026
Merged

refactor: cut the hand-rolled deepEqual and dead scaffolding#67
btravers merged 1 commit into
mainfrom
chore/ponytail-audit-cuts

Conversation

@btravers

Copy link
Copy Markdown
Contributor

A ponytail audit of the whole tree, applied. +25 / −231 lines, no new dependencies.

The one decision to make

equals now delegates to node:util's isDeepStrictEqual instead of a 172-line hand-rolled traversal. Every case equal.spec.ts pins passes against it unchanged — bigint, Set/Map by contents, nested key order, typed arrays and ArrayBuffer bytewise, RegExp, Date, and both cyclic-value tests (including the Set-matching poison cases).

Two consequences, both in the changeset:

  • This makes the package Node-only. A browser or edge bundle without a node:util shim will no longer resolve it. There is no browser field today and nothing else imports a node: builtin, so this is the first such constraint. If browser consumers matter, this commit is the one to drop.
  • +0 and -0 now compare unequal (Object.is) where SameValueZero made them equal. No test pinned it.

The rest

CutWhy
Two of three JSON-LD blocks in the docs headWebSite and Organization restated title/url/logo VitePress already emits; "entity" is not an Organization
test:types script / turbo task / package scriptCI runs format, lint, typecheck, test, knip, build — and typecheck already runs the .test-d.ts pass. Confirmed against btravstack/config's ci-reusable.yml
IsAtLeastAsWideAsInlined at its two uses in IsNarrowLiteral
RootInstance's duplicate intersectionNow ConstructedInstance<string, S, A> — same type, one definition
schemaOfOne call site; inlined into shape()
Array.isArray(values) in discriminantValueszod v4 gives a Set for z.literal(...).values and undefined for z.enum(...).values — measured, no schema reached it

Tried and reverted

A shared root vitest.shared.ts replacing four byte-identical configs. Tests ran fine, but knip discovers spec files through each package's own vitest config, so consolidating made it report all 16 spec files and 5 devDependencies as unused. Teaching knip costs more config than the 21 duplicate lines it saves.

Verification

Full gate green in gate order: format --check, lint, typecheck (all four billing-domain steps, both compilers, plus the emitted-.d.ts check), 179 + 18 tests, knip, build.

The declaration-emit acceptance rules were re-measured rather than assumed: zeroGeneratedKeys< / ImmutableKeys< in the consumer emit set, and the RootInstance alias made index.d.mts47 bytes smaller (40,768 → 40,721), measured by building both ways.

Not cut, checked and justified in the audit: freeze.ts's schema-directed passthrough walk (every branch is spec-pinned, and removing it re-freezes objects the caller still owns), the *Src alias block in entity.ts, the ten top-level type re-exports in index.ts, and the double-compiler emit gate.

`equals` delegates to `node:util`'s `isDeepStrictEqual` instead of a 172-line
traversal. Every case `equal.spec.ts` pins passes against it unchanged —
bigint, Set/Map by contents, nested key order, typed arrays and ArrayBuffer
bytewise, RegExp, Date, and both cyclic-value tests — with one difference:
`+0`/`-0` now compare unequal (Object.is) where SameValueZero made them equal.
No test pinned that. The import makes the package Node-only.
Also removed, all verified against the full gate:
- two of the three JSON-LD blocks in the docs head; `WebSite` and
`Organization` restated title/url/logo VitePress already emits
- the `test:types` script/turbo task/script triple — CI runs format, lint,
typecheck, test, knip, build, and `typecheck` already runs the `.test-d.ts`
pass
- `IsAtLeastAsWideAs`, inlined at its two uses in `IsNarrowLiteral`
- `RootInstance`, now `ConstructedInstance<string, S, A>` rather than a second
spelling of the same intersection — measured 47 bytes SMALLER in the emitted
`index.d.mts`, with zero `GeneratedKeys<`/`ImmutableKeys<` in the consumer
emit set
- `schemaOf`, inlined at its one call site in `shape()`
- the `Array.isArray(values)` branch in `discriminantValues`: zod v4 gives a
Set for `z.literal(...).values` and `undefined` for `z.enum(...).values`, so
no schema reached it
A shared vitest config was tried and reverted: knip discovers spec files
through each package's own config, so consolidating reported all 16 spec files
and 5 devDependencies as unused.
CopilotAI lite review requested due to automatic review settings August 12, 2026 18:54

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors @btravstack/entity to remove dead scaffolding and replace the hand-rolled deep equality implementation with Node’s node:utilisDeepStrictEqual, while also pruning unused scripts/tasks and a few type/util helpers.

Changes:

  • Replace the previous deepEqual traversal with node:util’s isDeepStrictEqual for Entity#equals, and update tests accordingly (making the package Node-only).
  • Remove the test:types turbo task and package scripts, relying on the existing typecheck pipeline to run the .test-d.ts pass.
  • Inline/remove small helpers and simplify a few internal types/utilities (schemaOf, IsAtLeastAsWideAs, RootInstance aliasing).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
turbo.jsonRemoves the test:types task from the turbo pipeline.
packages/entity/src/union.tsRemoves an unreachable discriminant .values array fallback (zod v4 measured behavior).
packages/entity/src/types.tsSimplifies RootInstance to reuse ConstructedInstance<string, S, A>.
packages/entity/src/shape.tsInlines schemaOf behavior using isFieldSpec for unwrapping field specs.
packages/entity/src/field.tsDeletes schemaOf helper (now inlined at call site).
packages/entity/src/equal.tsDeletes the hand-rolled deep equality implementation.
packages/entity/src/equal.spec.tsSwitches equality spec assertions to use node:utilisDeepStrictEqual.
packages/entity/src/entity.tsImplements equals via isDeepStrictEqual and updates the rationale doc comment.
packages/entity/package.jsonRemoves test:types script (keeps .test-d.ts under typecheck).
package.jsonRemoves root-level test:types script.
docs/.vitepress/config.tsRemoves redundant JSON-LD blocks from the docs head.
CLAUDE.mdUpdates architecture notes to reflect the removal of equal.ts and Node-only equality.
.changeset/lazy-pans-brake.mdDocuments the Node-only change and the +0 vs -0 equality behavior change.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@btravers
btravers merged commit c7fddb4 into mainAug 12, 2026
14 checks passed
@btravers
btravers deleted the chore/ponytail-audit-cuts branch August 12, 2026 18:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@btravers