Skip to content

feat: add strict infinite hook generation#3106

Draft
the-inconvenience-store wants to merge 16 commits intoorval-labs:masterfrom
the-inconvenience-store:feat/3101-useinfinite-require-query-param
Draft

feat: add strict infinite hook generation#3106
the-inconvenience-store wants to merge 16 commits intoorval-labs:masterfrom
the-inconvenience-store:feat/3101-useinfinite-require-query-param

Conversation

@the-inconvenience-store
Copy link
Copy Markdown

@the-inconvenience-store the-inconvenience-store commented Mar 13, 2026

Introduce useInfiniteRequireQueryParam to gate infinite and suspense-infinite hook generation to endpoints that actually include the configured useInfiniteQueryParam

  • useInfiniteRequireQueryParam to query option types and normalisation
  • gate infinite/suspense-infite generation in query generator when strict mode is enabled
  • update framework adapaters (shared, angular and vue) to support strict pageParam injection
  • add unit tests for query option nroamlisation
  • add regression spec and config scenarios for react,vue, and angular query
  • include angular query in api snapshot harness

closes #3101

Not sure if there was a reason why angular-query was excluded for the snapshot testing harness, but this PR does re-introduce it as I was testing the changes in Angular.

If desired I can push a commit with angular-query snapshots disabled and removed again.

Thanks

Summary by CodeRabbit

  • New Features

    • Added validation to only generate infinite query hooks when the specified query parameter exists in the operation schema.
    • Added configuration control for requiring query parameters in infinite query operations.
  • Documentation

    • Documented side effects when using the infinite query parameter configuration option.

Introduce useInfiniteRequireQueryParam to gate infinite and suspense-infinite
- useInfiniteRequireQueryParam to query option types and normalisation
- gate infinite/suspense-infite generation in query generator when strict mode is enabled
- update framework adapaters (shared, angular and vue) to support strict pageParam injection
- add unit tests for query option nroamlisation
- add regression spec and config scenarios for react,vue, and angular query
- include angular query in api snapshot harness

closes orval-labs#3101
Copilot AI review requested due to automatic review settings March 13, 2026 03:14
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 13, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 538408af-92d5-4079-b90a-8a69f6bd9a11

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Enhanced infinite-query generation to validate the configured query parameter exists in an endpoint's schema before emitting infinite-query hooks. Added schema-parsing utilities and conditional gating logic that inspects operation parameters, logs warnings when mismatches occur, and propagates a requireQueryParam flag through framework adapters to control HTTP property generation.

Changes

