参数校验 (@halsp/validator)
安装 @halsp/validator 以支持参数校验功能,可以自动校验请求参数
基于 class-validator 和 @halsp/pipe 校验请求参数
使用链式装饰器,减少引用,改进 class-validator 的装饰器风格
安装
npm install @halsp/validator
开始使用
可以利用 @halsp/pipe 管道功能,在中间件中定义校验规则
也可以定义数据传输模型,并在数据传输模型中定义校验规则
startup
在入口文件中添加如下代码,开启 @halsp/validator 的功能
import "@halsp/validator";
startup.useValidator()
装饰数据传输模型
import { V } from "@halsp/validator";
import { Body } from "@halsp/pipe";
import { Middleware } from "@halsp/core";
// 数据传输模型
class TestDto {
@V.IsString().IsNotEmpty()
prop1!: string;
@V.IsInt().Min(6)
prop2!: number;
get prop3() {
return this.prop1 + this.prop2;
}
}
// 中间件 或 服务
class TestMiddleware extends Middleware {
@Body
private readonly body!: TestDto;
async invoke(): Promise<void> {
this.ok(this.body);
}
}
上面的中间件 TestMiddleware 会在使用前自动校验 TestDto 中的字段值
使用 @halsp/pipe
import { V } from "@halsp/validator";
import { Body } from "@halsp/pipe";
import { Middleware } from "@halsp/core";
// 中间件
class TestMiddleware extends Middleware {
@Body("prop1")
@V.IsString().IsNotEmpty()
private readonly prop1!: string;
@Body("prop2")
@V.IsInt().Min(6)
private readonly p2!: any;
async invoke(): Promise<void> {
this.ok(this.body);
}
}
上面的中间件 TestMiddleware 同样会在使用前自动校验 body 的 prop1 和 prop2 字段值
配置
可以使用全局配置,也可以使用局部配置
全局配置
可以为 startup.useValidator 传参一个配置对象
startup.useValidator({
stopAtFirstError: true
})
也可以传参一个回调函数,用于动态设置配置
startup.useValidator(({ ctx, val, propertyType }) => ({
stopAtFirstError: true,
}));
局部配置
使用装饰器 UseValidatorOptions 装饰 dto 类
@UseValidatorOptions({
stopAtFirstError: true
})
class TestDto {
@V.IsString().IsNotEmpty()
b1!: string;
@V.IsInt().Min(6)
b2!: number;
get b() {
return this.b1 + this.b2;
}
}
TIP
局部配置优先于全局配置,最终配置取自二者合并后的对象
指定模型可用性
用 ValidatorEnable 装饰器指定模型在哪些情况可用
ValidatorEnable 接收一个回调函数
({ ctx: Context; val: any }) => boolean | Promise<boolean>
参数 val 是该模型对应的值
@ValidatorEnable(({ ctx: Context; val: any }) => ctx.set("test") == val)
class TestClass {
@V.IsInt()
b1!: number;
}
现有校验装饰器
包含 class-validator 全部校验装饰器,装饰器参数也完全相同
此外还提供了 Is 装饰器,可以使用自定义校验规则,用于更复杂的需求
也能封装自定义校验,用于复用自定义校验规则
自定义校验装饰器 Is()
Is 装饰器可以实现自定义校验
class TestDto {
@V
.Is(
(value, property) => typeof value == "number",
`${property} must be a number`
)
.Is((value, property) => (value > 6), `${property} must more than 6`)
readonly prop!: number;
}
上面的代码限制字段 prop 的值必须是一个数字,并且值大于 6
Is 装饰器有两个参数
validate校验规则回调函数,返回 bool,有三个参数value请求参数实际值property数据传输模型属性名,或@halsp/pipe取的属性名如@Header('prop')args装饰器输入参数数组
errorMessage校验失败响应的错误,可以是一个字符串,也可以是一个回调函数,回调函数的参数同validate回调函数
封装的自定义校验
Is 装饰器虽然很灵活,但没法复用
调用函数 addCustomValidator 即可增加一个自定义校验,然后在代码中多处重复使用
@halsp/swagger 就是基于此功能增加了描述性装饰器(没有校验功能)
如实现一个下面的校验规则:判断请求参数是否为指定值
import { addCustomValidator } from '@halsp/validator';
addCustomValidator({
name: "CustomEquals",
validate: (value, property, args) => value == args[0],
errorMessage: (value, property, args) => `${property} must equal with ${args[0]}, now is ${value}`,
});
class TestDto{
@V.CustomEquals(6)
readonly prop!: number;
}
如果请求参数的 prop 值是 7,会校验失败,抛出如下错误
{
"status": 400
"message": 'prop must equal with 6, now is 7'
}
定义声明
虽然 addCustomValidator 可以直接添加一个装饰器并且能够使用,但没有智能提示,在 TypeScript 下使用也会报错
因此 TypeScript 还需要添加声明才能更安全、方便的使用
import { ValidatorDecoratorReturnType } from "@halsp/validator";
declare module "@halsp/validator" {
interface ValidatorLib {
CustomEquals: (num: number) => ValidatorDecoratorReturnType;
CustomDecorator2: () => ValidatorDecoratorReturnType;
}
}
类型声明代码,可以写在 .d.ts 文件中,也可以写在普通 .ts 中
如在 types/index.d.ts 文件中声明,即可以全局使用。也可以在 index.ts 等文件声明
addCustomValidator 参数
addCustomValidator 接收三个参数
validate校验规则回调函数,返回 bool,与Is装饰器不同的是有三个参数,前两个参数相同value请求参数实际值property数据传输模型属性名,或@halsp/pipe取的属性名如@Header('prop')args装饰器输入参数数组
errorMessage校验失败响应的错误,可以是一个字符串,也可以是一个回调函数,回调函数的参数同validate回调函数name装饰器名称,必须唯一,且与已有装饰器不能重名
