Pinia Colada
Generate Vue queries and mutations with Pinia Colada.
Set client: 'pinia-colada' to generate request functions, query keys,
query/mutation options and Vue composables. Install @pinia/colada 1.x (1.4.4 or
later) and its Vue/Pinia peer dependencies in your application.
Configuration
import { defineConfig } from 'orval';
export default defineConfig({
pets: {
input: './openapi.json',
output: {
target: './src/api/pets.ts',
client: 'pinia-colada',
httpClient: 'fetch', // or 'axios'
override: { fetch: { includeHttpResponseReturnType: false } },
},
},
});Register Pinia and the PiniaColada plugin in your Vue application.
GET and HEAD operations generate queries; other methods generate mutations.
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { PiniaColada } from '@pinia/colada';
import App from './App.vue';
createApp(App).use(createPinia()).use(PiniaColada).mount('#app');Generated output
For an operation named getPet, the client generates the request function,
getGetPetQueryKey, getGetPetQueryOptions, and useGetPet. For a mutation
named createPet, it generates createPet, CreatePetMutationVariables,
getCreatePetMutationOptions, and useCreatePet.
Query options factories can be used without creating a composable:
const key = getGetPetQueryKey(1);
const options = getGetPetQueryOptions(1, {
query: { staleTime: 30_000 },
});Queries
Operation inputs accept plain values, refs and getters. Generated query keys include the HTTP method, route and operation arguments. Colada receives matching key/request values when reactive arguments change.
import { ref } from 'vue';
const petId = ref(1);
const pet = useGetPet(petId, { query: { staleTime: 30_000 } });
const key = getGetPetQueryKey(1);
const options = getGetPetQueryOptions(1);Each reactive input is typed as MaybeRefOrGetter<T>, so a path or query input
can be a value, a Vue ref, or a getter:
useGetPet(petId.value);
useGetPet(petId);
useGetPet(() => petId.value);Use options.query for Colada options, including a custom key, and
options.request for Fetch/Axios request options. For reactive query options,
pass the composable an options getter, such as
() => ({ query: { enabled: isReady.value } }). The query's AbortSignal is
forwarded through request options when available. The built-in Fetch transport
throws for HTTP failures so Colada can enter its error state. Axios preserves
its normal response object; Fetch response shape follows
fetch.includeHttpResponseReturnType.
When overriding query.key, include every variable that affects the response.
For reactive inputs, return the key from the same options getter:
const pet = useGetPet(petId, () => ({
query: { key: ['pets', petId.value] },
}));A constant key shared by different pet IDs would reuse the same cache entry.
Invalidate custom keys using the same key factory; getGetPetQueryKey() still
returns the default generated key. See Colada's query key guidance.
Mutations
Mutation variables contain the operation's path, query, header and body
arguments, using their generated names and types. Pass Colada lifecycle
callbacks through options.mutation.
const cache = useQueryCache();
const createPet = useCreatePet({
mutation: {
onSuccess: () =>
cache.invalidateQueries({
key: getListPetsQueryKey().slice(0, 2),
}),
},
});
await createPet.mutateAsync({ createPetBody: { name: 'Milo' } });The generator does not guess which queries a mutation invalidates. Choose the
affected keys in application code. getCreatePetMutationOptions() also exposes
reusable options without creating a composable.
Mutation variables keep the generated operation argument types. The same types
are used by mutate and mutateAsync, and lifecycle callbacks receive typed
data, variables, and context:
const createPet = useCreatePet({
mutation: {
onMutate: () => ({ previousName: 'Milo' }),
onSuccess(data, variables, context) {
console.log(data.id, variables.createPetBody.name, context.previousName);
},
},
});
createPet.mutate({ createPetBody: { name: 'Milo' } });
await createPet.mutateAsync({ createPetBody: { name: 'Luna' } });Request and query options
Colada options are passed inside options.query, while Fetch or Axios request
options are passed inside options.request:
useGetPet(petId, {
query: { enabled: true, staleTime: 30_000 },
request: { headers: { 'x-client': 'web' } },
});For reactive options, pass a getter so the query key and options are resolved together:
const isReady = ref(true);
useGetPet(petId, () => ({
query: { enabled: isReady.value },
request: { headers: { 'x-client': 'web' } },
}));When requestOptions: false is configured, the generated operation does not
accept request options and the generated Colada wrapper does not expose
options.request. When request options are enabled together with
optionsParamRequired: true, the request options argument is required for
operations that support it. useNamedParameters changes the generated
operation argument shape; the Pinia Colada wrapper follows that generated
shape.
Compatibility
The client uses Orval's existing Fetch/Axios serializers and supports plain function mutators. Custom mutators must reject failed requests themselves. Hook mutators are not supported. JSON, multipart and URL-encoded bodies follow the request generator's existing configuration.
The built-in Fetch transport is configured to reject failed HTTP responses so that Colada receives them through its error state. Axios keeps its normal response shape. A plain Fetch mutator should reject failed responses itself, and a plain Axios mutator should return the value expected by the generated request function.
For example, a plain Fetch mutator can preserve the generated request contract while rejecting failed responses:
export async function customFetch<T>(
url: string,
options?: RequestInit,
): Promise<T> {
const response = await fetch(url, options);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.status === 204 || response.status === 205
? (undefined as T)
: response.json();
}An Axios mutator can return the response data directly when that is the shape expected by the generated operation:
import axios, { type AxiosRequestConfig } from 'axios';
export const customAxios = <T>(
config: AxiosRequestConfig,
options?: AxiosRequestConfig,
): Promise<T> =>
axios({ ...config, ...options }).then((response) => response.data);The generated query function forwards Colada's AbortSignal to the request
when request options are available. If a reactive query input changes while a
request is pending, the previous request can be cancelled by the query
library.
The client works with the single, split, tags, and tags-split output
modes. It does not generate dedicated infinite-query helpers or Nuxt
integration, and hook mutators are not supported.
Use the generated options and keys with Colada's cache APIs. The sample at
samples/pinia-colada demonstrates queries, CRUD mutations, cache invalidation,
and error recovery in English.
Full Example
See the complete Pinia Colada example for Fetch and Axios output, custom mutators, payload serialization, type checks, and browser tests.