Generate queryOptions, mutationOptions, and query key helpers for TanStack Query.
The @karnak19/pbkit-tanstack package provides a plugin that generates framework-agnostic TanStack Query options and query key helpers.
Install
Section titled “Install”bun add @karnak19/pbkit-tanstack @tanstack/query-coreAdd the plugin to your pbkit.config.ts:
import { tanstackPlugin } from "@karnak19/pbkit-tanstack"
export default { input: "https://my-pb.example.com", output: "./src/generated", sdk: { baseUrl: "https://my-pb.example.com", }, plugins: [tanstackPlugin],}After running bunx pbkit generate, a tanstack.gen.ts file is created alongside types.gen.ts, client.gen.ts, and sdk.gen.ts.
Generated output
Section titled “Generated output”The plugin generates three categories of helpers per collection:
Query key helpers
Section titled “Query key helpers”Type-safe query key factories for manual cache invalidation:
// Single record keyarticleQueryKey("RECORD_ID") // ["articles", "RECORD_ID"] as const
// First match keygetFirstArticleQueryKey("status='published'") // ["articles", "first", "status='published'"] as const
// List keyarticlesQueryKey({ page: 1, perPage: 20 }) // ["articles", { page: 1, perPage: 20 }] as const
// Full list keyfullListArticlesQueryKey() // ["articles", "full", undefined] as constQuery options
Section titled “Query options”Pre-configured queryOptions for use with useQuery:
import { articleOptions, articlesOptions } from "./generated/tanstack.gen"import { useQuery } from "@tanstack/react-query"
// Get a single recordconst { data } = useQuery(articleOptions("RECORD_ID"))
// List with paginationconst { data } = useQuery(articlesOptions({ page: 1, perPage: 20 }))Mutation options
Section titled “Mutation options”Pre-configured mutationOptions for use with useMutation:
import { createArticleMutationOptions, updateArticleMutationOptions } from "./generated/tanstack.gen"import { useMutation, useQueryClient } from "@tanstack/react-query"
const queryClient = useQueryClient()
// Createconst createMut = useMutation(createArticleMutationOptions())
// Updateconst updateMut = useMutation(updateArticleMutationOptions())Usage example
Section titled “Usage example”import { articleOptions, articlesOptions, articleQueryKey, createArticleMutationOptions,} from "./generated/tanstack.gen"import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
function ArticleList() { const { data, isLoading } = useQuery(articlesOptions({ page: 1, perPage: 20 }))
if (isLoading) return <p>Loading...</p>
return ( <ul> {data.items.map(article => ( <li key={article.id}>{article.title}</li> ))} </ul> )}
function CreateArticle() { const queryClient = useQueryClient() const createMut = useMutation({ ...createArticleMutationOptions(), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["articles"] }) }, })
return ( <button onClick={() => createMut.mutate({ title: "New", status: "draft" })} disabled={createMut.isPending} > Create </button> )}Cache invalidation
Section titled “Cache invalidation”Unlike hook-based approaches, the plugin gives you query key helpers for manual cache invalidation. This gives you full control over when and how to invalidate:
import { articleQueryKey } from "./generated/tanstack.gen"
const queryClient = useQueryClient()
// Invalidate a specific recordqueryClient.invalidateQueries({ queryKey: articleQueryKey("RECORD_ID") })
// Invalidate all article queriesqueryClient.invalidateQueries({ queryKey: ["articles"] })Framework-agnostic
Section titled “Framework-agnostic”The generated options import from @tanstack/query-core, not @tanstack/react-query. This means you can use them with any TanStack Query adapter (React, Solid, Svelte, Vue).
Collection filtering
Section titled “Collection filtering”The plugin respects the collections config — excluded collections won’t generate options, and disabled operations won’t generate the corresponding helpers.
export default { collections: { articles: { operations: { delete: false } }, // no deleteArticleMutationOptions }, plugins: [tanstackPlugin],}