Builder Chain
Builder Chain
Actions are built using a chainable API. Each method returns a new builder with the configuration applied.
Methods
| Method | Description |
|---|---|
.schema(zodSchema) | Set input validation schema |
.outputSchema(zodSchema) | Set output validation schema |
.use(middleware) | Add middleware to the chain |
.metadata(meta) | Attach metadata (accessible in middleware) |
.action(handler) | Define the action handler (terminal) |
.schema()
Sets the Zod schema used to validate input before the handler runs.
.schema(zodSchema: ZodType)
Parameters:
| Parameter | Type | Description |
|---|---|---|
zodSchema | ZodType | Any Zod schema (object, string, array, etc.) |
Example:
actionClient
.schema(z.object({
title: z.string().min(1).max(200),
body: z.string().min(1),
}))
.action(async ({ parsedInput }) => {
// parsedInput is typed as { title: string; body: string }
})
If validation fails, the errors are returned to the client as validationErrors — the handler is never called.
.outputSchema()
Sets the Zod schema used to validate the action's return value.
.outputSchema(zodSchema: ZodType)
Parameters:
| Parameter | Type | Description |
|---|---|---|
zodSchema | ZodType | Any Zod schema to validate the output |
Example:
actionClient
.schema(z.object({ id: z.string() }))
.outputSchema(z.object({
name: z.string(),
email: z.string().email(),
}))
.action(async ({ parsedInput }) => {
const user = await db.user.findUnique({ where: { id: parsedInput.id } })
return { name: user.name, email: user.email }
})
.use()
Adds middleware to the action chain. Middleware runs in order before the handler.
.use(middleware: MiddlewareFunction)
Middleware function signature:
async ({ ctx, next, event, metadata, clientInput }) => {
return next({ ctx: { ...ctx, newData: 'value' } })
}
Middleware parameters:
| Parameter | Type | Description |
|---|---|---|
ctx | object | Context from previous middleware |
next | (opts: { ctx }) => Promise | Continue to next middleware or handler |
event | H3Event | H3 request event |
metadata | object | Action metadata |
clientInput | unknown | Raw input before validation |
Example:
actionClient
.use(async ({ next, event }) => {
const session = await getUserSession(event)
if (!session) throw new Error('Unauthorized')
return next({ ctx: { userId: session.user.id } })
})
next(). Failing to do so will throw an error..metadata()
Attaches metadata to the action. This metadata is available in middleware via the metadata parameter.
.metadata(meta: Record<string, unknown>)
Example:
actionClient
.metadata({ requiredRole: 'admin', rateLimit: 10 })
.schema(z.object({ userId: z.string() }))
.action(async ({ parsedInput }) => { ... })
.action()
Defines the action handler. This is the terminal method — it creates the action.
.action(handler: ActionHandler)
Handler function signature:
async ({ parsedInput, ctx }) => {
return { /* result */ }
}
Handler parameters:
| Parameter | Type | Description |
|---|---|---|
parsedInput | TInput | Validated input (typed from .schema()) |
ctx | object | Context from the middleware chain |
Example:
actionClient
.schema(z.object({ name: z.string() }))
.action(async ({ parsedInput }) => {
return { greeting: `Hello, ${parsedInput.name}!` }
})
Chain Order
Methods can be called in any order, except .action() which must be last:
// All valid:
actionClient.schema(schema).action(handler)
actionClient.use(mw).schema(schema).action(handler)
actionClient.metadata(meta).use(mw).schema(schema).action(handler)
actionClient.schema(schema).outputSchema(outSchema).use(mw).action(handler)
createSafeActionClient
API reference for createSafeActionClient — configure error handling, middleware, and create reusable type-safe action clients for Nuxt.
useAction
API reference for the useAction Vue composable — reactive execution, status tracking, validation errors, and lifecycle callbacks for type-safe server actions.