-
-
Notifications
You must be signed in to change notification settings - Fork 94
/
validate.ts
87 lines (76 loc) · 2.55 KB
/
validate.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
import type { Document, Error as MongooseError } from 'mongoose';
import { version } from 'mongoose';
import { ValidationError } from '../../errors';
const versionNumber = Number(version.charAt(0));
export type ValidationErrorData = {
path: string;
message: string;
value: any;
/**
* This `idx` property is used only for *Many operations.
* It stores idx from received array of records which occurs Validation Error.
*/
idx?: number;
};
export type ValidationsWithMessage = {
message: string;
errors: Array<ValidationErrorData>;
};
export async function validateDoc(doc: Document): Promise<ValidationsWithMessage | null> {
const validations: MongooseError.ValidationError | null =
versionNumber >= 7
? doc.validateSync()
: await new Promise((resolve) => doc.validate(resolve as any));
return validations?.errors
? {
message: validations.message,
errors: Object.keys(validations.errors).map((key) => {
// transform object to array[{ path, message, value }, {}, ...]
const { message, value } = validations.errors[key] as any;
return {
path: key,
message,
value,
};
}),
}
: null;
}
/**
* Make async validation for mongoose document.
* And if it has validation errors then throw one Error with embedding all validation errors into it.
*/
export async function validateAndThrow(doc: Document): Promise<void> {
const validations: ValidationsWithMessage | null = await validateDoc(doc);
if (validations) {
throw new ValidationError(validations);
}
}
/**
* Make async validation for array of mongoose documents.
* And if they have validation errors then throw one Error with embedding
* all validator errors into one array with addition of `idx` property.
* `idx` represent record index in array received from user.
*/
export async function validateManyAndThrow(docs: Document[]): Promise<void> {
const combinedValidators: Array<ValidationErrorData> = [];
let hasValidationError = false;
for (let idx = 0; idx < docs.length; idx++) {
const validations: ValidationsWithMessage | null = await validateDoc(docs[idx]);
if (validations) {
validations.errors.forEach((validatorError) => {
combinedValidators.push({
...validatorError,
idx,
});
});
hasValidationError = true;
}
}
if (hasValidationError) {
throw new ValidationError({
message: 'Nothing has been saved. Some documents contain validation errors',
errors: combinedValidators,
});
}
}