alepha@docs:~/docs/reference/primitives$
cat $action.md
2 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}