-
Notifications
You must be signed in to change notification settings - Fork 102
/
i18n-validation-exception.filter.ts
90 lines (81 loc) · 2.65 KB
/
i18n-validation-exception.filter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import {
ArgumentsHost,
Catch,
ExceptionFilter,
ValidationError,
} from '@nestjs/common';
import iterate from 'iterare';
import { I18nContext } from '../i18n.context';
import {
I18nValidationError,
I18nValidationExceptionFilterDetailedErrorsOption,
I18nValidationExceptionFilterErrorFormatterOption,
I18nValidationException,
} from '../interfaces';
import { mapChildrenToValidationErrors, formatI18nErrors } from '../utils';
type I18nValidationExceptionFilterOptions =
| I18nValidationExceptionFilterDetailedErrorsOption
| I18nValidationExceptionFilterErrorFormatterOption;
@Catch(I18nValidationException)
export class I18nValidationExceptionFilter implements ExceptionFilter {
constructor(
private readonly options: I18nValidationExceptionFilterOptions = {
detailedErrors: true,
},
) {}
catch(exception: I18nValidationException, host: ArgumentsHost) {
const i18n = I18nContext.current();
const errors = formatI18nErrors(exception.errors ?? [], i18n.service, {
lang: i18n.lang,
});
switch (host.getType() as string) {
case 'http':
const response = host.switchToHttp().getResponse();
response
.status(this.options.errorHttpStatusCode || exception.getStatus())
.send({
statusCode:
this.options.errorHttpStatusCode || exception.getStatus(),
message: exception.getResponse(),
errors: this.normalizeValidationErrors(errors),
});
break;
case 'graphql':
exception.errors = this.normalizeValidationErrors(
errors,
) as I18nValidationError[];
return exception;
}
}
private isWithErrorFormatter(
options: I18nValidationExceptionFilterOptions,
): options is I18nValidationExceptionFilterErrorFormatterOption {
return 'errorFormatter' in options;
}
protected normalizeValidationErrors(
validationErrors: ValidationError[],
): string[] | I18nValidationError[] | object {
if (
this.isWithErrorFormatter(this.options) &&
!('detailedErrors' in this.options)
)
return this.options.errorFormatter(validationErrors);
if (
!this.isWithErrorFormatter(this.options) &&
!this.options.detailedErrors
)
return this.flattenValidationErrors(validationErrors);
return validationErrors;
}
protected flattenValidationErrors(
validationErrors: ValidationError[],
): string[] {
return iterate(validationErrors)
.map((error) => mapChildrenToValidationErrors(error))
.flatten()
.filter((item) => !!item.constraints)
.map((item) => Object.values(item.constraints))
.flatten()
.toArray();
}
}