Skip to content

Spec 016 T018-T020: the API description, generated from the contract - #708

Merged
adamjohnwright merged 3 commits into
mainfrom
spec016/t018-generator-v2
Oct 27, 2026
Merged

adamjohnwright merged 3 commits into
mainfrom
spec016/t018-generator-v2

Conversation

@adamjohnwright

Copy link
Copy Markdown
Contributor

Replaces #707, with its review's findings fixed (second and third commits):

  • Path variables declared. Each templated path now declares its variables, as OpenAPI requires. Redocly's spec rules found 70 errors and now pass (@redocly/cli 2.71.1).
  • Clashing names fail. Component names that would clash once made valid now fail the generator, instead of leaving one schema for two.
  • Locale-independent order. Schemas sort by code unit, the same in every locale.
  • Stricter route check. It reads the generator's own route table, not a regex over the source.
  • Knip entry. Knip takes the route table as an entry, since the generator reads it by path: the dead-code check caught it once the regex read went.
  • Counts corrected: 91 routes on 90 paths (one path is both GET and POST), 79 of them not yet in the contract.

That review also checked the description against the recordings: all 195 recorded answers of the twelve described routes validate (ajv 2020-12), and one entry given an extra field fails them.

Spec 016 User Story 4: an OpenAPI description generated from the contract, not maintained by hand. Java's own description lists most answers as a generic object.

  • projects/contract/routes.ts: the route table, the interface Routes. It maps each "METHOD /path", as the service's registry has it, to its 200 answer: twelve search routes for now.
  • tools/contract/generate.ts (ts-json-schema-generator 2.9.0, a dev dependency) writes projects/contract/openapi.json:
    • an OpenAPI 3.1 document of all 91 routes the content service serves (90 paths);
    • the twelve the contract describes come with their answer schemas, and the other 79 are marked x-contract: "not yet";
    • the search entry is oneOf its six kinds (research R4: no single tag tells them apart), and a Java long is integer/int64;
    • a generic instance's name is made a valid component name (GroupedResult_SearchEntry);
    • it generates in about 1.7 s, the same bytes every run, and writes only when run as a script.
  • tools/contract/generate.spec.ts:
    • T019: every contract route is one the service serves, and every served route is listed. Shown failing on a row for a route the registry lacks.
    • T020: the committed file equals what the generator writes. Shown failing on a contract field renamed without regenerating.
  • Small changes: tools/load.spec.ts gains contract. The generated file is in .prettierignore, since the up-to-date check holds it instead.

Lock: it gains the generator, commander, safe-stable-stringify and a hoisted glob. With the hoisting, one transitive copy of brace-expansion goes from 5.0.9 to 5.0.12, within its range. Pushed with LOCKFILE_BUMP=1.

Preflight passes. The first push's smoke run had three diagram tests time out while other container builds loaded the machine; they pass on their own (9/9) and in this push.

🤖 Generated with Claude Code

adamjohnwright and others added 3 commits October 27, 2026 02:55
tools/contract/generate.ts (ts-json-schema-generator 2.9.0) writes
projects/contract/openapi.json, an OpenAPI 3.1 document of every route the
content service serves: the twelve search routes the contract's route
table (projects/contract/routes.ts) describes, with their answers, and the
78 others marked not yet. The search entry is oneOf its six kinds; a Java
long is int64. generate.spec.ts holds the table to the registry and the
committed file to what the generator writes; each shown failing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e counts

Each templated path declares its variables, as OpenAPI requires (Redocly's
spec rules now pass). Component names that would clash once made valid
fail the generator rather than leaving one schema for two; schemas sort by
code unit, the same in every locale; the route check reads the generator's
own table, not a regex over the source. The description has 91 routes on
90 paths, 79 not yet in the contract.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generator reads projects/contract/routes.ts by path, which knip cannot
follow; without the entry it counts the route table, and the types only it
uses, as dead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adamjohnwright
adamjohnwright merged commit 2ea0fd0 into main Oct 27, 2026
8 checks passed
@adamjohnwright
adamjohnwright deleted the spec016/t018-generator-v2 branch October 27, 2026 12:17
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.

1 participant