mcpField
E
elysiajs

elysiajs

github.com/saltyaom开发438 次安装40 周前更新
代码仓库

关于 elysiajs

elysiajs 是面向 ElysiaJS 开发的技能指南,供编码 Agent 在构建和维护后端服务时参考。内容涵盖路由、验证、认证、插件与部署,并强调查阅官方最新 API。

主要功能

  1. 01Elysia 路由与服务器开发
  2. 02请求与响应验证
  3. 03认证与授权模式
  4. 04插件及外部库集成
  5. 05测试与部署指南

适用场景

  1. 01创建或修改 Elysia 路由
  2. 02为请求配置数据验证
  3. 03添加认证或插件
  4. 04编写测试并部署服务

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/saltyaom/vibe-book-rental --skill elysiajs

安装后在 Claude Code 中输入/elysiajs确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
basic.ts
body-parser.ts
complex.ts
cookie.ts
error.ts
file.ts
guard.ts
map-response.ts
redirect.ts
rename.ts
schema.ts
state.ts
upload-file.ts
websocket.ts
integrations/
ai-sdk.md
astro.md
better-auth.md
cloudflare-worker.md
deno.md
drizzle.md
expo.md
nextjs.md
nodejs.md
nuxt.md
prisma.md
react-email.md
sveltekit.md
tanstack-start.md
vercel.md
patterns/
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.md
  • Eden、Eden Treaty - 端到端类型安全 RPC 客户端,用于将类型从后端共享到前端

资源

根据需要使用以下参考资料。

建议查看 route.md,其中包含最重要的基础构建模块及示例。

plugin.md 和 validation.md 也很重要,可按需查阅。

references/

按主题拆分的详细文档:

  • bun-fullstack-dev-server.md - 使用 HMR 的 Bun 全栈开发服务器。无需打包器的 React。
  • cookie.md - Cookie 详细文档
  • deployment.md - 生产环境部署指南 / Docker
  • eden.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 SDK
  • astro.md - 在 Astro API 路由中使用 Elysia
  • better-auth.md - 将 Elysia 与 better-auth 集成
  • cloudflare-worker.md - 在 Cloudflare Worker 上使用 Elysia 适配器
  • deno.md - 在 Deno 上使用 Elysia
  • drizzle.md - 将 Elysia 与 Drizzle ORM 集成
  • expo.md - 在 Expo API 路由中使用 Elysia
  • nextjs.md - 在 Nextjs API 路由中使用 Elysia
  • nodejs.md - 在 Node.js 上运行 Elysia
  • nuxt.md - 在 API 路由中使用 Elysia
  • prisma.md - 将 Elysia 与 Prisma 集成
  • react-email.d - 使用 React 和 Elysia 创建并发送电子邮件
  • sveltekit.md - 在 Svelte Kit API 路由上运行 Elysia
  • tanstack-start.md - 在 Tanstack Start / React Query 上运行 Elysia
  • vercel.md - 将 Elysia 部署到 Vercel
examples/(可选)
  • basic.ts - Elysia 基础示例
  • body-parser.ts - 通过 .onParse 自定义请求体解析器的示例
  • complex.ts - Elysia 服务的综合用法
  • cookie.ts - 设置 Cookie
  • error.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 模式的详细指南

评论

支持 Markdown