fix: make serialize:true scope id track reactive hook-time path params - #150
Merged
Conversation
The derived scope id was frozen at hook setup from resolvedPath.value. With reactive hook-time path params (ref/getter), a hook whose param changed kept the stale scope id, so two hooks converging on the same resource could run concurrently: exactly the last-write-wins race that serialize documents preventing. The scope is now a computed derived from hook-time params only (vue-query unrefs it per dispatch via cloneDeepUnref). Mutate-time extraPathParams are deliberately excluded so deferred params keep the documented template-fallback behaviour and never leak between calls. Regression test verified to fail against the previous implementation.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a reactivity defect in the mutation serialize: true option so the derived TanStack Query scope.id stays in sync when hook-time path params are reactive (e.g. route params). This prevents “converging” hooks from accidentally running concurrently under different (stale) scope ids.
Changes:
- Make the derived serialization scope id reactive (computed) and based only on hook-time path params (excluding mutate-time
extraPathParams). - Add a regression test covering reactive hook-time path param changes and subsequent queuing behavior.
- Patch release housekeeping: version bump, CHANGELOG entry, and README clarification about reactive scope ids.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/openapi-mutation.ts |
Reworks serialize → scope.id derivation to track reactive hook-time params and avoid leaking mutate-time params into subsequent scope ids. |
tests/unit/mutation-serialize.test.ts |
Adds regression test ensuring two hooks converge on the same resource and properly serialize after a reactive param change. |
README.md |
Documents that serialize: true scope ids are reactive when hook-time params are refs/getters. |
package.json |
Version bump to 0.23.1. |
package-lock.json |
Lockfile version bump alignment to 0.23.1. |
CHANGELOG.md |
Adds 0.23.1 entry describing the fix. |
…lers
serialize is typed as plain boolean | string, but untyped JS callers
could pass a ref/getter and get silently wrong behaviour (Ref(false)
truthy -> enabled, Ref('group') non-string -> template scope id).
Unwrap with toValue() before the enable check and scope-id derivation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a reactivity defect in the
serializeoption shipped in 0.23.0 (#149): the derived scope id was computed once at hook setup, so reactive hook-time path params that changed afterwards left the hook with a stale scope id.The bug
serializeScopewas a plain object built fromresolvedPath.valueat setup.serializedocuments preventing.The fix
serializeScopeis now acomputedderiving the id from hook-time params only (resolvePath(config.path, toValue(resolvedPathParamsInput))). vue-query wraps mutation options in acomputedand unrefs them per dispatch (cloneDeepUnref), and query-core resolvesscope.idper mutation viascopeFor, so eachmutate()sees the current id.extraPathParamsare deliberately excluded: deferred params keep the documented template-fallback behaviour, and one call's params cannot leak into the next call's scope.Risk assessment
scopeprecedence, warning behaviour, and deferred-param fallback are untouched (all covered by existing tests, 9/9 passing).Release
Validation
npm run check✅npx vitest run tests/unit/mutation-serialize.test.ts→ 9/9 ✅