关于 elysiajs
elysiajs 是面向 ElysiaJS 开发的技能指南,供编码 Agent 在构建和维护后端服务时参考。内容涵盖路由、验证、认证、插件与部署,并强调查阅官方最新 API。
主要功能
- 01Elysia 路由与服务器开发
- 02请求与响应验证
- 03认证与授权模式
- 04插件及外部库集成
- 05测试与部署指南
适用场景
- 01创建或修改 Elysia 路由
- 02为请求配置数据验证
- 03添加认证或插件
- 04编写测试并部署服务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ saltyaom/ vibe-book-rental --skill elysiajs安装后在 Claude Code 中输入/elysiajs确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/basic.tsbody-parser.tscomplex.tscookie.tserror.tsfile.tsguard.tsmap-response.tsredirect.tsrename.tsschema.tsstate.tsupload-file.tswebsocket.tsintegrations/ai-sdk.mdastro.mdbetter-auth.mdcloudflare-worker.mddeno.mddrizzle.mdexpo.mdnextjs.mdnodejs.mdnuxt.mdprisma.mdreact-email.mdsveltekit.mdtanstack-start.mdvercel.mdpatterns/mvc.md详细介绍
ElysiaJS 开发技能
始终查阅 elysiajs.com/llms.txt 获取代码示例和最新 API。
概述
ElysiaJS 是一个 TypeScript 框架,用于构建以 Bun 为先(但不限于 Bun)的类型安全、高性能后端服务。本技能提供使用 Elysia 进行开发的全面指南,涵盖路由、验证、身份验证、插件、集成和部署。
何时使用此技能
当用户要求以下操作时,启用此技能:
- 创建或修改 ElysiaJS 路由、处理程序或服务
- 使用 TypeBox 或其他模式库(Zod、Valibot)设置验证
- 实现身份验证(JWT、基于会话、宏、守卫)
- 添加插件(CORS、OpenAPI、静态文件、JWT)
- 与外部服务集成(Drizzle ORM、Better Auth、Next.js、Eden Treaty)
- 为实时功能设置 WebSocket 端点
- 为 Elysia 实例创建单元测试
- 将 Elysia 服务部署到生产环境
快速开始
快速搭建:
bun create elysia app
基本服务
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)
基本用法
HTTP 方法
import { Elysia } from 'elysia'
new Elysia()
.get('/', 'GET')
.post('/', 'POST')
.put('/', 'PUT')
.patch('/', 'PATCH')
.delete('/', 'DELETE')
.options('/', 'OPTIONS')
.head('/', 'HEAD')
路径参数
.get('/user/:id', ({ params: { id } }) => id)
.get('/post/:id/:slug', ({ params }) => params)
查询参数
.get('/search', ({ query }) => query.q)
// GET /search?q=elysia → "elysia"
请求正文
.post('/user', ({ body }) => body)
请求头
.get('/', ({ headers }) => headers.authorization)
TypeBox 验证
基本类型
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' }))
})
})
嵌套对象
body: t.Object({
user: t.Object({
name: t.String(),
address: t.Object({
street: t.String(),
city: t.String()
})
})
})
数组
body: t.Object({
tags: t.Array(t.String()),
users: t.Array(t.Object({
id: t.String(),
name: t.String()
}))
})
文件上传
.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']
})
})
})
响应验证
.get('/user/:id', ({ params: { id } }) => ({
id,
name: 'John',
email: '[email protected]'
}), {
params: t.Object({
id: t.Number()
}),
response: {
200: t.Object({
id: t.Number(),
name: t.String(),
email: t.String()
}),
404: t.String()
}
})
标准模式(Zod、Valibot、ArkType)
Zod
import { z } from 'zod'
.post('/user', ({ body }) => body, {
body: z.object({
name: z.string(),
age: z.number().min(0),
email: z.string().email()
})
})
错误处理
.get('/user/:id', ({ params: { id }, status }) => {
const user = findUser(id)
if (!user) {
return status(404, 'User not found')
}
return user
})
守卫(应用于多个路由)
.guard({
params: t.Object({
id: t.Number()
})
}, app => app
.get('/user/:id', ({ params: { id } }) => id)
.delete('/user/:id', ({ params: { id } }) => id)
)
宏
.macro({
hi: (word: string) => ({
beforeHandle() { console.log(word) }
})
})
.get('/', () => 'hi', { hi: 'Elysia' })
项目结构(推荐)
Elysia 不对项目结构做强制规定,而是根据用户需求调整。如果没有具体偏好,我们建议采用基于功能和领域驱动的文件夹结构,让每个功能都拥有自己的文件夹,其中包含控制器、服务和模型。
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 tests
各文件的职责如下:
- 控制器(index.ts):处理 HTTP 路由、请求验证和 Cookie。
- 服务(service.ts):处理业务逻辑;如有可能,应与 Elysia 控制器解耦。
- 模型(model.ts):定义请求和响应的数据结构及验证规则。
最佳实践
Elysia 不限定设计模式;如果没有其他要求,我们可以采用 MVC 模式,并搭配基于功能的文件夹结构。
- 控制器:
- 对于依赖 HTTP 的控制器,优先使用 Elysia 作为控制器
- 对于不依赖 HTTP 的场景,除非另有明确要求,否则优先使用服务
- 使用
onError处理本地自定义错误 - 通过
Elysia.models({ ...models })将模型注册到 Elysia 实例,并使用命名空间前缀Elysia.prefix('model', 'Namespace.')为模型添加前缀 - 优先使用 Elysia 提供的按名称引用模型的方式,而不是使用实际的
Model.name
- 服务:
- 优先使用类(如果可行,也可使用抽象类)
- 优先使用从
Model派生的接口/类型 - 错误时返回
status(import { status } from 'elysia') - 优先
return Error,而不是throw Error
- 模型:
- 始终导出验证模型及其验证模型的类型
- 自定义错误应包含在 Model 中
Elysia 核心概念
使用 Elysia 前,需要了解一些重要概念和规则。
封装——默认隔离
除非指定作用域,否则生命周期(钩子、中间件)不会在实例之间泄漏。
作用域级别:
local(默认)——当前实例及其后代scoped——父级、当前实例及其后代global——所有实例
.onBeforeHandle(() => {}) // only local instance
.onBeforeHandle({ as: 'global' }, () => {}) // exports to all
方法链式调用——类型所必需
必须链式调用。每个方法都会返回新的类型引用。
❌ 不要这样做:
const app = new Elysia()
app.state('build', 1) // loses type
app.get('/', ({ store }) => store.build) // build doesn't exists
✅ 应这样做:
new Elysia()
.state('build', 1)
.get('/', ({ store }) => store.build)
显式依赖
每个实例彼此独立。声明所用依赖。
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())
适用于全局作用域的情况:
- 未添加类型(cors、helmet)
- 全局生命周期(日志记录、跟踪)
适用于显式声明的情况:
- 添加类型(state、models)
- 业务逻辑(auth、db)
去重
插件会重复执行,除非为其命名:
new Elysia() // rerun on `.use`
new Elysia({ name: 'ip' }) // runs once across all instances
顺序很重要
事件会应用于其后注册的路由。
.onBeforeHandle(() => console.log('1'))
.get('/', () => 'hi') // has hook
.onBeforeHandle(() => console.log('2')) // doesn't affect '/'
类型推断
仅内联函数才能准确推断类型。
对于控制器,在内联包装器中解构:
.post('/', ({ body }) => Controller.greet(body), {
body: t.Object({ name: t.String() })
})
从 schema 获取类型:
type MyType = typeof MyType.static
引用模型
模型可以按名称引用,尤其适合用于记录 API
new Elysia()
.model({
book: t.Object({
name: t.String()
})
})
.post('/', ({ body }) => body.name, {
body: 'book'
})
可以使用 .prefix / .suffix 重命名模型
new Elysia()
.model({
book: t.Object({
name: t.String()
})
})
.prefix('model', 'Namespace')
.post('/', ({ body }) => body.name, {
body: 'Namespace.Book'
})
设置 prefix 后,模型名称默认会首字母大写。
技术术语
以下是 Elysia 中使用的技术术语:
OpenAPI Type Gen-@elysiajs/openapi中用于根据类型生成 OpenAPI 的函数名fromTypes,请参阅plugins/openapi.mdEden、Eden Treaty- 端到端类型安全 RPC 客户端,用于将类型从后端共享到前端
资源
根据需要使用以下参考资料。
建议查看 route.md,其中包含最重要的基础构建模块及示例。
plugin.md 和 validation.md 也很重要,可按需查阅。
references/
按主题拆分的详细文档:
bun-fullstack-dev-server.md- 使用 HMR 的 Bun 全栈开发服务器。无需打包器的 React。cookie.md- Cookie 详细文档deployment.md- 生产环境部署指南 / Dockereden.md- 端到端类型安全 RPC 客户端,用于将类型从后端共享到前端guard.md- 一次性设置验证/生命周期macro.md- 通过键值对组合多个 schema/生命周期,构建可复用的 Elysia(推荐用于复杂配置,例如身份验证、授权、基于角色的访问检查)plugin.md- 将 Elysia 的一部分解耦为独立组件route.md- Elysia 基础构建模块:路由、处理器和上下文testing.md- 单元测试及示例validation.md- 设置输入/输出验证,以及所有自定义验证规则列表websocket.md- 实时功能
plugins/
Elysia 官方插件的详细文档、用法和配置参考:
bearer.md- 为 Elysia 添加 bearer 功能(@elysiajs/bearer)cors.md- 开箱即用的 CORS 配置(@elysiajs/cors)cron.md- 运行可访问 Elysia 上下文的 cron 作业(@elysiajs/cron)graphql-apollo.md- 集成 GraphQL Apollo(@elysiajs/graphql-apollo)graphql-yoga.md- 集成 GraphQL Yoga(@elysiajs/graphql-yoga)html.md- HTML 和 JSX 插件的设置与用法(@elysiajs/html)jwt.md- JWT / JWK 插件(@elysiajs/jwt)openapi.md- OpenAPI 文档和 OpenAPI Type Gen / 根据类型生成 OpenAPI(@elysiajs/openapi)opentelemetry.md- OpenTelemetry、插桩和记录 span 的实用工具(@elysiajs/opentelemetry)server-timing.md- 用于调试的服务器计时指标(@elysiajs/server-timing)static.md- 为 Elysia 服务器提供静态文件/文件夹(@elysiajs/static)
integrations/
将 Elysia 与外部库/运行时集成的指南:
ai-sdk.md- 在 Elysia 中使用 Vercel AI SDKastro.md- 在 Astro API 路由中使用 Elysiabetter-auth.md- 将 Elysia 与 better-auth 集成cloudflare-worker.md- 在 Cloudflare Worker 上使用 Elysia 适配器deno.md- 在 Deno 上使用 Elysiadrizzle.md- 将 Elysia 与 Drizzle ORM 集成expo.md- 在 Expo API 路由中使用 Elysianextjs.md- 在 Nextjs API 路由中使用 Elysianodejs.md- 在 Node.js 上运行 Elysianuxt.md- 在 API 路由中使用 Elysiaprisma.md- 将 Elysia 与 Prisma 集成react-email.d- 使用 React 和 Elysia 创建并发送电子邮件sveltekit.md- 在 Svelte Kit API 路由上运行 Elysiatanstack-start.md- 在 Tanstack Start / React Query 上运行 Elysiavercel.md- 将 Elysia 部署到 Vercel
examples/(可选)
basic.ts- Elysia 基础示例body-parser.ts- 通过.onParse自定义请求体解析器的示例complex.ts- Elysia 服务的综合用法cookie.ts- 设置 Cookieerror.ts- 错误处理file.ts- 从服务返回本地文件guard.ts- 设置多个验证架构和生命周期map-response.ts- 自定义响应映射器redirect.ts- 重定向响应rename.ts- 重命名上下文属性schema.ts- 设置验证state.ts- 设置全局状态upload-file.ts- 带验证的文件上传websocket.ts- 用于实时通信的 Web Socket
patterns/(可选)
patterns/mvc.md- 使用 Elysia 实现 MVC 模式的详细指南