Skip to content

fix: generate tsc-safe TypeScript for parameters and payloads presets#374

Open
ALagoni97 wants to merge 1 commit into
mainfrom
fix/openapi-ts-parameters-payloads-tsc
Open

fix: generate tsc-safe TypeScript for parameters and payloads presets#374
ALagoni97 wants to merge 1 commit into
mainfrom
fix/openapi-ts-parameters-payloads-tsc

Conversation

@ALagoni97

@ALagoni97 ALagoni97 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Note for reviewers: the payloads/headers fix (#373, defects 3 & 4) is implemented here as a post-processing preset because @asyncapi/modelina@6.0.0-next.11 is an external published package with no patch tooling in this repo. These two defects could alternatively be solved upstream in Modelina's MarshalFunction/UnmarshalFunction (lib/.../generators/typescript/presets/utils/) instead — that would be a separate repo and release. The preset keeps the fix self-contained and testable here.

Problem

Generation reports zero errors, but the generated .ts does not compile. A downstream publish pipeline runs npm i && npm run build && npm publish; the tsc build step exits non-zero and nothing publishes. These are silent-at-generation, fatal-at-build defects.

Fixes four independent template defects across two presets, tracked upstream as #372 (parameters) and #373 (payloads).

Defects & fixes

parameters preset — #372 (src/codegen/inputs/openapi/generators/parameters.ts)

  1. Query serializer/deserializer used the raw spec name as the property accessor. Fields are constrained to camelCase (skip) but the code emitted this.SkipTS2551 Property 'Skip' does not exist. Introduced a ParameterConfig carrying both name (original wire key) and propertyName (constrained accessor), plus a buildConstrainedNameMap() helper. Every this.* accessor now uses the constrained name; every wire key (params.append('Skip'), params.has(...), URL placeholders, extractPathParameters switch cases) keeps the original casing. The path serializer already behaved correctly; this makes serialize, deserialize, fromUrl, and extractPathParameters consistent.
  2. deserializeUrl was only generated when the class had query params, but fromUrl() always calls it. A path-only parameters class failed with TS2551 Property 'deserializeUrl' does not exist. deserializeUrl is now always emitted (a harmless no-op when there are no query params).

payloads / headers presets — #373 (new src/codegen/modelina/presets/marshalling.ts)

These defects originate in Modelina's TS_COMMON_PRESET marshalling. Modelina is an external published package with no patch tooling in this repo, so the fix is a small post-processing preset (createMarshallingFixPreset) that runs immediately after TS_COMMON_PRESET. Each replacement is derived from the model, so it targets exactly the affected property line and leaves everything else untouched.

  1. Unconditional null fallback for non-nullable date-time in unmarshal(). instance.created = obj["created"] == null ? null : new Date(...) yields Date | null where the field is declared DateTS2322. The null branch is dropped for required, non-nullable date fields.
  2. Nullable array guarded only by !== undefined in marshal(), then iterated. null slips past the guard into for (const item of this.signers)TS2531 Object is possibly 'null'. An explicit !== null guard is added.

Wired into both payloads.ts and headers.ts, which share the same marshalling setup.

Verification

Closes #372
Closes #373

🤖 Generated with Claude Code

Generation reported zero errors but the emitted .ts failed `tsc`, breaking
downstream `npm run build` in publish pipelines. Four template defects across
two presets are fixed.

parameters preset (#372):
- Serialize/deserialize now access the constrained camelCase field
  (this.skip) instead of the raw spec name (this.Skip), while the wire key
  (params.append('Skip'), path placeholders, extractPathParameters cases)
  keeps the original casing. Threaded a ParameterConfig carrying both names.
- Always emit deserializeUrl (a no-op with no query params) so path-only
  classes, whose fromUrl() calls it unconditionally, compile.

payloads/headers presets (#373):
- New createMarshallingFixPreset corrects Modelina's class marshal/unmarshal
  output (Modelina is an external package with no patch tooling). Derived
  from the model so each replacement targets only the affected property:
  - drop the `== null ? null : new Date(...)` fallback for required,
    non-nullable date-time fields (was Date | null, declared Date).
  - null-guard nullable arrays before iterating them in marshal().

Verified by regenerating both minimal repros and the full safepay-v2 client
through tsc --strict (clean), plus regression tests for all four defects.

Refs: #372, #373

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ALagoni97 ALagoni97 requested a review from jonaslagoni as a code owner July 2, 2026 18:42
@netlify

netlify Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploy Preview for the-codegen-project canceled.

Name Link
🔨 Latest commit a6558e7
🔍 Latest deploy log https://app.netlify.com/projects/the-codegen-project/deploys/6a46b10498687a0008253073

@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
the-codegen-project Ready Ready Preview, Comment Jul 2, 2026 6:46pm
the-codegen-project-mcp Ready Ready Preview, Comment Jul 2, 2026 6:46pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant