Skip to content

Commit 0f28135

Browse files
authored
Merge pull request #69 from exceptionless/main
Fixed Class Validator using development debug messages
2 parents c9e33d8 + 7905cb7 commit 0f28135

File tree

2 files changed

+75
-9
lines changed

2 files changed

+75
-9
lines changed

packages/class-validator/src/__tests__/class-validator.test.ts

+55-4
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,24 @@ import {
66
IsEmail,
77
IsInt,
88
IsNotEmpty,
9+
IsOptional,
10+
IsString,
911
IsUUID,
1012
Min,
13+
ValidateNested,
1114
} from 'class-validator';
1215
import {expectTypeOf} from 'expect-type';
1316
import {describe, expect, test} from 'vitest';
1417

1518
import {assert, validate, wrap} from '..';
1619

1720
describe('class-validator', () => {
21+
class NestedSchema {
22+
@IsString()
23+
@IsNotEmpty()
24+
value!: string;
25+
}
26+
1827
class Schema {
1928
@IsInt()
2029
@Min(0)
@@ -34,6 +43,12 @@ describe('class-validator', () => {
3443

3544
@IsDateString()
3645
updatedAt!: string;
46+
47+
@ValidateNested()
48+
nested!: NestedSchema;
49+
@IsOptional()
50+
@ValidateNested()
51+
nestedArray?: NestedSchema[];
3752
}
3853
const schema = Schema;
3954

@@ -44,14 +59,26 @@ describe('class-validator', () => {
4459
id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74',
4560
name: 'John Doe',
4661
updatedAt: '2021-01-01T00:00:00.000Z',
47-
};
62+
} as Schema;
63+
4864
const badData = {
4965
age: '123',
5066
createdAt: '2021-01-01T00:00:00.000Z',
5167
5268
id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74',
5369
name: 'John Doe',
70+
updatedAt: '2021-01-01T00:00:00.000Z'
71+
};
72+
73+
const badNestedData = {
74+
age: 123,
75+
createdAt: '2021-01-01T00:00:00.000Z',
76+
77+
id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74',
78+
name: 'John Doe',
5479
updatedAt: '2021-01-01T00:00:00.000Z',
80+
nested: new NestedSchema(),
81+
nestedArray: [new NestedSchema()],
5582
};
5683

5784
test('infer', () => {
@@ -67,11 +94,35 @@ describe('class-validator', () => {
6794
expect(await validate(schema, badData)).toStrictEqual({
6895
issues: [
6996
{
70-
message: `An instance of Schema has failed the validation:
71-
- property age has failed the following constraints: min, isInt
72-
`,
97+
message: 'age must not be less than 0',
7398
path: ['age'],
7499
},
100+
{
101+
message: 'age must be an integer number',
102+
path: ['age'],
103+
}
104+
],
105+
success: false,
106+
});
107+
108+
expect(await validate(schema, badNestedData)).toStrictEqual({
109+
issues: [
110+
{
111+
message: 'value should not be empty',
112+
path: ['nested.value'],
113+
},
114+
{
115+
message: 'value must be a string',
116+
path: ['nested.value'],
117+
},
118+
{
119+
message: 'value should not be empty',
120+
path: ['nestedArray[0].value'],
121+
},
122+
{
123+
message: 'value must be a string',
124+
path: ['nestedArray[0].value'],
125+
}
75126
],
76127
success: false,
77128
});

packages/class-validator/src/validation.ts

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
/* eslint-disable prettier/prettier */
12
import type {AdapterResolver} from './resolver';
2-
import type {ValidationAdapter} from '@typeschema/core';
3+
import type {ValidationAdapter, ValidationIssue} from '@typeschema/core';
34

45
import {memoize} from '@typeschema/core';
6+
import { ValidationError } from "class-validator";
57

68
const importValidationModule = memoize(async () => {
79
const {validate} = await import('class-validator');
@@ -13,6 +15,22 @@ export const validationAdapter: ValidationAdapter<
1315
> = async schema => {
1416
const {validate} = await importValidationModule();
1517
return async data => {
18+
function getIssues(error: ValidationError, parentPath = ""): ValidationIssue[] {
19+
const currentPath = parentPath
20+
? Number.isInteger(+error.property) ? `${parentPath}[${error.property}]` : `${parentPath}.${error.property}`
21+
: error.property;
22+
const constraints = error.constraints ? Object.values(error.constraints) : [];
23+
const childIssues = error.children ? error.children.flatMap(childError => getIssues(childError, currentPath)) : [];
24+
25+
return [
26+
...constraints.map((message) => ({
27+
message: message,
28+
path: [currentPath],
29+
})),
30+
...childIssues
31+
];
32+
}
33+
1634
const errors = await validate(Object.assign(new schema(), data));
1735
if (errors.length === 0) {
1836
return {
@@ -22,10 +40,7 @@ export const validationAdapter: ValidationAdapter<
2240
};
2341
}
2442
return {
25-
issues: errors.map(error => ({
26-
message: error.toString(),
27-
path: [error.property],
28-
})),
43+
issues: errors.flatMap(error => getIssues(error)),
2944
success: false,
3045
};
3146
};

0 commit comments

Comments
 (0)