1.1.0 (2026-03-31)
1.0.0 (2026-03-06)
- feat!: remove deprecated two-parameter overloads from
useQueryanduseQueryState(422c391)
Deprecations from 0.21.5 are now removed:
-
The
useQuery(setupOptions, paramsGetter)anduseQueryState(setupOptions, paramsGetter)two-parameter forms have been removed. Migrate to the single function parameter form:// Before useQuery(opts, () => id.value) useQueryState(opts, () => id.value)
// After useQuery(() => opts(id.value)) useQueryState(() => opts(id.value).key)
An ast-grep codemod is available to automate most callsites (may not cover all edge cases):
ast-grep scan -r node_modules/@pinia/colada/codemods/rules/migration-0-21-to-1-0.yaml -i src0.21.7 (2026-03-02)
0.21.6 (2026-02-26)
- infinite: allow initial null page (00e4ed1), closes #518 #519
- infinite: ensure page params are attached to entries (e43b3fd), closes #517
- use shallowRef (3f8235b)
0.21.5 (2026-02-22)
- ssr: prevent memory leak (#514) (9fd9baa)
- types: restore UseQueryOptions variance for placeholderData callback (ef4a006)
-
The two-parameter form of
useQuery(setup, () => params)anduseQueryState(setup, () => params)is deprecated. Use a single function parameter instead:- useQuery(useContactList, () => ({ search: search.value })) + useQuery(() => useContactList({ search: search.value }))
A codemod is available to automate this migration. Commit your changes first, then run:
pnpm --package=@ast-grep/cli dlx ast-grep scan -r node_modules/@pinia/colada/codemods/rules/migration-0-21-to-1-0.yaml -i src
See Migration Codemods for details.
0.21.4 (2026-02-09)
0.21.3 (2026-02-06)
- infinite-query: compute hasNextPage correctly on cache hit (#480) (895914a)
- skip refetchOnWindowFocus and refetchOnReconnect for inactive defined queries (1d7f9d2), closes #485
0.21.2 (2026-01-20)
- correct GC time display for prefetched queries (#464) (80e2c5a)
- query: gc prefetched queries (ba1e90c)
0.21.1 (2026-01-09)
- make ext readonly (8dd595a)
0.21.0 (2026-01-06)
- refactor!: remove @vue/devtools-api dependencies (9bfd035)
- expose internal utility types (bb3a7d0)
- use the native @pinia/colada-devtools. See https://pinia-colada.esm.dev/guide/installation.html#Pinia-Colada-Devtools for instructions
0.20.0 (2025-12-23)
This release completely changed how useInfiniteQuery() works, the parameters and returned values:
- The
mergeoption has been removed anddatacontains an object withpagesandpageParamsarrays that can be flattened. initialPagehas now been replaced withinitialPageParamloadMorehas been renamedloadNextPagegetNextPageParamis now a required option- Invalidating now works just as with regular queries, which means that you probably want to set
stalevalue higher (or disable it) to avoid refetching multiple pages when an infinite query is invalidated. Also, you might want to setrefetchOn*options tofalse. - It's now possible to have bi-directional navigation
- There is now
hasNextPageandhasPreviousPage
Any feedback on the feature and improvements is welcome!
Here is a complete example of what it looks in action:
<script setup lang="ts">
import { useInfiniteQuery } from '@pinia/colada'
import { onWatcherCleanup, useTemplateRef, watch } from 'vue'
const {
state: factsPages,
loadNextPage,
asyncStatus,
isDelaying,
hasNextPage,
} = useInfiniteQuery({
key: ['feed'],
query: async ({ pageParam }) => factsApi.get<CatFacts>({ query: { page: pageParam, limit: 10 } }),
initialPageParam: 1,
getNextPageParam(lastPage) {
return lastPage.next_page_url
}
// plugins
retry: 0,
delay: 0,
})
// we only need an array
const facts = computed(() => factPages.value.data?.pages.flat())
const loadMoreEl = useTemplateRef('load-more')
watch(loadMoreEl, (el) => {
if (el) {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0]?.isIntersecting) {
loadNextPage()
}
},
{
rootMargin: '300px',
threshold: [0],
},
)
observer.observe(el)
onWatcherCleanup(() => {
observer.disconnect()
})
}
})
</script>
<template>
<div>
<button :disabled="asyncStatus === 'loading' || isDelaying" @click="loadMore()">
Load more (or scroll down)
</button>
<template v-if="facts?.length">
<p>We have loaded {{ facts.length }} facts</p>
<details>
<summary>Show raw</summary>
<pre>{{ facts }}</pre>
</details>
<blockquote v-for="fact in facts">
{{ fact }}
</blockquote>
<p v-if="hasNextPage" ref="load-more">Loading more...</p>
</template>
</div>
</template>- infinite: add cancelRefetch (16de801)
- infinite: maxPages (7639145)
- nextPage works (d011030)
- throwOnError in infiniteQuery (5010b11)
0.19.1 (2025-12-17)
- initialDataUpdatedAt (e16ff61), closes #298
- warns if the user extends in create instead of ext (d71a890), closes #442
0.19.0 (2025-12-16)
- use global options for mutations (0f3a56c)
- types: usemutationoptionswithdefaults (67ea7a6)
- Mutations id are now just an incremented number that starts at 1. There is no longer a
$nappended to keys for mutations and mutations without a key do not have an artificial key anymore. This is because initially the cache map was a more complex type but with it being a simple Map, there is no point in complexifying the keys. As a result themutationCache.get()now takes the id of the mutation whilegetEntries()work the same. Theexactfilter has also been removed as mutations are, by nature, meant to be called multiple times.
0.18.1 (2025-12-11)
0.18.0 (2025-12-02)
- While technically a fix, this is a breaking change if
you were relying on an external signal that aborts within the
query. It used to not set the state by just being an AbortError DomException and now it will become an error. This behavior is more correct as we don't want to ignore aborted signals that are external. Each fetch creates an AbortController and passes the signal toquerywhich is aborted (without a reason) if any other method of the store fetches again. This is done to avoid using an outdated request.
- query: preserve any external AbortError (0cdf7b9)
0.17.9 (2025-11-24)
- export mutation cache (892049f)
- expose mutation cache (7f6316f)
- warn wrong useMutationcache usage (211911d)
0.17.8 (2025-11-07)
- allow passing extra options to defineQueryOptions (597597f)
- types: allow interfaces in keys (19ab616), closes #420
0.17.7 (2025-10-30)
- avoid watched on enabled (30439c0)
0.17.6 (2025-09-25)
- Improve type of
DefineQueryOptions(#388) (22297f0) - make type inference of DefineQueryOptions.placeholderData correct (#343) (7da95dd)
0.17.5 (2025-09-11)
0.17.4 (2025-09-09)
0.17.3 (2025-09-01)
0.17.2 (2025-08-25)
- expose internal method to plugins (740e1ce)
- allow initial fetch with refetchOnMount false and placeholderData (#350) (e9b9972)
- always propagate errors (9268b37), closes #371
0.17.1 (2025-06-13)
0.17.0 (2025-06-03)
- replace
EntryNodeKeywithEntryKey - types: The
EntryKeyTaggedtype now has multiple type params and an array is no longer assignable to it. This is necessary to correctly infer the types forTDataandTDataInitialand if you were manually usingEntryKeyTagged, you will either need to cast arrays to it or useEntryKeyinstead. In most cases this should not affect you. This makes types stricter and also disallows setting a query data toundefined. If you were doingqueryCache.setQueryData(key, undefined), usequeryCache.setEntryStateinstead.
- add a queryCache.get method to a typed entry (2f7db57)
- add error to tagged keys (7ad07c4)
- useQueryState (e1e84eb), closes #23
- types: avoid incorrect undefined from tagged keys (9358619)
- types: make options parameter optional in types (#224) (20bca79)
- remove deprecated
EntryNodeKey(6c7d15b)
0.16.1 (2025-05-22)
0.16.0 (2025-05-21)
This is the biggest release to date! Many bug fixes, typed keys, a lighter and faster build!
- query:
queryCache.invalidateQueries()now accepts a second parameter to control whether to refetch or not active queries. It can be set to'all'to force fetch all queries. This replaces the existing behavior of passingactive: null(can be removed now) which wasn't actually working. You shouldn't be negatively affected by this change as it wasn't working previously. - The internal cache structure has been refactored to be simpler, faster and smaller. Keys now support deeply nested objects and partially matches them when filtering (e.g.
queryCache.getEntries()). To achieve this, the hydrated version of the cache has changed.serializeTreeMaphas been removed butserializeQueryCache(which should be preferred) has been kept.EntryNodeKeyandTreeMapNode(internals) have been removed.EntryNodeKeywas juststring | number.toCacheKeyhas been adapted and now returns a plain string rather than an array. This also fixedqueryCache.getEntries(['1'])actually returning entries defined with a numeric key ([1]). The type forkeyis now stricter to ensure everything works well at the type level, you might notice it doesn't allowundefinedas a value (except in objects), this is intended as the serialized version (JSON) transforms it nonull, and will not match in the cache if used, if you want an nullish value, usenull. The documentation has been updated to reflect this - types: If you built a plugin, you will have to rename the type params of generics like
UseQueryEntryExtensionsfromTResulttoTData. Otherwise, this change won't affect you.
- allow deeply nested structured keys (59227a8), closes #149
- query: allow dynamic typed keys (0053deb)
- query: allow for typed query keys (5068a52)
- queryCache.setQueriesData (4818d3e)
- types: explicit types for useInfiniteQuery (5eb9e3b)
- types: stricter keys (02f0269)
- avoid fetch with initialData (d1eb4c2)
- query: gc entries created through dynamic useQuery in defineQuery (90d5d83)
- query: invalidate inactive queries too (cf5a790), closes #287
- query: restore reactivity after unmounting defineQuery (dc2315a), closes #290
- types: make key types stricter (9669605)
- Revert "refactor: use external interface for QueryCache" (d6befc4)
- types: rename
TResultinto TData (09338a2)
0.15.3 (2025-05-06)
- correctly handle refetchOn* when false (262c090)
0.15.2 (2025-05-03)
0.15.1 (2025-04-26)
- support node 18 (3466bdf)
0.15.0 (2025-04-18)
- mutations: mutations are now created each time they are invoked. This
change will only affect users directly creating entries with the mutation store
(which should be avoided except in very advanced cases). Given the new
structure of mutation entries and the fact that they are recreated for each
mutation in order to keep a history of mutations, the new process simplifies
things and reduces bundle size. The actions
createandensurein the mutation store are now simpler and take less arguments (many were redundant). Alongside these changes, the mutation store has fixed many subtle bugs.
- add gcTime option for global mutations (2850167)
- add mutation id (8c8edd5)
- hmr: refetch on component change (56aad7a)
- mutations: simplify the entry creation in the mutation store (a96a8ff)
- untrack mutation entries (6b65f19)
- an entry with no options is stale (3f59d6c)
- defineQuery: avoid pausing still active (fe00447), closes #246
- mutations: create entries for each individual mutation (3def820)
- query: avoid deleting children of gced queries (5ec6dcc)
- setQueryData sets the status and trigger gc if possible (8137fbd)
- types: allow tuples in keys (f8e8087)
- types: infer initial data in setEntryState (0a94887)
- Revert "refactor: deprecate onMutate in favor of onBeforeMutate" (02add4a). This change never actually made it, it's here for the trace.
0.14.2 (2025-03-26)
0.14.1 (2025-03-18)
- types: allow extending global query options (28acdd0)
0.14.0 (2025-03-18)
This version introduces codemods to automate migrations 🎉. Try them out with:
pnpm --package=@ast-grep/cli dlx ast-grep scan -r node_modules/@pinia/colada/codemods/rules/migration-0-13-to-0-14.yaml -i srcYou can also globally install ast-grep and run:
ast-grep scan -r node_modules/@pinia/colada/codemods/rules/migration-0-13-to-0-14.yaml -i srcRemember to commit changes before running the codemods.
-
Every global query (
useQuery()anddefineQuery()) option passed toPiniaColadahas been moved to its own optionqueryOptions:app.use(PiniaColada, { plugins: [], - gcTime: 20_000, + queryOptions: { + gcTime: 20_000, + }, })You can also use the new codemods to automatically migrate this.
-
types: This changes allows for Pinia Colada global options to auto complete but it also requires you to use pass an options object to
app.use(PiniaColada, {}). This is just for typing reasons (it could be a limitation of Vue) but the same old code actually works.-app.use(PiniaColada) +app.use(PiniaColada, {})
-
Replace
serializewithserializeTreeMap -
Removed
reviveTreeMap(not needed) -
Removed internal
createdQueryEntry
- add codemods for migrations (1a2d552)
- allow global placeholderData (a98528a), closes #216
- allow invalidating all queries no matter their active status (a64f674)
- allow nullish filters (aadd11d)
- avoid cancels to change the status (138857c), closes #210
- avoid unnecessary triggerCache (a3494a0)
- initialize the infinite query pages (9efb7d4)
- types: correctly type PiniaColada Vue plugin (f01326f)
- types: placeholderData does not guarantee data (aed71c1), closes #217
- inline filter fn (2aa1254)
0.13.8 (2025-03-09)
- add more actions to the mutation cache (a38595c)
- pass previous placeholderData if present (a576093), closes #197
0.13.7 (2025-03-04)
- queryCache should not invalidate query when it disabled (#204) (e12f98c)
- warn: avoid repeated queries warn (0fbe29a), closes #192
0.13.6 (2025-02-12)
- add devtools (43912aa)
- apply multiple filters to getEntries (da5b00c)
0.13.5 (2025-02-06)
- add experimental useInfiniteQuery (0a958e6)
- avoid clearing timeouts early (bf7ef2f)
- correctly track new define queries when switching pages (f9eeec1)
- make the cache watchable (cf30e68)
- trigger updates on untrack (91e497a)
0.13.4 (2025-01-31)
0.13.3 (2025-01-14)
- query: always use
placeholderData(4c6a3f7), closes #154 - query: avoid creating entries after unmounting (e2ff278), closes #155
0.13.2 (2025-01-03)
0.13.1 (2024-12-20)
- types: placeholderData no longer allows returning
null, onlyundefined. This won't affect most use cases and enables better type inference.
transformErrorwas never fully implemented so they are being removed and might come back if they is a real-word use case for them- If you were using the
delayLoadingRefutil, use the@pinia/colada-plugin-delayinstead. - Renaming
ErrortodefaultErrorallows to differentiate the property from the existing global Error class. Upgrading should be straightforward.
- add initial delay plugin (42c8760)
- add track and untrack actions for plugins (8902ba3)
- allow dynamic values for auto refetches (63d2fd0)
- allow extending useQuery return (ef06628)
- expose more types (4447d6d)
- plugins: pass scope for added variables (a3b666f)
- work without the plugin (696f88e)
- avoid broken reactivity in defineQuery (4c48abc)
- dedupe pinia colada (6ace8e8)
- keep data if signal is aborted (de5cde5)
- pass onMutate context (618312b), closes #95
- remove queryCache from mutation hooks (3f1119a)
- run create in ssr too (1a6fa4a)
- ssr: throw on error in query (58b7f69)
- upgrade to new cache format (03e1683)
- query: remove unused transformError and setup options (de0cb48)
- remove delayLoadingRef helper in favor of the plugins (4c9b4cb)
- rename the global
Errorproperty inTypesConfigto (0021426)
- allow gcTime to never be set (4714b9a)
- eagerly change asyncStatus on cancel (b2f1349)
- staleTime of 0 always refreshes (66ef9ec)
- mutations: This wasn't needed as instead, one can use
useQueryCache()outside. It could be added back if needed but it's more pragmatic to start without it. - query: The
queryCache.cancelQuery()is renamed toqueryCache.cancel()to better match the other functions naming. A new functionqueryCache.cancelQueries()is added to actually cancel one or multiple queries instead of just one. - plugins: In plugins,
cacheis renamed toqueryCachefor consistency. - This makes it clearer that
queryCacheis the result ofuseQueryCache().
- add mutation store (#47) (7954f83)
- hmr: warn against bugs (7bb44a0)
- nuxt: add auto imports (964bce2)
- nuxt: support colada.options (57a0430)
- predicate in filter (2fc62b7)
- query: add cancelQueries (a374ee2)
- run defined mutations in effect scope (86ff5ed)
- nuxt: plugins (fd95add)
- tree shake unused stores (e0ede7e)
- mutations: Remove
queryCachefrom the context (d9c2509) - plugins: rename
cachetoqueryCache(c97639b) - rename
cachestoqueryCache(e514d33)
- This change is mainly to simplify migration from TanStack Query.
- caches.invalidateQueries only fetches active queries
- The
keysoption that automatically invalidate keys has been renamed toinvalidateKeysand moved to a plugin. This is in practice not needed. It's just an opinionated convenience that can be replaced by directly invalidating queries in the cache with theonSettled()hook inuseMutation():
const { mutate } = useMutation({
onSettled({ caches, vars: { id } }) {
caches.invalidateQueries({ key: ['contacts-search'] })
caches.invalidateQueries({ key: ['contacts', id] })
},
mutation: (contact) => patchContact(contact),
})- caches.invalidateQueries only fetches active queries (e8d9088)
- rename
keystoinvalidateKeysand move to plugin (f709928) - useMutation hooks now use positional arguments (dce00b4)
- allow nullish return in placeholderData (1fae179)
- wip nuxt module (66eca6e)
- wip placeholderData (307e366)
- query-cache: To better match the arguments, the
setQueryStateaction has been renamed tosetEntryState.
- mutations: add variables (2e03a93)
- query-cache: Rename
setQueryStatetosetEntryState(f481eb0) - warn: warn about reused keys (7375a19)
- skip reactivity traversal in store (3984a3a)
- ssr: expose reviveTreeMap (32b4f17)
- ssr: mark raw tree node in reviver (4ff13ad)
-
isFetchingfromuseQuery()is renamed toisLoadingto better reflect that it's connected toasyncStatus. -
The setup option in useQuery now receives the options as the second argument instead of a context object with the query return value and the options. This allows the setup function to have a more predictable signature and makes it easier to type. Only
PiniaColadahas this option, it has been removed from useQuery. Overall, the option still needs more thinking and will probably change in the future again. -
plugins: The
onSuccess,onError, andonSettledglobal hooks have been moved fromPiniaPluginto a Pinia Colada plugin:PiniaColadaQueryHooksPluginapp.use(PiniaColada, { + plugins: [ + PiniaColadaQueryHooksPlugin({ onSuccess() {}, onError() {}, onSettled() {}, + }), + ], }) -
This feature splits up the
statusstate into two different status properties: -
statusis now just for the data'pending' | 'success' | 'error' -
queryStatustells if the query is still running or not with'idle' | 'running' -
refetch,refreshand similar methods now resolve thestateproperty without rejecting. This is usually more convenient. -
The
QueryStatustype has been split intoDataStateStatusandOperationStateStatus. -
the cache store is going through a refactor to empower plugins. This change shouldn't affect end users unless you are directly using the cache store. As a result a lot of the actions have been renamed
-
refetch -> fetch
-
invalidateEntry -> invalidate
-
ensureEntry -> ensure
Their arguments have changed as well.
- This release removes the deprecated
QueryPlugin. UsePiniaColadainstead.
- add a
stateproperty touseQueryfor type narrowing (22f3e21) - mutation: refetch active queries (#65) (3ebc734)
- plugins: Refactor query global hooks into a plugin (bbe5199)
- query: add
activeproperty to query entry (994db63), closes #65 - split useMutation status like useQuery (6c6078f)
- rename
isFetchingtoisLoading(003f7a1) - rename cache store actions (792ec6e)
- Replace QueryPlugin with PiniaColada (2a3f3d9)
- useQuery setup option now receives the options as the second argument (a86b41d)
- hmr: always update options (a6a6b7a)
- rename type
UseEntryKeytoEntryKey - the exported type 'UseQueryKey' is replaced by the more generic type 'UseEntryKey', which will be also used to type mutations
- debug plugin (8fde25b)
- expose plugin types (83ef198)
- mutation: allow passing mutation variables to mutation key getter (bc8a47f)
- retry plugin (0d837a2)
- support plugins and deprecate
QueryPluginin favor ofPiniaColada(bde53d9) - use-query: Add enabled option (#43) (1b755c5)
- wip: add gcTime (#29) (56659d1)
- gcTime on defined queries (#50) (82df409)
- query: query refresh on defineQuery output composable call (28a3ec1)
- trigger nested actions (7e3a9f6)
- Revert "refactor: add a stale getter" (6e059f4)
- mutation: Rename type
UseQueryStatustoQueryStatus - mutation:
mutateno longer returns a promise and catches errors to be safely used in templates. The old behavior remains the same withmutateAsync - mutation: the
mutationoption inuseMutation()now only accepts one argument for the variables. This allows to add extra parameters in the future like a signal, an extra context, etc
- abort pending query signal on new query (6b6195f)
- allow typing the error with transformError (fd35f6f)
- mutation: add mutateAsync (5c97b69)
- mutation: allow passing the context to mutation (b9acca0)
- mutation: defineMutation wip (5866907)
- mutation: require one argument only for useMutation (86b5996)
- query: add data and errors to global hooks (b4caeca)
- query: defineQuery (e0f7768)
- return promise when invalidating query (c431284)
- useMutation: add hook context (0894a81)
- useMutation: add hooks (c44af13)
- mutation: rename UseQueryStatus to QueryStatus (ff0067a)
- onScopeDispose guard (0ed15fe)
- allow writing to entries (8e9ac7e)
- types: allow default error type (68c2f8d)
- avoid computed warns (c11ee2f)
- remove internal global defaults
- force array of keys to avoid easy mistakes
- pass signal to query (bf1666c)
- add delayLoadingRef (ebbc503)
- avoid warn onScopeDispose (47ac1a6)
- rename data fetching store
- replace class usage
- add
QueryPluginto configure useQuery() statusproperty,isPending,isFetchingare now a bit different.
- ssr: wip initial version (8e6cbf6)
- adapt status (2d5625c)
- add
QueryPluginto configure useQuery() (67cb2d3) - rename data fetching store (b9ef0fb)
- replace class usage (9bf1fd9)
- useMutation: options (23eccb1)
- The option
fetcherforuseQuery()has been renamed toquery. The optionmutatorforuseMutation()has been renamedmutation.
- rename options for
useQueryanduseMutation(28ecc75)
- remove iife version
- accept function in setEntryData (2abb7c0)
- allow array of keys (7be2e80)
- do not refresh by default outside of components (b6e45fb)
- traverse tree map (b12547f)
- wip tree map (b87bff4)
- remove iife version (0ee5c8a)
- rename options
- swallow error in automatic refreshes (d955754)
- rename options (f6d01c5)
- initial version (7abe80d)