alepha@docs:~/docs/reference/primitives$
cat $action.md2 min read
#$action
#Import
typescript
1import { $action } from "alepha/server";
#Overview
Creates a server action primitive for defining type-safe HTTP endpoints.
Server actions are the core building blocks for REST APIs in Alepha, providing declarative HTTP endpoints with full type safety, automatic validation, and OpenAPI documentation.
Key Features
- Full TypeScript inference for request/response types
- Automatic schema validation using TypeBox
- Convention-based URL generation with customizable paths
- Direct invocation (
run()) or HTTP requests (fetch()) - Built-in authentication and authorization support
- Automatic content-type handling (JSON, form-data, plain text)
URL Generation
Important: All $action paths are automatically prefixed with /api.
ts
1$action({ path: "/users" }) // → GET /api/users2$action({ path: "/users/:id" }) // → GET /api/users/:id3$action({ path: "/hello" }) // → GET /api/hello
This prefix is configurable via the SERVER_API_PREFIX environment variable.
HTTP method defaults to GET, or POST if body schema is provided.
Common Use Cases
- CRUD operations with type safety
- File upload and download endpoints
- Microservice communication
#Options
| Option | Type | Required | Description |
|---|---|---|---|
name |
string |
No | Name of the action |
group |
string |
No | Group actions together |
path |
string |
No | Pathname of the route |
method |
RouteMethod |
No | The route method |
schema |
TConfig |
No | The config schema of the route |
description |
string |
No | A short description of the action |
disabled |
boolean |
No | Disable the route |
handler |
ServerActionHandler<TConfig> |
Yes | Main route handler |
#Examples
ts
1class UserController { 2 getUsers = $action({ 3 path: "/users", 4 schema: { 5 query: t.object({ 6 page: t.optional(t.number({ default: 1 })), 7 limit: t.optional(t.number({ default: 10 })) 8 }), 9 response: t.object({10 users: t.array(t.object({11 id: t.text(),12 name: t.text(),13 email: t.text()14 })),15 total: t.number()16 })17 },18 handler: async ({ query }) => {19 const users = await this.userService.findUsers(query);20 return { users: users.items, total: users.total };21 }22 });23 24 createUser = $action({25 method: "POST",26 path: "/users",27 schema: {28 body: t.object({29 name: t.text(),30 email: t.text({ format: "email" })31 }),32 response: t.object({ id: t.text(), name: t.text() })33 },34 handler: async ({ body }) => {35 return await this.userService.create(body);36 }37 });38}