Skip to content

fix(query): honor per-operation useMutation override for GET operations#3360

Merged
melloware merged 1 commit into
orval-labs:masterfrom
wadakatu:fix/issue-3358-per-operation-usemutation-get
May 16, 2026
Merged

fix(query): honor per-operation useMutation override for GET operations#3360
melloware merged 1 commit into
orval-labs:masterfrom
wadakatu:fix/issue-3358-per-operation-usemutation-get

Conversation

@wadakatu

@wadakatu wadakatu commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #3358.

A per-operation override.operations.<id>.query.useMutation: true was silently discarded for GET operations — the operation stayed a Query hook instead of becoming a Mutation hook. This is the inverse asymmetry of the per-operation useQuery: true path, which already routes non-GET operations to Query hooks.

output: { override: { operations: {
  reprint: { query: { useMutation: true } },  // GET op → expected a Mutation hook
  search:  { query: { useQuery: true } },      // POST op → correctly a Query hook
}}}

search (POST → Query) works; reprint (GET → Mutation) does not.

Root cause

packages/query/src/query-generator.ts:

let isMutation = effectiveUseMutation && verb !== Verbs.GET;

effectiveUseMutation already resolves precedence and encodes the per-verb default (operationQueryOptions?.useMutation ?? override.query.useMutation ?? verb !== Verbs.GET). The trailing && verb !== Verbs.GET therefore only ever suppressed an explicit opt-in: an unset GET op already resolves to false, so the gate changed nothing for the default case and instead discarded useMutation: true.

The isQuery branch has no such verb gate, which is why useQuery: true already works for any verb. The conflict-resolution block right below — if (verb === Verbs.GET && isMutation) { isQuery = false; } — was unreachable dead code because of this gate, confirming that GET → Mutation was the intended design.

Fix

Drop the verb gate so isMutation honors explicit intent for every verb, mirroring isQuery:

let isMutation = effectiveUseMutation;

Behavior matrix:

Setting on a GET operation Before After
(unset) Query hook Query hook (unchanged — effectiveUseMutation resolves to false)
per-operation useMutation: true Query hook Mutation hook
global useMutation: true Query hook Mutation hook (see breaking change)

Non-GET operations are unaffected: effectiveUseMutation still defaults to true for them.

generateMutationHook does not assume a non-GET verb, so a GET-verb Mutation hook generates valid code (same shape as a param-only DELETE); the new snapshot type-checks via orval-tests build.

Breaking change

