Skip to content

feat: fully typed SDK generation for Python and TypeScript - #36

Merged
santiagomed merged 1 commit into
mainfrom
smedinarolong/fully-typed-codegen
Jul 21, 2026
Merged

feat: fully typed SDK generation for Python and TypeScript#36
santiagomed merged 1 commit into
mainfrom
smedinarolong/fully-typed-codegen

Conversation

@santiagomed

@santiagomed santiagomed commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What

Replaces template-side type mapping with a Rust type-rendering engine (xdk-lib/src/types.rs). Generated SDKs are now fully typed wherever the spec defines types — no more any/Any for refs, enums, arrays, or compositions.

TypeScript: schemas.ts gets real interfaces, literal-union enums, union/intersection compositions; typed params and request/response models throughout. any count in src: ~1334 → 626 (remaining are spec-free-form objects and the deliberate Options index signature).

Python: new generated xdk/schemas.py with Pydantic models for all component schemas (nested inline objects hoisted, aliases topo-sorted, forward refs resolved at import). Per-tag models alias these; union responses get RootModel wrappers. Kills the Tweet = Any alias table and the required-fields-forced-to-str bug. Any count: ~932 → 190.

Robustness: has_request_model/has_json_response flags computed once in Rust (import/definition conditions can't drift), output dirs cleaned before generation, parameter dedup for non-conforming specs, spec-valid test mocks generated from response schemas, nullable parsed, Python keyword-safe field names.

Validation

Gate Result
cargo fmt / clippy -D warnings clean
cargo test 180/180
Staging spec (local snapshot) Python 1301/1301 · TS build + tsc clean + 1196/1196
Live prod spec (2.167) Python 1276/1276 · TS build + tsc clean + 1171/1171
Method-name stability old vs new generator on identical spec: byte-identical method sets (Python 171, TS 155) — zero renames/removals
Replace template-side type mapping with a Rust type-rendering engine
(xdk-lib/src/types.rs) so generated SDKs are fully typed wherever the
OpenAPI spec defines types.

Type engine:
- $refs render as schema type names (cycle-safe: never recurses into
  reference bodies); enums as literal unions / typing.Literal; arrays
  keep item types; oneOf/anyOf become unions, allOf intersections (TS);
  nullable (newly parsed) maps to '| null' / Optional
- Python identifier safety: keyword fields get a '_' suffix plus
  Field(alias=...); schema names colliding with typing imports get an
  X prefix (List -> XList)
- example_json builds minimal spec-valid payloads for generated tests

TypeScript:
- schemas.ts declarations fully rendered in Rust: real interfaces,
  literal-union enums, typed compositions (was 'any')
- typed parameters, request/response models, and Options interfaces

Python:
- new generated xdk/schemas.py: Pydantic models for every component
  schema (nested inline objects hoisted into named models, aliases
  topologically sorted, forward refs resolved at import)
- per-tag models alias the schema models; union responses get RootModel
  wrappers; removes the 'Tweet = Any' alias table, the required-fields-
  forced-to-str bug, and flattened union handling

Generator robustness:
- has_request_model / has_json_response flags computed once in Rust and
  used by every template that imports or references a model, so import
  and definition conditions cannot drift
- output directories cleaned before generation (stale modules from a
  previous spec no longer break builds)
- parameters deduplicated by (name, in) for specs that illegally declare
  a parameter twice
- generated test mocks derive from the response schemas (spec-valid)
  instead of fabricated placeholder values

Verified on staging and prod specs: both SDKs build, type-check, and
pass their full test suites; public method names are byte-identical to
the previous generator's output for the same spec. specs/ pins the
staging spec for reproducible local generation.

@tcaldwell-x tcaldwell-x left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yolo

@santiagomed
santiagomed merged commit 1427815 into main Jul 21, 2026
4 checks passed
santiagomed added a commit that referenced this pull request Jul 21, 2026
The fully-typed-codegen PR (#36) accidentally committed the staging spec
snapshot. Replace it with the production spec as specs/openapi.json and
gitignore environment-specific snapshots so they stay local-only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants