Skip to content
我们的赞助商
博客

Elysia 1.4 - 超对称性

'Elysia 1.4' 作为标题,左侧有 'Supersymmetry' 字样,右侧有 ElysiaJS chan。

以 Sta 的歌曲 Supersymmetry(Tone Sphere 结局主题曲)命名。

Elysia 1.4 的亮点在于 Standard Schema,以及 “类型健全性”

Standard Schema

在过去的 3 年中,Elysia 一直使用 TypeBox 作为唯一的验证器,这是 Elysia 最受欢迎的功能之一,因为它提供了出色的性能和类型推断。

但是,从早期开始,我们社区最常请求的功能之一就是支持 TypeBox 之外的更多验证器(elysia#20)。

由于 Elysia 与 TypeBox 深度绑定,为每个验证器单独添加支持需要大量努力,并且为了跟上每个验证器的变化,需要大量的维护工作。

幸运的是,有一个名为 Standard Schema 的新提案,它定义了一种标准方式,使用相同的 API 来使用不同的 schema,从而允许我们支持多个验证器,而无需为每个验证器编写自定义集成。

Elysia 现在支持 Standard Schema,允许您使用您喜欢的验证器,例如:

  • Zod
  • Valibot
  • Effect Schema
  • ArkType
  • Joi
  • 以及更多!

您可以像使用 TypeBox 一样提供 schema,它将开箱即用:

ts
import { 
Elysia
,
t
} from 'elysia'
import {
z
} from 'zod'
import * as
v
from 'valibot'
const
app
= new
Elysia
()
.
post
(
'/user/:id', ({
body
,
params
}) => {
body
params
}, {
params
:
z
.
object
({
id
:
z
.
coerce
.
number
()
}),
body
:
v
.
object
({
name
:
v
.
literal
('lilith')
}) })

您可以在单个路由中使用多个验证器,它们将无缝协作,并且类型推断也将正确工作。

OpenAPI

有一个请求是为 Standard Schema 支持用于 OpenAPI 生成的 JSON Schema,但尚未实现。

然而,我们提供了自定义的 mapJsonSchemaopenapi,允许您提供自定义函数来将 schema 映射到 JSON Schema 作为变通方法。

这允许您使用您喜欢的验证器生成美丽的 OpenAPI 文档。

Zod with OpenAPI support

使用 Zod 原生的 OpenAPI schema 支持,通过 describe 为 schema 添加描述

但是,如果您的验证器不支持 JSON Schema,我们提供独特的 OpenAPI type gen 从您的验证器的 TypeScript 类型直接生成 OpenAPI schema。

这意味着 Elysia 支持所有支持 Standard Schema 的验证器的 OpenAPI 生成,即使它不直接支持 JSON Schema。

Valibot with OpenAPI support

Valibot 不直接支持 JSON Schema,但我们使用 OpenAPI type gen 来处理它

不仅输入类型正确,OpenAPI type gen 还会生成所有可能的输出类型,包括错误响应。

这是 Elysia 的独特功能,我们为能够提供它而感到自豪。

Standalone Validator

您还可以使用 standalone validator 来使用多个 schema 验证单个输入:

ts
import { 
Elysia
,
t
} from 'elysia'
import {
z
} from 'zod'
import * as
v
from 'valibot'
const
app
= new
Elysia
()
.
guard
({
schema
: 'standalone',
body
:
z
.
object
({
id
:
z
.
coerce
.
number
()
}) }) .
post
(
'/user/:id', ({
body
}) =>
body
,
{
body
:
v
.
object
({
name
:
v
.
literal
('lilith')
}) })

此示例使用 Zod 和 Valibot 同时验证 body。这允许您将代码库中现有的来自不同验证器的 schema 一起使用。

这通过使用每个验证器解析输入的一部分,然后将每个结果存储为快照并合并在一起,形成单个输出,以确保类型完整性。

Using multiple validators to validate part of a body

使用 TypeBox、Zod、Valibot、Joi、Yup、ArkType、Effect Schema、TypeMap、Rescript Schema 来验证 body 的不同部分

我们同时测试了 8 个验证器,对输入的每个部分进行验证,它运行得完美无缺。

我们为开箱即用支持 Standard Schema 而感到自豪,这是 Elysia 不再绑定到单个验证器的重要一步,我们期待看到您将用它构建什么。

Macro

Macro 是 Elysia 最强大且最灵活的功能之一。

它允许您定义自定义属性,可以修改和扩展 Elysia 的功能,从而允许您创建自己喜欢的“子框架”。

Macro 的多功能性令人惊叹,它允许您轻松实现其他框架难以实现的事情。

在 Elysia 1.4 中,我们带来了几项改进,使 macro 更加多功能。

Macro Schema

您现在可以为您的 macro 定义 schema,允许您直接从 macro 定义自定义验证。

Macro with schema

支持 schema 的 Macro

带有 schema 的 Macro 将自动验证并推断类型以确保类型安全,并且它可以与现有的 schema 共存。

您还可以从不同的 macro 堆叠多个 schema,甚至来自 Standard Validator 的 schema,它们将无缝协作。

Macro schema 还支持 同一 macro 内 lifecycle 的类型推断 由于 TypeScript 的限制,仅适用于命名单一 macro。

Macro with extension

使用命名单一 macro 将类型推断到同一 macro 内的 lifecycle

如果您想在同一 macro 内使用 lifecycle 类型推断,您可能想使用命名单一 macro 而不是多个堆叠 macro。

请勿与使用 macro schema 将类型推断到路由的 lifecycle 事件混淆。那完全没问题,此限制仅适用于在同一 macro 内使用 lifecycle。

Macro Extension

您现在可以扩展现有的 macro,允许您基于现有功能构建。

Macro with extension

支持扩展的 Macro

这允许您基于现有 macro 构建,并为其添加更多功能。

它还支持递归和自动去重,允许您扩展已经扩展了另一个 macro 的现有 macro,而不会出现任何问题。

然而,如果您不小心创建了循环依赖,Elysia 有一个 16 的限制栈来防止运行时和类型推断中的无限循环。

Macro Detail

您现在可以为您的 macro 定义 OpenAPI 细节,允许您直接从 macro 为您的 OpenAPI 文档添加更多细节。

如果路由已经具有 OpenAPI 细节,它将合并细节但优先使用路由细节而非 macro 细节。

Lifecycle Type Soundness

OpenAPI Type Gen 引入以来,它从类型直接生成 OpenAPI schema,我们发现为每个 lifecycle 事件拥有类型健全性将很棒。

这样,我们可以准确记录每个 lifecycle 事件的返回类型,并且 macro 可以准确表示单个路由可以返回的所有可能性。

通过重构超过 3,000 行的纯类型、响应状态类型协调,包括所有 lifecycle API 的类型级单元测试以确保类型完整性,以及大量的类型性能优化,以确保类型推断不会变慢。

所有这些复杂的成就允许我们记录单个路由可以返回的所有可能性。

Type Soundness

记录单个路由可以返回的所有可能性

这不仅改善了开发体验,还通过确保所有可能性在 API 文档和 Eden Treaty 的客户端中都被考虑,提高了代码库的可靠性。

类型健全性涵盖所有 lifecycle 事件和 macro,允许您拥有完整的 API 文档。唯一的例外是由于速度慢的内联 lifecycle 事件。

我们还设法将类型推断性能提高了约 9-11%,并尽管类型复杂性大幅增加,类型实例化减少了 11.5%。

Type inference

根据我们的内部基准,类型实例化减少了 11.57%

Group standalone schema

以前,带有 schema 的 group 将使用覆盖策略,这意味着如果您在 group 中定义 schema,它将覆盖路由中的现有 schema。

如果您想定义新 schema,您必须手动包含现有 schema。这不是很人性化,如果您忘记包含现有 schema,可能会导致错误。

从 1.4 开始,带有 schema 的 group 将使用 standalone 策略,这意味着如果您在 group 中定义 schema,它不会覆盖而是与路由 schema 共存。

group standalone

带有 schema 的 group 将与路由 schema 共存

这允许您在 group 中定义新 schema,而无需手动包含现有 schema。

Notable changes

我们在 1.3.9 中关闭了大约 300 个问题,因此对于 1.4,我们没有太多 bug 修复,因为我们解决了我们已知的大多数问题。

Improvement

  • #861 在定义 GET 路由时自动添加 HEAD 方法
  • #1389 在参考模型中 NoValidate

Change

  • 出于安全原因,ObjectString/ArrayString 不再默认生成默认值
  • 当格式可能是 JSON 时,Cookie 现在动态解析
  • 导出 fileType 用于外部文件类型验证,以获得准确的响应
  • 出于安全原因,ObjectString/ArrayString 不再默认生成默认值
  • 当格式可能是 JSON 时,Cookie 现在动态解析

Breaking Change

  • 由于非类型健全性,移除 macro v1
  • 移除 error 函数,使用 status 代替
  • mapResponseafterResponse 中的 response 弃用,使用 responseValue 代替

Afterword

这是我们第一次在发布说明封面图像中展示我们的吉祥物 Elysia chan!这也将成为后续发布说明的传统!

我们的封面艺术反映了 Supersymmetry(音乐)封面艺术的主题,其中 ElysiaJS chan 以相似的姿势镜像 Weirs

Elysia chan mirroring Supersymmetry

Elysia chan 镜像 Supersymmetry 封面艺术中 Weirs 的相同姿势 (pixiv)

她不是很可爱吗?我真的很喜欢她的样子!我个人努力提高我的艺术技能来画它,希望你喜欢!

总之,希望你喜欢这个发布!我们期待看到你将用它构建什么!

祝你有愉快的一天!

我是全部

在这个微小的微观宇宙中

你苦乐参半的心每一口

我都爱


你知道

这个生命的游戏是我们的“riverrun,”

你是我旅途中幸运的朋友


剩下时间不多了

天空显示其褪色

星星游行

是时候改变我们的命运了

Elysia:人性化框架