@kubb/plugin-solid-query
Generate SolidJS Query hooks from your OpenAPI schema.
Installation
bun add -d @kubb/plugin-solid-querypnpm add -D @kubb/plugin-solid-querynpm install --save-dev @kubb/plugin-solid-queryyarn add -D @kubb/plugin-solid-queryOptions
output
Specify the export location for the files and define the behavior of the output.
output.path
Path to the output folder or file that contains the generated code.
TIP
if output.path is a file, group cannot be used.
| Type: | string |
|---|---|
| Required: | true |
| Default: | 'hooks' |
output.barrelType
Specify what to export and optionally disable barrel file generation.
TIP
Using propagate will prevent a plugin from creating a barrel file, but it will still propagate, allowing output.barrelType to export the specific function or type.
| Type: | 'all' | 'named' | 'propagate' | false |
|---|---|
| Required: | false |
| Default: | 'named' |
export * from "./gen/petService.ts"export { PetService } from "./gen/petService.ts"output.banner
Add a banner comment at the top of every generated file.
| Type: | string | (oas: Oas) => string |
|---|---|
| Required: | false |
output.footer
Add a footer comment at the end of every generated file.
| Type: | string | (oas: Oas) => string |
|---|---|
| Required: | false |
output.override
Whether Kubb overrides existing external files that can be generated if they already exist.
| Type: | boolean |
|---|---|
| Required: | false |
| Default: | false |
contentType
Define which content type to use.
By default, Kubb uses the first JSON-valid media type.
| Type: | 'application/json' | (string & {}) |
|---|---|
| Required: | false |
group
Grouping combines files in a folder based on a specific type.
For example, with this configuration:
group: {
type: 'tag',
name({ group }){
return `${group}Controller`
}
}This generates the following structure:
.
├── src/
│ └── petController/
│ │ ├── addPet.ts
│ │ └── getPet.ts
│ └── storeController/
│ ├── createStore.ts
│ └── getStoreById.ts
├── petStore.yaml
├── kubb.config.ts
└── package.jsongroup.type
Specify the property to group files by.
| Type: | 'tag' |
|---|---|
| Required: | true |
'tag': Uses the first tag fromoperation.getTags().at(0)?.name
group.name
Return the name of a group based on the group name, this will be used for the file and name generation.
| Type: | (context: GroupContext) => string |
|---|---|
| Required: | false |
| Default: | (ctx) => '${ctx.group}Controller' |
client
client.importPath
Path to the client used for API calls. Supports both relative and absolute paths.
When to use importPath
Use importPath when you want to:
- Customize the HTTP client: Provide your own client implementation with custom configurations (e.g., baseURL, headers, interceptors)
- Add authentication: Include authentication tokens or other security mechanisms in your client
- Override default behavior: Replace the default Kubb client with your own implementation
Default behavior
When importPath is not specified:
- If
bundle: false(default): Uses@kubb/plugin-client/clients/${client}where client is eitheraxiosorfetch - If
bundle: true: Bundles the client into.kubb/fetch.ts
Import structure
Generated code imports:
- Client as default import
- Types as named type imports
Example for axios client:
/**
* Generated by Kubb (https://kubb.dev/).
* Do not edit manually.
*/
import client from '${client.importPath}'
import type { RequestConfig, ResponseErrorConfig } from '${client.importPath}'
// ... rest of generated fileIMPORTANT
When using importPath with query plugins such as @kubb/plugin-react-query, @kubb/plugin-vue-query, @kubb/plugin-svelte-query, @kubb/plugin-solid-query, or @kubb/plugin-swr, the generated hooks also import type Client from the custom module:
import type { Client, RequestConfig, ResponseErrorConfig } from '@/lib/client'Your custom client module must export these three types. If any of them is missing, TypeScript will report an unresolvable import error.
export type RequestConfig<TData = unknown> = {
url?: string
method: 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE'
params?: object
data?: TData | FormData
responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
signal?: AbortSignal
headers?: HeadersInit
}
export type ResponseConfig<TData = unknown> = {
data: TData
status: number
statusText: string
}
export type ResponseErrorConfig<TError = unknown> = TError
// The Client type alias is required when using query plugins
export type Client = <TData, _TError = unknown, TVariables = unknown>(
config: RequestConfig<TVariables>
) => Promise<ResponseConfig<TData>>
export const client: Client = async (config) => { /* ... */ }
export default clientExample configuration with custom client:
import { defineConfig } from '@kubb/core'
import { pluginClient } from '@kubb/plugin-client'
export default defineConfig({
// ...
plugins: [
pluginClient({
importPath: './src/client.ts' // Path to your custom client
}),
],
})TIP
Learn more about defining a custom client here.
| Type: | string |
|---|---|
| Required: | false |
client.dataReturnType
Return type used when calling the client.
| Type: | 'data' | 'full' |
|---|---|
| Required: | false |
| Default: | 'data' |
'data'returns ResponseConfig[data].'full'returns ResponseConfig.
export async function getPetById<TData>(
petId: GetPetByIdPathParams,
): Promise<ResponseConfig<TData>["data"]> {
...
}export async function getPetById<TData>(
petId: GetPetByIdPathParams,
): Promise<ResponseConfig<TData>> {
...
}client.baseURL
Sets a custom base URL for all generated calls.
| Type: | string |
|---|---|
| Required: | false |
client.clientType
Specify whether to use function-based or class-based clients.
| Type: | 'function' | 'class' |
|---|---|
| Required: | false |
| Default: | 'function' |
WARNING
This plugin is only compatible with clientType: 'function' (the default). If clientType: 'class' is detected, the plugin will automatically generate its own inline function-based client instead of importing from @kubb/plugin-client.
client.bundle
Controls whether the HTTP client runtime is copied into the generated .kubb directory.
| Type: | boolean |
|---|---|
| Required: | false |
| Default: | false |
trueadds a.kubb/fetch.tsfile containing the selected client template (fetch or axios). Generated clients remain self-contained.falsekeeps generated clients slim by importing the shared runtime from@kubb/plugin-client/clients/{client}.- Override this behavior by providing a custom
client.importPath.
paramsType
Defines how parameters are passed to generated functions. Switch between object-style parameters and inline parameters.
| Type: | 'object' | 'inline' |
|---|---|
| Required: | false |
| Default: | 'inline' |
TIP
When paramsType is set to 'object', pathParams will also be set to 'object'.
'object'returns params and pathParams as an object.'inline'returns params as comma-separated params.
export async function deletePet(
{
petId,
headers,
}: {
petId: DeletePetPathParams['petId']
headers?: DeletePetHeaderParams
},
config: Partial<RequestConfig> = {},
) {
...
}export async function deletePet(
petId: DeletePetPathParams['petId'],
headers?: DeletePetHeaderParams,
config: Partial<RequestConfig> = {}
){
...
}paramsCasing
Transform parameter names to a specific casing format for path, query, and header parameters in generated client code.
IMPORTANT
When using paramsCasing, ensure that @kubb/plugin-ts also has the same paramsCasing setting. This option automatically maps transformed parameter names back to their original API names in HTTP requests.
| Type: | 'camelcase' |
|---|---|
| Required: | false |
| Default: | undefined |
'camelcase'transforms parameter names to camelCase
// Function parameters use camelCase
export async function deletePet(
petId: DeletePetPathParams['petId'], // ✓ camelCase
headers?: DeletePetHeaderParams,
config: Partial<RequestConfig> = {}
) {
// Automatically maps back to original name for the API
const pet_id = petId
return fetch({
method: 'DELETE',
url: `/pet/${pet_id}`, // Uses original API parameter name
...
})
}// Parameters use original API naming
export async function deletePet(
pet_id: DeletePetPathParams['pet_id'], // Original naming
headers?: DeletePetHeaderParams,
config: Partial<RequestConfig> = {}
) {
return fetch({
method: 'DELETE',
url: `/pet/${pet_id}`,
...
})
}TIP
The client automatically generates mapping code to convert camelCase parameter names back to the original API format. You write code with developer-friendly camelCase names, but HTTP requests use the exact parameter names from your OpenAPI specification.
pathParamsType
Defines how pathParams are passed to generated functions.
| Type: | 'object' | 'inline' |
|---|---|
| Required: | false |
| Default: | 'inline' |
'object'returns pathParams as an object.'inline'returns pathParams as comma-separated params.
export async function getPetById (
{ petId }: GetPetByIdPathParams,
) {
...
}export async function getPetById(
petId: GetPetByIdPathParams,
) {
...
}parser
Parser used before returning data.
| Type: | 'client' | 'zod' |
|---|---|
| Required: | false |
| Default: | 'client' |
'zod'uses@kubb/plugin-zodto parse data.'client'returns data without parsing.
queryKey
Customize the queryKey that will be used for the query.
The function receives an object with:
operation: The OpenAPI operation object with methods likegetTags(),getOperationId(), etc.schemas: An object containing operation schemas includingpathParams,queryParams,request,response, etc.
WARNING
When using a string you need to use JSON.stringify.
| Type: | (props: { operation: Operation; schemas: OperationSchemas }) => unknown[] |
|---|---|
| Required: | false |
Examples
Using tags and path parameters
Generate a queryKey with operation tags and path parameters:
import { defineConfig } from '@kubb/core'
import { pluginSolidQuery } from '@kubb/plugin-solid-query'
export default defineConfig({
// ...
plugins: [
pluginSolidQuery({
queryKey: ({ operation, schemas }) => {
const tags = operation.getTags().map(tag => JSON.stringify(tag.name))
const pathParams = schemas.pathParams?.keys || []
return [...tags, ...pathParams]
},
}),
],
})For a GET operation with tags ["user"] and path parameter username, this generates:
export const getUserByNameQueryKey = ({ username }: { username: GetUserByNamePathParams["username"] }) =>
["user", username] as constUsing the default transformer
You can extend the default queryKey transformer:
import { pluginSolidQuery } from '@kubb/plugin-solid-query'
import { QueryKey } from '@kubb/plugin-solid-query/components'
export default defineConfig({
// ...
plugins: [
pluginSolidQuery({
queryKey: (props) => {
const defaultKeys = QueryKey.getTransformer(props)
return [JSON.stringify('v5'), ...defaultKeys]
},
}),
],
})This prepends a version to the default queryKey:
export const findPetsByTagsQueryKey = (params?: FindPetsByTagsQueryParams) =>
["v5", { url: '/pet/findByTags' }, ...(params ? [params] : [])] as constUsing operation ID
Create a simple queryKey using the operation ID:
import { pluginSolidQuery } from '@kubb/plugin-solid-query'
export default defineConfig({
// ...
plugins: [
pluginSolidQuery({
queryKey: ({ operation }) => {
return [JSON.stringify(operation.getOperationId())]
},
}),
],
})Conditional keys based on parameters
Include query parameters when they exist:
import { pluginSolidQuery } from '@kubb/plugin-solid-query'
export default defineConfig({
// ...
plugins: [
pluginSolidQuery({
queryKey: ({ operation, schemas }) => {
const keys = [JSON.stringify(operation.getOperationId())]
// Add path parameter values (without quotes, so they reference the variables)
if (schemas.pathParams?.keys) {
keys.push(...schemas.pathParams.keys)
}
// Add query params conditionally (the string gets embedded as code)
if (schemas.queryParams?.name) {
keys.push('...(params ? [params] : [])')
}
return keys
},
}),
],
})query
Override some useQuery behaviors.
To disable the creation of hooks pass false, this will result in only creating queryOptions.
| Type: | Query |
|---|---|
| Required: | false |
type Query = {
methods: Array<HttpMethod>
importPath?: string
} | falsequery.methods
Define which HttpMethods can be used for queries
| Type: | Array<HttpMethod> |
|---|---|
| Required: | ['get'] |
query.importPath
Path to the useQuery that will be used to do the useQuery functionality. It will be used as import { useQuery } from '${hook.importPath}'. It allows both relative and absolute path. the path will be applied as is, so relative path should be based on the file being generated.
| Type: | string |
|---|---|
| Required: | false |
| Default: | '@tanstack/solid-query' |
mutation
Override some useMutation behaviors.
To disable queries pass false.
| Type: | Mutation |
|---|---|
| Required: | false |
type Mutation = {
methods: Array<HttpMethod>
importPath?: string
} | falsemutation.methods
Define which HttpMethods can be used for mutations
| Type: | Array<HttpMethod> |
|---|---|
| Required: | false |
| Default: | ['post', 'put', 'delete'] |
mutation.importPath
Path to the useQuery that will be used to do the useQuery functionality. It will be used as import { useMutation } from '${hook.importPath}'. It allows both relative and absolute path. the path will be applied as is, so relative path should be based on the file being generated.
| Type: | string |
|---|---|
| Required: | false |
| Default: | '@tanstack/solid-query' |
mutationKey
Customize the mutationKey.
WARNING
When using a string you need to use JSON.stringify.
| Type: | (props: { operation: Operation; schemas: OperationSchemas }) => unknown[] |
|---|---|
| Required: | false |
include
Array containing include parameters to include tags, operations, methods, paths, or content types.
| Type: | Array<Include> |
|---|---|
| Required: | false |
export type Include = {
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
pattern: string | RegExp
}exclude
Array containing exclude parameters to exclude or skip tags, operations, methods, paths, or content types.
| Type: | Array<Exclude> |
|---|---|
| Required: | false |
export type Exclude = {
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
pattern: string | RegExp
}override
Array containing override parameters to override options based on tags, operations, methods, paths, or content types.
| Type: | Array<Override> |
|---|---|
| Required: | false |
export type Override = {
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
pattern: string | RegExp
options: PluginOptions
}generators
See Generators for more information on how to use generators.
| Type: | Array<Generator<PluginSolidQuery>> |
|---|---|
| Required: | false |
transformers
transformers.name
Customize the names based on the type that is provided by the plugin.
| Type: | (name: string, type?: ResolveType) => string |
|---|---|
| Required: | false |
type ResolveType = 'file' | 'function' | 'type' | 'const'Example
import { defineConfig } from '@kubb/core'
import { pluginOas } from '@kubb/plugin-oas'
import { pluginSolidQuery } from '@kubb/plugin-solid-query'
import { pluginTs } from '@kubb/plugin-ts'
export default defineConfig({
input: {
path: './petStore.yaml',
},
output: {
path: './src/gen',
},
plugins: [
pluginOas(),
pluginTs(),
pluginSolidQuery({
output: {
path: './hooks',
},
group: {
type: 'tag',
name: ({ group }) => `${group}Hooks`,
},
client: {
dataReturnType: 'full',
},
query: {
methods: [ 'get' ],
importPath: "@tanstack/solid-query"
},
}),
],
})