elysiajs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseElysiaJS Development Skill
ElysiaJS 开发技能
Always consult elysiajs.com/llms.txt for code examples and latest API.
如需代码示例和最新API,请始终参考elysiajs.com/llms.txt。
Overview
概述
ElysiaJS is a TypeScript framework for building Bun-first (but not limited to Bun) type-safe, high-performance backend servers. This skill provides comprehensive guidance for developing with Elysia, including routing, validation, authentication, plugins, integrations, and deployment.
ElysiaJS是一个TypeScript框架,用于构建优先支持Bun(但不限于Bun)的类型安全、高性能后端服务器。本技能提供了使用Elysia开发的全面指南,包括路由、验证、认证、插件、集成和部署。
When to Use This Skill
何时使用本技能
Trigger this skill when the user asks to:
- Create or modify ElysiaJS routes, handlers, or servers
- Setup validation with TypeBox or other schema libraries (Zod, Valibot)
- Implement authentication (JWT, session-based, macros, guards)
- Add plugins (CORS, OpenAPI, Static files, JWT)
- Integrate with external services (Drizzle ORM, Better Auth, Next.js, Eden Treaty)
- Setup WebSocket endpoints for real-time features
- Create unit tests for Elysia instances
- Deploy Elysia servers to production
当用户提出以下需求时,触发本技能:
- 创建或修改ElysiaJS路由、处理器或服务器
- 使用TypeBox或其他模式库(Zod、Valibot)设置验证
- 实现认证(JWT、基于会话、宏、守卫)
- 添加插件(CORS、OpenAPI、静态文件、JWT)
- 与外部服务集成(Drizzle ORM、Better Auth、Next.js、Eden Treaty)
- 设置WebSocket端点以实现实时功能
- 为Elysia实例创建单元测试
- 将Elysia服务器部署到生产环境
Quick Start
快速开始
Quick scaffold:
bash
bun create elysia app快速搭建项目:
bash
bun create elysia appBasic Server
基础服务器
typescript
import { Elysia, t, status } from 'elysia'
const app = new Elysia()
.get('/', () => 'Hello World')
.post('/user', ({ body }) => body, {
body: t.Object({
name: t.String(),
age: t.Number()
})
})
.get('/id/:id', ({ params: { id } }) => {
if(id > 1_000_000) return status(404, 'Not Found')
return id
}, {
params: t.Object({
id: t.Number({
minimum: 1
})
}),
response: {
200: t.Number(),
404: t.Literal('Not Found')
}
})
.listen(3000)typescript
import { Elysia, t, status } from 'elysia'
const app = new Elysia()
.get('/', () => 'Hello World')
.post('/user', ({ body }) => body, {
body: t.Object({
name: t.String(),
age: t.Number()
})
})
.get('/id/:id', ({ params: { id } }) => {
if(id > 1_000_000) return status(404, 'Not Found')
return id
}, {
params: t.Object({
id: t.Number({
minimum: 1
})
}),
response: {
200: t.Number(),
404: t.Literal('Not Found')
}
})
.listen(3000)Basic Usage
基础用法
HTTP Methods
HTTP方法
typescript
import { Elysia } from 'elysia'
new Elysia()
.get('/', 'GET')
.post('/', 'POST')
.put('/', 'PUT')
.patch('/', 'PATCH')
.delete('/', 'DELETE')
.options('/', 'OPTIONS')
.head('/', 'HEAD')typescript
import { Elysia } from 'elysia'
new Elysia()
.get('/', 'GET')
.post('/', 'POST')
.put('/', 'PUT')
.patch('/', 'PATCH')
.delete('/', 'DELETE')
.options('/', 'OPTIONS')
.head('/', 'HEAD')Path Parameters
路径参数
typescript
.get('/user/:id', ({ params: { id } }) => id)
.get('/post/:id/:slug', ({ params }) => params)typescript
.get('/user/:id', ({ params: { id } }) => id)
.get('/post/:id/:slug', ({ params }) => params)Query Parameters
查询参数
typescript
.get('/search', ({ query }) => query.q)
// GET /search?q=elysia → "elysia"typescript
.get('/search', ({ query }) => query.q)
// GET /search?q=elysia → "elysia"Request Body
请求体
typescript
.post('/user', ({ body }) => body)typescript
.post('/user', ({ body }) => body)Headers
请求头
typescript
.get('/', ({ headers }) => headers.authorization)typescript
.get('/', ({ headers }) => headers.authorization)TypeBox Validation
TypeBox验证
Basic Types
基础类型
typescript
import { Elysia, t } from 'elysia'
.post('/user', ({ body }) => body, {
body: t.Object({
name: t.String(),
age: t.Number(),
email: t.String({ format: 'email' }),
website: t.Optional(t.String({ format: 'uri' }))
})
})typescript
import { Elysia, t } from 'elysia'
.post('/user', ({ body }) => body, {
body: t.Object({
name: t.String(),
age: t.Number(),
email: t.String({ format: 'email' }),
website: t.Optional(t.String({ format: 'uri' }))
})
})Nested Objects
嵌套对象
typescript
body: t.Object({
user: t.Object({
name: t.String(),
address: t.Object({
street: t.String(),
city: t.String()
})
})
})typescript
body: t.Object({
user: t.Object({
name: t.String(),
address: t.Object({
street: t.String(),
city: t.String()
})
})
})Arrays
数组
typescript
body: t.Object({
tags: t.Array(t.String()),
users: t.Array(t.Object({
id: t.String(),
name: t.String()
}))
})typescript
body: t.Object({
tags: t.Array(t.String()),
users: t.Array(t.Object({
id: t.String(),
name: t.String()
}))
})File Upload
文件上传
typescript
.post('/upload', ({ body }) => body.file, {
body: t.Object({
file: t.File({
type: 'image', // image/* mime types
maxSize: '5m' // 5 megabytes
}),
files: t.Files({ // Multiple files
type: ['image/png', 'image/jpeg']
})
})
})typescript
.post('/upload', ({ body }) => body.file, {
body: t.Object({
file: t.File({
type: 'image', // image/* 类型的MIME
maxSize: '5m' // 5兆字节
}),
files: t.Files({ // 多文件上传
type: ['image/png', 'image/jpeg']
})
})
})Response Validation
响应验证
typescript
.get('/user/:id', ({ params: { id } }) => ({
id,
name: 'John',
email: 'john@example.com'
}), {
params: t.Object({
id: t.Number()
}),
response: {
200: t.Object({
id: t.Number(),
name: t.String(),
email: t.String()
}),
404: t.String()
}
})typescript
.get('/user/:id', ({ params: { id } }) => ({
id,
name: 'John',
email: 'john@example.com'
}), {
params: t.Object({
id: t.Number()
}),
response: {
200: t.Object({
id: t.Number(),
name: t.String(),
email: t.String()
}),
404: t.String()
}
})Standard Schema (Zod, Valibot, ArkType)
标准模式(Zod、Valibot、ArkType)
Zod
Zod
typescript
import { z } from 'zod'
.post('/user', ({ body }) => body, {
body: z.object({
name: z.string(),
age: z.number().min(0),
email: z.string().email()
})
})typescript
import { z } from 'zod'
.post('/user', ({ body }) => body, {
body: z.object({
name: z.string(),
age: z.number().min(0),
email: z.string().email()
})
})Error Handling
错误处理
typescript
.get('/user/:id', ({ params: { id }, status }) => {
const user = findUser(id)
if (!user) {
return status(404, 'User not found')
}
return user
})typescript
.get('/user/:id', ({ params: { id }, status }) => {
const user = findUser(id)
if (!user) {
return status(404, 'User not found')
}
return user
})Guards (Apply to Multiple Routes)
守卫(应用于多个路由)
typescript
.guard({
params: t.Object({
id: t.Number()
})
}, app => app
.get('/user/:id', ({ params: { id } }) => id)
.delete('/user/:id', ({ params: { id } }) => id)
)typescript
.guard({
params: t.Object({
id: t.Number()
})
}, app => app
.get('/user/:id', ({ params: { id } }) => id)
.delete('/user/:id', ({ params: { id } }) => id)
)Macro
宏
typescript
.macro({
hi: (word: string) => ({
beforeHandle() { console.log(word) }
})
})
.get('/', () => 'hi', { hi: 'Elysia' })typescript
.macro({
hi: (word: string) => ({
beforeHandle() { console.log(word) }
})
})
.get('/', () => 'hi', { hi: 'Elysia' })Project Structure (Recommended)
推荐项目结构
Elysia takes an unopinionated approach but based on user request. But without any specific preference, we recommend a feature-based and domain driven folder structure where each feature has its own folder containing controllers, services, and models.
src/
├── index.ts # Main server entry
├── modules/
│ ├── auth/
│ │ ├── index.ts # Auth routes (Elysia instance)
│ │ ├── service.ts # Business logic
│ │ └── model.ts # TypeBox schemas/DTOs
│ └── user/
│ ├── index.ts
│ ├── service.ts
│ └── model.ts
└── plugins/
└── custom.ts
public/ # Static files (if using static plugin)
test/ # Unit testsEach file has its own responsibility as follows:
- Controller (index.ts): Handle HTTP routing, request validation, and cookie.
- Service (service.ts): Handle business logic, decoupled from Elysia controller if possible.
- Model (model.ts): Define the data structure and validation for the request and response.
Elysia采用无主见的设计方式,但会根据用户需求调整。如果没有特定偏好,我们推荐基于功能和领域驱动的文件夹结构,每个功能拥有独立的文件夹,包含控制器、服务和模型。
src/
├── index.ts # 主服务器入口
├── modules/
│ ├── auth/
│ │ ├── index.ts # 认证路由(Elysia实例)
│ │ ├── service.ts # 业务逻辑
│ │ └── model.ts # TypeBox模式/数据传输对象
│ └── user/
│ ├── index.ts
│ ├── service.ts
│ └── model.ts
└── plugins/
└── custom.ts
public/ # 静态文件(如果使用静态插件)
test/ # 单元测试每个文件的职责如下:
- 控制器(index.ts):处理HTTP路由、请求验证和Cookie。
- 服务(service.ts):处理业务逻辑,尽可能与Elysia控制器解耦。
- 模型(model.ts):定义请求和响应的数据结构与验证规则。
Best Practice
最佳实践
Elysia is unopinionated on design pattern, but if not provided, we can relies on MVC pattern pair with feature based folder structure.
- Controller:
- Prefers Elysia as a controller for HTTP dependant controller
- For non HTTP dependent, prefers service instead unless explicitly asked
- Use to handle local custom errors
onError - Register Model to Elysia instance via and prefix model by namespace `Elysia.prefix('model', 'Namespace.')
Elysia.models({ ...models }) - Prefers Reference Model by name provided by Elysia instead of using an actual
Model.name
- Service:
- Prefers class (or abstract class if possible)
- Prefers interface/type derive from
Model - Return (
status) for errorimport { status } from 'elysia' - Prefers instead of
return Errorthrow Error
- Models:
- Always export validation model and type of validation model
- Custom Error should be in contains in Model
Elysia对设计模式无强制要求,但如果没有特殊说明,我们推荐结合MVC模式和基于功能的文件夹结构。
- 控制器:
- 优先将Elysia作为依赖HTTP的控制器
- 对于非HTTP依赖的逻辑,优先使用服务,除非明确要求
- 使用处理本地自定义错误
onError - 通过注册模型,并使用
Elysia.models({ ...models })为模型添加命名空间前缀Elysia.prefix('model', 'Namespace.') - 优先使用Elysia提供的模型名称引用,而非实际的
Model.name
- 服务:
- 优先使用类(或抽象类,如果可能)
- 优先从派生接口/类型
Model - 错误返回使用(从'elysia'导入
status)status - 优先使用而非
return Errorthrow Error
- 模型:
- 始终导出验证模型和验证模型的类型
- 自定义错误应包含在模型中
Elysia Key Concept
Elysia核心概念
Elysia has a every important concepts/rules to understand before use.
在使用Elysia之前,需要理解一些非常重要的概念/规则。
Encapsulation - Isolates by Default
封装 - 默认隔离
Lifecycles (hooks, middleware) don't leak between instances unless scoped.
Scope levels:
- (default) - current instance + descendants
local - - parent + current + descendants
scoped - - all instances
global
ts
.onBeforeHandle(() => {}) // only local instance
.onBeforeHandle({ as: 'global' }, () => {}) // exports to all生命周期(钩子、中间件)不会泄露到其他实例,除非设置了作用域。
作用域级别:
- (默认)- 当前实例及其后代
local - - 父实例、当前实例及其后代
scoped - - 所有实例
global
ts
.onBeforeHandle(() => {}) // 仅作用于当前实例
.onBeforeHandle({ as: 'global' }, () => {}) // 作用于所有实例Method Chaining - Required for Types
方法链式调用 - 类型安全的必要条件
Must chain. Each method returns new type reference.
❌ Don't:
ts
const app = new Elysia()
app.state('build', 1) // loses type
app.get('/', ({ store }) => store.build) // build doesn't exists✅ Do:
ts
new Elysia()
.state('build', 1)
.get('/', ({ store }) => store.build)必须使用链式调用。每个方法都会返回新的类型引用。
❌ 错误示例:
ts
const app = new Elysia()
app.state('build', 1) // 丢失类型
app.get('/', ({ store }) => store.build) // build不存在✅ 正确示例:
ts
new Elysia()
.state('build', 1)
.get('/', ({ store }) => store.build)Explicit Dependencies
显式依赖
Each instance independent. Declare what you use.
ts
const auth = new Elysia()
.decorate('Auth', Auth)
.model(Auth.models)
new Elysia()
.get('/', ({ Auth }) => Auth.getProfile()) // Auth doesn't exists
new Elysia()
.use(auth) // must declare
.get('/', ({ Auth }) => Auth.getProfile())Global scope when:
- No types added (cors, helmet)
- Global lifecycle (logging, tracing)
Explicit when:
- Adds types (state, models)
- Business logic (auth, db)
每个实例相互独立。必须声明你使用的依赖。
ts
const auth = new Elysia()
.decorate('Auth', Auth)
.model(Auth.models)
new Elysia()
.get('/', ({ Auth }) => Auth.getProfile()) // Auth不存在
new Elysia()
.use(auth) // 必须声明依赖
.get('/', ({ Auth }) => Auth.getProfile())适合全局作用域的场景:
- 不添加类型的功能(如cors、helmet)
- 全局生命周期(如日志、追踪)
适合显式声明的场景:
- 添加类型的功能(如state、models)
- 业务逻辑(如认证、数据库)
Deduplication
去重
Plugins re-execute unless named:
ts
new Elysia() // rerun on `.use`
new Elysia({ name: 'ip' }) // runs once across all instances插件会重复执行,除非为其命名:
ts
new Elysia() // 每次`.use`时重新执行
new Elysia({ name: 'ip' }) // 在所有实例中仅执行一次Order Matters
顺序很重要
Events apply to routes registered after them.
ts
.onBeforeHandle(() => console.log('1'))
.get('/', () => 'hi') // has hook
.onBeforeHandle(() => console.log('2')) // doesn't affect '/'事件仅对之后注册的路由生效。
ts
.onBeforeHandle(() => console.log('1'))
.get('/', () => 'hi') // 会触发钩子
.onBeforeHandle(() => console.log('2')) // 不会影响'/'Type Inference
类型推断
Inline functions only for accurate types.
For controllers, destructure in inline wrapper:
ts
.post('/', ({ body }) => Controller.greet(body), {
body: t.Object({ name: t.String() })
})Get type from schema:
ts
type MyType = typeof MyType.static仅内联函数能保证准确的类型。
对于控制器,在内部包装函数中解构参数:
ts
.post('/', ({ body }) => Controller.greet(body), {
body: t.Object({ name: t.String() })
})从模式获取类型:
ts
type MyType = typeof MyType.staticReference Model
引用模型
Model can be reference by name, especially great for documenting an API
ts
new Elysia()
.model({
book: t.Object({
name: t.String()
})
})
.post('/', ({ body }) => body.name, {
body: 'book'
})Model can be renamed by using /
.prefix.suffixts
new Elysia()
.model({
book: t.Object({
name: t.String()
})
})
.prefix('model', 'Namespace')
.post('/', ({ body }) => body.name, {
body: 'Namespace.Book'
})Once , model name will be capitalized by default.
prefix可以通过名称引用模型,这对API文档非常有用
ts
new Elysia()
.model({
book: t.Object({
name: t.String()
})
})
.post('/', ({ body }) => body.name, {
body: 'book'
})可以使用 / 重命名模型
.prefix.suffixts
new Elysia()
.model({
book: t.Object({
name: t.String()
})
})
.prefix('model', 'Namespace')
.post('/', ({ body }) => body.name, {
body: 'Namespace.Book'
})设置后,模型名称默认会首字母大写。
prefixTechnical Terms
技术术语
The following are technical terms that is use for Elysia:
- - function name
OpenAPI Type GenfromfromTypesfor generating OpenAPI from types, see@elysiajs/openapiplugins/openapi.md - ,
Eden- e2e type safe RPC client for share type from backend to frontendEden Treaty
以下是Elysia中使用的技术术语:
- - 来自
OpenAPI Type Gen的@elysiajs/openapi函数,用于从类型生成OpenAPI,详见fromTypesplugins/openapi.md - ,
Eden- 端到端类型安全的RPC客户端,用于在前后端共享类型Eden Treaty
Resources
资源
Use the following references as needed.
It's recommended to checkout for as it contains the most important foundation building blocks with examples.
route.mdplugin.mdvalidation.md根据需要使用以下参考资料。
建议查看,因为它包含了最重要的基础构建块和示例。
route.mdplugin.mdvalidation.mdreferences/
references/
Detailed documentation split by topic:
- - Bun Fullstack Dev Server with HMR. React without bundler.
bun-fullstack-dev-server.md - - Detailed documentation on cookie
cookie.md - - Production deployment guide / Docker
deployment.md - - e2e type safe RPC client for share type from backend to frontend
eden.md - - Setting validation/lifecycle all at once
guard.md - - Compose multiple schema/lifecycle as a reusable Elysia via key-value (recommended for complex setup, eg. authentication, authorization, Role-based Access Check)
macro.md - - Decouple part of Elysia into a standalone component
plugin.md - - Elysia foundation building block: Routing, Handler and Context
route.md - - Unit tests with examples
testing.md - - Setup input/output validation and list of all custom validation rules
validation.md - - Real-time features
websocket.md
按主题划分的详细文档:
- - 支持HMR的Bun全栈开发服务器,无需打包器即可运行React。
bun-fullstack-dev-server.md - - Cookie的详细文档
cookie.md - - 生产环境部署指南 / Docker
deployment.md - - 端到端类型安全的RPC客户端,用于在前后端共享类型
eden.md - - 一次性设置验证/生命周期
guard.md - - 通过键值对组合多个模式/生命周期,作为可复用的Elysia组件(推荐用于复杂设置,如认证、授权、基于角色的访问检查)
macro.md - - 将Elysia的部分功能解耦为独立组件
plugin.md - - Elysia的基础构建块:路由、处理器和上下文
route.md - - 带示例的单元测试
testing.md - - 设置输入/输出验证及所有自定义验证规则列表
validation.md - - 实时功能
websocket.md
plugins/
plugins/
Detailed documentation, usage and configuration reference for official Elysia plugin:
- - Add bearer capability to Elysia (
bearer.md)@elysiajs/bearer - - Out of box configuration for CORS (
cors.md)@elysiajs/cors - - Run cron job with access to Elysia context (
cron.md)@elysiajs/cron - - Integration GraphQL Apollo (
graphql-apollo.md)@elysiajs/graphql-apollo - - Integration with GraphQL Yoga (
graphql-yoga.md)@elysiajs/graphql-yoga - - HTML and JSX plugin setup and usage (
html.md)@elysiajs/html - - JWT / JWK plugin (
jwt.md)@elysiajs/jwt - - OpenAPI documentation and OpenAPI Type Gen / OpenAPI from types (
openapi.md)@elysiajs/openapi - - OpenTelemetry, instrumentation, and record span utilities (
opentelemetry.md)@elysiajs/opentelemetry - - Server Timing metric for debug (
server-timing.md)@elysiajs/server-timing - - Serve static files/folders for Elysia Server (
static.md)@elysiajs/static
官方Elysia插件的详细文档、用法和配置参考:
- - 为Elysia添加Bearer能力(
bearer.md)@elysiajs/bearer - - 开箱即用的CORS配置(
cors.md)@elysiajs/cors - - 运行可访问Elysia上下文的定时任务(
cron.md)@elysiajs/cron - - 集成GraphQL Apollo(
graphql-apollo.md)@elysiajs/graphql-apollo - - 集成GraphQL Yoga(
graphql-yoga.md)@elysiajs/graphql-yoga - - HTML和JSX插件的设置与用法(
html.md)@elysiajs/html - - JWT / JWK插件(
jwt.md)@elysiajs/jwt - - OpenAPI文档及OpenAPI类型生成 / 从类型生成OpenAPI(
openapi.md)@elysiajs/openapi - - OpenTelemetry、工具化和记录跨度工具(
opentelemetry.md)@elysiajs/opentelemetry - - 用于调试的服务器计时指标(
server-timing.md)@elysiajs/server-timing - - 为Elysia服务器提供静态文件/文件夹服务(
static.md)@elysiajs/static
integrations/
integrations/
Guide to integrate Elysia with external library/runtime:
- - Using Vercel AI SDK with Elysia
ai-sdk.md - - Elysia in Astro API route
astro.md - - Integrate Elysia with better-auth
better-auth.md - - Elysia on Cloudflare Worker adapter
cloudflare-worker.md - - Elysia on Deno
deno.md - - Integrate Elysia with Drizzle ORM
drizzle.md - - Elysia in Expo API route
expo.md - - Elysia in Nextjs API route
nextjs.md - - Run Elysia on Node.js
nodejs.md - - Elysia on API route
nuxt.md - - Integrate Elysia with Prisma
prisma.md - - Create and Send Email with React and Elysia
react-email.d - - Run Elysia on Svelte Kit API route
sveltekit.md - - Run Elysia on Tanstack Start / React Query
tanstack-start.md - - Deploy Elysia to Vercel
vercel.md
将Elysia与外部库/运行时集成的指南:
- - 在Elysia中使用Vercel AI SDK
ai-sdk.md - - 在Astro API路由中使用Elysia
astro.md - - 将Elysia与better-auth集成
better-auth.md - - 在Cloudflare Worker适配器上运行Elysia
cloudflare-worker.md - - 在Deno上运行Elysia
deno.md - - 将Elysia与Drizzle ORM集成
drizzle.md - - 在Expo API路由中使用Elysia
expo.md - - 在Next.js API路由中使用Elysia
nextjs.md - - 在Node.js上运行Elysia
nodejs.md - - 在Nuxt API路由中使用Elysia
nuxt.md - - 将Elysia与Prisma集成
prisma.md - - 使用React和Elysia创建并发送邮件
react-email.d - - 在Svelte Kit API路由中运行Elysia
sveltekit.md - - 在Tanstack Start / React Query中运行Elysia
tanstack-start.md - - 将Elysia部署到Vercel
vercel.md
examples/ (optional)
examples/(可选)
- - Basic Elysia example
basic.ts - - Custom body parser example via
body-parser.ts.onParse - - Comprehensive usage of Elysia server
complex.ts - - Setting cookie
cookie.ts - - Error handling
error.ts - - Returning local file from server
file.ts - - Setting mulitple validation schema and lifecycle
guard.ts - - Custom response mapper
map-response.ts - - Redirect response
redirect.ts - - Rename context's property
rename.ts - - Setup validation
schema.ts - - Setup global state
state.ts - - File upload with validation
upload-file.ts - - Web Socket for realtime communication
websocket.ts
- - Elysia基础示例
basic.ts - - 通过
body-parser.ts实现自定义请求体解析器示例.onParse - - Elysia服务器综合用法示例
complex.ts - - 设置Cookie示例
cookie.ts - - 错误处理示例
error.ts - - 从服务器返回本地文件示例
file.ts - - 设置多个验证模式和生命周期示例
guard.ts - - 自定义响应映射器示例
map-response.ts - - 重定向响应示例
redirect.ts - - 重命名上下文属性示例
rename.ts - - 设置验证示例
schema.ts - - 设置全局状态示例
state.ts - - 带验证的文件上传示例
upload-file.ts - - 实时通信WebSocket示例
websocket.ts
patterns/ (optional)
patterns/(可选)
- - Detail guideline for using Elysia with MVC patterns
patterns/mvc.md
- - 在Elysia中使用MVC模式的详细指南
patterns/mvc.md