useEden
Proxy hook with all route methods for queries, mutations, and cache operations
useEden
The useEden hook returns an options proxy that mirrors your Elysia API structure. Each route is decorated with TanStack Query methods.
function useEden(): EdenOptionsProxy<TApp>Returns an EdenOptionsProxy<TApp> — a proxy object that mirrors your API routes, handles path parameters via function calls, and decorates each endpoint with query/mutation methods.
Route Methods
Query Routes (GET, HEAD, OPTIONS)
| Method | Description |
|---|---|
queryOptions | Creates options for useQuery / useSuspenseQuery |
queryKey | Generates a query key for cache operations |
queryFilter | Creates a filter for invalidateQueries, cancelQueries, etc. |
infiniteQueryOptions | Creates options for useInfiniteQuery on supported non-union cursor routes |
infiniteQueryKey | Generates an infinite query key on supported non-union cursor routes |
infiniteQueryFilter | Creates an infinite-query filter on supported non-union cursor routes |
Mutation Routes (POST, PUT, PATCH, DELETE)
| Method | Description |
|---|---|
mutationOptions | Creates options for useMutation |
mutationKey | Generates a mutation key |
queryOptions
Creates type-safe options for useQuery, useSuspenseQuery, prefetchQuery, and other TanStack Query functions.
eden.route.get.queryOptions(input, opts?): QueryOptionsParameters
| Parameter | Type | Description |
|---|---|---|
input | TInput | SkipToken | Query parameters or skipToken to disable. Optional only when the route query has no required fields |
opts | EdenQueryOptionsIn | TanStack Query options (excluding reserved) |
Returns
| Property | Type | Description |
|---|---|---|
queryKey | DataTag<EdenQueryKey> | Unique key based on path and input |
queryFn | QueryFunction | Fetch function via Eden client |
eden | { path: string } | Route metadata |
Reserved Options
Automatically set and cannot be overridden: queryKey, queryFn, queryHash, queryHashFn.
Eden-specific Options
| Option | Type | Description |
|---|---|---|
eden.abortOnUnmount | boolean | Abort request when component unmounts |
Example
const eden = useEden()
// Basic
const { data } = useQuery(eden.users.get.queryOptions())
// With query params and TQ options
const { data } = useQuery(
eden.users.get.queryOptions(
{ role: 'admin' },
{ staleTime: 5 * 60 * 1000 }
)
)
// Path params
const { data } = useQuery(
eden.users({ id: '123' }).get.queryOptions()
)
// Conditional with skipToken
const { data } = useQuery(
eden.users({ id: userId ?? '' }).get.queryOptions(
userId ? undefined : skipToken
)
)mutationOptions
Creates type-safe options for useMutation.
eden.route.post.mutationOptions(opts?): MutationOptionsParameters
| Parameter | Type | Description |
|---|---|---|
opts | EdenMutationOptionsIn | TanStack Query mutation options (excluding reserved) |
Returns
| Property | Type | Description |
|---|---|---|
mutationKey | EdenMutationKey | Unique key based on route path |
mutationFn | MutationFunction | Mutation function via Eden client |
eden | { path: string } | Route metadata |
Reserved Options
Automatically set: mutationKey, mutationFn.
Example
const eden = useEden()
const queryClient = useQueryClient()
const createUser = useMutation({
...eden.users.post.mutationOptions(),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: eden.users.get.queryKey() })
}
})
createUser.mutate({ name: 'Alice', email: 'alice@example.com' })infiniteQueryOptions
Creates type-safe options for useInfiniteQuery with cursor-based pagination.
This method and the related key and filter helpers are available only when the
route declares a usable top-level cursor query field on a non-union query
schema. A required null-only or any cursor is not usable.
eden.route.get.infiniteQueryOptions(input, opts): InfiniteQueryOptionsParameters
| Parameter | Type | Description |
|---|---|---|
input | TInput | SkipToken | Query params (excluding cursor) or skipToken |
opts.getNextPageParam | (lastPage) => TCursor | undefined | Required. Returns next page cursor |
opts.initialCursor | NonNullable<TCursor> | null | Defaults to null for optional cursor fields; required cursor fields need an explicit non-null value |
opts.getPreviousPageParam | (firstPage) => TCursor | undefined | For bi-directional pagination |
opts.maxPages | number | Max pages to keep in memory |
Example
const eden = useEden()
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(
eden.posts.get.infiniteQueryOptions(
{ limit: 10 },
{
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
initialCursor: null,
}
)
)queryKey
Generates a typed query key for cache operations.
eden.route.get.queryKey(input?): DataTag<EdenQueryKey>Key structure:
eden.users.get.queryKey()
// => [['users', 'get'], { type: 'query' }]
eden.users.get.queryKey({ role: 'admin' })
// => [['users', 'get'], { input: { role: 'admin' }, type: 'query' }]
eden.users({ id: '1' }).get.queryKey()
// => [['users', 'get'], { input: { id: '1' }, type: 'query' }]mutationKey
Generates a mutation key from route path.
eden.route.post.mutationKey(): EdenMutationKeyeden.users.post.mutationKey()
// => [['users', 'post']]infiniteQueryKey
Generates an infinite query key (separate from regular query cache).
eden.route.get.infiniteQueryKey(
input?,
{ initialCursor?: TCursor | null }?
): DataTag<EdenQueryKey>eden.posts.get.infiniteQueryKey()
// => [['posts', 'get'], {
// type: 'infinite',
// infinite: { initialPageParam: null }
// }]
eden.posts.get.infiniteQueryKey({ category: 'tech' })
eden.posts.get.infiniteQueryKey(
{ category: 'tech' },
{ initialCursor: 'start' }
)The initial cursor is part of the exact infinite-query key. Pass the same
initialCursor used by infiniteQueryOptions. Omission targets the default
null cursor for optional cursor routes; required cursor routes must provide a
non-null value.
queryFilter
Creates a query filter for bulk cache operations like invalidateQueries, cancelQueries, removeQueries.
eden.route.get.queryFilter(input?, filters?): QueryFilters| Parameter | Type | Description |
|---|---|---|
input | TInput | Optional input to narrow the filter |
filters | QueryFilterOptions | TanStack Query filter options (exact, type, stale, fetchStatus, predicate) |
// Invalidate all user queries
queryClient.invalidateQueries(eden.users.get.queryFilter())
// Invalidate with specific input
queryClient.invalidateQueries(
eden.users.get.queryFilter({ role: 'admin' }, { exact: false })
)infiniteQueryFilter
Same as queryFilter but scoped to infinite queries.
eden.route.get.infiniteQueryFilter(
input?,
filters?
): QueryFiltersqueryClient.invalidateQueries(eden.posts.get.infiniteQueryFilter())
queryClient.invalidateQueries(
eden.posts.get.infiniteQueryFilter(
{ category: 'tech' },
{ initialCursor: 'start' }
)
)The filter matches every initial-cursor variant for the selected route input by
default. Pass initialCursor to target one cursor identity. With the default
hash, object and array cursors are complete values rather than partial prefixes;
a custom queryKeyHashFn defines identity exactly as it does for the cache.
Route input still uses TanStack Query's normal partial matching. With
exact: true, an optional cursor route may omit initialCursor to target its
default null variant. A required cursor route may omit initialCursor only
for a broad filter with exact absent or false; exact and cursor-specific
filters require an explicit non-null cursor.
Low-level APIs
For use outside React context (loaders, server components, utilities):
import {
edenQueryOptions,
edenMutationOptions,
edenInfiniteQueryOptions,
} from 'eden-tanstack-react-query'
// edenQueryOptions
const opts = edenQueryOptions({
path: ['users', 'get'],
input: { role: 'admin' },
fetch: async (input, signal) => { /* ... */ },
opts: { staleTime: 5000 }
})
// edenMutationOptions
const opts = edenMutationOptions({
path: ['users', 'post'],
mutate: async (input) => { /* ... */ },
})
// edenInfiniteQueryOptions
const opts = edenInfiniteQueryOptions({
path: ['posts', 'get'],
input: { limit: 10 },
initialPageParam: null as string | null,
fetch: async (inputWithCursor, signal) => { /* ... */ },
opts: { getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined }
})Types
DecorateQueryProcedure
Methods on GET/HEAD/OPTIONS routes:
| Method | Type | Description |
|---|---|---|
queryOptions | (input, opts?) => EdenQueryOptions | Options for useQuery; input is conditional on the route query |
queryKey | (input?) => DataTag<EdenQueryKey> | Query key for cache ops |
queryFilter | (input?, filters?) => QueryFilters | Filter for invalidation |
DecorateInfiniteQueryProcedure
Methods on non-union query routes with a usable required or optional top-level
cursor input:
| Method | Type | Description |
|---|---|---|
infiniteQueryOptions | (input, opts) => EdenInfiniteQueryOptions | Options for useInfiniteQuery |
infiniteQueryKey | (input?, keyOpts?) => DataTag<EdenQueryKey> | Infinite query key; required cursors need explicit key options |
infiniteQueryFilter | (input?, filters?) => QueryFilters | Broad or cursor-specific filter; required cursors need an explicit value for exact matching |
DecorateMutationProcedure
Methods on POST/PUT/PATCH/DELETE routes:
| Method | Type | Description |
|---|---|---|
mutationOptions | (opts?) => EdenMutationOptions | Options for useMutation |
mutationKey | () => EdenMutationKey | Mutation key |