Skip to content

docs: correct snippets and pointers left by the Diataxis split - #23

Merged
btravers merged 2 commits into
mainfrom
docs/fix-restructure-fallout
Aug 7, 2026
Merged

docs: correct snippets and pointers left by the Diataxis split#23
btravers merged 2 commits into
mainfrom
docs/fix-restructure-fallout

Conversation

@btravers

@btravers btravers commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

A review of #22 turned up eight defects, all introduced or left behind by the restructure. No runtime behaviour changes; the only src/ edit is a docstring pointer.

Snippets that would not compile if copied

  • docs/how-to/http-contract.md called converter.convert(schema, { strategy: "input" }). @orpc/zod's converter takes the direction as a bare string — as the type-checked packages/entity/src/contract.spec.ts:28 already spells it — and returns a [jsonSchema, optional] tuple, which the snippet now destructures.
  • docs/how-to/model-an-aggregate.md read order.customer.shout from a Customer declared without the computed option. The example came from nesting.spec.ts, where Customer does declare it; the restructure dropped the options object and kept the usage. Restored the option rather than deleting the usage — the JSON.stringify round-trip comment depends on it.
  • docs/how-to/persist-and-rehydrate.md used the schema value OrgId in type position. Now z.infer<typeof OrgId>, as the other guides spell it.

Entity.* vs SomeEntity.*

factory, factoryAsync and make are statics on a declared entity class; the exported Entity builder carries only union. Both docs/reference.md and the README entry-point table spelled them Entity.*, indistinguishable from the genuine Entity.union two sections away — so Entity.make(row) reads as valid and fails with TypeError: Entity.make is not a function. Now SomeEntity.*, matching the spelling extend already used.

An id generator that breaks on the tenth call

docs/how-to/test-domain-logic.md built `…00000000000${(n += 1)}`. The last UUID group is 12 hex characters only while n <= 9; on the tenth createOrg(...) the group becomes 13, z.uuid() rejects, and the factory returns Err(InvalidEntity) — so a downstream .getOrThrow() fails for a reason unrelated to what the test is exercising. Now String((n += 1)).padStart(12, "0").

Pointers the split invalidated

  • CONTRIBUTING.md's binding "Design rules" section pointed at packages/entity/README.md for the public behaviour; that file is now a short npm card. Repointed at docs/reference.md and docs/explanation.md.
  • packages/entity/src/freeze.ts's docstring ended "the README says so" about the live-mutable-object carve-out. That statement now lives at docs/explanation.md. Per the repo convention that these comments are load-bearing pointers rather than decoration, repointed.

The changeset claim

.changeset/docs-diataxis.md asserted "Nothing was discarded", which would have shipped verbatim into the CHANGELOG and was not accurate. Rather than only soften it, this restores the three things the review identified as lost:

  • the computed-vs-getter rule and decision table → docs/explanation.md
  • the immutability compile-error / TypeError examples → docs/explanation.md
  • the factoryAsync usage example → docs/reference.md

The sentence is still dropped: the restored sections are what was verified missing, and the claim covered more than that.

Verification

Full gate green — format --check, lint, typecheck (all three passes), test (120 passed), knip, build.

The gate does not type-check documentation snippets, so the changed ones were checked separately: a scratch module under packages/entity/src reproducing the aggregate declaration and usage, both converter calls, the repository signature, and the id generator compiles clean under the project's tsc. The scratch file is not part of this branch.

Not changed

The how-to guides reference branded schemas (OrgId, Slug, CustomerId, Upper, …) that no snippet defines — the preamble blockquotes cover imports only. It is consistent across all four guides and reads as deliberate shorthand, so it is left alone here, but it does mean "make every snippet's imports explicit" (08a98a2) stops short of the domain vocabulary. Worth a follow-up if the intent was fully copy-pasteable examples.

🤖 Generated with Claude Code

Review of #22 turned up eight defects, all introduced or left behind by the
restructure. Three would fail to compile if copied:

- `http-contract.md` called `converter.convert(schema, { strategy: "input" })`.
  `@orpc/zod`'s converter takes the direction as a bare string, as the
  type-checked `contract.spec.ts` already spells it, and returns a
  `[jsonSchema, optional]` tuple.
