Skip to main content

Crate taskfast_codegen

Crate taskfast_codegen 

Source
Expand description

TaskFast OpenAPI spec tooling.

The authoritative spec lives at spec/openapi.yaml. The platform team evolves it against Elixir routes; clients generate from it. A small set of structural redundancies would cause progenitor to emit distinct Rust types for schemas that are semantically identical (e.g. multiple {error, message} objects under different names). This crate’s normalize_spec folds those aliases into a single canonical shape in memory, leaving the on-disk spec untouched.

Consumers:

  • cargo xtask sync-spec (binary) — writes a normalized artifact for inspection.
  • taskfast-client/build.rs — pipes the normalized YAML into progenitor.

§Rewrite rules

Today: every name in ERROR_ALIASES is a structural clone of #/components/schemas/Error. The normalizer:

  1. Asserts each alias is byte-for-byte structurally equal to Error (ignoring description/example doc-only fields) — drift fails loud.
  2. Rewrites every $ref: '#/components/schemas/<alias>' to point at #/components/schemas/Error.
  3. Removes the alias definitions from components.schemas.

Adding a new alias ⇒ append to ERROR_ALIASES. If a schema grows a real distinguishing field, remove it from ERROR_ALIASES; the drift check will refuse to normalize otherwise.

§Multipart strip

progenitor 0.9 can’t codegen multipart/form-data request bodies. Rather than maintain a patched fork, the normalizer drops operations whose request body declares only multipart variants — today that is POST /tasks/{task_id}/artifacts (uploadArtifact). The upload path is hand-rolled in taskfast-client using reqwest::multipart directly; the Artifact response schema still comes through codegen because it’s referenced by the surviving GET /tasks/{task_id}/artifacts operation. The removed operationIds are reported via Report::stripped_operations so callers can verify nothing unexpected disappeared.

§Multi-media-type request collapse

progenitor 0.x panics (more media types than expected) when a request body declares more than one content media type. The OAuth endpoints (POST /oauth2/token, POST /oauth2/revoke) accept both application/json and application/x-www-form-urlencoded, each pointing at the same request schema. The normalizer collapses such bodies to a single preferred media type (application/json when present, else the first declared), which is lossless here because the variants share a schema. Runs after the multipart strip so multipart-bearing operations are already gone and never get collapsed instead of removed. Count surfaced via Report::request_media_collapsed.

§Error response strip

progenitor 0.9 asserts response_types.len() <= 1 for both the success and error response sets (see progenitor-impl/src/method.rs — extract_responses). Nearly every TaskFast operation declares 2–5 distinct error response shapes (Error, ValidationError, ClaimFailure, etc.), which trips the error-side assertion. Rather than synthesize a union error type that we’d throw away anyway, the normalizer drops every non-2xx (and non-default) response before handing the spec to progenitor. Surfacing of 4xx/5xx failures is the job of taskfast-client::errors::Error, which reads the response body manually on the way up.

This means the generated client sees every unhappy status as progenitor_client::Error::UnexpectedResponse(reqwest::Response) — we re-classify into our typed taskfast_client::errors::Error in the calling layer.

§Closed-object strip

Every additionalProperties: false is removed so generated types ignore unknown keys — an additive server change must not break installed CLIs (gh#172).

§Response-enum strip

String enums reachable from success or default response bodies are opened so additive server enum values decode in released CLIs (gh#176). Request-only enums stay typed; shared schemas prioritize response tolerance.

§Response-required relax

required lists in response-reachable schemas are cut down to KEEP_REQUIRED, the fields CLI code reads as plain values. Every other response property becomes Option, so a server that drops a required field the CLI never reads no longer breaks released CLIs (gh#178).

Structs§

Report

Constants§

ERROR_ALIASES
Schemas known to be structural clones of #/components/schemas/Error.
KEEP_REQUIRED
Response properties that stay required: (schema key, property).

Functions§

normalize_spec
Normalize an OpenAPI YAML document: collapse ERROR_ALIASES into Error.
normalize_spec_with_report
As normalize_spec but also returns a summary of what changed.