-
Notifications
You must be signed in to change notification settings - Fork 0
/
runner.ts
97 lines (86 loc) · 2.39 KB
/
runner.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
91
92
93
94
95
96
97
import { Field } from './field'
import { Validation } from './validation'
/**
* Result of running all {@link Validation | Validations }
*/
export type RunnerResult = {
/**
* error messages
*/
errors: null | string[]
/**
* value that was validated against
*/
value: any
}
/**
* Runner
* Runs validations and reports results
*/
export class Runner {
constructor(public validations: Validation[], protected bailEarly = false) {}
/**
* Run validations, it will run all validations, and then return the result.
* @param value - value to validate against
* @param field - {@link Field} associated with validations
* @param [dependency] Dependency {@link Field } that triggered the validation
* @returns promise of {@link RunnerResult}
*/
async validate(
value: any,
field: Field<any>,
dependency?: Field<any>
): Promise<RunnerResult> {
if (!this.validations.length) {
return { errors: null, value }
}
if (this.bailEarly) {
return await this.bailEarlyValidation(value, field, dependency)
}
const errors: string[] = []
const validationsToRun = []
for (const validation of this.validations) {
validationsToRun.push(
Promise.resolve(validation.fn(value, field, dependency)).then(
(result) => {
return {
result,
msg: validation.msg
}
}
)
)
}
const resolved = await Promise.all(validationsToRun)
for (const validation of resolved) {
if (typeof validation.result === 'string') {
errors.push(validation.result)
} else if (!validation.result) {
errors.push(validation.msg)
}
}
return errors.length ? { errors, value } : { errors: null, value }
}
/**
* Runs validations, and returns on first validation that errors out
* @param value
* @param field
* @param [dependency]
* @returns early validation
*/
protected async bailEarlyValidation(
value: any,
field: Field<any>,
dependency?: Field<any>
): Promise<RunnerResult> {
for (const validation of this.validations) {
const result = await validation.fn(value, field, dependency)
if (typeof result === 'string') {
return { errors: [result], value }
} else if (!result) {
return { errors: [validation.msg], value }
}
}
return { errors: null, value }
}
}