- `model-an-aggregate.md` read `order.customer.shout` from a `Customer`
  declared without the `computed` option the source spec gives it. Restore the
  option rather than delete the usage; the round-trip comment depends on it.
- `persist-and-rehydrate.md` used the schema value `OrgId` in type position.

`Entity.factory` / `factoryAsync` / `make` are statics on a declared entity,
not on the `Entity` builder, which carries only `union`. Both the reference
and the README table spelled them `Entity.*`, indistinguishable from the real
`Entity.union` two sections away. Use `SomeEntity.*`, as `extend` already did.

The test-domain-logic id generator interpolated a counter into a fixed run of
zeros, so the last UUID group grew to 13 characters on the tenth call and the
factory started returning `Err(InvalidEntity)` for a reason unrelated to the
test.

Repoint two references the split invalidated: CONTRIBUTING's design-rules
section and `freeze.ts`'s docstring both pointed at README sections that now
live in `docs/`.

Finally the changeset claimed nothing was discarded, which was not true and
would have shipped verbatim to the CHANGELOG. Restore what was missing --
the computed-vs-getter rule, the immutability compile-error examples, the
`factoryAsync` example -- and drop the claim, which covers more than was
verified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 7, 2026 10:38

Copilot AI 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 corrects documentation snippets, references, and pointers that were left incorrect after the Diátaxis documentation split (with no runtime behavior changes; only a docstring pointer in src/).

Changes:

  • Fix multiple docs snippets so they reflect the real API surface and compile when used as intended in the guides.
  • Clarify entry-point usage by switching misleading Entity.* references to SomeEntity.* in docs/README where appropriate.
  • Repair pointers invalidated by the split (CONTRIBUTING + freeze.ts docstring) and remove an inaccurate changeset claim.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Updates entry-point table to use SomeEntity.* instead of Entity.*.
packages/entity/src/freeze.ts Updates the docstring pointer from README to docs/explanation.md.
docs/reference.md Renames Entity.* headings to SomeEntity.* and restores/expands factoryAsync example.
docs/how-to/test-domain-logic.md Fixes the sample UUID generator to remain valid past 9 calls.
docs/how-to/persist-and-rehydrate.md Fixes OrgId type usage in the repository signature (z.infer<typeof OrgId>).
docs/how-to/model-an-aggregate.md Restores the computed option so the example matches its later usage.
docs/how-to/http-contract.md Fixes @orpc/zod converter usage (direction string + tuple return).
docs/explanation.md Restores explanation/examples around deep immutability and computed-vs-getter guidance.
CONTRIBUTING.md Repoints “Design rules” documentation references to the new docs locations.
.changeset/docs-diataxis.md Removes the inaccurate “Nothing was discarded” claim from the release text.
Suppressed comments (2)

docs/reference.md:89

  • Same issue as factory: the heading lists AsyncResult<Entity, InvalidEntity>, but the API returns AsyncResult<T, InvalidEntity> for the concrete entity class. Using SomeEntity in the return type matches the actual typing and avoids conflating the return type with the Entity builder.
### `SomeEntity.factoryAsync(generators)` → `(input) => AsyncResult<Entity, InvalidEntity>`

docs/reference.md:103

  • make returns a Result<T, InvalidEntity> for the concrete declared entity class, not Result<Entity, InvalidEntity>. Updating the heading avoids implying there is a runtime/type named Entity returned here.
### `SomeEntity.make(data)` → `Result<Entity, InvalidEntity>`

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/reference.md Outdated
Comment thread docs/explanation.md Outdated
The `Entity.*` -> `SomeEntity.*` pass renamed the headings but left
`Result<Entity, InvalidEntity>` in the return position, which is worse than
before: this PR gave `Entity` the specific meaning "the builder", and the
builder is not what comes back. `make<T>`, `factory<T>` and `factoryAsync<T>`
are all `this`-typed on the concrete class, so the result is that class.
`entity.update` had the same defect and is fixed with them.

Also drop the quoted engine message from the frozen-array example. V8 says
"Cannot add property 1, object is not extensible" rather than the string the
old README carried, and other engines word it differently again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@btravers
btravers merged commit 8c2485b into main Aug 7, 2026
13 checks passed
@btravers
btravers deleted the docs/fix-restructure-fallout branch August 7, 2026 11:52
Sign up for free to 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