Eden TanStack Query
API Reference

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)

MethodDescription
queryOptionsCreates options for useQuery / useSuspenseQuery
queryKeyGenerates a query key for cache operations
queryFilterCreates a filter for invalidateQueries, cancelQueries, etc.
infiniteQueryOptionsCreates options for useInfiniteQuery on supported non-union cursor routes
infiniteQueryKeyGenerates an infinite query key on supported non-union cursor routes
infiniteQueryFilterCreates an infinite-query filter on supported non-union cursor routes

Mutation Routes (POST, PUT, PATCH, DELETE)

MethodDescription
mutationOptionsCreates options for useMutation
mutationKeyGenerates a mutation key

queryOptions

Creates type-safe options for useQuery, useSuspenseQuery, prefetchQuery, and other TanStack Query functions.

eden.route.get.queryOptions(input, opts?): QueryOptions

Parameters

ParameterTypeDescription
inputTInput | SkipTokenQuery parameters or skipToken to disable. Optional only when the route query has no required fields
optsEdenQueryOptionsInTanStack Query options (excluding reserved)

Returns

PropertyTypeDescription
queryKeyDataTag<EdenQueryKey>Unique key based on path and input
queryFnQueryFunctionFetch function via Eden client
eden{ path: string }Route metadata

Reserved Options

Automatically set and cannot be overridden: queryKey, queryFn, queryHash, queryHashFn.

Eden-specific Options

OptionTypeDescription
eden.abortOnUnmountbooleanAbort 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?): MutationOptions

Parameters

ParameterTypeDescription
optsEdenMutationOptionsInTanStack Query mutation options (excluding reserved)

Returns

PropertyTypeDescription
mutationKeyEdenMutationKeyUnique key based on route path
mutationFnMutationFunctionMutation 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): InfiniteQueryOptions

Parameters

ParameterTypeDescription
inputTInput | SkipTokenQuery params (excluding cursor) or skipToken
opts.getNextPageParam(lastPage) => TCursor | undefinedRequired. Returns next page cursor
opts.initialCursorNonNullable<TCursor> | nullDefaults to null for optional cursor fields; required cursor fields need an explicit non-null value
opts.getPreviousPageParam(firstPage) => TCursor | undefinedFor bi-directional pagination
opts.maxPagesnumberMax 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(): EdenMutationKey
eden.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
ParameterTypeDescription
inputTInputOptional input to narrow the filter
filtersQueryFilterOptionsTanStack 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?
): QueryFilters
queryClient.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:

MethodTypeDescription
queryOptions(input, opts?) => EdenQueryOptionsOptions for useQuery; input is conditional on the route query
queryKey(input?) => DataTag<EdenQueryKey>Query key for cache ops
queryFilter(input?, filters?) => QueryFiltersFilter for invalidation

DecorateInfiniteQueryProcedure

Methods on non-union query routes with a usable required or optional top-level cursor input:

MethodTypeDescription
infiniteQueryOptions(input, opts) => EdenInfiniteQueryOptionsOptions for useInfiniteQuery
infiniteQueryKey(input?, keyOpts?) => DataTag<EdenQueryKey>Infinite query key; required cursors need explicit key options
infiniteQueryFilter(input?, filters?) => QueryFiltersBroad or cursor-specific filter; required cursors need an explicit value for exact matching

DecorateMutationProcedure

Methods on POST/PUT/PATCH/DELETE routes:

MethodTypeDescription
mutationOptions(opts?) => EdenMutationOptionsOptions for useMutation
mutationKey() => EdenMutationKeyMutation key

On this page