Lifting the gate also means a global override.query.useMutation: true now routes GET operations to Mutation hooks — symmetric with how global useQuery: true already routes non-GET operations to Query hooks (the explicit-intent-propagates-to-every-verb philosophy of #3323). No existing test or sample sets useMutation: true globally (the only useMutation config in the repo is useMutation: false), so no existing snapshot changes. A breaking change label is likely appropriate, consistent with #3323.

Test plan

  • New snapshot config perOperationUseMutationOnGetshowPetById (GET /pets/{petId}) with per-operation useMutation: true now emits useShowPetById / getShowPetByIdMutationOptions; other operations (GET listPets, POST createPets, DELETE deletePetById) are unchanged.
  • bun run build / typecheck / lint / test / test:snapshots / format:check / bun run --filter orval-tests build all pass locally.
  • Verified pre-fix that showPetById generated a Query hook (bug reproduced), post-fix a Mutation hook.

Documentation

docs/content/docs/reference/configuration/output.mdx — the useMutation section now documents that an explicit useMutation: true (global or per-operation) applies to all HTTP verbs, including routing a GET operation to a Mutation hook, mirroring the existing wording for useQuery.

Summary by CodeRabbit

  • Documentation

    • Updated override.query.useMutation configuration documentation with clarification on default behavior, per-operation routing for GET requests, and conflict-resolution rules when both query and mutation are enabled
  • Improvements

    • Per-operation configuration now properly honors mutation routing directives for GET operations

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 57f288a4-877b-4726-a7ab-9cf1e16e803c

📥 Commits

Reviewing files that changed from the base of the PR and between e3b888e and 2e7a08c.

📒 Files selected for processing (24)
  • docs/content/docs/reference/configuration/output.mdx
  • packages/query/src/query-generator.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/endpoints.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/cat.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/catType.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/createPetsBody.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/createPetsParams.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/createPetsSort.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/dachshund.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/dachshundBreed.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/dog.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/dogType.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/error.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/index.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/labradoodle.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/labradoodleBreed.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/listPetsParams.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/listPetsSort.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/pet.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/petCallingCode.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/petCountry.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/petWithTag.ts
  • tests/__snapshots__/react-query/per-operation-use-mutation-on-get/model/pets.ts
  • tests/configs/react-query.config.ts

📝 Walkthrough

Walkthrough

This PR fixes a bug where per-operation useMutation: true overrides were ignored for GET HTTP verbs. The core change removes a GET-excluding gate in query-hook initialization, updated documentation clarifies the new behavior, and a new test case validates the fix.

Changes

Per-operation GET-to-mutation routing

Layer / File(s) Summary
Core query-mutation selection gate
packages/query/src/query-generator.ts, docs/content/docs/reference/configuration/output.mdx
generateQueryHook now initializes isMutation directly from effectiveUseMutation without excluding GET verbs, allowing explicit per-operation useMutation: true to route GET to mutation hooks. Documentation clarifies default behavior (mutation for non-GET, query for GET) and the conflict-resolution rule when both are enabled.
Per-operation mutation test case and snapshots
tests/configs/react-query.config.ts, tests/__snapshots__/react-query/per-operation-use-mutation-on-get/*
New test configuration perOperationUseMutationOnGet overrides the showPetById GET operation to use useMutation: true, generating complete React Query endpoints with mutation hooks and model types that demonstrate the fix routes the GET correctly to useShowPetById mutation and getShowPetByIdMutationOptions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related issues

  • orval-labs/orval#3358: Per-operation useMutation: true override was not working for GET operations; this PR fixes the root cause by removing the verb-excluding gate.

Possibly related PRs

  • orval-labs/orval#3323: Both PRs modify the per-verb useQuery/useMutation gating logic in query-generator.ts to change how GET operations are routed; this PR completes that change by honoring explicit useMutation for GET.

Suggested labels

bug

Suggested reviewers

  • snebjorn
  • melloware

Poem

🐰 A GET request bound to query's chain,
Now dances free as a mutation's reign,
With config's voice, "useMutation: true,"
The override wins—the fix is new! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: honoring per-operation useMutation override for GET operations, which aligns with the primary change in query-generator.ts.
Linked Issues check ✅ Passed The PR directly addresses issue #3358 by fixing the bug where per-operation useMutation: true was ignored for GET operations. The code changes remove the verb gate that prevented explicit useMutation overrides from applying to GET requests.
Out of Scope Changes check ✅ Passed All changes align with the stated objectives. Documentation updates clarify the useMutation behavior, test snapshots demonstrate the fix working for GET operations with useMutation override, and the configuration test entry validates the per-operation override mechanism.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@melloware melloware added tanstack-query TanStack Query related issue breaking change Breaking change on upgrade labels May 15, 2026
A per-operation `override.operations.<id>.query.useMutation: true` was
silently discarded for GET operations: the operation stayed a Query
hook instead of becoming a Mutation hook. This was the inverse
asymmetry of the per-operation `useQuery: true` path, which already
worked for non-GET verbs.

`effectiveUseMutation` already encodes the per-verb default
(`verb !== Verbs.GET`), so the extra `&& verb !== Verbs.GET` gate on
`isMutation` only ever suppressed an explicit opt-in. Drop the gate so
`isMutation` honors explicit intent for every verb, mirroring how
`isQuery` honors `useQuery: true` for non-GET verbs.

Closes orval-labs#3358
@wadakatu wadakatu force-pushed the fix/issue-3358-per-operation-usemutation-get branch from 7c111d1 to 2e7a08c Compare May 16, 2026 00:40
@wadakatu wadakatu marked this pull request as ready for review May 16, 2026 00:48
Copilot AI review requested due to automatic review settings May 16, 2026 00:48

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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds coverage and documentation for honoring useMutation: true overrides on GET operations in the React Query client generator.

Changes:

  • Adds a new test fixture/config and snapshots validating per-operation useMutation: true on a GET endpoint.
  • Updates query hook generation to honor explicit useMutation for GET verbs.
  • Clarifies documentation for useMutation behavior and precedence rules.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

File Description
tests/configs/react-query.config.ts Adds a new test config entry to generate snapshots for the useMutation-on-GET override scenario.
packages/query/src/query-generator.ts Removes the GET verb gate so explicit useMutation: true is honored for GET operations.
docs/content/docs/reference/configuration/output.mdx Documents that explicit useMutation applies regardless of HTTP verb and describes precedence.
tests/snapshots/react-query/per-operation-use-mutation-on-get/** Adds generated snapshot outputs verifying the new behavior.
Comments suppressed due to low confidence (1)

tests/snapshots/react-query/per-operation-use-mutation-on-get/model/listPetsParams.ts:1

  • The generated JSDoc block has malformed formatting (missing * alignment on lines 15–17), which degrades the readability of generated typings and can render poorly in editors/TS tooling. Fixing this likely requires normalizing multi-line description rendering in the generator so each line is prefixed with * (and avoiding stray blank lines).
/**

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +285 to +290
// Closes #3358 — a per-operation `override.operations.<id>.query.
// useMutation: true` now routes a GET operation to a Mutation hook.
// Previously the verb gate in `query-generator.ts` discarded explicit
// `useMutation: true` for GET, so the operation stayed a Query hook —
// the inverse asymmetry of the per-operation `useQuery: true` path
// that already worked for non-GET verbs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the catch! This is a // source-code comment rather than rendered Markdown, so there's no inline code-span rendering involved here. I deliberately kept the wrapping consistent with the sibling comment ~30 lines above — the perOperationFalseDisablesGlobalTrue block added in #3323 — which wraps override.operations.<id>.query.useQuery: false across a line break in exactly the same way. Reflowing only this block would make it inconsistent with that sibling, and normalizing both is out of scope for this fix. Leaving it as-is for consistency.

@wadakatu

Copy link
Copy Markdown
Contributor Author

Hi @melloware, would you be able to review this when you have a moment? Thanks!

@melloware

Copy link
Copy Markdown
Collaborator

Sure will review tomorrow

@melloware melloware merged commit 14171f4 into orval-labs:master May 16, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Breaking change on upgrade tanstack-query TanStack Query related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Not able to create Mutation from api its GET anymore on operation level

3 participants