Skip to content

fix(axios): eliminate module-level returnTypesToWrite map - #3696

Merged
melloware merged 1 commit into
orval-labs:masterfrom
aqeelat:fix/3685-axios-returntypes-module-level-map
Jul 12, 2026
Merged

fix(axios): eliminate module-level returnTypesToWrite map#3696
melloware merged 1 commit into
orval-labs:masterfrom
aqeelat:fix/3685-axios-returntypes-module-level-map

Conversation

@aqeelat

@aqeelat aqeelat commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Problem

The axios generator used a module-level Map (returnTypesToWrite) to collect *Result type declarations during implementation generation, then read them during footer generation. In tags-split mode, all implementations are generated first (populating the map), then footers are generated per-tag. When two operations from different tags shared the same operationName (via override.operationName), the second overwrote the first's entry, causing the wrong *Result type to be emitted in the first tag's footer.

Closes #3685.

Solution

Eliminate the module-level map entirely. The return type generator is now:

  1. Returned from generateAxiosImplementation as GeneratorClient.returnType
  2. Stored on GeneratorOperation.types.result in generateOperations
  3. Passed to the footer via the new optional operations param on ClientFooterBuilder / GeneratorClientFooter
  4. Read from operations[].types.result in generateAxiosFooter

This removes all module-level state and ordering concerns. Each tag's footer only emits types for its own operations.

Changes

  • GeneratorClient gains optional returnType?: (title?) => string
  • ClientFooterBuilder and GeneratorClientFooter gain optional operations?: GeneratorOperation[]
  • generateAxiosImplementation returns { implementation, returnType } instead of side-effecting on a map
  • generateAxiosFooter reads from operations[].types.result instead of the module-level map
  • Module-level returnTypesToWrite Map deleted
  • target.ts and target-tags.ts pass filtered operations to the footer
  • generateClientFooter in client.ts passes operations through to per-client footers

Tests

  • New regression test: two tags with different return types verify each tag emits its own *Result type
  • 3323 tests pass, 0 new failures (8 pre-existing failures unrelated to this change)

Summary by CodeRabbit

  • Bug Fixes
    • Improved generated Axios client typing so each operation uses its correct per-operation response type.
    • Fixed tag-split generation so return types stay isolated per tag, avoiding cross-tag type mixing.
    • Enhanced client/footer generation to retain per-operation result typing consistently.
  • New Features
    • Added optional return-type and per-operation context to generator callback contracts.
  • Tests
    • Added a new test suite to verify tag-split Axios return types are generated correctly.

Copilot AI review requested due to automatic review settings July 9, 2026 20:00

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1d9288d8-21b5-4bc7-88be-62cd2e0133db

📥 Commits

Reviewing files that changed from the base of the PR and between 92ed48b and f1f65ec.

📒 Files selected for processing (7)
  • packages/axios/src/index.ts
  • packages/core/src/types.ts
  • packages/core/src/writers/target-tags.ts
  • packages/core/src/writers/target.ts
  • packages/orval/src/api.ts
  • packages/orval/src/client.ts
  • packages/orval/src/generate-spec.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/core/src/writers/target.ts
  • packages/core/src/writers/target-tags.ts
  • packages/orval/src/client.ts
  • packages/core/src/types.ts
  • packages/axios/src/index.ts

📝 Walkthrough

Walkthrough

This PR removes axios' shared returnTypesToWrite map, carries return type metadata on generated operations, updates footer generation to read that metadata, and adds a tags-split regression test for per-tag *Result output.

Changes

Per-operation return type propagation

Layer / File(s) Summary
Core type contracts and operation wiring
packages/core/src/types.ts, packages/core/src/writers/target.ts, packages/core/src/writers/target-tags.ts
Adds returnType and operations footer data to core generator types, and passes operation lists into footer generation.
Axios return type generation
packages/axios/src/index.ts
Removes the shared returnTypesToWrite map, returns { implementation, returnType } from axios implementation generators, and emits footer result types from per-operation metadata.
Orval client footer and operation metadata
packages/orval/src/client.ts
Forwards operations into client footer generation in the non-function path and attaches types.result from client.returnType to generated operations.
Tag isolation regression test
packages/orval/src/generate-spec.test.ts
Adds a tags-split test that checks distinct *Result and AxiosResponse<...> types for tagged operations sharing an operation name.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
    participant target as target.ts / target-tags.ts
    participant client as generateOperations
    participant axios as generateAxiosImplementation
    participant footer as generateAxiosFooter

    target->>client: build operations and footer inputs
    client->>axios: generate implementation + returnType
    axios-->>client: { implementation, returnType }
    client-->>target: operations with types.result
    target->>footer: footer({ operations, operationNames, ... })
    footer->>footer: emit per-operation Result types
Loading

Suggested labels: bug

Suggested reviewers: melloware, wadakatu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the main axios change and matches the PR's core fix.
Linked Issues check ✅ Passed The changes remove shared state, store return types on operations, pass operations to footers, and add regression coverage for the tag-collision bug.
Out of Scope Changes check ✅ Passed The additional type, footer, and operation-key updates all support the axios tags-split fix and regression test.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/orval/src/client.ts (1)

