-
Notifications
You must be signed in to change notification settings - Fork 1
/
and.ts
62 lines (57 loc) · 1.67 KB
/
and.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
import {
getOption,
InferOutputTypes,
InferTypes,
makeSchema,
Schema,
} from "../schema";
import { Intersect } from "../utility";
import { isFailure, mergeValidations, ValidationResult } from "../validation";
export function and<T extends readonly Schema<unknown>[]>(
...schemas: T
): Schema<
Intersect<InferTypes<T>>,
Intersect<InferOutputTypes<T>>,
{ type: "and"; schemas: T }
> {
type ResultI = Intersect<InferTypes<T>>;
type ResultO = Intersect<InferOutputTypes<T>>;
class Aggregator {
constructor(readonly earlyExit: boolean) {}
public result: ValidationResult<ResultI>;
onValidate(validation: ValidationResult<unknown>): boolean {
this.result = mergeValidations(this.result, validation);
return this.earlyExit && isFailure(validation);
}
}
return makeSchema(
(v, o) => {
const aggregator = new Aggregator(getOption(o, "earlyExit"));
for (const schema of schemas) {
const validation = schema.validate(v, o);
if (aggregator.onValidate(validation)) {
break;
}
}
return aggregator.result;
},
async (v, o) => {
const aggregator = new Aggregator(getOption(o, "earlyExit"));
for (const schema of schemas) {
const validation = await schema.validateAsync(v, o);
if (aggregator.onValidate(validation)) {
break;
}
}
return aggregator.result;
},
() => ({ type: "and", schemas }),
(v, o) => {
const results: Partial<ResultO>[] = [];
for (const schema of schemas) {
results.push(schema.parse(v, o).parsedValue as ResultO);
}
return Object.assign({}, ...results) as ResultO;
}
);
}