使用 Kaapi 构建现代后端:请求验证 第2部分
Source: Dev.to
本系列面向热爱 TypeScript 并欣赏 Hapi 设计哲学的后端开发者。
再次验证…?
也许你已经跟随了关于请求验证的上一篇文章,使用了 Joi、ArkType、Valibot 或 Zod。
你已经拥有了一个光鲜的 Kaapi 应用,路由整洁,验证可靠。一切看起来都很简洁且令人放心。
你可能是从下面这样的代码开始的:
import { z } from 'zod';
app
.base()
.zod({
params: z.object({
name: z.string().min(3).max(10)
})
})
.route({
method: 'GET',
path: '/hello/{name}',
handler: function (request, h) {
return `Hello ${request.params.name}!`;
}
});
说实话?
这完全可以正常工作。
直到有一天,你的应用不再小。
某个时刻,路由开始增多。你不再在同一个文件里内联定义它们,而是把它们放在各自的文件中,按功能分组。于是,那条曾经很好用的链子已经不再适用。
于是问题出现了:
当路由不再靠近你的应用时,如何让验证仍然紧贴在路由旁边?
这正是我们在这里要解决的。
新的设置(你可能已经做过了)
你想要两件事:
- 独立定义路由 – 在一个地方使用
app.route(...)注册它们。 - 验证、类型安全,并且可以自由选择你喜欢的验证器。
让我们一次一个验证器地逐步讲解。
Joi:熟悉的路径
如果你正在使用 Joi,则没有任何变化。这是有意为之。
npm i joi
import { Kaapi, KaapiServerRoute } from '@kaapi/kaapi';
import Joi from 'joi';
const app = new Kaapi({ /* ... */ });
const route: KaapiServerRoute = {
method: 'GET',
path: '/hello/{name}',
options: {
validate: {
params: Joi.object({
name: Joi.string().min(3).max(10).required()
})
}
},
handler: function (request, h) {
return `Hello ${request.params.name}!`;
}
};
app.route(route);
没有魔法。没有惊喜。
如果你以前使用过 Hapi,这应该会让你有回家的感觉。
Zod:与 TypeScript 对话的验证
现在假设你想要 强类型推断,但又不想在泛型之间来回切换。
npm i zod @kaapi/validator-zod
扩展 Kaapi
import { Kaapi } from '@kaapi/kaapi';
import { validatorZod } from '@kaapi/validator-zod';
const app = new Kaapi({ /* ... */ });
await app.extend(validatorZod);
定义路由
import { withSchema } from '@kaapi/validator-zod';
import { z } from 'zod';
const route = withSchema({
params: z.object({
name: z.string().min(3).max(10)
})
}).route({
method: 'GET',
path: '/hello/{name}',
handler: function (request, h) {
return `Hello ${request.params.name}!`;
}
});
app.route(route);
没有泛型。你的类型直接来自于 schema。你只需编写一次验证,TypeScript 就会自动跟随。
Valibot:相同思路,不同风格
Valibot 与 Zod 同属一类,只是语法略有不同。
npm i valibot @kaapi/validator-valibot
扩展 Kaapi
import { Kaapi } from '@kaapi/kaapi';
import { validatorValibot } from '@kaapi/validator-valibot';
const app = new Kaapi({ /* ... */ });
await app.extend(validatorValibot);
定义路由
import { withSchema } from '@kaapi/validator-valibot';
import * as v from 'valibot';
const route = withSchema({
params: v.object({
name: v.pipe(v.string(), v.minLength(3), v.maxLength(10))
})
}).route({
method: 'GET',
path: '/hello/{name}',
handler: function (request, h) {
return `Hello ${request.params.name}!`;
}
});
app.route(route);
ArkType:您可以阅读的模式
npm i arktype @kaapi/validator-arktype
扩展 Kaapi
import { Kaapi } from '@kaapi/kaapi';
import { validatorArk } from '@kaapi/validator-arktype';
const app = new Kaapi({ /* ... */ });
await app.extend(validatorArk);
定义路由
import { withSchema } from '@kaapi/validator-arktype';
import { type } from 'arktype';
const route = withSchema({
params: type({
name: '3 <= string <= 10'
})
}).route({
method: 'GET',
path: '/hello/{name}',
handler: function (request, h) {
return `Hello ${request.params.name}!`;
}
});
app.route(route);
实际重要的内容
不论使用哪种验证器:
- 路由是独立定义的。
- 每个路由自行选择所需的验证器。
- 注册保持极其简单:
app.route(route);
- Joi 开箱即用。
- Zod、Valibot 和 ArkType 通过
withSchema插入。
相同的应用。相同的 API。不同的工具。
那么… 你 应该使用哪个验证器?
| 目标 | 推荐的验证器 |
|---|---|
| 最小代码量 | Joi or ArkType |
| 无需泛型的强类型推断 | Zod or Valibot |
| 易读的模式 | ArkType |
| 优秀的自动文档 | Zod, Valibot, or Joi |
Kaapi 并不强迫你做出选择。
它为你提供了完整的工具箱。挑选你喜欢使用的螺丝刀吧。
Source code
想要完整示例吗?
👉 github.com/kaapi/kaapi‑examples
shygyver/kaapi-monorepo-playground
示例位于 validation-app 目录下。
查看 README 获取运行说明。
更多 Kaapi 文章即将发布。
本文仅讨论将验证保持在其应有的位置。
📦 立即开始
npm install @kaapi/kaapi
🔗 了解更多: Kaapi Wiki