Skip to content

fix(query): pass operationId and operationName to queryOptions mutator - #3427

Merged
melloware merged 2 commits into
orval-labs:masterfrom
wadakatu:fix/3153-queryoptions-operation-info
May 23, 2026
Merged

fix(query): pass operationId and operationName to queryOptions mutator#3427
melloware merged 2 commits into
orval-labs:masterfrom
wadakatu:fix/3153-queryoptions-operation-info

Conversation

@wadakatu

@wadakatu wadakatu commented May 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #3153.

mutationOptions mutators have received { operationId, operationName } as their third argument since #1974, but the symmetric queryOptions mutator was left with only { url }. That asymmetry makes it impossible to write queryOptions overrides that branch on operation identity (the very thing the issue reporter is trying to do).

This PR extends the third argument of queryOptions mutator calls from { url } to { url, operationId, operationName }. The change is additive — mutators that today read arg3.url keep working unchanged, so this ships as a fix(query) rather than a breaking change.

What changed

  • packages/query/src/query-generator.ts — threaded operationId into generateQueryImplementation (it was already in scope at generateQueryHook) and extended the third arg at both call sites:
    • the main query options builder
    • the applyQueryOptionsMutator helper that backs invalidate / set / get (the helper's call shape must stay in lockstep with the main builder's, otherwise the augmented queryKey is silently recomputed against a stale arg shape)
  • Docs: added a short note to output.mdx documenting the new third-arg shape

Why not match mutationOptions exactly

mutationOptions passes { url } as arg 2 and { operationId, operationName } as arg 3. queryOptions passes { queryProperties } as arg 2 — that 2nd-arg asymmetry is shipped behavior and changing it would be breaking. Combining url + operation info into arg 3 lets queryOptions mutators access everything they need without touching the 2nd arg's shape.

Tests

Added a focused regression test in tests/api-generation.spec.ts (react-query issue-3153 ...) backed by a new fixture project petstoreCustomQueryOptionsWithOperation and a new 3-arg test mutator tests/mutators/custom-query-options-with-operation.ts. The mutator body references operation.operationId, so a regression that drops the field would also fail TypeScript compilation under bun run --filter orval-tests build.

The existing useInvalidateWithQueryOptionsMutator fixture (1-arg mutator) is left untouched so that the hasThirdArg: false code path keeps regression coverage.

Counting occurrences (2 per operation) verifies both call sites emit the new third arg — catching the "fixed one site, forgot the other" regression without resorting to multi-line whitespace-flexible regex.

