chore: sync the spec and regenerate response types - #21
Merged
Conversation
`spec/openapi.json` was vendored before the API's response-typing work and
had 209 of 239 operations describing no response body. openapi-typescript
turns a bodyless operation into `responses: never`, and extracting a 200
body from that infers `unknown` - so most of this SDK's surface typed its
return values as `unknown`, which is the drift the 1.0 rewrite was meant
to end.
Copied the current spec from datamaker@next and ran `pnpm generate`:
- 178 operations gain a real response type (30 typed -> 209 of 240)
- components.schemas grows 15 -> 123
- GET /scenarios/jobs is new
Additive only. All 15 pre-existing schemas are byte-identical, so nothing
that compiles today stops compiling - hence a minor, not a major.
Verified with a type-level proof (not committed) asserting exact types
rather than assignability, since `unknown` and `never` both swallow a
loose assignability check and make such a test vacuous. It confirms
`GET /scenarios` yields Scenario[]; that the environment-variable
asymmetry survives generation (GET is an array of {key, value}, the
writes are a Record - collapsing them upstream would have broken exactly
one); and that PlanRun.files is optional rather than nullable. Run
against the OLD schema every one of those assertions fails, so the proof
is not vacuous.
31 operations stay untyped upstream on purpose and still resolve to
`unknown`: the Tosca/Jira/SAP pass-throughs, and the routes that return
credentials.
This does NOT extend the resource clients - dm.projects, dm.templates and
friends still cover what they covered before. The win here is in the
exported `paths` and `components` types; widening the clients is separate
work.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
spec/openapi.jsonwas vendored before the API's response-typing work: 209 of its 239 operations described no response body.That is not a cosmetic gap.
openapi-typescriptturns a bodyless operation intoresponses: never, and extracting a 200 body out of that infersunknown— so most of this SDK's surface typed its return values asunknown, which is precisely the drift the 1.0 rewrite existed to end.Copied the current spec from
datamaker@nextand ranpnpm generate.What changes
components["schemas"]GET /scenarios/jobsis new.minor, notmajor.Verification
Beyond the four CI steps, I wrote a type-level proof (scratch, not committed) and — importantly — checked it wasn't vacuous.
A naive assertion here is worthless: both
unknownandneverswallow a loose assignability check, soconst x: Body<...> = {...}passes against the old schema too. My first attempt at this proof did exactly that and told me nothing. The real proof asserts exact type identity:It confirms:
GET /scenariosyields exactlyScenario[].GETis{key, value}[], the writes are aRecord<string, string>. Had those been collapsed into one schema upstream, exactly one of these two assertions would fail.PlanRun["files"]isPlanRunFile[] | undefined— optional, not nullable./export/rest, still deliberately bodyless upstream, resolves tounknown— which is the mechanism this whole PR is about, demonstrated rather than asserted.Run against the old schema, assertions 1–3 all fail. Assertion 4 passes against both, correctly, since that route is bodyless in each.
pnpm generate:check— generated types match the specpnpm lint(tsc) — cleanpnpm test— 11/11pnpm build— ESM + CJS + DTSScope — what this does not do
It widens the exported
pathsandcomponentstypes, which consumers can use directly. It does not add methods to the resource clients:dm.projects,dm.templates,dm.sets,dm.keymaps,dm.maskingPoliciesanddm.plansstill cover exactly what they covered before, becauseresources.tshand-picks the schemas it exposes. There are now 108 more schemas available to build against; wiring them into ergonomic clients is a separate, larger piece of work worth its own PR.Still
unknown, on purpose31 operations remain deliberately untyped upstream: the 22 Tosca/Jira/SAP pass-throughs, whose bodies belong to those systems rather than to DataMaker, and 9 routes that return credentials and are kept out of the published contract (automators-com/datamaker#2882, #2916, #2919). The API now has a CI ratchet (automators-com/datamaker#2922) that stops any new operation from shipping bodyless, so this gap should not reopen.
datamaker-pyneeds the same backfill and has not had it.🤖 Generated with Claude Code