# Vue Query

Generate fully typed [TanStack Query for Vue](https://tanstack.com/query/latest/docs/vue/overview) composables from your OpenAPI specification.

## Configuration

Set the `client` option to `vue-query`:

```ts
import { defineConfig } from 'orval';

export default defineConfig({
  petstore: {
    output: {
      mode: 'tags-split',
      target: 'src/api/petstore.ts',
      schemas: 'src/api/model',
      client: 'vue-query',
      mock: true,
    },
    input: {
      target: './petstore.yaml',
    },
  },
});
```

## Generated Output

Orval generates one composable per path in your OpenAPI specification. For example, [this specification](https://github.com/orval-labs/orval/blob/master/samples/vue-query/petstore.yaml) generates:

```ts
export const showPetById = (
  petId: string,
  options?: AxiosRequestConfig,
): Promise<AxiosResponse<Pet>> => {
  return axios.get(`/pets/${petId}`, options);
};

export const getShowPetByIdQueryKey = (petId: string) => [`/pets/${petId}`];

export const useShowPetById = <
  TData = AsyncReturnType<typeof showPetById>,
  TError = Error,
>(
  petId: string,
  options?: {
    query?: UseQueryOptions<AsyncReturnType<typeof showPetById>, TError, TData>;
    axios?: AxiosRequestConfig;
  },
) => {
  const { query: queryOptions, axios: axiosOptions } = options ?? {};

  const queryKey = queryOptions?.queryKey ?? getShowPetByIdQueryKey(petId);
  const queryFn = () => showPetById(petId, axiosOptions);

  const query = useQuery<AsyncReturnType<typeof queryFn>, TError, TData>(
    queryKey,
    queryFn,
    {
      enabled: petId !== null && petId !== undefined,
      ...queryOptions,
    },
  );

  return {
    queryKey,
    ...query,
  };
};
```

## Reactive Parameters

Generated composables accept reactive parameters so the query re-runs when an
input changes. On **Vue Query v5** (which requires Vue 3.3+), every parameter is
typed as [`MaybeRefOrGetter<T>`](https://vuejs.org/api/utility-types.html#maybereforgetter)
- that is `T | Ref<T> | (() => T)` - and is unwrapped internally with
[`toValue()`](https://vuejs.org/api/reactivity-utilities.html#tovalue). This lets
you pass the getter directly, with no `computed` wrapper:

```ts
// All three forms work:
useShowPetById(petId.value);
useShowPetById(petId); 
useShowPetById(() => props.petId);
```

`MaybeRefOrGetter<T>` is a superset of `MaybeRef<T>`, so existing call sites that
pass refs or plain values keep working unchanged. Projects generating against
Vue Query v4 (or the legacy `vue-query` v3 package) continue to use
`MaybeRef<T>`/`unref()`, since those targets may run on Vue versions older than
3.3.

## Infinite Queries

Generate `useInfiniteQuery` composables:

```ts
import { defineConfig } from 'orval';

export default defineConfig({
  petstore: {
    output: {
      client: 'vue-query',
      override: {
        query: {
          useQuery: true,
          useInfinite: true,
          useInfiniteQueryParam: 'nextId',
          options: {
            staleTime: 10000,
          },
        },
      },
    },
    input: {
      target: './petstore.yaml',
    },
  },
});
```

## Per-Operation Overrides

Override query options for specific operations:

```ts
import { defineConfig } from 'orval';

export default defineConfig({
  petstore: {
    output: {
      client: 'vue-query',
      override: {
        operations: {
          listPets: {
            query: {
              useInfinite: true,
            },
          },
        },
      },
    },
    input: {
      target: './petstore.yaml',
    },
  },
});
```

## Set Query Data

When `useSetQueryData: true` is set, Orval generates type-safe helper functions to update cached query data:

```ts
export const setListPetsQueryData = (
  queryClient: QueryClient,
  params: MaybeRefOrGetter<ListPetsParams> | undefined,
  updater:
    | Awaited<ReturnType<typeof listPets>>
    | undefined
    | ((
        old: Awaited<ReturnType<typeof listPets>> | undefined,
      ) => Awaited<ReturnType<typeof listPets>> | undefined),
) => {
  queryClient.setQueriesData<Awaited<ReturnType<typeof listPets>>>(
    { queryKey: getListPetsQueryKey(params) },
    updater,
  );
};
```

The helper uses [`setQueriesData`](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetqueriesdata) so query keys are matched by prefix. Pass `undefined` for query params or body to update every cached entry sharing the same path; the updater is invoked once per matched entry.

> **Warning:**
> Prior to this change the helper called `setQueryData`, which writes (and creates) a single exact-key entry. `setQueriesData` only updates entries that already exist and matches by prefix, so calls with a fully-specified key may behave differently — review existing call sites when upgrading.

## Get Query Data

When `useGetQueryData: true` is set, Orval generates type-safe helper functions to read cached query data:

```ts
export const getListPetsQueryData = (
  queryClient: QueryClient,
  params: ListPetsParams,
) =>
  queryClient.getQueryData<Awaited<ReturnType<typeof listPets>>>(
    getListPetsQueryKey(params),
  );
```

## Full Example

See the [complete Vue Query example](https://github.com/orval-labs/orval/tree/master/samples/vue-query) on GitHub.