179-202: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep operations in the footer fallback path.

When an OutputClientFunc returns an object-style footer, the deprecated array call can fall back here, but Lines 197-202 drop operations. Axios emits *Result aliases only from operations, so custom client-function wrappers can lose those aliases.

Proposed fix
   } catch {
     implementation = footer({
       operationNames,
+      operations,
       title: titles.implementation,
       hasMutator,
       hasAwaitedType,
     });
   }

Based on learnings, footer generation must read result types from per-operation data to avoid cross-tag/name collisions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/orval/src/client.ts` around lines 179 - 202, The footer fallback in
client.ts is dropping operations when `OutputClientFunc` falls back from the
deprecated array call, which can cause missing `*Result` aliases. Update the
footer generation path in the try/catch around implementation so the
object-style footer call in the catch includes operations, matching the main
footer invocation and preserving per-operation result type data. Use the
implementation/footer logic in client.ts as the place to keep the same
operations payload in both paths.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/orval/src/generate-spec.test.ts`:
- Around line 1265-1316: The regression test currently uses different operation
names, so it does not exercise the shared operationName collision in
returnTypesToWrite. Update generateSpec - returnTypesToWrite isolation across
tags to force both tag groups to use the same operationName via
override.operations (for example in the SPEC setup used by generateSpec), then
assert each generated tag footer still emits the correct *Result type for its
own response schema. Use the existing generateSpec, normalizeOptions, and
operationName-related setup in this test file so the coverage matches the
module-level map collision bug.

---

Outside diff comments:
In `@packages/orval/src/client.ts`:
- Around line 179-202: The footer fallback in client.ts is dropping operations
when `OutputClientFunc` falls back from the deprecated array call, which can
cause missing `*Result` aliases. Update the footer generation path in the
try/catch around implementation so the object-style footer call in the catch
includes operations, matching the main footer invocation and preserving
per-operation result type data. Use the implementation/footer logic in client.ts
as the place to keep the same operations payload in both paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54964359-4de3-458e-9cfc-72c01b3bb203

📥 Commits

Reviewing files that changed from the base of the PR and between 1134ba5 and 218d317.

📒 Files selected for processing (6)
  • packages/axios/src/index.ts
  • packages/core/src/types.ts
  • packages/core/src/writers/target-tags.ts
  • packages/core/src/writers/target.ts
  • packages/orval/src/client.ts
  • packages/orval/src/generate-spec.test.ts

Comment thread packages/orval/src/generate-spec.test.ts
@pkg-pr-new

pkg-pr-new Bot commented Jul 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

@orval/angular

bun add https://pkg.pr.new/@orval/angular@f1f65ec

@orval/axios

bun add https://pkg.pr.new/@orval/axios@f1f65ec

@orval/core

bun add https://pkg.pr.new/@orval/core@f1f65ec

@orval/effect

bun add https://pkg.pr.new/@orval/effect@f1f65ec

@orval/fetch

bun add https://pkg.pr.new/@orval/fetch@f1f65ec

@orval/hono

bun add https://pkg.pr.new/@orval/hono@f1f65ec

@orval/mcp

bun add https://pkg.pr.new/@orval/mcp@f1f65ec

@orval/mock

bun add https://pkg.pr.new/@orval/mock@f1f65ec

orval

bun add https://pkg.pr.new/orval@f1f65ec

@orval/query

bun add https://pkg.pr.new/@orval/query@f1f65ec

@orval/solid-start

bun add https://pkg.pr.new/@orval/solid-start@f1f65ec

@orval/swr

bun add https://pkg.pr.new/@orval/swr@f1f65ec

@orval/zod

bun add https://pkg.pr.new/@orval/zod@f1f65ec

commit: f1f65ec

@aqeelat
aqeelat force-pushed the fix/3685-axios-returntypes-module-level-map branch from 218d317 to 92ed48b Compare July 9, 2026 20:25
…#3685)

The axios generator used a module-level Map (returnTypesToWrite) to collect
*Result type declarations during implementation generation, then read them
during footer generation. In tags-split mode, all implementations are generated
first (populating the map), then footers are generated per-tag. When two
operations from different tags shared the same operationName (via override),
the second overwrote the first's entry, causing the wrong *Result type to be
emitted in the first tag's footer.

Fix: eliminate the module-level map entirely. The return type generator is now
returned from generateAxiosImplementation as part of GeneratorClient.returnType,
stored on GeneratorOperation.types.result, and passed to the footer via the new
optional operations param on ClientFooterBuilder/GeneratorClientFooter.

The footer reads from operations[].types.result instead of the side-effect map,
ensuring each tag's footer only emits types for its own operations.
@aqeelat
aqeelat force-pushed the fix/3685-axios-returntypes-module-level-map branch from 92ed48b to f1f65ec Compare July 9, 2026 21:01
@melloware melloware added the axios Axios related issue label Jul 12, 2026
@melloware
melloware merged commit 957e04b into orval-labs:master Jul 12, 2026
7 checks passed
@aqeelat
aqeelat deleted the fix/3685-axios-returntypes-module-level-map branch July 15, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

axios Axios related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(axios): module-level returnTypesToWrite map causes wrong *Result type in tags-split mode

3 participants