Cohort / File(s) Summary
Framework Adapter Interface & Implementations
packages/query/src/framework-adapter.ts, packages/query/src/frameworks/angular.ts, packages/query/src/frameworks/vue.ts, packages/query/src/frameworks/index.ts
Updated method signatures to accept requireQueryParam?: boolean parameter, enabling adapters to conditionally use ?? (nullish coalescing) instead of || (logical OR) when selecting query parameter values.
Query Generation Core Logic
packages/query/src/query-generator.ts
Added string-parsing helpers (countPrecedingBackslashes, isEscaped, parseTopLevelSegments, hasQueryParamInSchema) to detect whether a schema contains a specific query parameter. Implemented schema-based gating in generateQueryImplementation to only emit infinite-query hooks for endpoints declaring the configured useInfiniteQueryParam, with warning logs for mismatches.
Test Configurations
tests/configs/angular-query.config.ts, tests/configs/react-query.config.ts, tests/configs/vue-query.config.ts
Added new useInfiniteQueryParamImplicit configuration entries targeting infinite-query-param-implicit.yaml specification, enabling useInfinite/useSuspenseInfiniteQuery with useInfiniteQueryParam: 'page'.
Test Specification & Generated Models
tests/specifications/infinite-query-param-implicit.yaml, tests/__snapshots__/react-query/use-infinite-query-param-implicit/model/*, tests/__snapshots__/vue-query/use-infinite-query-param-implicit/model/*
Added new OpenAPI spec with two endpoints (one with page query param, one without) and generated TypeScript model definitions reflecting the schema structure.
Generated Endpoint Snapshots
tests/__snapshots__/react-query/use-infinite-query-param-implicit/endpoints.ts, tests/__snapshots__/vue-query/use-infinite-query-param-implicit/endpoints.ts
Added new snapshot fixtures showing correct infinite-query generation only for the endpoint declaring the page parameter, omitting infinite variants from endpoints lacking that parameter.
Removed Infinite-Query Artifacts
tests/__snapshots__/react-query/*/endpoints.ts, tests/__snapshots__/vue-query/*/endpoints.ts, tests/__snapshots__/svelte-query/*/endpoints.ts
Removed all infinite-query helper functions, types, and hooks across snapshot files to reflect the new gating behavior (only endpoints with matching query params receive infinite-query generation).
Sample Code Cleanup
samples/angular-app/src/api/endpoints/*, samples/angular-app/src/api/model/*, samples/react-query/basic/src/api/endpoints/*, samples/vue-query/*/src/api/endpoints/*
Removed generated services, MSW mocks, and model types from sample applications (cleanup unrelated to the core feature).
Documentation
docs/content/docs/reference/configuration/output.mdx
Added "Side Effects" callout explaining that useInfiniteQueryParam only generates infinite hooks for endpoints including that parameter.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • melloware

Poem

🐰 Infinite queries now check the schema's call,
No more hooks for endpoints without params at all!
Smart detection filters out the mismatch with care,
Only paginated endpoints get infinite flair.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Minor out-of-scope removal detected: deletion of Angular app sample files (pets service, MSW mocks, models) and removal of infinite query exports from existing snapshots are not directly required by issue #3101, though they appear to be cleanup or downstream effects. Clarify whether the deletion of sample Angular app files and removal of infinite query exports from existing test snapshots are intentional scope or can be reverted to focus solely on the strict parameter generation feature.
✅ 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 summarizes the main change: adding strict infinite hook generation that gates infinite hooks to endpoints with the configured query parameter.
Linked Issues check ✅ Passed All code changes align with issue #3101: strict infinite hook generation now gates useInfinite/useSuspenseInfinite hooks only to endpoints that include the configured useInfiniteQueryParam query parameter, resolving the reported TypeScript errors.
Docstring Coverage ✅ Passed Docstring coverage is 85.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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a strict mode option to Orval Query generation so infinite (and suspense-infinite) hooks are only generated for endpoints that actually declare the configured useInfiniteQueryParam in their query params, with adapter updates and new regression fixtures/snapshots across React/Vue/Angular Query.

Changes:

  • Introduce useInfiniteRequireQueryParam in query option types + normalization (@orval/core, @orval/orval, @orval/query).
  • Gate infinite/suspense-infinite hook generation when strict mode is enabled and the configured query param isn’t present on the endpoint.
  • Add new test specification/config scenarios and extend snapshot harness to include Angular Query output.

Reviewed changes

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

Show a summary per file
File Description
tests/specifications/infinite-require-query-param.yaml New OpenAPI fixture to validate strict infinite param gating.
tests/configs/vue-query.config.ts Adds a Vue Query config scenario enabling strict infinite behavior.
tests/configs/react-query.config.ts Adds a React Query config scenario enabling strict infinite behavior.
tests/configs/angular-query.config.ts Adds an Angular Query config scenario enabling strict infinite behavior.
tests/api-generation.spec.ts Includes angular-query in snapshot generation harness.
packages/query/src/utils.ts Adds normalization support for useInfiniteRequireQueryParam.
packages/query/src/utils.test.ts Unit tests for query option normalization of the new flag.
packages/query/src/query-generator.ts Implements strict gating + passes strictness through to adapters.
packages/query/src/frameworks/vue.ts Updates Vue adapter to support strict pageParam injection behavior.
packages/query/src/frameworks/index.ts Updates shared default adapter infinite param injection to support strict mode.
packages/query/src/frameworks/angular.ts Updates Angular adapter infinite param injection to support strict mode.
packages/query/src/framework-adapter.ts Extends adapter interface to accept requireQueryParam.
packages/orval/src/utils/options.ts Normalizes useInfiniteRequireQueryParam at CLI/config layer.
packages/core/src/types.ts Adds useInfiniteRequireQueryParam to QueryOptions/NormalizedQueryOptions.
tests/snapshots/vue-query/use-infinite-require-query-param/endpoints.ts Snapshot for Vue Query strict infinite scenario.
tests/snapshots/vue-query/use-infinite-require-query-param/model/dashboardPageDto.ts Snapshot model output for Vue Query scenario.
tests/snapshots/vue-query/use-infinite-require-query-param/model/dashboardPageDtoItemsItem.ts Snapshot model output for Vue Query scenario.
tests/snapshots/vue-query/use-infinite-require-query-param/model/getFloorplanImageParams.ts Snapshot model output for Vue Query scenario.
tests/snapshots/vue-query/use-infinite-require-query-param/model/getFloorplanImageVariant.ts Snapshot model output for Vue Query scenario.
tests/snapshots/vue-query/use-infinite-require-query-param/model/index.ts Snapshot model barrel for Vue Query scenario.
tests/snapshots/vue-query/use-infinite-require-query-param/model/listDashboardsParams.ts Snapshot model output for Vue Query scenario.
tests/snapshots/react-query/use-infinite-require-query-param/endpoints.ts Snapshot for React Query strict infinite scenario.
tests/snapshots/react-query/use-infinite-require-query-param/model/dashboardPageDto.ts Snapshot model output for React Query scenario.
tests/snapshots/react-query/use-infinite-require-query-param/model/dashboardPageDtoItemsItem.ts Snapshot model output for React Query scenario.
tests/snapshots/react-query/use-infinite-require-query-param/model/getFloorplanImageParams.ts Snapshot model output for React Query scenario.
tests/snapshots/react-query/use-infinite-require-query-param/model/getFloorplanImageVariant.ts Snapshot model output for React Query scenario.
tests/snapshots/react-query/use-infinite-require-query-param/model/index.ts Snapshot model barrel for React Query scenario.
tests/snapshots/react-query/use-infinite-require-query-param/model/listDashboardsParams.ts Snapshot model output for React Query scenario.
tests/snapshots/angular-query/use-infinite-require-query-param/endpoints.ts Snapshot for Angular Query strict infinite scenario.
tests/snapshots/angular-query/use-infinite-require-query-param/model/dashboardPageDto.ts Snapshot model output for Angular Query scenario.
tests/snapshots/angular-query/use-infinite-require-query-param/model/dashboardPageDtoItemsItem.ts Snapshot model output for Angular Query scenario.
tests/snapshots/angular-query/use-infinite-require-query-param/model/getFloorplanImageParams.ts Snapshot model output for Angular Query scenario.
tests/snapshots/angular-query/use-infinite-require-query-param/model/getFloorplanImageVariant.ts Snapshot model output for Angular Query scenario.
tests/snapshots/angular-query/use-infinite-require-query-param/model/index.ts Snapshot model barrel for Angular Query scenario.
tests/snapshots/angular-query/use-infinite-require-query-param/model/listDashboardsParams.ts Snapshot model output for Angular Query scenario.
tests/snapshots/angular-query/tags-split/pets/pets.ts Adds Angular Query snapshot coverage for tags-split mode.
tests/snapshots/angular-query/tags-split/health/health.ts Adds Angular Query snapshot coverage for tags-split mode.
tests/snapshots/angular-query/tags-split/model/index.ts Adds Angular Query model snapshots for tags-split mode.
tests/snapshots/angular-query/tags-split/model/* Adds Angular Query model snapshot set for tags-split mode (pets + related types).
tests/snapshots/angular-query/split/endpoints.ts Adds Angular Query snapshot coverage for split mode.
tests/snapshots/angular-query/split/model/index.ts Adds Angular Query model snapshots for split mode.
tests/snapshots/angular-query/split/model/* Adds Angular Query model snapshot set for split mode (pets + related types).
tests/snapshots/angular-query/basic/endpoints.ts Adds Angular Query snapshot coverage for basic mode.
tests/snapshots/angular-query/basic/model/index.ts Adds Angular Query model snapshots for basic mode.
tests/snapshots/angular-query/basic/model/* Adds Angular Query model snapshot set for basic mode (pets + related types).

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

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (4)
packages/query/src/utils.test.ts (1)

71-90: Consider adding a merge-precedence regression test.

A case where global and per-query options set different useInfiniteRequireQueryParam values would protect future refactors in option merge logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/query/src/utils.test.ts` around lines 71 - 90, Add a regression test
for merge precedence of useInfiniteRequireQueryParam: call normalizeQueryOptions
with a globalOptions object (second arg or merged shape used by
normalizeQueryOptions) setting useInfiniteRequireQueryParam to one value and
pass a per-query options object to normalizeQueryOptions with the opposite
value, then assert that the returned result follows the intended precedence
(per-query option should override global). Reference normalizeQueryOptions and
the useInfiniteRequireQueryParam option in the test to ensure future refactors
preserve this override behavior.
packages/query/src/utils.ts (1)

30-32: Validate strict-mode config dependencies early.

At Line 30, useInfiniteRequireQueryParam is normalized independently. Consider failing fast when useInfiniteRequireQueryParam is true but useInfiniteQueryParam is missing, to avoid silent misconfiguration during hook generation.

Proposed guard in normalization
 export const normalizeQueryOptions = (
   queryOptions: QueryOptions = {},
   outputWorkspace: string,
 ): NormalizedQueryOptions => {
+  if (
+    queryOptions.useInfiniteRequireQueryParam &&
+    !queryOptions.useInfiniteQueryParam
+  ) {
+    throw new Error(
+      'useInfiniteRequireQueryParam requires useInfiniteQueryParam to be configured.',
+    );
+  }
+
   return {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/query/src/utils.ts` around lines 30 - 32, The normalization
currently adds useInfiniteRequireQueryParam independently which can silently
misconfigure hooks; update the normalization in utils.ts (the function that
processes queryOptions) to validate and fail fast: if
queryOptions.useInfiniteRequireQueryParam === true and the corresponding
useInfiniteQueryParam (or normalizedUseInfiniteQueryParam) is not present/true,
throw a clear Error (or invariant) naming both useInfiniteRequireQueryParam and
useInfiniteQueryParam so callers see the missing dependency during generation
instead of silently proceeding.
packages/query/src/query-generator.ts (1)

63-78: Prefer structural/top-level key detection over full-model regex matching.

Current detection relies on scanning queryParams.schema.model text and can be brittle for complex/nested model shapes. A top-level structural check will make strict gating more reliable and avoid accidental matches.

♻️ Suggested direction
-const hasQueryParamInSchema = (
-  queryParams: GetterQueryParam | undefined,
-  queryParam: string,
-): boolean => {
-  if (!queryParams?.schema.model) {
-    return false;
-  }
-
-  const escapedParam = escapeRegExp(queryParam);
-  const paramKeyRegex = new RegExp(
-    `(?:^|\\n)\\s*(?:'${escapedParam}'|\"${escapedParam}\"|${escapedParam})\\??:\\s`,
-    'm',
-  );
-
-  return paramKeyRegex.test(queryParams.schema.model);
-};
+const hasQueryParamInSchema = (
+  queryParams: GetterQueryParam | undefined,
+  queryParam: string,
+): boolean => {
+  const model = queryParams?.schema.model;
+  if (!model) return false;
+
+  // Restrict matching to top-level properties only
+  let depth = 0;
+  for (const rawLine of model.split('\n')) {
+    const line = rawLine.trim();
+    depth += (line.match(/{/g)?.length ?? 0);
+
+    if (depth === 1) {
+      const escapedParam = escapeRegExp(queryParam);
+      const topLevelKey = new RegExp(
+        `^(?:'${escapedParam}'|"${escapedParam}"|${escapedParam})\\??:\\s`,
+      );
+      if (topLevelKey.test(line)) return true;
+    }
+
+    depth -= (line.match(/}/g)?.length ?? 0);
+  }
+
+  return false;
+};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/query/src/query-generator.ts` around lines 63 - 78, Replace brittle
regex scanning in hasQueryParamInSchema with a structural top-level key check:
if queryParams?.schema.model is an object, test for the param by checking
top-level keys (e.g.,
Object.prototype.hasOwnProperty.call(queryParams.schema.model, queryParam) or
presence in schema.model.properties/top-level fields) instead of regex; only
fall back to any string-based heuristic when schema.model is a string (but
prefer parsing it into an object first or using a schema parser) so
hasQueryParamInSchema reliably detects top-level queryParam presence in
queryParams.schema.model.
tests/__snapshots__/angular-query/basic/endpoints.ts (1)

28-36: Importing Error shadows the global Error constructor.

The imported Error type from the model shadows JavaScript's built-in Error class. If any code in this file needs to throw or catch standard errors, it would inadvertently reference the imported type instead.

Since this is auto-generated code, the fix should be applied in the Orval generator—consider renaming the imported type (e.g., ApiError, PetStoreError) to avoid shadowing the global.

🔧 Suggested approach (in generator)
 import type {
   CreatePetsBody,
   CreatePetsParams,
-  Error,
+  Error as ApiError,
   ListPetsParams,
   Pet,
   PetWithTag,
   Pets,
 } from './model';

Then update all usages of Error to ApiError throughout the generated file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/__snapshots__/angular-query/basic/endpoints.ts` around lines 28 - 36,
The imported type named Error from the model shadows the global JavaScript Error
constructor; update the generator to rename this type (e.g., to ApiError or
PetStoreError) and change the import in the generated file so it reads the new
name instead of Error, then update all references in the generated code that
used Error (e.g., type annotations, return types, and interfaces in endpoints.ts
such as any usage alongside CreatePetsBody, CreatePetsParams, ListPetsParams,
Pet, PetWithTag, Pets) to the new ApiError name so the global Error remains
unshadowed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/query/src/frameworks/angular.ts`:
- Around line 97-100: The current construction overwrites caller-provided seed
values because when requireQueryParam is true it sets params[queryParam] to
pageParam even if pageParam is undefined; update the expression so that when
requireQueryParam is true you use the nullish-coalescing form (pageParam ??
params?.['${queryParam}']) instead of just pageParam to preserve an explicit
seed while keeping strict semantics; apply this change to the same expression in
the adapters that use the variables queryParam, requireQueryParam, pageParam and
params (present in angular.ts, vue.ts and index.ts) so all infinite-query
branches behave the same.

In `@tests/__snapshots__/angular-query/tags-split/health/health.ts`:
- Line 22: The imported schema name Error shadows the global Error; change the
import "import type { Error }" to a non-conflicting alias such as "import type {
Error as ErrorModel }" and update all local references from Error to ErrorModel
(e.g., the usages currently named Error in this file). Instead of editing
snapshots directly, update the Angular generator/template that emits this import
so generated files use the aliased name (ErrorModel) consistently across all
generated outputs (including the other snapshot file mentioned).

In
`@tests/__snapshots__/angular-query/use-infinite-require-query-param/endpoints.ts`:
- Around line 15-23: The import block is missing
CreateSuspenseInfiniteQueryOptions from `@tanstack/angular-query-experimental`
which causes compile failures where CreateSuspenseInfiniteQueryOptions is
referenced; update the type import list (the block that currently imports
CreateInfiniteQueryOptions, CreateInfiniteQueryResult, CreateQueryOptions,
CreateQueryResult, InfiniteData, QueryFunction, QueryKey) to also include
CreateSuspenseInfiniteQueryOptions so the referenced types resolve for the
functions/classes using CreateSuspenseInfiniteQueryOptions.

In
`@tests/__snapshots__/react-query/use-infinite-require-query-param/endpoints.ts`:
- Around line 39-47: The test stub currently declares the image response types
(getFloorplanImageResponse200 / getFloorplanImageResponseSuccess /
getFloorplanImageResponse) as Blob but the implementation is parsing the body as
text and running JSON.parse (which fails for binary image payloads); update the
response handling where the endpoint reads the body to call res.blob() instead
of res.text()/JSON.parse, return that Blob on success, and ensure any caller
expecting getFloorplanImageResponse uses the Blob value; apply the same change
to the other affected endpoint handling around the 68-85 region.

In `@tests/__snapshots__/vue-query/use-infinite-require-query-param/endpoints.ts`:
- Around line 7-18: The file is missing imports for the suspense-infinite API
used later; add the missing symbols from '@tanstack/vue-query'—specifically
import UseSuspenseInfiniteQueryOptions and useSuspenseInfiniteQuery (and any
related return types like UseSuspenseInfiniteQueryReturnType if used) into the
existing import list so references to UseSuspenseInfiniteQueryOptions and
useSuspenseInfiniteQuery compile.

---

Nitpick comments:
In `@packages/query/src/query-generator.ts`:
- Around line 63-78: Replace brittle regex scanning in hasQueryParamInSchema
with a structural top-level key check: if queryParams?.schema.model is an
object, test for the param by checking top-level keys (e.g.,
Object.prototype.hasOwnProperty.call(queryParams.schema.model, queryParam) or
presence in schema.model.properties/top-level fields) instead of regex; only
fall back to any string-based heuristic when schema.model is a string (but
prefer parsing it into an object first or using a schema parser) so
hasQueryParamInSchema reliably detects top-level queryParam presence in
queryParams.schema.model.

In `@packages/query/src/utils.test.ts`:
- Around line 71-90: Add a regression test for merge precedence of
useInfiniteRequireQueryParam: call normalizeQueryOptions with a globalOptions
object (second arg or merged shape used by normalizeQueryOptions) setting
useInfiniteRequireQueryParam to one value and pass a per-query options object to
normalizeQueryOptions with the opposite value, then assert that the returned
result follows the intended precedence (per-query option should override
global). Reference normalizeQueryOptions and the useInfiniteRequireQueryParam
option in the test to ensure future refactors preserve this override behavior.

In `@packages/query/src/utils.ts`:
- Around line 30-32: The normalization currently adds
useInfiniteRequireQueryParam independently which can silently misconfigure
hooks; update the normalization in utils.ts (the function that processes
queryOptions) to validate and fail fast: if
queryOptions.useInfiniteRequireQueryParam === true and the corresponding
useInfiniteQueryParam (or normalizedUseInfiniteQueryParam) is not present/true,
throw a clear Error (or invariant) naming both useInfiniteRequireQueryParam and
useInfiniteQueryParam so callers see the missing dependency during generation
instead of silently proceeding.

In `@tests/__snapshots__/angular-query/basic/endpoints.ts`:
- Around line 28-36: The imported type named Error from the model shadows the
global JavaScript Error constructor; update the generator to rename this type
(e.g., to ApiError or PetStoreError) and change the import in the generated file
so it reads the new name instead of Error, then update all references in the
generated code that used Error (e.g., type annotations, return types, and
interfaces in endpoints.ts such as any usage alongside CreatePetsBody,
CreatePetsParams, ListPetsParams, Pet, PetWithTag, Pets) to the new ApiError
name so the global Error remains unshadowed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 16d58673-f16c-4e9d-a8f9-17e374fb4e6a

📥 Commits

Reviewing files that changed from the base of the PR and between b0a8e8c and d85d41e.

📒 Files selected for processing (99)
  • packages/core/src/types.ts
  • packages/orval/src/utils/options.ts
  • packages/query/src/framework-adapter.ts
  • packages/query/src/frameworks/angular.ts
  • packages/query/src/frameworks/index.ts
  • packages/query/src/frameworks/vue.ts
  • packages/query/src/query-generator.ts
  • packages/query/src/utils.test.ts
  • packages/query/src/utils.ts
  • tests/__snapshots__/angular-query/basic/endpoints.ts
  • tests/__snapshots__/angular-query/basic/model/cat.ts
  • tests/__snapshots__/angular-query/basic/model/catType.ts
  • tests/__snapshots__/angular-query/basic/model/createPetsBody.ts
  • tests/__snapshots__/angular-query/basic/model/createPetsParams.ts
  • tests/__snapshots__/angular-query/basic/model/createPetsSort.ts
  • tests/__snapshots__/angular-query/basic/model/dachshund.ts
  • tests/__snapshots__/angular-query/basic/model/dachshundBreed.ts
  • tests/__snapshots__/angular-query/basic/model/dog.ts
  • tests/__snapshots__/angular-query/basic/model/dogType.ts
  • tests/__snapshots__/angular-query/basic/model/error.ts
  • tests/__snapshots__/angular-query/basic/model/index.ts
  • tests/__snapshots__/angular-query/basic/model/labradoodle.ts
  • tests/__snapshots__/angular-query/basic/model/labradoodleBreed.ts
  • tests/__snapshots__/angular-query/basic/model/listPetsParams.ts
  • tests/__snapshots__/angular-query/basic/model/listPetsSort.ts
  • tests/__snapshots__/angular-query/basic/model/pet.ts
  • tests/__snapshots__/angular-query/basic/model/petCallingCode.ts
  • tests/__snapshots__/angular-query/basic/model/petCountry.ts
  • tests/__snapshots__/angular-query/basic/model/petWithTag.ts
  • tests/__snapshots__/angular-query/basic/model/pets.ts
  • tests/__snapshots__/angular-query/split/endpoints.ts
  • tests/__snapshots__/angular-query/split/model/cat.ts
  • tests/__snapshots__/angular-query/split/model/catType.ts
  • tests/__snapshots__/angular-query/split/model/createPetsBody.ts
  • tests/__snapshots__/angular-query/split/model/createPetsParams.ts
  • tests/__snapshots__/angular-query/split/model/createPetsSort.ts
  • tests/__snapshots__/angular-query/split/model/dachshund.ts
  • tests/__snapshots__/angular-query/split/model/dachshundBreed.ts
  • tests/__snapshots__/angular-query/split/model/dog.ts
  • tests/__snapshots__/angular-query/split/model/dogType.ts
  • tests/__snapshots__/angular-query/split/model/error.ts
  • tests/__snapshots__/angular-query/split/model/index.ts
  • tests/__snapshots__/angular-query/split/model/labradoodle.ts
  • tests/__snapshots__/angular-query/split/model/labradoodleBreed.ts
  • tests/__snapshots__/angular-query/split/model/listPetsParams.ts
  • tests/__snapshots__/angular-query/split/model/listPetsSort.ts
  • tests/__snapshots__/angular-query/split/model/pet.ts
  • tests/__snapshots__/angular-query/split/model/petCallingCode.ts
  • tests/__snapshots__/angular-query/split/model/petCountry.ts
  • tests/__snapshots__/angular-query/split/model/petWithTag.ts
  • tests/__snapshots__/angular-query/split/model/pets.ts
  • tests/__snapshots__/angular-query/tags-split/health/health.ts
  • tests/__snapshots__/angular-query/tags-split/model/cat.ts
  • tests/__snapshots__/angular-query/tags-split/model/catType.ts
  • tests/__snapshots__/angular-query/tags-split/model/createPetsBody.ts
  • tests/__snapshots__/angular-query/tags-split/model/createPetsParams.ts
  • tests/__snapshots__/angular-query/tags-split/model/createPetsSort.ts
  • tests/__snapshots__/angular-query/tags-split/model/dachshund.ts
  • tests/__snapshots__/angular-query/tags-split/model/dachshundBreed.ts
  • tests/__snapshots__/angular-query/tags-split/model/dog.ts
  • tests/__snapshots__/angular-query/tags-split/model/dogType.ts
  • tests/__snapshots__/angular-query/tags-split/model/error.ts
  • tests/__snapshots__/angular-query/tags-split/model/index.ts
  • tests/__snapshots__/angular-query/tags-split/model/labradoodle.ts
  • tests/__snapshots__/angular-query/tags-split/model/labradoodleBreed.ts
  • tests/__snapshots__/angular-query/tags-split/model/listPetsParams.ts
  • tests/__snapshots__/angular-query/tags-split/model/listPetsSort.ts
  • tests/__snapshots__/angular-query/tags-split/model/pet.ts
  • tests/__snapshots__/angular-query/tags-split/model/petCallingCode.ts
  • tests/__snapshots__/angular-query/tags-split/model/petCountry.ts
  • tests/__snapshots__/angular-query/tags-split/model/petWithTag.ts
  • tests/__snapshots__/angular-query/tags-split/model/pets.ts
  • tests/__snapshots__/angular-query/tags-split/pets/pets.ts
  • tests/__snapshots__/angular-query/use-infinite-require-query-param/endpoints.ts
  • tests/__snapshots__/angular-query/use-infinite-require-query-param/model/dashboardPageDto.ts
  • tests/__snapshots__/angular-query/use-infinite-require-query-param/model/dashboardPageDtoItemsItem.ts
  • tests/__snapshots__/angular-query/use-infinite-require-query-param/model/getFloorplanImageParams.ts
  • tests/__snapshots__/angular-query/use-infinite-require-query-param/model/getFloorplanImageVariant.ts
  • tests/__snapshots__/angular-query/use-infinite-require-query-param/model/index.ts
  • tests/__snapshots__/angular-query/use-infinite-require-query-param/model/listDashboardsParams.ts
  • tests/__snapshots__/react-query/use-infinite-require-query-param/endpoints.ts
  • tests/__snapshots__/react-query/use-infinite-require-query-param/model/dashboardPageDto.ts
  • tests/__snapshots__/react-query/use-infinite-require-query-param/model/dashboardPageDtoItemsItem.ts
  • tests/__snapshots__/react-query/use-infinite-require-query-param/model/getFloorplanImageParams.ts
  • tests/__snapshots__/react-query/use-infinite-require-query-param/model/getFloorplanImageVariant.ts
  • tests/__snapshots__/react-query/use-infinite-require-query-param/model/index.ts
  • tests/__snapshots__/react-query/use-infinite-require-query-param/model/listDashboardsParams.ts
  • tests/__snapshots__/vue-query/use-infinite-require-query-param/endpoints.ts
  • tests/__snapshots__/vue-query/use-infinite-require-query-param/model/dashboardPageDto.ts
  • tests/__snapshots__/vue-query/use-infinite-require-query-param/model/dashboardPageDtoItemsItem.ts
  • tests/__snapshots__/vue-query/use-infinite-require-query-param/model/getFloorplanImageParams.ts
  • tests/__snapshots__/vue-query/use-infinite-require-query-param/model/getFloorplanImageVariant.ts
  • tests/__snapshots__/vue-query/use-infinite-require-query-param/model/index.ts
  • tests/__snapshots__/vue-query/use-infinite-require-query-param/model/listDashboardsParams.ts
  • tests/api-generation.spec.ts
  • tests/configs/angular-query.config.ts
  • tests/configs/react-query.config.ts
  • tests/configs/vue-query.config.ts
  • tests/specifications/infinite-require-query-param.yaml

@melloware
Copy link
Copy Markdown
Collaborator

@the-inconvenience-store looks like build is failing and CodeRabbit suggestions?

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/query/src/query-generator.ts`:
- Around line 63-78: The current hasQueryParamInSchema uses a regex
(paramKeyRegex) against queryParams.schema.model which over-matches nested keys
(e.g., properties with the same name deeper in the type), causing false
positives; update the check to reliably detect only top-level properties by
parsing the TypeScript/JSON model text instead of relying solely on regex, e.g.,
use the TypeScript compiler API / ts-morph to parse queryParams.schema.model and
inspect the top-level type or object literal properties for queryParam, or if
you must keep a text-based approach tighten the match in hasQueryParamInSchema
so the pattern disallows matches preceded by a dot/identifier or nested context
(ensure no '.' or identifier char immediately before the match and require it to
be a direct property of the top-level object); change function
hasQueryParamInSchema to use the parser-based top-level-key check (or stricter
regex) on queryParams.schema.model and remove the existing paramKeyRegex usage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8e371193-4f98-49e8-a884-b6577403bc42

📥 Commits

Reviewing files that changed from the base of the PR and between d85d41e and 9acebe5.

📒 Files selected for processing (5)
  • packages/orval/src/utils/options.ts
  • packages/query/src/frameworks/angular.ts
  • packages/query/src/frameworks/index.ts
  • packages/query/src/frameworks/vue.ts
  • packages/query/src/query-generator.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/query/src/frameworks/angular.ts

@melloware
Copy link
Copy Markdown
Collaborator

@the-inconvenience-store is there any way to implement this without another new param? Also if there is a new parameter it means you need to update the /docs

@the-inconvenience-store
Copy link
Copy Markdown
Author

the-inconvenience-store commented Mar 18, 2026

@the-inconvenience-store is there any way to implement this without another new param? Also if there is a new parameter it means you need to update the /docs

yeah i just didn't want to make any changes that might confuse/break people's current setups. of course it could be automatic, so i suppose it's up to you if you want to release it as breaking change for v9 instead of a minor feat.

let me know your preference and i'll make edits accordingly

cheers

@melloware
Copy link
Copy Markdown
Collaborator

so my thoguht is if this is a string useInfiniteQueryParam?: string; could you just introduce a new mode there?

@the-inconvenience-store
Copy link
Copy Markdown
Author

so my thoguht is if this is a string useInfiniteQueryParam?: string; could you just introduce a new mode there?

would you rather:
make the strict mode implicit if useInfiniteQueryParam is not undefined. if they provide a string then we implicitly apply the new strict mode behaviour. alternatively, change the type to an object for example:

...
useInfiniteQueryParam : {
    queryParam: string // <-- current query param behaviour
    strictMode: bool // <-- toggle new behaviour
} | string // <-- backwards compat with current query param behaviour

@melloware
Copy link
Copy Markdown
Collaborator

I think i like your implicitly apply this behavior option.

@melloware melloware added the tanstack-query TanStack Query related issue label Mar 19, 2026
@the-inconvenience-store
Copy link
Copy Markdown
Author

I think i like your implicitly apply this behavior option.

🫡

will push my changes soon, cheers!

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/query/src/query-generator.ts`:
- Around line 898-905: The warning is emitted whenever useInfiniteQueryParam is
configured but missing, even for operations that never request an infinite hook;
update the guard so createLogger().warn(...) only runs when this specific
operation actually requests an infinite query (introduce or reuse a
per-operation boolean like operationRequestsInfinite) — e.g. only call
createLogger().warn if operationRequestsInfinite && effectiveInfiniteQueryParam
&& !hasConfiguredInfiniteQueryParam, and compute canGenerateInfiniteQuery
accordingly (e.g. const canGenerateInfiniteQuery = !operationRequestsInfinite ?
true : (!effectiveInfiniteQueryParam || hasConfiguredInfiniteQueryParam)); apply
the same change to the other similar block(s) around the
canGenerateInfiniteQuery logic (references: effectiveInfiniteQueryParam,
hasConfiguredInfiniteQueryParam, createLogger().warn, canGenerateInfiniteQuery,
operationName).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ffc2f7b7-8da6-4983-8e4e-6fa7f7b9286d

📥 Commits

Reviewing files that changed from the base of the PR and between 7e1b8b4 and bfd5573.

⛔ Files ignored due to path filters (14)
  • samples/svelte-query/custom-fetch/src/gen/models/cat.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/catType.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/createPetsBodyItem.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/dachshund.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/dachshundBreed.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/dog.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/dogType.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/error.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/index.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/listPetsParams.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/pet.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/models/pets.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/pets/pets.msw.ts is excluded by !**/gen/**
  • samples/svelte-query/custom-fetch/src/gen/pets/pets.ts is excluded by !**/gen/**
📒 Files selected for processing (45)
  • docs/content/docs/reference/configuration/output.mdx
  • packages/query/src/framework-adapter.ts
  • packages/query/src/query-generator.ts
  • samples/angular-app/src/api/endpoints/index.msw.ts
  • samples/angular-app/src/api/endpoints/pets/pets.msw.ts
  • samples/angular-app/src/api/endpoints/pets/pets.service.ts
  • samples/angular-app/src/api/model/createPetsBody.ts
  • samples/angular-app/src/api/model/createPetsBodyStatus.ts
  • samples/angular-app/src/api/model/error.ts
  • samples/angular-app/src/api/model/index.ts
  • samples/angular-app/src/api/model/listPetsParams.ts
  • samples/angular-app/src/api/model/pet.ts
  • samples/angular-app/src/api/model/petStatus.ts
  • samples/angular-app/src/api/model/pets.ts
  • samples/angular-app/src/api/model/searchPetsParams.ts
  • samples/angular-app/src/api/model/searchPetsStatus.ts
  • samples/react-query/basic/src/api/endpoints/petstoreFromFileSpecWithTransformer.ts
  • samples/vue-query/vue-query-basic/src/api/endpoints/petstoreFromFileSpecWithTransformer.ts
  • tests/__snapshots__/react-query/error-type/endpoints.ts
  • tests/__snapshots__/react-query/mutator-client/endpoints.ts
  • tests/__snapshots__/react-query/mutator-multi-arguments/endpoints.ts
  • tests/__snapshots__/react-query/mutator/endpoints.ts
  • tests/__snapshots__/react-query/use-infinite-query-param-implicit/endpoints.ts
  • tests/__snapshots__/react-query/use-infinite-query-param-implicit/model/dashboardPageDto.ts
  • tests/__snapshots__/react-query/use-infinite-query-param-implicit/model/dashboardPageDtoItemsItem.ts
  • tests/__snapshots__/react-query/use-infinite-query-param-implicit/model/getFloorplanImageParams.ts
  • tests/__snapshots__/react-query/use-infinite-query-param-implicit/model/getFloorplanImageVariant.ts
  • tests/__snapshots__/react-query/use-infinite-query-param-implicit/model/index.ts
  • tests/__snapshots__/react-query/use-infinite-query-param-implicit/model/listDashboardsParams.ts
  • tests/__snapshots__/svelte-query/mutator/endpoints.ts
  • tests/__snapshots__/svelte-query/named-parameters/endpoints.ts
  • tests/__snapshots__/svelte-query/petstore/endpoints.ts
  • tests/__snapshots__/vue-query/mutator/endpoints.ts
  • tests/__snapshots__/vue-query/petstore/endpoints.ts
  • tests/__snapshots__/vue-query/use-infinite-query-param-implicit/endpoints.ts
  • tests/__snapshots__/vue-query/use-infinite-query-param-implicit/model/dashboardPageDto.ts
  • tests/__snapshots__/vue-query/use-infinite-query-param-implicit/model/dashboardPageDtoItemsItem.ts
  • tests/__snapshots__/vue-query/use-infinite-query-param-implicit/model/getFloorplanImageParams.ts
  • tests/__snapshots__/vue-query/use-infinite-query-param-implicit/model/getFloorplanImageVariant.ts
  • tests/__snapshots__/vue-query/use-infinite-query-param-implicit/model/index.ts
  • tests/__snapshots__/vue-query/use-infinite-query-param-implicit/model/listDashboardsParams.ts
  • tests/configs/angular-query.config.ts
  • tests/configs/react-query.config.ts
  • tests/configs/vue-query.config.ts
  • tests/specifications/infinite-query-param-implicit.yaml
💤 Files with no reviewable changes (13)
  • samples/angular-app/src/api/model/createPetsBody.ts
  • samples/angular-app/src/api/endpoints/index.msw.ts
  • samples/angular-app/src/api/model/listPetsParams.ts
  • samples/angular-app/src/api/model/pet.ts
  • samples/angular-app/src/api/model/pets.ts
  • samples/angular-app/src/api/model/searchPetsParams.ts
  • samples/angular-app/src/api/model/createPetsBodyStatus.ts
  • samples/angular-app/src/api/model/petStatus.ts
  • samples/angular-app/src/api/model/index.ts
  • samples/angular-app/src/api/model/searchPetsStatus.ts
  • samples/angular-app/src/api/model/error.ts
  • samples/angular-app/src/api/endpoints/pets/pets.msw.ts
  • samples/angular-app/src/api/endpoints/pets/pets.service.ts
✅ Files skipped from review due to trivial changes (13)
  • tests/snapshots/react-query/use-infinite-query-param-implicit/model/dashboardPageDtoItemsItem.ts
  • docs/content/docs/reference/configuration/output.mdx
  • tests/snapshots/vue-query/use-infinite-query-param-implicit/model/getFloorplanImageParams.ts
  • tests/snapshots/react-query/use-infinite-query-param-implicit/model/listDashboardsParams.ts
  • tests/snapshots/react-query/use-infinite-query-param-implicit/model/dashboardPageDto.ts
  • tests/snapshots/react-query/use-infinite-query-param-implicit/model/getFloorplanImageParams.ts
  • tests/snapshots/vue-query/use-infinite-query-param-implicit/model/listDashboardsParams.ts
  • tests/snapshots/react-query/use-infinite-query-param-implicit/model/index.ts
  • tests/snapshots/vue-query/use-infinite-query-param-implicit/model/dashboardPageDtoItemsItem.ts
  • tests/snapshots/vue-query/use-infinite-query-param-implicit/model/dashboardPageDto.ts
  • tests/snapshots/vue-query/use-infinite-query-param-implicit/model/getFloorplanImageVariant.ts
  • tests/snapshots/react-query/use-infinite-query-param-implicit/model/getFloorplanImageVariant.ts
  • tests/snapshots/vue-query/use-infinite-query-param-implicit/model/index.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/query/src/framework-adapter.ts
  • tests/configs/vue-query.config.ts
  • tests/configs/angular-query.config.ts

@melloware
Copy link
Copy Markdown
Collaborator

looks like Snapshots are failing now

@melloware
Copy link
Copy Markdown
Collaborator

looks like conflicts need to be resolved

@melloware melloware marked this pull request as draft March 24, 2026 05:00
@the-inconvenience-store
Copy link
Copy Markdown
Author

@melloware resolved, cheers :)

@melloware
Copy link
Copy Markdown
Collaborator

Looks like SNAPSHOTs are failing now

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.

useInfiniteQueryParam should only be added to hooks with that query parameter present

4 participants