diff --git a/Validator.ts b/Validator.ts index bb77032..35a786f 100644 --- a/Validator.ts +++ b/Validator.ts @@ -26,7 +26,7 @@ export type Schema = { [key: string]: Validatable } | { export async function validate( value: any, validators: Validatable, -): Promise { +): Promise { if (instanceofValidatorArray(validators) || instanceofValidator(validators)) { return validateValue(value, validators); } else { diff --git a/mod.ts b/mod.ts index 3bcac77..e1fd508 100644 --- a/mod.ts +++ b/mod.ts @@ -6,5 +6,6 @@ export { Validatable, ArraySymbol, } from "./Validator.ts"; -export * from "./validators/string.ts"; -export * from "./validators/number.ts"; +export { isString } from "./validators/string.ts"; +export { isNumber, isInteger } from "./validators/number.ts"; +export { or } from "./validators/logic.ts"; diff --git a/validators/logic.test.ts b/validators/logic.test.ts new file mode 100644 index 0000000..cf80128 --- /dev/null +++ b/validators/logic.test.ts @@ -0,0 +1,27 @@ +import { or } from "./logic.ts"; +import { validate, Validator, isString, isInteger } from "../mod.ts"; +import { + assertEquals, + assertNotEquals, +} from "https://deno.land/std@0.53.0/testing/asserts.ts"; + +Deno.test("or (match)", async () => { + const values: [any, Validator[]][] = [ + ["", [isString, isInteger]], + [1, [isString, isInteger]], + ]; + for (const [value, validators] of values) { + assertEquals(await validate(value, or(...validators)), []); + } +}); + +Deno.test("or (no match)", async () => { + const values: [any, Validator[]][] = [ + [true, [isString, isInteger]], + [3.1415, [isString, isInteger]], + [1, [isString]], + ]; + for (const [value, validators] of values) { + assertNotEquals(await validate(value, or(...validators)), []); + } +}); diff --git a/validators/logic.ts b/validators/logic.ts new file mode 100644 index 0000000..97153f5 --- /dev/null +++ b/validators/logic.ts @@ -0,0 +1,18 @@ +import { Validator, Args, Validatable, validate } from "../mod.ts"; + +export function or(...funcs: Validatable[]): Validator { + return { + type: "or", + check: async (value: any) => { + const errors = await Promise.all(funcs.map((x) => validate(value, x))); + if (errors.every((x) => x.length > 0)) { + return { + errors, + }; + } + }, + message: (value: any, args?: Args) => { + return "At least one of the rules has to be successful."; + }, + }; +}