|
| 1 | +# @opencode-ai/httpapi-codegen |
| 2 | + |
| 3 | +Build-time source generation for domain-oriented Effect APIs derived from `HttpApi` and Effect Schema contracts. |
| 4 | + |
| 5 | +The package is private while its API is explored. Its tests are the executable specification for the generator. It must remain independent of OpenCode Core and use synthetic `HttpApi` fixtures. |
| 6 | + |
| 7 | +## Settled rules |
| 8 | + |
| 9 | +- Flatten path, query, header, and payload fields into one input object. |
| 10 | +- Reject duplicate field names across input channels. |
| 11 | +- Emit no method argument for zero fields, an optional object when every field is optional, and a required object when any field is required. |
| 12 | +- Unwrap exact `{ data: A }` success envelopes. |
| 13 | +- Map no-content success to `void`. |
| 14 | +- Preserve other single success values. |
| 15 | +- Reject ambiguous multiple-success contracts. |
| 16 | +- Expose streaming success as `Stream`, not `Effect<Stream>`. |
| 17 | +- Reject schemas whose wire/domain transformation cannot be generated exactly. |
| 18 | +- Map transport, unexpected-status, and response-decoding failures to one stable generated `ClientError`. |
| 19 | +- Generate only the Effect API initially; Promise runtime ownership, cancellation, and stream adaptation are deferred. |
| 20 | +- Commit generated source for review; CI regenerates and fails when the worktree changes. |
| 21 | +- Track generated files in `.httpapi-codegen.json` so regeneration removes only stale files previously owned by the generator. |
| 22 | + |
| 23 | +## Boundary |
| 24 | + |
| 25 | +This package generates only the remote API derived from `HttpApi`. It does not generate embedded implementations or embedded-only capabilities. The OpenCode integration composes two distinct total objects: |
| 26 | + |
| 27 | +- A remote object containing the generated HTTP capabilities. |
| 28 | +- An embedded object implementing the shared shape against local services and adding embedded-only capabilities. |
| 29 | + |
| 30 | +The embedded object may be a structural superset of the remote object, but the constructors and concrete result types remain distinct. |
| 31 | + |
| 32 | +Codegen generates every endpoint in the `HttpApi` it receives. OpenCode owns the product decision by composing the exact remote API before invoking the generator; the generic package has no endpoint filtering policy. |
| 33 | + |
| 34 | +The public `generate(Api, { directory })` operation is an Effect requiring `FileSystem`. Internally it composes a pure `compile(Api)` phase with `write(output, directory)`. Compiler tests inspect virtual files directly; writer tests use `FileSystem.makeNoop`. |
| 35 | + |
| 36 | +Generation formats TypeScript with Prettier before writing. Output paths are flat, unique, and checked against traversal, reserved manifest names, and existing symbolic links. |
| 37 | + |
| 38 | +Generated source starts with one self-contained module per `HttpApiGroup`, plus root client and index modules. Schema dependencies may be duplicated across group modules. Cross-group schema partitioning is deferred until measured output or bundle cost requires it. |
| 39 | + |
| 40 | +Codegen preserves group and endpoint identifiers exactly. The composed remote `HttpApi` owns public names such as `session` and `get`; the generator performs no prefix stripping, casing conversion, or public-name annotation mapping. |
0 commit comments