Skip to content

Composables

All composables are auto-imported and fully typed from your ZModel schema. They communicate with the auto-generated server endpoints and keep a normalized store in sync.

useZenstackCreate

Creates a new record.

ts
const { mutate, data, error, status, loading, reset } = useZenstackCreate('User')

Usage

ts
const { mutate: createUser, error, loading } = useZenstackCreate('User')

async function onSubmit() {
  await createUser({ email: '[email protected]', name: 'Alice' })
}

Returns

PropertyTypeDescription
dataRef<Item | null>The created record
errorRef<$Zerror | null>Error from the last call
statusRef<'idle' | 'pending' | 'success' | 'error'>Current status
loadingComputedRef<boolean>true while the request is in flight
mutate(input) => Promise<Item | null>Trigger the create operation
reset() => voidReset data, error, and status to initial values

useZenstackRead

Fetches a single record by ID.

ts
const { data, error, status, loading, query } = await useZenstackRead('User', userId)

Usage

ts
const { data: user } = await useZenstackRead('User', userId)

// With related models
const { data: user } = await useZenstackRead('User', userId, {
  include: { posts: true },
})

Options

OptionTypeDefaultDescription
fetchPolicyFetchPolicymodule defaultOverride the global fetch policy for this call
immediatebooleantrueRun the query immediately on call
includeobjectRelated models to include (typed from schema)

Returns

PropertyTypeDescription
dataRef<Item | null>The fetched record
errorRef<$Zerror | null>Error from the last query
statusRef<Status>Current status
loadingComputedRef<boolean>true while fetching
query() => Promise<void>Re-run the query manually

useZenstackReadMany

Fetches a list of records with optional filtering, ordering, and pagination.

ts
const { data, error, status, loading, query, queryMore, canQueryMore, reset } =
  await useZenstackReadMany('User')

Usage

ts
// Basic list
const { data: users } = await useZenstackReadMany('User')

// Filtered and ordered
const search = ref('')

const { data: users } = await useZenstackReadMany('User', {
  where: () => ({ name: { contains: search.value } }),
  orderBy: { createdAt: 'desc' },
  take: 20,
  watch: true, // re-query automatically when reactive `where`/`orderBy` change
})

// Load more (cursor-based pagination)
const { data: posts, queryMore, canQueryMore } = await useZenstackReadMany('Post', {
  take: 10,
})

// Call queryMore() to append the next page
await queryMore()

// Example with VueUse useInfiniteScroll
import { useInfiniteScroll } from '@vueuse/core'

const containerRef = ref<HTMLElement | null>(null)

useInfiniteScroll(
  containerRef,
  () => queryMore(),
  {
    distance: 10,
    canLoadMore: () => canQueryMore.value
  }
)

Options

OptionTypeDefaultDescription
fetchPolicyFetchPolicymodule defaultOverride the global fetch policy
immediatebooleantrueRun the query immediately
includeobjectRelated models to include
whereMaybeRefOrGetter<Where>Filter criteria
orderByMaybeRefOrGetter<OrderBy>Sort criteria
takenumberMax records per page
watchbooleanfalseRe-query when where/orderBy refs change

Returns

PropertyTypeDescription
dataRef<Item[] | null>The fetched records
errorRef<$Zerror | null>Error from the last query
statusRef<Status>Current status
loadingComputedRef<boolean>true while fetching
canQueryMoreRef<boolean>false when all records have been loaded
query() => Promise<void>Re-run the query (resets to first page)
queryMore() => Promise<void>Append the next page of results
reset() => voidReset data and pagination state

useZenstackUpdate

Updates an existing record by ID.

ts
const { mutate, data, error, status, loading, reset } = useZenstackUpdate('User')

Usage

ts
const { mutate: updateUser, loading } = useZenstackUpdate('User')

await updateUser(userId, { name: 'New Name' })

Returns

PropertyTypeDescription
dataRef<Item | null>The updated record
errorRef<$Zerror | null>Error from the last call
statusRef<Status>Current status
loadingComputedRef<boolean>true while the request is in flight
mutate(id, input) => Promise<Item | null>Trigger the update
reset() => voidReset state

useZenstackDelete

Deletes a record by ID.

ts
const { mutate, data, error, status, loading, reset } = useZenstackDelete('User')

Usage

ts
const { mutate: deleteUser, loading } = useZenstackDelete('User')

await deleteUser(userId)

Returns

PropertyTypeDescription
dataRef<Item | null>The deleted record
errorRef<$Zerror | null>Error from the last call
statusRef<Status>Current status
loadingComputedRef<boolean>true while the request is in flight
mutate(id) => Promise<Item | null>Trigger the delete
reset() => voidReset state

Error Handling

All composables return an error ref typed as $Zerror | null. This type is an extension of FetchError that includes ZenStack's specific ORMError properties when a database or policy error occurs.

$Zerror Properties

When the server encounters a ZenStack error, the error object will contain the following properties inside its data payload:

PropertyTypeDescription
reasonORMErrorReasonThe reason code for the error (e.g., 'rejected-by-policy', 'not-found', 'db-query-error', 'invalid-input').
modelstringThe name of the ZModel that the error pertains to.
dbErrorCodeunknownThe raw error code given by the underlying database driver.
dbErrorMessagestringThe raw error message given by the underlying database driver.
rejectedByPolicyReasonRejectedByPolicyReasonIf reason is 'rejected-by-policy', this indicates why ('no-access', 'cannot-read-back', etc).
statusCodenumberThe HTTP status code returned by the auto-generated API endpoint (e.g., 403 for policy rejections).

For more details on ZenStack's error handling, refer to the ZenStack ORM Errors Documentation.