# Solid Query

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

## Configuration

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

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

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

## Generated Output

Orval generates one primitive per path using `@tanstack/solid-query`. For example:

```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 createShowPetById = <
  TData = Awaited<ReturnType<typeof showPetById>>,
  TError = Error,
>(
  petId: string,
  options?: {
    query?: CreateQueryOptions<
      Awaited<ReturnType<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 = createQuery<Awaited<ReturnType<typeof queryFn>>, TError, TData>(
    () => ({
      queryKey,
      queryFn,
      enabled: petId !== null && petId !== undefined,
      ...queryOptions,
    }),
  );

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

## Key Differences from React Query

Solid Query uses the `create` prefix instead of `use`:

- `createQuery` instead of `useQuery`
- `createMutation` instead of `useMutation`
- `createInfiniteQuery` instead of `useInfiniteQuery`

The generated primitives follow SolidJS conventions and work seamlessly with Solid's reactivity system.

## Infinite Queries

Generate infinite query primitives:

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

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

TanStack Query requires `initialPageParam` and `getNextPageParam` on every infinite
query, and orval cannot infer either of them. Solid Query is generated without the
`as` cast the other frameworks use, so the generated primitive asks the caller for
them instead of asserting over the gap:

```ts
const pets = createListPetsInfinite(params, {
  query: {
    initialPageParam: undefined,
    getNextPageParam: (lastPage) => lastPage.nextId,
  },
});
```

Supply them once in `override.query.options` instead, and they are baked into the
generated primitive — the `options` argument then goes back to being optional:

```ts
options: {
  initialPageParam: undefined,
  getNextPageParam: (lastPage) => lastPage.nextId,
},
```

`initialData` is not accepted on the `query` object. Pass it through the generated
primitive's own overload instead, which is what preserves the distinction between
`data` being defined and possibly undefined.

## SolidStart vs Solid Query

If you're using SolidStart, consider using the [SolidStart client](/docs/guides/solid-start) instead, which uses native Solid Router primitives (`query()` and `action()`) for better SSR integration.

## 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: 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 Solid Query example](https://github.com/orval-labs/orval/tree/master/samples/solid-query) on GitHub.
