refactor!: remove encode(), leaving toJSON() as the only projection - #3
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR resolves an API naming mismatch in the entity instance surface by renaming the instance method encode() (which returned the stored/decoded shape) to toStored(), aligning the name with the data shape it actually returns and the make() round-trip it supports.
Changes:
- Renamed the instance method
encode()totoStored()across the implementation and type surface. - Updated internal uses (
toJSON(),equals(),update()) to delegate totoStored(). - Updated documentation, specs, and added root README documentation for the existing
entityNamestatic.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Replaced encode() references with toStored(), reframed round-trip guidance, and documented entityName usage. |
| packages/entity/src/types.ts | Updated the shared instance interface surface from encode() to toStored(). |
| packages/entity/src/equality.spec.ts | Updated equality test to use toStored() instead of encode(). |
| packages/entity/src/entity.ts | Renamed the instance method implementation to toStored() and updated internal call sites (toJSON, equals, update). |
| packages/entity/src/entity.spec.ts | Updated instance-method behavior tests to reflect toStored(). |
| packages/entity/src/decoded.spec.ts | Updated decoded/omitted/add behavior tests and round-trip test wording to use toStored(). |
| packages/entity/README.md | Updated package README method docs from encode() to toStored() and clarified entityName as _tag’s static counterpart. |
| .changeset/silly-donuts-smoke.md | Added a breaking-change changeset describing the rename and migration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
btravers
commented
Aug 6, 2026
btravers
force-pushed
the
refactor/encode-naming
branch
from
August 6, 2026 19:43
c8890ab to
f907363
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes the original rename approach. Per review, the method is removed
rather than renamed — the naming collision it was meant to fix disappears when
the method does not exist.
Why removal beats renaming
encode()andtoJSON()returned byte-identical data:Two public methods, one value — the alias
CONTRIBUTING.mdexists to prevent.toJSON()is the one that has to stay. It is not a name this package chose; itis the hook
JSON.stringifylooks for. Without it, serializing an entity walksown enumerable properties and leaks a subclass's own instance fields — the same
bug spread has, as the first line above shows. So
encode()was the removableone.
It was also genuinely misnamed: it returned the stored (
decoded) shapewhile the exported
Encoded<T>helper names the wire shape. For an entityusing
decoded: { omit, add }these differ —Encoded<typeof ApiKey>carriessecret, the projection carriesfingerprintand nosecret. That mismatch iswhy
decode(x.encode())never round-tripped, and the README now frames thepairing positively (
make(x.toJSON())) instead of apologising for a name.Changes
entity.ts—encode()deleted.toJSON,equalsandupdatenow routethrough a module-private
project, so the internals do not depend on aserialization hook a subclass is free to override.
types.ts—encode()removed fromBaseInstance; theDeepReadonlycomment updated to reference the one remaining projection.
entity.test-d.ts, both READMEs,CLAUDE.md— all call sites andprose updated (38 references).
entity.test-d.tsgains a@ts-expect-errorpinning thatencode()is gone.That assertion passing
tscis the proof the removal is complete.CLAUDE.mdcorrected while here: it said "Five source modules" and referencedencode();freeze.tsfrom fix: make entity data deeply immutable #7 makes six.Also:
entityNamedocumentedFinding 5's second half. It was tested but documented nowhere in the root
README. Added, with the reason all three tag spellings coexist without being
aliases:
_tagis instance-side and whatP.tag(...)matches;entityNameisthe only path for code holding the class and no instance; both derive from the
single
Entity(tag)declaration.Gate
format --check,lint,typecheck(both passes),test(76, 9 files),knip,build— all green. Rebased onto currentmain, so the earlierconflict with #7 is gone.