Test plan

  • bun run build --force
  • bun run test (all 12 packages green, 1787+ tests in core alone)
  • bun run test:snapshots (4155 tests; only the new fixture's snapshot was added — no existing snapshot changed)
  • bun run typecheck
  • bun run lint
  • bun run format:check
  • bun run --filter orval-tests build (typecheck-generated for all 15 clients + verify-mock-generated)

Summary by CodeRabbit

  • New Features

    • Custom query/mutation option handlers now receive operation identity info (operationId and operationName) along with the URL for richer, operation-aware query key construction.
  • Documentation

    • Clarified docs describing the shapes and parameters passed to custom queryOptions/mutationOptions mutators.
  • Tests

    • Added regression tests validating operation identity is included for generated React Query code.

Review Change Stack

The `mutationOptions` mutator has received `{ operationId, operationName }`
as its third argument since orval-labs#1974, but the symmetric `queryOptions` mutator
was left with only `{ url }`. That asymmetry made it impossible to write
`queryOptions` overrides that branch on operation identity (e.g. attach
per-operation metadata or invalidate by `operationId`).

Extend the third argument of `queryOptions` mutator calls from `{ url }`
to `{ url, operationId, operationName }`. The change is additive —
mutators that today read `arg3.url` keep working unchanged. Both call
sites are updated: the main query options builder and the
`applyQueryOptionsMutator` helper that backs `invalidate`/`set`/`get`.

The 2nd-arg asymmetry between `queryOptions` (`{ queryProperties }`) and
`mutationOptions` (`{ url }`) is shipped behaviour and is left alone.

Closes orval-labs#3153
Copilot AI review requested due to automatic review settings May 22, 2026 23:18
@coderabbitai

coderabbitai Bot commented May 22, 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: 151c2449-9f48-450f-86d9-bbc75fb5126e

📥 Commits

Reviewing files that changed from the base of the PR and between b60f0f6 and 4c1c27e.

📒 Files selected for processing (2)
  • docs/content/docs/reference/configuration/output.mdx
  • tests/api-generation.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/content/docs/reference/configuration/output.mdx

📝 Walkthrough

Walkthrough

Threads operation identity into React Query codegen: generator accepts operationId, invokes non-hook queryOptions mutators with { url, operationId, operationName }, updates query-key rewriting, adds docs, test config/mutator helper, generated snapshots, and a regression test validating the change.

Changes

Query Options Operation Identity Enhancement

Layer / File(s) Summary
Core generator: threading operationId through query variants
packages/query/src/query-generator.ts
generateQueryImplementation now accepts operationId; when queryOptionsMutator.hasThirdArg the identity argument passed and used for query-key rewriting is { url, operationId, operationName }; generateQueryHook supplies operationId to variant generation.
Generated endpoints snapshot with operation-aware query options
tests/__snapshots__/react-query/custom-query-options-with-operation/endpoints.ts
Generated endpoint helpers/hooks for Petstore (listPets, createPets, showPetById, deletePetById, healthCheck, showPetWithOwner) that wire customQueryOptionsWithOperation and use operation-enhanced query keys in invalidate helpers.
Generated model types for test fixture
tests/__snapshots__/react-query/custom-query-options-with-operation/model/*
Added generated model files (Cat, Dog, Pet, Error, params, sorts, and related types) used by the endpoint snapshots.
Test infrastructure: configuration and mutator helper
tests/configs/react-query.config.ts, tests/mutators/custom-query-options-with-operation.ts
Add petstoreCustomQueryOptionsWithOperation generator config and customQueryOptionsWithOperation helper that prepends operation context (url, operationId, operationName) to options.queryKey.
Regression test validating operation identity delivery
tests/api-generation.spec.ts
New Vitest regression (react-query issue-3153) that asserts generated output contains url and that operationId and operationName appear in the expected call sites.
Feature documentation
docs/content/docs/reference/configuration/output.mdx
Documented the third-parameter shapes that queryOptions and mutationOptions mutators receive for operation-aware branching.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • orval-labs/orval#3389: Modifies the same non-hook queryOptionsMutator branch in query-generator.ts for enabled-guard logic.
  • orval-labs/orval#3290: Also updates query key routing through non-hook queryOptions mutator in invalidate* helpers.

Suggested labels

tanstack-query

Suggested reviewers

  • melloware

Poem

🐰 I hop through code with nimble cheer,
I brought operation names so branching's clear.
From generator down to mutator's call,
operationId and name are heard by all.
Hooray — query keys know their story near!

🚥 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 clearly and specifically summarizes the main change: passing operationId and operationName to the queryOptions mutator, which addresses the core objective of the PR.
Linked Issues check ✅ Passed The PR fully satisfies issue #3153 requirements: queryOptions mutators now receive { url, operationId, operationName } as the third argument, matching mutationOptions functionality without changing the second argument shape.
Out of Scope Changes check ✅ Passed All changes directly support the objective: code generation updates pass operationId through, documentation clarifies the new third-arg shape, test fixtures validate the implementation, and mutator examples demonstrate the feature.
Docstring Coverage ✅ Passed Docstring coverage is 80.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.

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 support for passing operation identity into React Query queryOptions mutators, enabling per-operation customization (e.g., tagging/invalidation) and preventing a regression where only url was available.

Changes:

  • Extend React Query query-options mutator third argument to include { url, operationId, operationName }.
  • Add a regression test and new generated snapshot fixture for the feature.
  • Document the updated mutator third-parameter contract.

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/mutators/custom-query-options-with-operation.ts Adds a test mutator that prefixes query keys with operation identity fields.
tests/configs/react-query.config.ts Adds a new test generation target wiring the custom queryOptions mutator.
tests/api-generation.spec.ts Adds a regression test asserting operation identity is passed at both query-options mutator call sites.
tests/snapshots/react-query/custom-query-options-with-operation/endpoints.ts New snapshot validating generated code now passes operation identity into the mutator.
tests/snapshots/react-query/custom-query-options-with-operation/model/pets.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/petWithTag.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/petCountry.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/petCallingCode.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/pet.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/listPetsSort.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/listPetsParams.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/labradoodleBreed.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/labradoodle.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/index.ts New generated model barrel snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/error.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/dogType.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/dog.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/dachshundBreed.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/dachshund.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/createPetsSort.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/createPetsParams.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/createPetsBody.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/catType.ts New generated model snapshot fixture for the added test target.
tests/snapshots/react-query/custom-query-options-with-operation/model/cat.ts New generated model snapshot fixture for the added test target.
packages/query/src/query-generator.ts Updates query codegen to pass operationId/operationName into third-arg mutators at both call sites.
docs/content/docs/reference/configuration/output.mdx Documents the third-arg mutator payload as including operation identity.

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

}${
queryOptionsMutator.hasThirdArg ? `, { url: \`${route}\` }` : ''
queryOptionsMutator.hasThirdArg
? `, { url: \`${route}\`, operationId: '${operationId}', operationName: '${operationName}' }`

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.

Out of scope for this PR. The same single-quote interpolation pattern is already in use for mutationOptions (see packages/query/src/mutation-generator.ts:471, introduced in #1974):

mutationOptionsMutator.hasThirdArg
  ? `, { operationId: '${operationId}', operationName: '${operationName}' }`
  : ''

If operationId / operationName need safe escaping, both call sites should switch together (and probably url too — that one also predates this PR). Doing it on the query side only here would diverge the two mutator types' output formats. Happy to file a follow-up issue for repo-wide operation-id encoding once this lands.

Comment on lines +861 to +864
When a `queryOptions` or `mutationOptions` mutator declares a third
parameter, orval passes `{ url, operationId, operationName }` so the mutator
can branch on operation identity (for example, to attach per-operation
metadata or invalidate by `operationId`).

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.

Good catch — fixed in 4c1c27e. The docs now describe the two shapes separately:

  • queryOptions{ url, operationId, operationName }
  • mutationOptions{ operationId, operationName } (url is in the 2nd arg)

Comment thread tests/api-generation.spec.ts Outdated
Comment on lines +413 to +426
const operations: Array<{ operationId: string; url: string }> = [
{ operationId: 'listPets', url: '/pets' },
{ operationId: 'showPetById', url: '/pets/${petId}' },
{ operationId: 'showPetWithOwner', url: '/pets/${petId}/owner' },
{ operationId: 'healthCheck', url: '/health' },
];

const occurrencesOf = (needle: string) => content.split(needle).length - 1;

for (const { operationId, url } of operations) {
expect(content).toContain(`url: \`${url}\``);
// Two occurrences each: one from the main builder, one from the helper.
expect(occurrencesOf(`operationId: '${operationId}'`)).toBe(2);
expect(occurrencesOf(`operationName: '${operationId}'`)).toBe(2);

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.

Fixed in 4c1c27eoperations table now carries operationName as an explicit field rather than reusing operationId, and the loop asserts each independently.

test(query): decouple operationName from operationId in orval-labs#3153 regression
@melloware melloware added the tanstack-query TanStack Query related issue label May 23, 2026
@melloware
melloware merged commit 8f4ae4a into orval-labs:master May 23, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tanstack-query TanStack Query related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

queryOptions mutator is missing operationId and operationName (available in mutationOptions)

3 participants