Commit 7899f57
feat(client): bind erased SDK return types to their spec contracts (#11929)
* feat(client): bind erased SDK return types to their spec contracts
`packages/client/src/index.ts` dropped the precise contract types at the SDK
boundary on a package that already depends on `@objectstack/spec`, so the types
were reachable and the `any` was forced by nothing.
Four spellings of the same erasure, all measured at head and all bound here:
32 `Promise<any>`, 5 `Promise<any[]>`, 4 `Promise<{ …any[]… }>`, and 14
fixed-shape `<T = any>` methods (8 on `ObjectStackClient`, 6 mirrored on
`ScopedProjectClient`) — 55 sites, of which 51 are bound and 4 are deliberate.
Each binding is the DECLARED return of the service method the route calls,
verified per method against the handler's emit rather than swept: four
federation methods are envelope-wrapped (`{ tables }`, not `RemoteTable[]`),
`security.explain` takes the `z.input` form its contract declares because no
parse runs on that path, and `search` has a same-named wrong type
(`SearchResult`) sitting one import away.
The fixed-shape generics become `<T extends X = X>`, not `<T = X>`: the default
alone closes the erasure only for an unannotated call, because TypeScript infers
`T` from the assignment's contextual type. Measured on the pin file.
`automation.create` / `automation.update` / `search` / `data.clone` keep
`Promise<any>` with a docblock each — they are missing CONTRACTS, not missing
annotations, and authoring one lands in `packages/spec`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019siH5jDmk5hrayvfyojUqR
* docs(api): repair the two client-sdk fences this narrowing falsifies
`content/docs/api/client-sdk.mdx` carries an UNMARKED ```typescript fence (no
`<!-- os:check -->`), so `check:skill-examples` never compiled it and CI could
not have caught this. Measured by extracting the fence verbatim into the
package's own test tsc program and diffing diagnostics with
`packages/client/src/index.ts` at this branch vs at origin/main: exactly two
diagnostics are INTRODUCED by the narrowing, both TS2345.
1. `run.runId` -> `resume(flowName: string, runId: string)`.
`AutomationResult.runId` is optional — a completed run carries none — so
the argument is `string | undefined`. Narrowed with `&& run.runId`.
2. `suggestions[0].id` -> `confirm(id: string)`.
`AudienceBindingSuggestion` is `Record<string, unknown>` by contract, so
the property reads as `unknown`. Wrapped in `String(...)`.
Both edits carry a one-line explanation, because each is the migration an
external consumer has to make and the page's job is to teach it.
Re-measured after the fix: 0 introduced diagnostics. Five diagnostics remain in
BOTH states (four `err is of type unknown` in the catch block, one unused local)
— pre-existing artifacts of compiling a doc snippet under strict settings it was
never written for, identical before and after, and not touched here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019siH5jDmk5hrayvfyojUqR
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 3689991 commit 7899f57
5 files changed
Lines changed: 460 additions & 80 deletions
File tree
- .changeset
- content/docs/api
- packages/client/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
400 | 400 | | |
401 | 401 | | |
402 | 402 | | |
403 | | - | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
404 | 406 | | |
405 | 407 | | |
406 | 408 | | |
| |||
438 | 440 | | |
439 | 441 | | |
440 | 442 | | |
441 | | - | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
442 | 447 | | |
443 | 448 | | |
444 | 449 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1351 | 1351 | | |
1352 | 1352 | | |
1353 | 1353 | | |
1354 | | - | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
1355 | 1360 | | |
1356 | 1361 | | |
1357 | 1362 | | |
| |||
0 commit comments