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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants