Releases: gpu-cli/openapi-to-rust
v0.4.0
What's Changed
- fix(client): emit typed enum for const/enum on parameter schemas by @lightsofapollo in #13
Full Changelog: v0.3.0...v0.4.0
v0.3.0
What's Changed
- fix(generator): treat string
constas single-value enum (closes #10) by @lightsofapollo in #12
Full Changelog: v0.2.1...v0.3.0
v0.2.1
Full Changelog: v0.2.0...v0.2.1
v0.2.0
Breaking change. Generated method signatures change from HttpResult<T> to Result<T, ApiOpError<E>> so multi-response operations and typed error bodies work correctly. Closes #8.
What changed
ApiError<E>envelope always carriesstatus + headers + raw body, with optionaltyped: Option<E>populated when the body matched a declared schema. You can now inspect what the server actually sent without modifying the generated code.ApiOpError<E> = Transport(HttpError) | Api(ApiError<E>)is the new return-type wrapper for every generated operation method.- Per-operation error enums are emitted when an op declares non-2xx body schemas:
{Op}ApiError { Status400(BadRequestBody), Status404(NotFoundBody), … }. Ops with no declared error schemas fall back toApiOpError<serde_json::Value>so the body is still inspectable as JSON. - Always-on raw body capture — the response handler reads the body to a string before any typed parse, so deserialization failures preserve the bytes.
- Root-cause fix for the original collision in #8: the inline-response naming function now uses the response status code, so a 200 + 400 spec no longer overwrites the 200 schema with the 400 schema in the registry.
Why no all-responses enum
A single enum Response { Status200(_), Status400(_) } would force every caller to match every variant for every call and lose Result ergonomics. Successes are Ok(T); errors are typed Err(ApiOpError<E>).
Migration
The HttpError::Http { ... } variant and from_status helper are removed from generated code (replaced by ApiError<E>). The is_client_error / is_server_error helpers move to ApiError<E>.
Old:
let result: Result<Foo, HttpError> = client.foo().await;
match result {
Err(HttpError::Http { status, body, .. }) => { /* ... */ }
/* ... */
}New:
let result: Result<Foo, ApiOpError<FooApiError>> = client.foo().await;
match result {
Err(ApiOpError::Api(e)) => {
// e.status, e.headers, e.body always populated
// e.typed: Option<FooApiError> when the body matched a declared schema
}
Err(ApiOpError::Transport(e)) => { /* network/timeout */ }
/* ... */
}v0.1.15
Two follow-ups to issue #7 that surfaced after 0.1.14:
anyOfwith{"type": "null"}and 3+ variants previously panicked with"()" is not a valid Identbecause the null branch produced a phantom()type alias.analyze_anyof_unionnow filters{"type": "null"}variants up front, mirroring theoneOffix.oneOfwith an array variant whose items reduce toserde_json::Value(e.g.items: {}) previously emittedVec<SerdeJsonValue>. The generator now emitsVec<serde_json::Value>(andVec<Vec<serde_json::Value>>) as path tokens instead of mangling the::into a single ident.
Fixes #7.
v0.1.14
Fix oneOf with {"type": "null"} variants (#7).
Previously, an inline oneOf: [{"type": "null"}, {"type": "string"}] schema generated an untagged enum with a phantom SerdeJsonValue(SerdeJsonValue) variant — a non-existent type produced by mangling serde_json::Value into a single ident. anyOf already handled the same shape correctly.
oneOf now matches anyOf:
oneOf: [Type, null]reduces to the non-null type with the property marked nullable (Option<T>).oneOfwith 3+ variants including{"type": "null"}filters the null branch out instead of leaking it through.- The generator emits
serde_json::Valueas a path defensively, so any future analyzer path that pushes it as a union variant target stays valid Rust.
Fixes #7.
v0.1.3
What's New
Bug Fixes (#2)
- Resolve
$refparameter references — Parameters defined via$refincomponents/parametersare now properly resolved before extraction - Merge path-item-level parameters — Parameters defined at the PathItem level are now inherited by all operations on that path (operation-level params take precedence per the OpenAPI spec)
- Fix
urlvariable name collision — Renamed internal URL construction variable torequest_urlto avoid shadowing when an operation has a parameter namedurl
Improvements (#3)
- Use raw identifiers for Rust keywords — Fields like
typenow generater#typeinstead oftype_, producing more idiomatic Rust code
New Features
- Operation registry generator — New
registry_generatorthat emits static operation metadata (method, path, params, body, response schema) for CLI/proxy routing use cases - Robust YAML/JSON parsing — Handle integers exceeding i64/u64 range, lossy JSON fallback for specs with large numbers
- 50+ real-world OpenAPI specs — Added specs from Stripe, GitHub, Cloudflare, OpenAI, and more with download script and batch test harness
Breaking Changes
- Generated field names for Rust keywords changed from
type_tor#type(affects consumers of generated code) Info.versionis nowOption<String>instead ofString