feat(query): add useFlatInput option to merge params into a single object#3167
feat(query): add useFlatInput option to merge params into a single object#3167inas-sirhan wants to merge 10 commits into
Conversation
…ject
- Add useFlatInput?: boolean config under override
- Queries: destructure path params by name, rest spread for query params
- Mutations: destructure path + query param fields by name, rest spread for body
- Uses TypeScript intersection types (e.g. { userId: number } & GetUserOrdersParams)
- Throws error on duplicate field names across path/query params
- Throws error if used together with useNamedParameters
- Headers stay as a separate parameter
- Snapshot tests for petstore, multi-params, and path+query+body cases
Closes orval-labs#3160
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds an optional flat-input generation mode ( Changes
Sequence Diagram(s)sequenceDiagram
participant Gen as Generator
participant Val as FlatInputChecker
participant Adapter as FrameworkAdapter
participant Runtime as GeneratedHook/Mutation
Gen->>Val: collect prop names + queryParams.fieldNames
Val-->>Gen: return OK / throw duplicate-name Error
Gen->>Adapter: emit definitions (include overrideVariableType when flat)
Adapter->>Runtime: generate hook/mutation args & types (uses overrideVariableType)
Runtime->>Runtime: runtime call uses flattened args shape when enabled
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 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/flat-input.ts`:
- Around line 20-29: The duplicate-name check currently builds allNames from
pathParamNames and queryFieldNames only, so body fields are not validated;
update useFlatInput to also collect body field names (e.g.,
requestBody.fieldNames or derive bodyFieldNames from the operation's requestBody
schema) and include them in allNames (const allNames = [...pathParamNames,
...queryFieldNames, ...bodyFieldNames]); keep using the existing seen Set and
throw the same Error (including operationName) when a duplicate is found so
path, query, and body field name collisions are rejected consistently.
In `@packages/query/src/mutation-generator.ts`:
- Around line 127-155: The generated flat-input type string stored in
definitions is sometimes already an intersection like "{ orgId: string } &
SearchItemsParams & SearchItemsBody" but later code wraps it again with
"{${definitions}}", producing "{{ ... }}" invalid TS; update the flat-input
branch in mutation-generator.ts (the code using useFlatInput, definitions and
flatMutationCallArgs) to detect when definitions is already an
object/intersection (e.g., startsWith('{') or contains '&') and in that case
pass definitions directly instead of wrapping it in another "{...}"; keep the
existing behavior for single plain types so single-type cases still get wrapped
as an object when needed.
In `@packages/query/src/query-generator.ts`:
- Around line 388-393: The current hasMultiplePropTypes check only counts
categories and fails for cases like multiple path params; change it to count
actual exposed props instead of categories. Replace the boolean expression for
hasMultiplePropTypes with a totalProps calculation that sums pathParams.length
plus the number of props in queryParamProp (if present) plus the number of props
in bodyProp (if present), then set hasMultiplePropTypes = totalProps > 1 so
useFlatInput will flatten when there are multiple exposed inputs (mirror the
mutation generator's props.length > 1 behavior).
- Around line 413-426: The new queryOptionsFn signature was changed to a single
flattened object (useFlatInput / flatInputDestructure) but callers still build
and pass the old split props (queryProps) into generatePrefetch and into
queryProperties/httpFunctionProps, causing mismatched args; update the code so
that when useFlatInput is true you derive queryProperties/httpFunctionProps from
the flattened shape (flatProps / flatInputDestructure) or simply pass flatProps
into generatePrefetch and any caller that previously used queryProps, ensuring
queryProperties, httpFunctionProps and generatePrefetch all consume the same
flat shape as queryOptionsFn.
In `@tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts`:
- Around line 88-89: useGetUsersUserIdOrders is calling
getGetUsersUserIdOrdersQueryOptions with positional args (userId, params,
options) but the helper's signature expects a single flat object ({ userId,
...params }) and optional options; update the call site in
useGetUsersUserIdOrders to pass one object merging userId and params (e.g., {
userId, ...params }) as the first argument and pass options as the second
argument so the query key is built from the correct shape for
getGetUsersUserIdOrdersQueryOptions.
- Around line 80-85: The query key builder getGetUsersUserIdOrdersQueryKey
currently treats an empty params object as present and appends it to the key,
causing cache forks; update the function to only append params when they are
non-null/undefined AND not an empty object (e.g., check params &&
Object.keys(params).length > 0) so getGetUsersUserIdOrdersQueryKey(userId) and
getGetUsersUserIdOrdersQueryKey(userId, {}) produce the same key; apply the same
empty-object guard to the other similar query key builders in this diff.
In `@tests/__snapshots__/react-query/flat-input-path-query-body/endpoints.ts`:
- Around line 77-79: The emitted mutation types and call order are wrong: remove
the stray double braces so the generic target type becomes "{ orgId: string } &
SearchItemsParams & SearchItemsBody" (fix both getSearchItemsMutationOptions and
useSearchItems) and correct the mutationFn invocation to call searchItems(orgId,
data, { page, limit }, fetchOptions) to match the function signature
(searchItems(orgId, searchItemsBody, params?, options?)). Ensure mutationFn
references the same parameter names used in the file (e.g., orgId, data, page,
limit, fetchOptions) and update both occurrences noted
(getSearchItemsMutationOptions, useSearchItems, and the mutationFn block).
In
`@tests/__snapshots__/react-query/flat-input-path-query-body/model/searchItemsParams.ts`:
- Around line 8-11: The exported type alias SearchItemsParams has its properties
(page, limit) unindented; update the generator/pretty-printer that renders
exported type aliases so that properties inside a type block are prefixed with
two spaces like other generated types (ensure the rendering branch that outputs
"export type <Name> = {" indents subsequent property lines and closing "};");
locate the code that formats/renderTypeAlias or the snapshot emitter for the
react-query flat-input-path-query-body model and adjust the indentation logic so
page and limit are emitted with two-space indentation consistent with other
types.
In `@tests/__snapshots__/react-query/flat-input-petstore/endpoints.ts`:
- Around line 244-246: The generated TypeScript has three issues: the variable
type is emitted as "{CreatePetsParams & CreatePetsBody}" (invalid — remove the
braces), the required CreatePetsHeaders parameter is missing from
getCreatePetsMutationOptions and useCreatePets (add a headers?:
CreatePetsHeaders parameter and thread it through), and the createPets call uses
the wrong argument order; change calls from createPets({ limit, sort }, data,
fetchOptions) to createPets(data, { limit, sort }, headers, fetchOptions).
Update the UseMutationOptions generic type to use CreatePetsParams &
CreatePetsBody (without braces) and apply the same fixes to the other
occurrences noted (around the other get*/use* functions at the referenced
blocks).
In `@tests/configs/react-query.config.ts`:
- Around line 776-823: In the React Query configs flatInputPetstore,
flatInputMultiParams, and flatInputPathQueryBody the output option uses the
unsupported key prettier: true; replace each occurrence with formatter:
'prettier' so Orval recognizes and applies formatting—update the output objects
inside flatInputPetstore, flatInputMultiParams, and flatInputPathQueryBody to
use formatter: 'prettier' instead of prettier: true.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9ed130db-738e-4f22-b6f6-0be9b94508a9
📒 Files selected for processing (43)
packages/core/src/getters/query-params.tspackages/core/src/types.tspackages/query/src/flat-input.tspackages/query/src/mutation-generator.tspackages/query/src/query-generator.tstests/__snapshots__/react-query/flat-input-multi-params/endpoints.tstests/__snapshots__/react-query/flat-input-multi-params/model/getUsersUserIdOrdersParams.tstests/__snapshots__/react-query/flat-input-multi-params/model/getUsersUserIdOrdersStatus.tstests/__snapshots__/react-query/flat-input-multi-params/model/index.tstests/__snapshots__/react-query/flat-input-path-query-body/endpoints.tstests/__snapshots__/react-query/flat-input-path-query-body/model/index.tstests/__snapshots__/react-query/flat-input-path-query-body/model/searchItems200.tstests/__snapshots__/react-query/flat-input-path-query-body/model/searchItems200ResultsItem.tstests/__snapshots__/react-query/flat-input-path-query-body/model/searchItemsBody.tstests/__snapshots__/react-query/flat-input-path-query-body/model/searchItemsBodyFilters.tstests/__snapshots__/react-query/flat-input-path-query-body/model/searchItemsParams.tstests/__snapshots__/react-query/flat-input-petstore/endpoints.tstests/__snapshots__/react-query/flat-input-petstore/model/cat.tstests/__snapshots__/react-query/flat-input-petstore/model/catType.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsBody.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsHeaders.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsParams.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsSort.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsXExample.tstests/__snapshots__/react-query/flat-input-petstore/model/dachshund.tstests/__snapshots__/react-query/flat-input-petstore/model/dachshundBreed.tstests/__snapshots__/react-query/flat-input-petstore/model/dog.tstests/__snapshots__/react-query/flat-input-petstore/model/dogType.tstests/__snapshots__/react-query/flat-input-petstore/model/error.tstests/__snapshots__/react-query/flat-input-petstore/model/index.tstests/__snapshots__/react-query/flat-input-petstore/model/labradoodle.tstests/__snapshots__/react-query/flat-input-petstore/model/labradoodleBreed.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsHeaders.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsParams.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsSort.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsXExample.tstests/__snapshots__/react-query/flat-input-petstore/model/pet.tstests/__snapshots__/react-query/flat-input-petstore/model/petCallingCode.tstests/__snapshots__/react-query/flat-input-petstore/model/petCountry.tstests/__snapshots__/react-query/flat-input-petstore/model/petWithTag.tstests/__snapshots__/react-query/flat-input-petstore/model/pets.tstests/configs/react-query.config.tstests/specifications/flat-input-with-body-query.yaml
| const queryFieldNames = queryParams?.fieldNames ?? []; | ||
|
|
||
| const allNames = [...pathParamNames, ...queryFieldNames]; | ||
| const seen = new Set<string>(); | ||
|
|
||
| for (const name of allNames) { | ||
| if (seen.has(name)) { | ||
| throw new Error( | ||
| `useFlatInput: duplicate parameter name "${name}" found in operation "${operationName}". ` + | ||
| `Path params, query params, and body fields must have unique names when using useFlatInput.`, |
There was a problem hiding this comment.
Also validate request-body field names here.
allNames only contains path and query names. If the body also exposes page, limit, or orgId, flat-input generation will silently pull that field out of ...data instead of rejecting the operation, even though this helper says body collisions are covered.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/query/src/flat-input.ts` around lines 20 - 29, The duplicate-name
check currently builds allNames from pathParamNames and queryFieldNames only, so
body fields are not validated; update useFlatInput to also collect body field
names (e.g., requestBody.fieldNames or derive bodyFieldNames from the
operation's requestBody schema) and include them in allNames (const allNames =
[...pathParamNames, ...queryFieldNames, ...bodyFieldNames]); keep using the
existing seen Set and throw the same Error (including operationName) when a
duplicate is found so path, query, and body field name collisions are rejected
consistently.
| const hasMultiplePropTypes = | ||
| (pathParams.length > 0 ? 1 : 0) + | ||
| (queryParamProp ? 1 : 0) + | ||
| (bodyProp ? 1 : 0) > | ||
| 1; | ||
|
|
There was a problem hiding this comment.
useFlatInput still won't flatten queries with only path params.
This check only counts prop categories, not actual exposed inputs. A GET with two path params still evaluates to one category, so queries keep positional args even though the mutation generator flattens the same shape with props.length > 1.
🤖 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 388 - 393, The current
hasMultiplePropTypes check only counts categories and fails for cases like
multiple path params; change it to count actual exposed props instead of
categories. Replace the boolean expression for hasMultiplePropTypes with a
totalProps calculation that sums pathParams.length plus the number of props in
queryParamProp (if present) plus the number of props in bodyProp (if present),
then set hasMultiplePropTypes = totalProps > 1 so useFlatInput will flatten when
there are multiple exposed inputs (mirror the mutation generator's props.length
> 1 behavior).
| if (queryParamProp && bodyProp) { | ||
| const knownNames = [...pathNames, ...queryFieldNames]; | ||
| flatInputDestructure = `{ ${[...knownNames, `...${bodyProp.name}`].join(', ')} }: ${flatInputType},`; | ||
| } else if (queryParamProp) { | ||
| flatInputDestructure = `{ ${[...pathNames, '...params'].join(', ')} }: ${flatInputType},`; | ||
| } else if (bodyProp) { | ||
| flatInputDestructure = `{ ${[...pathNames, `...${bodyProp.name}`].join(', ')} }: ${flatInputType},`; | ||
| } | ||
| } | ||
|
|
||
| const flatProps = | ||
| useFlatInput && flatInputDestructure ? flatInputDestructure : queryProps; | ||
|
|
||
| const queryOptionsFn = `export const ${queryOptionsFnName} = <TData = ${TData}, TError = ${errorType}>(${httpFirstParam}${flatProps} ${queryArgumentsForOptions}) => { |
There was a problem hiding this comment.
The new flat queryOptionsFn signature doesn't match its existing callers.
This branch changes queryOptionsFn to accept a single flattened object, but queryProperties / httpFunctionProps were already derived from the pre-flat prop shape, and Lines 498-506 still feed queryProps into generatePrefetch(). The new searchItems path+query+body case is exactly this shape, so the emitted query options/hooks keep calling the old split signature with missing or positional args.
🤖 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 413 - 426, The new
queryOptionsFn signature was changed to a single flattened object (useFlatInput
/ flatInputDestructure) but callers still build and pass the old split props
(queryProps) into generatePrefetch and into queryProperties/httpFunctionProps,
causing mismatched args; update the code so that when useFlatInput is true you
derive queryProperties/httpFunctionProps from the flattened shape (flatProps /
flatInputDestructure) or simply pass flatProps into generatePrefetch and any
caller that previously used queryProps, ensuring queryProperties,
httpFunctionProps and generatePrefetch all consume the same flat shape as
queryOptionsFn.
| export const getGetUsersUserIdOrdersQueryKey = (userId: number, | ||
| params?: GetUsersUserIdOrdersParams,) => { | ||
| return [ | ||
| `/users/${userId}/orders`, ...(params ? [params] : []) | ||
| ] as const; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Expect different outputs here; the second key shows the extra empty object
# produced by the current flat-input rest pattern.
node - <<'NODE'
const getKey = (userId, params) => [`/users/${userId}/orders`, ...(params ? [params] : [])];
const fromFlatInput = ({ userId, ...params }) => getKey(userId, params);
console.log(JSON.stringify(getKey(1)));
console.log(JSON.stringify(fromFlatInput({ userId: 1 })));
NODERepository: orval-labs/orval
Length of output: 102
🏁 Script executed:
cd /repo && find . -name "endpoints.ts" -path "*react-query/flat-input-multi-params*" | head -5Repository: orval-labs/orval
Length of output: 115
🏁 Script executed:
cd /repo && head -100 tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | cat -nRepository: orval-labs/orval
Length of output: 115
🏁 Script executed:
cd /repo && sed -n '50,120p' tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | cat -nRepository: orval-labs/orval
Length of output: 115
🏁 Script executed:
pwd && ls -la | head -20Repository: orval-labs/orval
Length of output: 1295
🏁 Script executed:
find . -name "endpoints.ts" -path "*flat-input-multi-params*" 2>/dev/null | head -3Repository: orval-labs/orval
Length of output: 130
🏁 Script executed:
cat -n tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | sed -n '1,120p'Repository: orval-labs/orval
Length of output: 4825
🏁 Script executed:
grep -n "getGetUsersUserIdOrders" tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | head -20Repository: orval-labs/orval
Length of output: 777
🏁 Script executed:
sed -n '88,104p' tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | cat -nRepository: orval-labs/orval
Length of output: 1058
🏁 Script executed:
# Check if there are other snapshot files with similar patterns
find tests/__snapshots__/react-query -name "endpoints.ts" | wc -lRepository: orval-labs/orval
Length of output: 62
🏁 Script executed:
# Compare with non-flat-input version to see the difference
find tests/__snapshots__/react-query -name "endpoints.ts" -not -path "*flat-input*" | head -1 | xargs sed -n '80,95p' | cat -nRepository: orval-labs/orval
Length of output: 441
🏁 Script executed:
# Find a non-flat-input endpoint with similar multi-params pattern
find tests/__snapshots__/react-query -name "endpoints.ts" -not -path "*flat-input*" -type f | head -3Repository: orval-labs/orval
Length of output: 234
🏁 Script executed:
# Look at a non-flat-input version if it exists
find tests/__snapshots__/react-query -type d -name "*multi-params*" | grep -v flat-inputRepository: orval-labs/orval
Length of output: 123
🏁 Script executed:
# Check the source code that generates these snapshots to understand the intentional behavior
find . -name "*query-generator*" -o -name "*flat*" | grep -E "\.(ts|tsx)$" | head -10Repository: orval-labs/orval
Length of output: 134
🏁 Script executed:
# Look at the actual source generator
find packages -name "*.ts" | xargs grep -l "getGetUsersUserIdOrdersQueryKey\|queryKey.*params.*\?\:" | head -5Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
cat packages/query/src/flat-input.ts | head -100Repository: orval-labs/orval
Length of output: 953
🏁 Script executed:
cat packages/query/src/query-generator.ts | head -150Repository: orval-labs/orval
Length of output: 4080
🏁 Script executed:
# Look for the logic that handles the queryKey with params
rg "getGetUsersUserIdOrdersQueryKey|queryKey.*params" packages/query/src/ -A 3Repository: orval-labs/orval
Length of output: 299
🏁 Script executed:
# Check if flat-input is a documented/intended pattern
find . -name "*.md" | xargs grep -l "flat.*input\|flat-input" 2>/dev/null | head -3Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Look for the queryKey generation logic
rg "queryKey.*params\s*\?" packages/query/src/ -B 2 -A 2 | head -40Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Check how params are passed in flat-input vs normal flow
sed -n '200,300p' packages/query/src/query-generator.ts | cat -nRepository: orval-labs/orval
Length of output: 3402
🏁 Script executed:
# Look for where the queryKey helper is generated
rg "export const.*QueryKey.*=.*\(" packages/query/src/ -A 3 | head -30Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Check the test setup for flat-input
find tests -name "*flat-input*" -type d | xargs ls -laRepository: orval-labs/orval
Length of output: 932
🏁 Script executed:
# Look at a flat-input test case config
find tests -name "*flat-input*" -type f | grep -E "\.(yml|yaml|json)$" | head -3Repository: orval-labs/orval
Length of output: 112
🏁 Script executed:
# Check if there's documentation in the issue or PR
git log --all --oneline --grep="flat" | head -10Repository: orval-labs/orval
Length of output: 272
🏁 Script executed:
# Look for test files that might show expected behavior
find tests -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "flat.*input\|flat-input" 2>/dev/null | head -3Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Check what setQueryData helper looks like to understand cache invalidation
rg "setQueryData\|queryKey" tests/__snapshots__/react-query/use-set-query-data-multi-params/ -A 2 | head -40Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Check the use-set-query-data snapshot to understand how setQueryData uses queryKey
sed -n '1,200p' tests/__snapshots__/react-query/use-set-query-data-multi-params/endpoints.ts | cat -n | grep -A 10 "setQueryData\|queryKey"Repository: orval-labs/orval
Length of output: 1798
🏁 Script executed:
# Check if there are any tests that validate queryKey behavior
find tests -name "*.test.ts" | xargs grep -l "queryKey" | head -3Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Look at how the generator decides to use the queryKey helper
rg "getGetUsersUserIdOrdersQueryKey\|queryKeyFnName" packages/query/src/ -B 2 -A 2 | head -50Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Check if there are recent commits/PRs related to this issue
git log --all --oneline --grep="queryKey\|cache.*params\|flat.*input" --since="2024-01-01" | head -20Repository: orval-labs/orval
Length of output: 410
🏁 Script executed:
# Look at the actual generated code to understand the current behavior more
cat tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | sed -n '80,150p' | cat -nRepository: orval-labs/orval
Length of output: 4285
🏁 Script executed:
# Check if this issue affects other snapshots
grep -r "params.*\?" tests/__snapshots__/react-query/flat-input*/ | grep "queryKey\|export const" | head -10Repository: orval-labs/orval
Length of output: 1461
🏁 Script executed:
# Verify the problem by checking how invalidation would work
node - <<'NODE'
// Simulate the flat-input scenario
const getKey = (userId, params) => [`/users/${userId}/orders`, ...(params ? [params] : [])];
// When hook is called with just userId (flat input spreads empty params)
const hookKey = getKey(1, {});
console.log("Hook key:", JSON.stringify(hookKey));
// When invalidating with just the helper and userId (no params)
const invalidationKey = getKey(1);
console.log("Invalidation key:", JSON.stringify(invalidationKey));
// Are they equal?
console.log("Keys match:", JSON.stringify(hookKey) === JSON.stringify(invalidationKey));
NODERepository: orval-labs/orval
Length of output: 148
🏁 Script executed:
# Check the other location mentioned ("Also applies to: 93-97")
sed -n '93,97p' tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | cat -nRepository: orval-labs/orval
Length of output: 358
🏁 Script executed:
# Verify if the issue affects queryFn as well
node - <<'NODE'
// The queryFn also receives params, which affects the actual fetch call
const fetchUrl = (userId, params) => {
// Simulate URL generation (params are used as query params)
return `/users/${userId}/orders?` + new URLSearchParams(params).toString();
};
console.log("URL with empty object:", fetchUrl(1, {}));
console.log("URL with undefined:", fetchUrl(1, undefined));
console.log("URL with no params:", fetchUrl(1));
NODERepository: orval-labs/orval
Length of output: 173
🏁 Script executed:
# Check if there's a related fix or issue in recent commits
git log --all --oneline --all | grep -i "querykey\|cache.*key\|invalidat" | head -15Repository: orval-labs/orval
Length of output: 1209
🏁 Script executed:
# Look at the specific commit that was mentioned in the logs
git show 32d946f8 --stat | head -30Repository: orval-labs/orval
Length of output: 1397
🏁 Script executed:
# Verify the behavior matches what the review comment describes
node - <<'NODE'
// Test what actually happens with the current code
const getGetUsersUserIdOrdersQueryKey = (userId, params) => {
return [`/users/${userId}/orders`, ...(params ? [params] : [])] ;
};
// Scenario 1: Hook called with flat input (only userId, no query params)
const flatInputKey = getGetUsersUserIdOrdersQueryKey(1, {});
console.log("Flat input hook creates key:", JSON.stringify(flatInputKey));
// Scenario 2: Manual invalidation using the helper (no params)
const invalidateKey = getGetUsersUserIdOrdersQueryKey(1);
console.log("Invalidation key:", JSON.stringify(invalidateKey));
// The problem
console.log("Cache invalidation will miss?", JSON.stringify(flatInputKey) !== JSON.stringify(invalidateKey));
// Scenario 3: With actual params
const withParamsKey = getGetUsersUserIdOrdersQueryKey(1, { status: 'pending' });
console.log("With actual params:", JSON.stringify(withParamsKey));
NODERepository: orval-labs/orval
Length of output: 245
🏁 Script executed:
# Check if there's a fix already in place for this specific issue
git show ddc25629 --stat | head -20Repository: orval-labs/orval
Length of output: 891
🏁 Script executed:
# Look at the actual changes in that commit
git show ddc25629 | head -80Repository: orval-labs/orval
Length of output: 3315
🏁 Script executed:
# Verify if the flat-input snapshots were updated in any recent commits
git log --oneline --all -- "tests/__snapshots__/react-query/flat-input*" | head -10Repository: orval-labs/orval
Length of output: 99
🏁 Script executed:
# Check if there are any tests for flat-input behavior
find tests -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "flat.*input\|flat-input" 2>/dev/nullRepository: orval-labs/orval
Length of output: 44
🏁 Script executed:
# Verify if the issue is acknowledged anywhere
rg "flat.*input.*params\|empty.*object.*cache\|queryKey.*fork" --type md | head -10Repository: orval-labs/orval
Length of output: 42
🏁 Script executed:
# Double-check the actual hook usage to confirm the problem
sed -n '31,69p' tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts | cat -nRepository: orval-labs/orval
Length of output: 1362
Empty params objects fork the React Query cache key, breaking cache invalidations.
With flat input pattern, when useGetUsersUserIdOrders({ userId }) is called without query params, the destructuring { userId, ...params } produces params = {}. This empty object is truthy, so getGetUsersUserIdOrdersQueryKey(userId, params) builds ['/users/1/orders', {}] instead of the ['/users/1/orders'] key that invalidations using getGetUsersUserIdOrdersQueryKey(userId) expect, causing cache misses.
Suggested fix
const {query: queryOptions, fetch: fetchOptions} = options ?? {};
+ const hasParams = Object.values(params).some((value) => value !== undefined);
- const queryKey = queryOptions?.queryKey ?? getGetUsersUserIdOrdersQueryKey(userId,params);
+ const queryKey = queryOptions?.queryKey ?? getGetUsersUserIdOrdersQueryKey(
+ userId,
+ hasParams ? params : undefined,
+ );
- const queryFn: QueryFunction<Awaited<ReturnType<typeof getUsersUserIdOrders>>> = ({ signal }) => getUsersUserIdOrders(userId,params, { signal, ...fetchOptions });
+ const queryFn: QueryFunction<Awaited<ReturnType<typeof getUsersUserIdOrders>>> = ({ signal }) =>
+ getUsersUserIdOrders(
+ userId,
+ hasParams ? params : undefined,
+ { signal, ...fetchOptions },
+ );Also applies to: 93-97
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts` around
lines 80 - 85, The query key builder getGetUsersUserIdOrdersQueryKey currently
treats an empty params object as present and appends it to the key, causing
cache forks; update the function to only append params when they are
non-null/undefined AND not an empty object (e.g., check params &&
Object.keys(params).length > 0) so getGetUsersUserIdOrdersQueryKey(userId) and
getGetUsersUserIdOrdersQueryKey(userId, {}) produce the same key; apply the same
empty-object guard to the other similar query key builders in this diff.
| export const getGetUsersUserIdOrdersQueryOptions = <TData = Awaited<ReturnType<typeof getUsersUserIdOrders>>, TError = unknown>({ userId, ...params }: { userId: number } & GetUsersUserIdOrdersParams, options?: { query?:Partial<UseQueryOptions<Awaited<ReturnType<typeof getUsersUserIdOrders>>, TError, TData>>, fetch?: RequestInit} | ||
| ) => { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Compare the flat-input helper signature with the hook call site.
sed -n '88,145p' tests/__snapshots__/react-query/flat-input-multi-params/endpoints.tsRepository: orval-labs/orval
Length of output: 3536
useGetUsersUserIdOrders still calls the helper with incorrect argument shape.
The hook signature expects and receives { userId, ...params } as a flat object, but it passes (userId, params, options) to getGetUsersUserIdOrdersQueryOptions. The helper now expects { userId, ...params } as its first argument; the current call passes positional arguments instead, leaving userId undestructured and producing an incorrect query key.
Fix
- const queryOptions = getGetUsersUserIdOrdersQueryOptions(userId,params,options)
+ const queryOptions = getGetUsersUserIdOrdersQueryOptions({ userId, ...params }, options)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts` around
lines 88 - 89, useGetUsersUserIdOrders is calling
getGetUsersUserIdOrdersQueryOptions with positional args (userId, params,
options) but the helper's signature expects a single flat object ({ userId,
...params }) and optional options; update the call site in
useGetUsersUserIdOrders to pass one object merging userId and params (e.g., {
userId, ...params }) as the first argument and pass options as the second
argument so the query key is built from the correct shape for
getGetUsersUserIdOrdersQueryOptions.
| export const getSearchItemsMutationOptions = <TError = unknown, | ||
| TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof searchItems>>, TError,{{ orgId: string } & SearchItemsParams & SearchItemsBody}, TContext>, fetch?: RequestInit} | ||
| ): UseMutationOptions<Awaited<ReturnType<typeof searchItems>>, TError,{{ orgId: string } & SearchItemsParams & SearchItemsBody}, TContext> => { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Expect the emitted type to be a plain intersection and the call to follow
# `(orgId, data, params, options)`. The current snapshot shows both regressions.
sed -n '54,119p' tests/__snapshots__/react-query/flat-input-path-query-body/endpoints.tsRepository: orval-labs/orval
Length of output: 2628
Flat-input searchItems mutation is emitted with invalid types and the wrong call order.
The type parameters use {{ orgId: string } & ...} with double braces (invalid syntax), and mutationFn calls searchItems(orgId, { page, limit }, data, fetchOptions) when it should be searchItems(orgId, data, { page, limit }, fetchOptions) to match the function signature (orgId, searchItemsBody, params?, options?). The double-brace syntax error appears in both getSearchItemsMutationOptions (lines 77–79) and useSearchItems (lines 111–116), while the argument order error is in the mutationFn (lines 91–95).
Suggested fix
export const getSearchItemsMutationOptions = <TError = unknown,
- TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof searchItems>>, TError,{{ orgId: string } & SearchItemsParams & SearchItemsBody}, TContext>, fetch?: RequestInit}
-): UseMutationOptions<Awaited<ReturnType<typeof searchItems>>, TError,{{ orgId: string } & SearchItemsParams & SearchItemsBody}, TContext> => {
+ TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof searchItems>>, TError,{ orgId: string } & SearchItemsParams & SearchItemsBody, TContext>, fetch?: RequestInit}
+): UseMutationOptions<Awaited<ReturnType<typeof searchItems>>, TError,{ orgId: string } & SearchItemsParams & SearchItemsBody, TContext> => {
@@
- return searchItems(orgId, { page, limit }, data,fetchOptions)
+ return searchItems(orgId, data, { page, limit }, fetchOptions)Apply the same brace fix in useSearchItems below.
🧰 Tools
🪛 Biome (2.4.9)
[error] 77-77: expected > but instead found =
(parse)
[error] 77-77: Invalid assignment to <TError
(parse)
[error] 78-78: Expected an expression, or an assignment but instead found ':'.
(parse)
[error] 78-78: expected , but instead found ?
(parse)
[error] 78-78: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{{ orgId'.
(parse)
[error] 78-78: expected , but instead found :
(parse)
[error] 78-78: expected ) but instead found }
(parse)
[error] 79-79: Expected a statement but instead found '& SearchItemsParams & SearchItemsBody'.
(parse)
[error] 79-79: Expected a statement but instead found ', TContext> =>'.
(parse)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/__snapshots__/react-query/flat-input-path-query-body/endpoints.ts`
around lines 77 - 79, The emitted mutation types and call order are wrong:
remove the stray double braces so the generic target type becomes "{ orgId:
string } & SearchItemsParams & SearchItemsBody" (fix both
getSearchItemsMutationOptions and useSearchItems) and correct the mutationFn
invocation to call searchItems(orgId, data, { page, limit }, fetchOptions) to
match the function signature (searchItems(orgId, searchItemsBody, params?,
options?)). Ensure mutationFn references the same parameter names used in the
file (e.g., orgId, data, page, limit, fetchOptions) and update both occurrences
noted (getSearchItemsMutationOptions, useSearchItems, and the mutationFn block).
| export const getCreatePetsMutationOptions = <TError = Error, | ||
| TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof createPets>>, TError,{CreatePetsParams & CreatePetsBody}, TContext>, fetch?: RequestInit} | ||
| ): UseMutationOptions<Awaited<ReturnType<typeof createPets>>, TError,{CreatePetsParams & CreatePetsBody}, TContext> => { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Expect the helper to accept `headers` and call
# `createPets(data, params, headers, options)`. The current snapshot does neither.
sed -n '221,286p' tests/__snapshots__/react-query/flat-input-petstore/endpoints.tsRepository: orval-labs/orval
Length of output: 2464
Flat-input createPets generation has invalid TypeScript syntax, drops required headers parameter, and swaps body/params argument order.
The variables type is emitted as {CreatePetsParams & CreatePetsBody} (invalid TS—braces should not wrap an intersection type), and neither getCreatePetsMutationOptions nor useCreatePets accepts the required CreatePetsHeaders parameter. The createPets function call also passes arguments in wrong order: currently createPets({ limit, sort }, data, fetchOptions) but should be createPets(data, { limit, sort }, headers, fetchOptions).
Suggested fix
export const getCreatePetsMutationOptions = <TError = Error,
- TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof createPets>>, TError,{CreatePetsParams & CreatePetsBody}, TContext>, fetch?: RequestInit}
-): UseMutationOptions<Awaited<ReturnType<typeof createPets>>, TError,{CreatePetsParams & CreatePetsBody}, TContext> => {
+ TContext = unknown>(headers: CreatePetsHeaders, options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof createPets>>, TError, CreatePetsParams & CreatePetsBody, TContext>, fetch?: RequestInit}
+): UseMutationOptions<Awaited<ReturnType<typeof createPets>>, TError, CreatePetsParams & CreatePetsBody, TContext> => {
@@
- return createPets({ limit, sort }, data,fetchOptions)
+ return createPets(data, { limit, sort }, headers, fetchOptions)The same headers parameter needs to flow through useCreatePets.
Also applies to: 258-262, 278-286
🧰 Tools
🪛 Biome (2.4.9)
[error] 244-244: expected > but instead found =
(parse)
[error] 244-244: Invalid assignment to <TError
(parse)
[error] 245-245: Expected an expression, or an assignment but instead found ':'.
(parse)
[error] 245-245: expected , but instead found ?
(parse)
[error] 245-245: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{CreatePetsParams & CreatePetsBody'.
(parse)
[error] 245-245: Expected an expression but instead found ','.
(parse)
[error] 245-245: Expected an expression, or an assignment but instead found ':'.
(parse)
[error] 245-245: expected ) but instead found }
(parse)
[error] 246-246: Expected a statement but instead found ', TContext> =>'.
(parse)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/__snapshots__/react-query/flat-input-petstore/endpoints.ts` around
lines 244 - 246, The generated TypeScript has three issues: the variable type is
emitted as "{CreatePetsParams & CreatePetsBody}" (invalid — remove the braces),
the required CreatePetsHeaders parameter is missing from
getCreatePetsMutationOptions and useCreatePets (add a headers?:
CreatePetsHeaders parameter and thread it through), and the createPets call uses
the wrong argument order; change calls from createPets({ limit, sort }, data,
fetchOptions) to createPets(data, { limit, sort }, headers, fetchOptions).
Update the UseMutationOptions generic type to use CreatePetsParams &
CreatePetsBody (without braces) and apply the same fixes to the other
occurrences noted (around the other get*/use* functions at the referenced
blocks).
|
Working on the problems |
- Fix double-wrapped braces in mutation variable types by threading overrideVariableType through getQueryOptionsDefinition and generateQueryArguments - Keep definitions in original format for downstream compatibility - Use separate flatVariableType for intersection types in mutationFn and options - Fix prettier: true -> formatter: 'prettier' in test configs
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
tests/__snapshots__/react-query/flat-input-path-query-body/endpoints.ts (1)
91-95:⚠️ Potential issue | 🔴 CriticalWrong argument order in
mutationFn- body and query params are swapped.The
searchItemsfunction signature is(orgId, searchItemsBody, params?, options?), but themutationFncalls it with(orgId, { page, limit }, data, fetchOptions). This passes query params where body is expected and vice versa, causing incorrect API behavior at runtime.The generator's
flatMutationCallArgsbuilds arguments as[pathArgs, queryArgs, bodyArg]but the underlying fetch function expects[path, body, query].🐛 Expected fix in generated output
const mutationFn: MutationFunction<Awaited<ReturnType<typeof searchItems>>, { orgId: string } & SearchItemsParams & SearchItemsBody> = (props) => { const {orgId, page, limit, ...data} = props ?? {}; - return searchItems(orgId, { page, limit }, data,fetchOptions) + return searchItems(orgId, data, { page, limit },fetchOptions) }The root cause is in the generator (
mutation-generator.tsaround line 176) whereflatMutationCallArgsis assembled - thebodyArgandqueryArgsorder should be swapped to match the function signature.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/__snapshots__/react-query/flat-input-path-query-body/endpoints.ts` around lines 91 - 95, The mutation is calling searchItems with the wrong argument order: searchItems(orgId, searchItemsBody, params?, options?) but mutationFn passes (orgId, { page, limit }, data, fetchOptions); fix the generator in mutation-generator.ts where flatMutationCallArgs is assembled by swapping the body and query positions so the built args become [pathArgs, bodyArg, queryArgs] (not [pathArgs, queryArgs, bodyArg]); update the code that produces mutationFn so mutationFn invokes searchItems(orgId, data, { page, limit }, fetchOptions) to match the searchItems signature.
🤖 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-options.ts`:
- Around line 79-80: The overrideVariableType value must be treated as falsy
when it's an empty string to avoid producing invalid generics like "TError,,
TContext"; update usages of overrideVariableType in query-options.ts (and the
code paths that receive flatVariableType from mutation-generator.ts) to sanitize
it before interpolation by replacing the nullish coalescing (??) check with a
truthy check (e.g., use overrideVariableType &&
overrideVariableType.trim().length ? overrideVariableType : undefined or
similar) so empty strings become undefined; apply the same guard to the other
occurrences referenced (around the overrideVariableType/type bindings and the
generic interpolation sites) so the mutation generics render correctly without
double commas.
In `@tests/__snapshots__/react-query/flat-input-path-query-body/endpoints.ts`:
- Around line 31-34: The generated type export type searchItemsResponseSuccess
includes an extra stray semicolon after its closing brace; update the template
or generator code that emits the type (the code that prints/export types like
searchItemsResponseSuccess) to avoid emitting an additional ";" after the type
declaration—locate the emitter for type aliases or the template that
concatenates "};" and ensure it does not append a second standalone semicolon,
then regenerate the output to confirm only a single terminating semicolon is
produced.
---
Duplicate comments:
In `@tests/__snapshots__/react-query/flat-input-path-query-body/endpoints.ts`:
- Around line 91-95: The mutation is calling searchItems with the wrong argument
order: searchItems(orgId, searchItemsBody, params?, options?) but mutationFn
passes (orgId, { page, limit }, data, fetchOptions); fix the generator in
mutation-generator.ts where flatMutationCallArgs is assembled by swapping the
body and query positions so the built args become [pathArgs, bodyArg, queryArgs]
(not [pathArgs, queryArgs, bodyArg]); update the code that produces mutationFn
so mutationFn invokes searchItems(orgId, data, { page, limit }, fetchOptions) to
match the searchItems signature.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: cfabe007-21c3-40b6-86c7-ad63568a7b51
📒 Files selected for processing (9)
packages/query/src/framework-adapter.tspackages/query/src/frameworks/angular.tspackages/query/src/frameworks/index.tspackages/query/src/frameworks/svelte.tspackages/query/src/mutation-generator.tspackages/query/src/query-options.tstests/__snapshots__/react-query/flat-input-path-query-body/endpoints.tstests/__snapshots__/react-query/flat-input-petstore/endpoints.tstests/configs/react-query.config.ts
✅ Files skipped from review due to trivial changes (1)
- tests/snapshots/react-query/flat-input-petstore/endpoints.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/configs/react-query.config.ts
- packages/query/src/mutation-generator.ts
There was a problem hiding this comment.
♻️ Duplicate comments (2)
tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts (2)
224-228:⚠️ Potential issue | 🔴 CriticalFix
useGetUsersUserIdOrdersto pass the flat-input object shape.Lines 224-228 call
getGetUsersUserIdOrdersQueryOptionswith positional args, but its signature expects a single flat object plus optionaloptions.Suggested fix
- const queryOptions = getGetUsersUserIdOrdersQueryOptions( - userId, - params, - options, - ); + const queryOptions = getGetUsersUserIdOrdersQueryOptions( + { userId, ...params }, + options, + );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts` around lines 224 - 228, The call to getGetUsersUserIdOrdersQueryOptions currently passes positional args (userId, params, options) but the function expects a single flat input object plus optional options; update the call in useGetUsersUserIdOrders to pass a single object merging the route param and query/body params (e.g. { userId, ...params }) as the first argument and then pass options as the second argument, so getGetUsersUserIdOrdersQueryOptions receives the flat input shape it expects.
103-109:⚠️ Potential issue | 🟠 MajorAvoid cache-key fork when flat input has no query fields.
Line 104 always passes
params(rest object), so{}becomes part of the query key and diverges from the key built without params.Suggested fix
const { query: queryOptions, fetch: fetchOptions } = options ?? {}; + const hasParams = Object.values(params).some((value) => value !== undefined); const queryKey = - queryOptions?.queryKey ?? getGetUsersUserIdOrdersQueryKey(userId, params); + queryOptions?.queryKey ?? + getGetUsersUserIdOrdersQueryKey(userId, hasParams ? params : undefined); const queryFn: QueryFunction< Awaited<ReturnType<typeof getUsersUserIdOrders>> > = ({ signal }) => - getUsersUserIdOrders(userId, params, { signal, ...fetchOptions }); + getUsersUserIdOrders(userId, hasParams ? params : undefined, { + signal, + ...fetchOptions, + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts` around lines 103 - 109, The query key diverges because you always pass the rest object params (even empty {}) into getGetUsersUserIdOrdersQueryKey and getUsersUserIdOrders; change both call sites to only pass params when it has properties (e.g., params && Object.keys(params).length ? params : undefined) so an empty object is not included in the cache key or request; update the queryKey expression (the call to getGetUsersUserIdOrdersQueryKey) and the queryFn invocation of getUsersUserIdOrders accordingly to use this conditional params value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@tests/__snapshots__/react-query/flat-input-multi-params/endpoints.ts`:
- Around line 224-228: The call to getGetUsersUserIdOrdersQueryOptions currently
passes positional args (userId, params, options) but the function expects a
single flat input object plus optional options; update the call in
useGetUsersUserIdOrders to pass a single object merging the route param and
query/body params (e.g. { userId, ...params }) as the first argument and then
pass options as the second argument, so getGetUsersUserIdOrdersQueryOptions
receives the flat input shape it expects.
- Around line 103-109: The query key diverges because you always pass the rest
object params (even empty {}) into getGetUsersUserIdOrdersQueryKey and
getUsersUserIdOrders; change both call sites to only pass params when it has
properties (e.g., params && Object.keys(params).length ? params : undefined) so
an empty object is not included in the cache key or request; update the queryKey
expression (the call to getGetUsersUserIdOrdersQueryKey) and the queryFn
invocation of getUsersUserIdOrders accordingly to use this conditional params
value.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b93ea9d9-c4c5-4727-96d7-05ecf661cab7
📒 Files selected for processing (22)
tests/__snapshots__/react-query/flat-input-multi-params/endpoints.tstests/__snapshots__/react-query/flat-input-multi-params/model/getUsersUserIdOrdersParams.tstests/__snapshots__/react-query/flat-input-multi-params/model/getUsersUserIdOrdersStatus.tstests/__snapshots__/react-query/flat-input-path-query-body/endpoints.tstests/__snapshots__/react-query/flat-input-path-query-body/model/searchItemsParams.tstests/__snapshots__/react-query/flat-input-petstore/endpoints.tstests/__snapshots__/react-query/flat-input-petstore/model/catType.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsHeaders.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsParams.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsSort.tstests/__snapshots__/react-query/flat-input-petstore/model/createPetsXExample.tstests/__snapshots__/react-query/flat-input-petstore/model/dachshundBreed.tstests/__snapshots__/react-query/flat-input-petstore/model/dog.tstests/__snapshots__/react-query/flat-input-petstore/model/dogType.tstests/__snapshots__/react-query/flat-input-petstore/model/labradoodleBreed.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsHeaders.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsParams.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsSort.tstests/__snapshots__/react-query/flat-input-petstore/model/listPetsXExample.tstests/__snapshots__/react-query/flat-input-petstore/model/pet.tstests/__snapshots__/react-query/flat-input-petstore/model/petCallingCode.tstests/__snapshots__/react-query/flat-input-petstore/model/petCountry.ts
✅ Files skipped from review due to trivial changes (15)
- tests/snapshots/react-query/flat-input-petstore/model/listPetsHeaders.ts
- tests/snapshots/react-query/flat-input-path-query-body/model/searchItemsParams.ts
- tests/snapshots/react-query/flat-input-petstore/model/dogType.ts
- tests/snapshots/react-query/flat-input-petstore/model/createPetsParams.ts
- tests/snapshots/react-query/flat-input-petstore/model/petCallingCode.ts
- tests/snapshots/react-query/flat-input-petstore/model/createPetsXExample.ts
- tests/snapshots/react-query/flat-input-multi-params/model/getUsersUserIdOrdersParams.ts
- tests/snapshots/react-query/flat-input-multi-params/model/getUsersUserIdOrdersStatus.ts
- tests/snapshots/react-query/flat-input-petstore/model/labradoodleBreed.ts
- tests/snapshots/react-query/flat-input-petstore/model/dog.ts
- tests/snapshots/react-query/flat-input-petstore/model/listPetsXExample.ts
- tests/snapshots/react-query/flat-input-petstore/model/listPetsSort.ts
- tests/snapshots/react-query/flat-input-petstore/model/createPetsHeaders.ts
- tests/snapshots/react-query/flat-input-petstore/model/listPetsParams.ts
- tests/snapshots/react-query/flat-input-petstore/model/pet.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- tests/snapshots/react-query/flat-input-petstore/model/petCountry.ts
- tests/snapshots/react-query/flat-input-petstore/model/createPetsSort.ts
- tests/snapshots/react-query/flat-input-petstore/model/catType.ts
- tests/snapshots/react-query/flat-input-petstore/model/dachshundBreed.ts
- tests/snapshots/react-query/flat-input-path-query-body/endpoints.ts
- tests/snapshots/react-query/flat-input-petstore/endpoints.ts
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/query/src/query-options.ts (1)
106-107:⚠️ Potential issue | 🟠 MajorUse sanitize +
??to satisfy lint without reintroducing empty-string generic breakage.Line 107 currently fixes empty-string fallback behavior, but CI fails on
prefer-nullish-coalescing. Switching directly to??can bring back invalid mutation generics whenoverrideVariableType === ''(downstream at Line 184/Line 189). Use a sanitized intermediate value.Suggested fix
- const varType = - overrideVariableType || (definitions ? `{${definitions}}` : 'void'); + const sanitizedOverrideVariableType = + typeof overrideVariableType === 'string' && + overrideVariableType.trim().length > 0 + ? overrideVariableType + : undefined; + const varType = + sanitizedOverrideVariableType ?? (definitions ? `{${definitions}}` : 'void');#!/bin/bash set -euo pipefail # Verify root-cause line now uses sanitize + nullish coalescing. fd -i "query-options.ts" --exec rg -n -C2 "sanitizedOverrideVariableType|const varType|\\?\\?" # Ensure raw `overrideVariableType ||` fallback is no longer present. fd -i "query-options.ts" --exec rg -n "overrideVariableType\\s*\\|\\|" || true🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/query/src/query-options.ts` around lines 106 - 107, The current fallback uses || which CI flags; create a sanitized intermediate like sanitizedOverrideVariableType that maps an empty string to undefined (e.g., const sanitizedOverrideVariableType = overrideVariableType === '' ? undefined : overrideVariableType) and then replace the varType assignment with nullish coalescing: const varType = sanitizedOverrideVariableType ?? (definitions ? `{${definitions}}` : 'void'); update references to use varType and remove the raw "overrideVariableType ||" pattern; this preserves empty-string protection while satisfying prefer-nullish-coalescing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/query/src/query-options.ts`:
- Around line 106-107: The current fallback uses || which CI flags; create a
sanitized intermediate like sanitizedOverrideVariableType that maps an empty
string to undefined (e.g., const sanitizedOverrideVariableType =
overrideVariableType === '' ? undefined : overrideVariableType) and then replace
the varType assignment with nullish coalescing: const varType =
sanitizedOverrideVariableType ?? (definitions ? `{${definitions}}` : 'void');
update references to use varType and remove the raw "overrideVariableType ||"
pattern; this preserves empty-string protection while satisfying
prefer-nullish-coalescing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7ad1f582-9bf6-4f0a-86d7-fc629e8c9f4d
📒 Files selected for processing (1)
packages/query/src/query-options.ts
- Consolidate all flat input logic into buildFlatInput() in flat-input.ts - Both query and mutation generators use the same utility - Fix mutation argument order to match client function signatures - Fix double-wrapped braces in mutation variable types via overrideVariableType - Skip flat input for mutations with headers (non-standard field names) - Add comprehensive test spec covering all 12 scenarios: no params, 1/2 path params, 1/2 query params, path+query, 2path+query, body only, path+body, query+body, path+query+body, delete with 2 path params
|
@anymaniax @snebjorn i have no idea if this use case makes sense to support. Please review. |
|
@melloware I personally used it and prefer it (used post processing for it) in my react, zod, react-hook-form apps. I also remember seeing it on Discord from long time ago, and a maintainer said a PR is welcome or so If another solution (maybe less invasive?) is preferred I can try other approaches and see where we land |
snebjorn
left a comment
There was a problem hiding this comment.
I didn't review the code, but rather the concept.
OAS 3.1 allows duplicate parameter names. This is valid
paths:
/users/{id}:
get:
parameters:
- name: id
in: path
required: true
schema:
type: integer
- in: query
name: id
schema:
type: stringand would result in getUsers({id: ..., id: ...}) which doesn't work.
|
@snebjorn |
|
IMO throwing an error on valid OAS is a bug, no matter how poorly the OAS was written 😄 Furthermore I'd be cautious about adding more state/options to an already messy/complex codebase. I wouldn't make this an option but rather switch to it instead. But the duplicate key issue would have to be addressed. And I'm not convinced it would be a net benefit, given the friction it would cause the users. |
|
@snebjorn This would solve the issue cleanly without throwing an error! It's your call but I believe it's a good and beneficial thing to have (from my personal experience), because it's just boilerplate to split the fields, especially when all fields are unique. Lemme know if you want this, I can try to minimize changes and prop drilling to make it more maintainable in the future |
Summary
Adds
useFlatInput?: booleanconfig option underoverridethat flattens path params, query params, and body into a single object argument for query hooks, query options functions, and mutations.Example
Query (path + query params):
Mutation (query params + body):
Mutation (path + query + body):
How it works
{ userId: number } & GetUserOrdersParams)useNamedParameters(they conflict)Tests
Snapshot tests for:
Closes #3164
Summary by CodeRabbit
New Features
Bug Fixes
Tests / Examples