我在 typeORM 实体字段电子邮件上设置了一个自定义的唯一验证器装饰器。Nestjs有依赖注入,但是没有注入服务。
错误是:TypeError:无法读取未定义的属性“findByEmail”
对实现自定义电子邮件验证器有什么帮助吗?
用户实体.ts
@Column()
@Validate(CustomEmail, {
message: "Title is too short or long!"
})
@IsEmail()
email: string;
Run Code Online (Sandbox Code Playgroud)
我的 CustomEmail 验证器是
import {ValidatorConstraint, ValidatorConstraintInterface,
ValidationArguments} from "class-validator";
import {UserService} from "./user.service";
@ValidatorConstraint({ name: "customText", async: true })
export class CustomEmail implements ValidatorConstraintInterface {
constructor(private userService: UserService) {}
async validate(text: string, args: ValidationArguments) {
const user = await this.userService.findByEmail(text);
return !user;
}
defaultMessage(args: ValidationArguments) {
return "Text ($value) is too short or too long!";
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以在列选项中设置唯一
@Column({
unique: true
})
Run Code Online (Sandbox Code Playgroud)
但这会引发一个 mysql 错误和使我的应用程序崩溃的 ExceptionsHandler,所以我无法自己处理它...
谢谢!
I can propose 2 different approaches here, the first one catches the constraint violation error locally without additional request, and the second one uses a global error filter, catching such errors in the entire application. I personally use the latter.
No need to make additional database request. You can catch the error violating the unique constraint and throw any HttpException you want to the client. In users.service.ts:
public create(newUser: Partial<UserEntity>): Promise<UserEntity> {
return this.usersRepository.save(newUser).catch((e) => {
if (/(email)[\s\S]+(already exists)/.test(e.detail)) {
throw new BadRequestException(
'Account with this email already exists.',
);
}
return e;
});
}
Run Code Online (Sandbox Code Playgroud)
Which will return:
Or even create a global QueryErrorFilter:
@Catch(QueryFailedError)
export class QueryErrorFilter extends BaseExceptionFilter {
public catch(exception: any, host: ArgumentsHost): any {
const detail = exception.detail;
if (typeof detail === 'string' && detail.includes('already exists')) {
const messageStart = exception.table.split('_').join(' ') + ' with';
throw new BadRequestException(
exception.detail.replace('Key', messageStart),
);
}
return super.catch(exception, host);
}
}
Run Code Online (Sandbox Code Playgroud)
Then in main.ts:
async function bootstrap() {
const app = await NestFactory.create(/**/);
/* ... */
const { httpAdapter } = app.get(HttpAdapterHost);
app.useGlobalFilters(new QueryErrorFilter(httpAdapter));
/* ... */
await app.listen(3000);
}
bootstrap();
Run Code Online (Sandbox Code Playgroud)
This will give generic $table entity with ($field)=($value) already exists. error message. Example:
| 归档时间: |
|
| 查看次数: |
8857 次 |
| 最近记录: |