From ae4c6008cb767f5f14fc528c462891b838e32d62 Mon Sep 17 00:00:00 2001 From: Grant Date: Sat, 19 Nov 2022 23:37:23 +0100 Subject: [PATCH 01/16] Rethink async typing successfully --- src/transformers/number/ceil.ts | 2 +- src/transformers/number/clamp.ts | 2 +- src/transformers/number/floor.ts | 2 +- src/transformers/number/round.ts | 2 +- src/transformers/number/toMultipleOf.ts | 2 +- src/transformers/string/lower.ts | 2 +- src/transformers/string/normalize.ts | 2 +- src/transformers/string/trim.ts | 2 +- src/transformers/string/truncate.ts | 2 +- src/transformers/string/upper.ts | 2 +- src/types.ts | 33 +++++++++++--- src/validate.ts | 53 ++++++++++++---------- src/validators/arrayOf.ts | 6 +-- src/validators/bail.ts | 10 ++-- src/validators/boolean/falsey.ts | 2 +- src/validators/boolean/isBool.ts | 2 +- src/validators/boolean/toBool.ts | 2 +- src/validators/boolean/truthy.ts | 2 +- src/validators/boolean/tryBool.ts | 2 +- src/validators/date/after.ts | 2 +- src/validators/date/before.ts | 4 +- src/validators/date/inRange.ts | 4 +- src/validators/date/isDate.ts | 2 +- src/validators/date/toDate.ts | 2 +- src/validators/date/tryDate.ts | 2 +- src/validators/either.ts | 2 +- src/validators/equals.ts | 2 +- src/validators/number/between.ts | 2 +- src/validators/number/closeTo.ts | 2 +- src/validators/number/gt.ts | 2 +- src/validators/number/gte.ts | 2 +- src/validators/number/isInt.ts | 2 +- src/validators/number/isMultipleOf.ts | 2 +- src/validators/number/isNumber.ts | 2 +- src/validators/number/lt.ts | 2 +- src/validators/number/lte.ts | 2 +- src/validators/number/toInt.ts | 2 +- src/validators/number/toNumber.ts | 2 +- src/validators/number/tryInt.ts | 2 +- src/validators/number/tryNumber.ts | 2 +- src/validators/oneOf.ts | 2 +- src/validators/optional.ts | 4 +- src/validators/string/betweenLength.ts | 2 +- src/validators/string/insensitiveEquals.ts | 2 +- src/validators/string/isEmail.ts | 2 +- src/validators/string/isString.ts | 2 +- src/validators/string/isUrl.ts | 3 +- src/validators/string/length.ts | 2 +- src/validators/string/maxLength.ts | 2 +- src/validators/string/minLength.ts | 2 +- src/validators/string/toString.ts | 2 +- src/validators/validateCondition.ts | 12 ++--- src/validators/validateRegex.ts | 2 +- tests/README.ts | 20 +++++--- tests/validate.ts | 6 +-- tests/validators/arrayOf.ts | 6 +-- tests/validators/bail.ts | 8 ++-- tests/validators/either.ts | 14 ++++-- tests/validators/optional.ts | 4 +- tests/validators/validateCondition.ts | 2 +- 60 files changed, 156 insertions(+), 121 deletions(-) diff --git a/src/transformers/number/ceil.ts b/src/transformers/number/ceil.ts index e46e721..85232f5 100644 --- a/src/transformers/number/ceil.ts +++ b/src/transformers/number/ceil.ts @@ -1,6 +1,6 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; -const ceil = (): ValidatorFunction => (value, conf) => { +const ceil = (): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); } diff --git a/src/transformers/number/clamp.ts b/src/transformers/number/clamp.ts index e5d23b3..20a1573 100644 --- a/src/transformers/number/clamp.ts +++ b/src/transformers/number/clamp.ts @@ -1,7 +1,7 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; const clamp = - (min: number, max: number): ValidatorFunction => + (min: number, max: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/transformers/number/floor.ts b/src/transformers/number/floor.ts index 5e3b625..9245d25 100644 --- a/src/transformers/number/floor.ts +++ b/src/transformers/number/floor.ts @@ -1,6 +1,6 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; -const floor = (): ValidatorFunction => (value, conf) => { +const floor = (): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); } diff --git a/src/transformers/number/round.ts b/src/transformers/number/round.ts index d86f745..3913a23 100644 --- a/src/transformers/number/round.ts +++ b/src/transformers/number/round.ts @@ -1,6 +1,6 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; -const round = (): ValidatorFunction => (value, conf) => { +const round = (): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); } diff --git a/src/transformers/number/toMultipleOf.ts b/src/transformers/number/toMultipleOf.ts index c7ea2b1..f4404cd 100644 --- a/src/transformers/number/toMultipleOf.ts +++ b/src/transformers/number/toMultipleOf.ts @@ -1,7 +1,7 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; const toMultipleOf = - (n: number, round = Math.round): ValidatorFunction => + (n: number, round = Math.round): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/transformers/string/lower.ts b/src/transformers/string/lower.ts index 7c8b01a..d8bf34c 100644 --- a/src/transformers/string/lower.ts +++ b/src/transformers/string/lower.ts @@ -1,6 +1,6 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; -const lower = (): ValidatorFunction => (value, conf) => { +const lower = (): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/transformers/string/normalize.ts b/src/transformers/string/normalize.ts index 9064df8..0edd08e 100644 --- a/src/transformers/string/normalize.ts +++ b/src/transformers/string/normalize.ts @@ -1,7 +1,7 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; const normalize = - (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'): ValidatorFunction => + (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/transformers/string/trim.ts b/src/transformers/string/trim.ts index 6cd08d8..9c9d427 100644 --- a/src/transformers/string/trim.ts +++ b/src/transformers/string/trim.ts @@ -1,6 +1,6 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; -const trim = (): ValidatorFunction => (value, conf) => { +const trim = (): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/transformers/string/truncate.ts b/src/transformers/string/truncate.ts index 37b5b91..e281386 100644 --- a/src/transformers/string/truncate.ts +++ b/src/transformers/string/truncate.ts @@ -1,7 +1,7 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; const truncate = - (n: number): ValidatorFunction => + (n: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/transformers/string/upper.ts b/src/transformers/string/upper.ts index 5c0095b..77d3a5e 100644 --- a/src/transformers/string/upper.ts +++ b/src/transformers/string/upper.ts @@ -1,6 +1,6 @@ import { Ignore, Success, ValidatorFunction } from '../../types.js'; -const upper = (): ValidatorFunction => (value, conf) => { +const upper = (): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/types.ts b/src/types.ts index 273a4f0..3b82c53 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,22 +9,41 @@ export interface ValidatorConfiguration { original: any; parent: any; } - -export interface ValidatorFunction { - (value: U, conf: ValidatorConfiguration): Promise; +export interface ValidatorFunction { + (value: I, conf: ValidatorConfiguration): Promise; } -export type ValidatorObject = { - [key in keyof T]: Validator; +export type ValidatorFunctionList1 = [ValidatorFunction] +export type ValidatorFunctionList2 = [ValidatorFunction, ValidatorFunction] +export type ValidatorFunctionList3 = [ValidatorFunction, ValidatorFunction, ValidatorFunction] +export type ValidatorFunctionList = + | ValidatorFunctionList1 + | ValidatorFunctionList2 + | ValidatorFunctionList3; + +export type ValueValidator = + | ValidatorFunctionList1 + | ValidatorFunctionList2 + | ValidatorFunctionList3 + | ValidatorFunction + | ValidatorObject; + +export type ValidatorObject = { + [key in keyof O]: ValueValidator; }; -export type Validator = ValidatorObject | ValidatorFunction[] | ValidatorFunction; +export type Validator = + | ValidatorFunctionList1 + | ValidatorFunctionList2 + | ValidatorFunctionList3 + | ValidatorFunction + | ValidatorObject; export interface FailureFunction { (v: T, conf: ValidatorConfiguration): string; } -export type InferValidator = T extends Validator ? U : never; +export type InferValidator = T extends Validator ? O : never; export const Success = function (t?: T): Promise { return Promise.resolve(t); diff --git a/src/validate.ts b/src/validate.ts index d6e7910..ccfb1e8 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -2,17 +2,21 @@ import { Validator, ValidatorConfiguration, ValidatorFunction, + ValidatorFunctionList, + ValidatorFunctionList1, + ValidatorFunctionList2, + ValidatorFunctionList3, ValidatorObject, ValidatorState, } from './types.js'; -const resolveValidatorList = function ( - validators: ValidatorFunction[], +const resolveValidatorList = function ( + validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration -): Promise { - return validators - .reduce>>((previousPromise, validator) => { +): Promise { + return (validators as ValidatorFunction[]) + .reduce>>((previousPromise, validator) => { return previousPromise.then(({ value, failures }) => validator(value, conf).then( (newValue) => ({ @@ -30,19 +34,19 @@ const resolveValidatorList = function ( if (failures.length > 0) { throw failures; } - return value; + return value as O; }); }; -const resolveValidatorObject = function ( - validator: ValidatorObject, +const resolveValidatorObject = function ( + validator: ValidatorObject, testValue: any, conf: ValidatorConfiguration -): Promise { - const keys = Object.keys(validator) as (keyof T)[]; +): Promise { + const keys = Object.keys(validator) as (keyof O)[]; return Promise.all( - keys.map>>((i) => - validate(validator[i], { + keys.map>>((i: keyof O) => + validate(validator[i as keyof O], { ...conf, name: i as string, path: conf.path.concat(i as string), @@ -53,7 +57,7 @@ const resolveValidatorObject = function ( ) ) ).then((results) => { - let sanitizedObject: { [key in keyof T]?: T[key] } = {}; + let sanitizedObject: { [key in keyof O]?: O[key] } = {}; let validationFailures: string[] = []; results.forEach((result) => { @@ -69,29 +73,30 @@ const resolveValidatorObject = function ( if (validationFailures.length > 0) { throw validationFailures; } - return sanitizedObject as T; + return sanitizedObject as O; }); }; -const isValidatorFunctionList = ( - validator: Validator -): validator is ValidatorFunction[] => { +const isValidatorFunctionList = (validator: Validator): validator is ValidatorFunctionList => { return typeof validator === 'object' && Array.isArray(validator); }; -const isValidatorObject = (validator: Validator): validator is ValidatorObject => { +const isValidatorObject = (validator: Validator): validator is ValidatorObject => { return typeof validator === 'object' && !Array.isArray(validator); }; -const isValidatorFunction = (validator: Validator): validator is ValidatorFunction => { +const isValidatorFunction = (validator: Validator): validator is ValidatorFunction => { return typeof validator === 'function'; }; -const validate = function ( - validator: Validator, - validateConf?: Partial -) { - return function (testValue: any, testConf?: Partial): Promise { +export function validate(v: ValidatorFunction, c?: Partial): (val: I, c?: Partial) => Promise +export function validate(v: ValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => Promise +export function validate(v: ValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => Promise +export function validate(v: ValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => Promise +export function validate(v: ValidatorObject, c?: Partial): (val: I, c?: Partial) => Promise +export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => Promise +export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => Promise { + return function (testValue: any, testConf?: Partial): Promise { // Set defaults to configuration const conf: ValidatorConfiguration = { name: 'object', diff --git a/src/validators/arrayOf.ts b/src/validators/arrayOf.ts index f0ca83f..35c3df8 100644 --- a/src/validators/arrayOf.ts +++ b/src/validators/arrayOf.ts @@ -2,7 +2,7 @@ import validate from '../validate.js'; import { Validator, ValidatorFunction, ValidatorState } from '../types.js'; const arrayOf = - (validator: Validator): ValidatorFunction => + (validator: Validator): ValidatorFunction => (testValues, conf) => { // Array of one item should use that validation to every item in the array if (typeof testValues !== 'object' || !Array.isArray(testValues)) { @@ -10,7 +10,7 @@ const arrayOf = } return Promise.all( - testValues.map>>((testValue, i) => + testValues.map>>((testValue, i) => validate(validator, { ...conf, name: `${conf.name}[${i}]`, @@ -30,7 +30,7 @@ const arrayOf = throw validationFailures; } - return results.map(({ value }) => value) as T[]; + return results.map(({ value }) => value) as O[]; }); }; diff --git a/src/validators/bail.ts b/src/validators/bail.ts index f977632..cc2c83f 100644 --- a/src/validators/bail.ts +++ b/src/validators/bail.ts @@ -1,14 +1,14 @@ -import { ValidatorFunction, ValidatorState } from '../types.js'; +import { ValidatorFunction, ValidatorFunctionList, ValidatorState } from '../types.js'; import validate from '../validate.js'; -const bail = (validators: ValidatorFunction[]): ValidatorFunction => { +const bail = (validators: ValidatorFunctionList): ValidatorFunction => { if (!Array.isArray(validators)) { // If not an array is passed, simply continue validation return validate(validators); } return (value, conf) => { - return validators - .reduce>>((previousPromise, validator) => { + return (validators as ValidatorFunction[]) + .reduce>>((previousPromise, validator) => { return previousPromise.then(({ value, failures }) => failures.length > 0 ? { value, failures } // Short-circuit for any error @@ -28,7 +28,7 @@ const bail = (validators: ValidatorFunction[]): ValidatorFunction => { if (failures.length > 0) { throw failures; } - return value; + return value as O; }); }; }; diff --git a/src/validators/boolean/falsey.ts b/src/validators/boolean/falsey.ts index d9ab96d..a075bd0 100644 --- a/src/validators/boolean/falsey.ts +++ b/src/validators/boolean/falsey.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const falsey = (): ValidatorFunction => +const falsey = (): ValidatorFunction => validateCondition( (value) => !value, (_, conf) => `Field ${conf.name} should be falsey.` diff --git a/src/validators/boolean/isBool.ts b/src/validators/boolean/isBool.ts index 3b96144..233a96c 100644 --- a/src/validators/boolean/isBool.ts +++ b/src/validators/boolean/isBool.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isBool = (): ValidatorFunction => +const isBool = (): ValidatorFunction => validateCondition( (v) => v === true || v === false, (_, conf) => `Field ${conf.name} should be a boolean.` diff --git a/src/validators/boolean/toBool.ts b/src/validators/boolean/toBool.ts index 2204266..a0c976a 100644 --- a/src/validators/boolean/toBool.ts +++ b/src/validators/boolean/toBool.ts @@ -1,6 +1,6 @@ import { Success, ValidatorFunction } from '../../types.js'; -const toBool = (): ValidatorFunction => (value) => { +const toBool = (): ValidatorFunction => (value) => { return Success(!!value); }; diff --git a/src/validators/boolean/truthy.ts b/src/validators/boolean/truthy.ts index aa5e38d..39f6ee5 100644 --- a/src/validators/boolean/truthy.ts +++ b/src/validators/boolean/truthy.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const truthy = (): ValidatorFunction => +const truthy = (): ValidatorFunction => validateCondition( (val) => !!val, (_, conf) => `Field ${conf.name} should be truthy.` diff --git a/src/validators/boolean/tryBool.ts b/src/validators/boolean/tryBool.ts index d4f0adf..38e4967 100644 --- a/src/validators/boolean/tryBool.ts +++ b/src/validators/boolean/tryBool.ts @@ -1,6 +1,6 @@ import { Failure, Success, ValidatorFunction } from '../../types.js'; -const tryBool: (t?: any[], f?: any[]) => ValidatorFunction = +const tryBool: (t?: any[], f?: any[]) => ValidatorFunction = (truthy = [true, 1], falsey = [false, 0]) => (value, conf) => { if (truthy.indexOf(value) !== -1) { diff --git a/src/validators/date/after.ts b/src/validators/date/after.ts index ecc9f6b..a97a350 100644 --- a/src/validators/date/after.ts +++ b/src/validators/date/after.ts @@ -3,7 +3,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const after: ( date: string | number | Date, opts?: { inclusive: boolean } -) => ValidatorFunction = +) => ValidatorFunction = (date, opts = { inclusive: false }) => (value, conf) => { if (!(value instanceof Date)) { diff --git a/src/validators/date/before.ts b/src/validators/date/before.ts index 9bc986f..44959ba 100644 --- a/src/validators/date/before.ts +++ b/src/validators/date/before.ts @@ -3,8 +3,8 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const before: ( date: string | number | Date, opts?: { inclusive?: boolean } -) => ValidatorFunction = - (date, opts = { inclusive: false }): ValidatorFunction => +) => ValidatorFunction = + (date, opts = { inclusive: false }): ValidatorFunction => (value, conf) => { if (!(value instanceof Date)) { return Ignore(); diff --git a/src/validators/date/inRange.ts b/src/validators/date/inRange.ts index 7af2742..bf1bc53 100644 --- a/src/validators/date/inRange.ts +++ b/src/validators/date/inRange.ts @@ -4,12 +4,12 @@ const inRange: ( minDate: string | number | Date, maxDate: string | number | Date, opts?: { minInclusive?: boolean; maxInclusive?: boolean } -) => ValidatorFunction = +) => ValidatorFunction = ( minDate, maxDate, opts = { minInclusive: false, maxInclusive: false } - ): ValidatorFunction => + ): ValidatorFunction => (value, conf) => { if (!(value instanceof Date)) { return Ignore(); diff --git a/src/validators/date/isDate.ts b/src/validators/date/isDate.ts index 2b87515..b609db8 100644 --- a/src/validators/date/isDate.ts +++ b/src/validators/date/isDate.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isDate = (): ValidatorFunction => +const isDate = (): ValidatorFunction => validateCondition( (value) => value instanceof Date && !Number.isNaN(value.getTime()), (_, conf) => `Field ${conf.name} should be a valid date.` diff --git a/src/validators/date/toDate.ts b/src/validators/date/toDate.ts index f6ed307..1f34afd 100644 --- a/src/validators/date/toDate.ts +++ b/src/validators/date/toDate.ts @@ -1,6 +1,6 @@ import { Success, ValidatorFunction } from '../../types.js'; -const toDate = (): ValidatorFunction => (value, conf) => { +const toDate = (): ValidatorFunction => (value, conf) => { const parsed = value instanceof Date ? value : new Date(value); return Success(parsed); }; diff --git a/src/validators/date/tryDate.ts b/src/validators/date/tryDate.ts index 2c66409..23ab2bb 100644 --- a/src/validators/date/tryDate.ts +++ b/src/validators/date/tryDate.ts @@ -1,6 +1,6 @@ import { Failure, Success, ValidatorFunction } from '../../types.js'; -const tryDate = (): ValidatorFunction => (value, conf) => { +const tryDate = (): ValidatorFunction => (value, conf) => { const parsed = value instanceof Date ? value : new Date(value); if (!Number.isNaN(parsed.getTime())) { return Success(parsed); diff --git a/src/validators/either.ts b/src/validators/either.ts index 9c6e840..ec11d83 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -2,7 +2,7 @@ import { InferValidator, Success, Validator, ValidatorFunction } from '../types. import validate from '../validate.js'; const either = - >(validators: V[]): ValidatorFunction> => + >(validators: V[]): ValidatorFunction> => (value, conf) => { return Promise.allSettled( validators.map( diff --git a/src/validators/equals.ts b/src/validators/equals.ts index b23c409..7a60d2f 100644 --- a/src/validators/equals.ts +++ b/src/validators/equals.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../types.js'; import validateCondition from './validateCondition.js'; -const equals = (to: T): ValidatorFunction => +const equals = (to: T): ValidatorFunction => validateCondition( (value) => value === to, (_, conf) => `Field ${conf.name} should be equal to ${to}.` diff --git a/src/validators/number/between.ts b/src/validators/number/between.ts index 50335c6..de5243d 100644 --- a/src/validators/number/between.ts +++ b/src/validators/number/between.ts @@ -4,7 +4,7 @@ const between: ( min: number, max: number, opts?: { minInclusive?: boolean; maxInclusive?: boolean } -) => ValidatorFunction = +) => ValidatorFunction = (min, max, opts = { minInclusive: false, maxInclusive: false }) => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { diff --git a/src/validators/number/closeTo.ts b/src/validators/number/closeTo.ts index 2e3592d..93bdcbf 100644 --- a/src/validators/number/closeTo.ts +++ b/src/validators/number/closeTo.ts @@ -1,6 +1,6 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; -const closeTo: (v: number, e?: number) => ValidatorFunction = +const closeTo: (v: number, e?: number) => ValidatorFunction = (exactValue, epsilon = Number.EPSILON) => (value, conf) => { if (typeof value !== 'number') { diff --git a/src/validators/number/gt.ts b/src/validators/number/gt.ts index 7255c7f..5075b84 100644 --- a/src/validators/number/gt.ts +++ b/src/validators/number/gt.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const gt = - (min: number): ValidatorFunction => + (min: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/gte.ts b/src/validators/number/gte.ts index d658c3b..b14232a 100644 --- a/src/validators/number/gte.ts +++ b/src/validators/number/gte.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const gte = - (min: number): ValidatorFunction => + (min: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/isInt.ts b/src/validators/number/isInt.ts index 889bc52..74eca3b 100644 --- a/src/validators/number/isInt.ts +++ b/src/validators/number/isInt.ts @@ -1,7 +1,7 @@ import { Failure, Success, ValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isInt = (): ValidatorFunction => +const isInt = (): ValidatorFunction => validateCondition( (value) => Number.isInteger(value), (_, conf) => `Field ${conf.name} should be an integer.` diff --git a/src/validators/number/isMultipleOf.ts b/src/validators/number/isMultipleOf.ts index 3e34f4b..ec11226 100644 --- a/src/validators/number/isMultipleOf.ts +++ b/src/validators/number/isMultipleOf.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const isMultipleOf = - (n: number): ValidatorFunction => + (n: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/isNumber.ts b/src/validators/number/isNumber.ts index 98378ab..91337e6 100644 --- a/src/validators/number/isNumber.ts +++ b/src/validators/number/isNumber.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isNumber = (): ValidatorFunction => +const isNumber = (): ValidatorFunction => validateCondition( (value) => typeof value === 'number' && !Number.isNaN(value), (_, conf) => `Field ${conf.name} should be a number.` diff --git a/src/validators/number/lt.ts b/src/validators/number/lt.ts index 4cc5f05..218ddc6 100644 --- a/src/validators/number/lt.ts +++ b/src/validators/number/lt.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const lt = - (max: number): ValidatorFunction => + (max: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/lte.ts b/src/validators/number/lte.ts index 28defd4..0ff9665 100644 --- a/src/validators/number/lte.ts +++ b/src/validators/number/lte.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const lte = - (max: number): ValidatorFunction => + (max: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/toInt.ts b/src/validators/number/toInt.ts index b70dc94..cfa6c01 100644 --- a/src/validators/number/toInt.ts +++ b/src/validators/number/toInt.ts @@ -1,6 +1,6 @@ import { Success, ValidatorFunction } from '../../types.js'; -const toInt = (): ValidatorFunction => (value) => { +const toInt = (): ValidatorFunction => (value) => { return Success(Number.parseInt(value as any)); }; diff --git a/src/validators/number/toNumber.ts b/src/validators/number/toNumber.ts index 625cd6c..40f4b3d 100644 --- a/src/validators/number/toNumber.ts +++ b/src/validators/number/toNumber.ts @@ -1,6 +1,6 @@ import { Success, ValidatorFunction } from '../../types.js'; -const toNumber = (): ValidatorFunction => (value, conf) => { +const toNumber = (): ValidatorFunction => (value, conf) => { return Success(Number.parseFloat(value as any)); }; diff --git a/src/validators/number/tryInt.ts b/src/validators/number/tryInt.ts index b511887..28b7199 100644 --- a/src/validators/number/tryInt.ts +++ b/src/validators/number/tryInt.ts @@ -1,6 +1,6 @@ import { Failure, Success, ValidatorFunction } from '../../types.js'; -const tryInt = (): ValidatorFunction => (value, conf) => { +const tryInt = (): ValidatorFunction => (value, conf) => { const parsed = Number.parseInt(value as any); if (!Number.isNaN(parsed)) { return Success(parsed); diff --git a/src/validators/number/tryNumber.ts b/src/validators/number/tryNumber.ts index c7db4c7..cffc119 100644 --- a/src/validators/number/tryNumber.ts +++ b/src/validators/number/tryNumber.ts @@ -1,6 +1,6 @@ import { Failure, Success, ValidatorFunction } from '../../types.js'; -const tryNumber = (): ValidatorFunction => (value, conf) => { +const tryNumber = (): ValidatorFunction => (value, conf) => { const parsed = Number.parseFloat(value as any); if (!Number.isNaN(parsed)) { return Success(parsed); diff --git a/src/validators/oneOf.ts b/src/validators/oneOf.ts index aef6a16..803f9ae 100644 --- a/src/validators/oneOf.ts +++ b/src/validators/oneOf.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../types.js'; import validateCondition from './validateCondition.js'; -const oneOf = (items: T[]): ValidatorFunction => +const oneOf = (items: T[]): ValidatorFunction => validateCondition( (value) => items.indexOf(value) !== -1, (_, conf) => `Field ${conf.name} should be one of ${items.join(', ')}.` diff --git a/src/validators/optional.ts b/src/validators/optional.ts index 386620d..c4a540a 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -2,7 +2,9 @@ import validate from '../validate.js'; import { ValidatorFunction, Validator, Success } from '../types.js'; const optional = - (validators: Validator): ValidatorFunction => + ( + validators: Validator + ): ValidatorFunction => (value, conf) => { if (typeof value === 'undefined') { return Success(); diff --git a/src/validators/string/betweenLength.ts b/src/validators/string/betweenLength.ts index 88ce1ba..36c1e57 100644 --- a/src/validators/string/betweenLength.ts +++ b/src/validators/string/betweenLength.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const betweenLength = - (min: number, max: number): ValidatorFunction => + (min: number, max: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/insensitiveEquals.ts b/src/validators/string/insensitiveEquals.ts index d56de03..a6d3191 100644 --- a/src/validators/string/insensitiveEquals.ts +++ b/src/validators/string/insensitiveEquals.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const insensitiveEquals = - (to: string): ValidatorFunction => + (to: string): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/isEmail.ts b/src/validators/string/isEmail.ts index be327e2..d983639 100644 --- a/src/validators/string/isEmail.ts +++ b/src/validators/string/isEmail.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../../types.js'; import validateRegex from '../validateRegex.js'; -const isEmail = (): ValidatorFunction => +const isEmail = (): ValidatorFunction => validateRegex( /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/, (_, { name }) => `Field ${name} should be an email.` diff --git a/src/validators/string/isString.ts b/src/validators/string/isString.ts index c2c57ad..50db84b 100644 --- a/src/validators/string/isString.ts +++ b/src/validators/string/isString.ts @@ -1,7 +1,7 @@ import { ValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isString = (): ValidatorFunction => +const isString = (): ValidatorFunction => validateCondition( (value) => typeof value === 'string', (_, conf) => `Field ${conf.name} should be string.` diff --git a/src/validators/string/isUrl.ts b/src/validators/string/isUrl.ts index 7576239..835d64f 100644 --- a/src/validators/string/isUrl.ts +++ b/src/validators/string/isUrl.ts @@ -1,7 +1,6 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; -import validateRegex from '../validateRegex.js'; -const isUrl = (): ValidatorFunction => (value, conf) => { +const isUrl = (): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/validators/string/length.ts b/src/validators/string/length.ts index 77a7380..3320d98 100644 --- a/src/validators/string/length.ts +++ b/src/validators/string/length.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const length = - (n: number): ValidatorFunction => + (n: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/maxLength.ts b/src/validators/string/maxLength.ts index 6afedc0..92e3bcf 100644 --- a/src/validators/string/maxLength.ts +++ b/src/validators/string/maxLength.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const maxLength = - (max: number): ValidatorFunction => + (max: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/minLength.ts b/src/validators/string/minLength.ts index 859dd04..0cd7114 100644 --- a/src/validators/string/minLength.ts +++ b/src/validators/string/minLength.ts @@ -1,7 +1,7 @@ import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; const minLength = - (min: number): ValidatorFunction => + (min: number): ValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/toString.ts b/src/validators/string/toString.ts index 5cb10c2..52b4bb9 100644 --- a/src/validators/string/toString.ts +++ b/src/validators/string/toString.ts @@ -1,6 +1,6 @@ import { Success, ValidatorFunction } from '../../types.js'; -const toString = (): ValidatorFunction => (value, conf) => { +const toString = (): ValidatorFunction => (value, conf) => { return Success('' + value); }; diff --git a/src/validators/validateCondition.ts b/src/validators/validateCondition.ts index 943b499..a81848e 100644 --- a/src/validators/validateCondition.ts +++ b/src/validators/validateCondition.ts @@ -6,14 +6,14 @@ import { ValidatorFunction, } from '../types.js'; -interface ConditionFunction { - (v: T, conf: ValidatorConfiguration): boolean; +interface ConditionFunction { + (v: I, conf: ValidatorConfiguration): boolean; } -const validateCondition = ( - condition: ConditionFunction, - errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` -): ValidatorFunction => { +const validateCondition = ( + condition: ConditionFunction, + errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` +): ValidatorFunction => { return function (field, conf) { if (condition(field, conf)) { return Success(); diff --git a/src/validators/validateRegex.ts b/src/validators/validateRegex.ts index f9f846e..94239a5 100644 --- a/src/validators/validateRegex.ts +++ b/src/validators/validateRegex.ts @@ -3,7 +3,7 @@ import { Failure, FailureFunction, Ignore, Success, ValidatorFunction } from '.. const validateRegex = ( regex: RegExp, errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` -): ValidatorFunction => { +): ValidatorFunction => { return function (field, conf) { if (typeof field !== 'string') { return Ignore(); diff --git a/tests/README.ts b/tests/README.ts index 818bb03..27ecb34 100644 --- a/tests/README.ts +++ b/tests/README.ts @@ -8,6 +8,7 @@ import validate, { Failure, Ignore, Validator, + ValidatorObject, } from '../src/index'; test('README: Validation functions', async () => { @@ -59,7 +60,7 @@ test('README: Bring your own validator - isUniqueEmail starting', async () => { }, }; - const isUniqueEmail = (): ValidatorFunction => + const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { const exists = await db.users.find({ email }); // User | null if (!exists) { @@ -90,7 +91,7 @@ test('README: Bring your own validator - isUniqueEmail full', async () => { }, }; - const isUniqueEmail = (): ValidatorFunction => + const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { if (typeof email !== 'string') { return Ignore(); @@ -133,7 +134,7 @@ test('README: Sanitize and transform - hash', async () => { }, }; - const isUniqueEmail = (): ValidatorFunction => + const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { if (typeof email !== 'string') { return Ignore(); @@ -152,7 +153,7 @@ test('README: Sanitize and transform - hash', async () => { }, }; - const hash = (): ValidatorFunction => + const hash = (): ValidatorFunction => async function (password, conf) { if (typeof password !== 'string') { return Ignore(); @@ -196,7 +197,7 @@ test('README: Higher-order validators - confirmPassword', async () => { }, }; - const isUniqueEmail = (): ValidatorFunction => + const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { if (typeof email !== 'string') { return Ignore(); @@ -215,7 +216,7 @@ test('README: Higher-order validators - confirmPassword', async () => { }, }; - const hash = (): ValidatorFunction => + const hash = (): ValidatorFunction => async function (password, conf) { if (typeof password !== 'string') { return Ignore(); @@ -224,7 +225,12 @@ test('README: Higher-order validators - confirmPassword', async () => { return Success(hashedPassword); }; - const confirmPassword = (validator: Validator): ValidatorFunction => + const confirmPassword = < + I extends { email: string; password: string; password_confirm: string }, + O extends { email: string; password: string } + >( + validator: ValidatorObject + ): ValidatorFunction => async function (user, conf) { if (!user?.password_confirm) { return Failure('You should confirm your password.'); diff --git a/tests/validate.ts b/tests/validate.ts index 0f828c2..370daf1 100644 --- a/tests/validate.ts +++ b/tests/validate.ts @@ -2,17 +2,17 @@ import { describe, expect, test } from '@jest/globals'; import validate from '../src/validate'; import { Failure, Success, ValidatorFunction } from '../src/types'; -const testSuccessfulValidation = (): ValidatorFunction => +const testSuccessfulValidation = (): ValidatorFunction => async function (_value, _conf) { return Success(); }; -const testFailingValidation = (): ValidatorFunction => +const testFailingValidation = (): ValidatorFunction => async function (_value, _conf) { return Failure('test failed'); }; -const testTransformValidation = (): ValidatorFunction => +const testTransformValidation = (): ValidatorFunction => async function (value, _conf) { return Success(value + value); }; diff --git a/tests/validators/arrayOf.ts b/tests/validators/arrayOf.ts index 455a9aa..e54a56c 100644 --- a/tests/validators/arrayOf.ts +++ b/tests/validators/arrayOf.ts @@ -3,17 +3,17 @@ import arrayOf from '../../src/validators/arrayOf'; import validate from '../../src/validate'; import { Failure, Success, ValidatorFunction } from '../../src/types'; -const testSuccessfulValidation = (): ValidatorFunction => +const testSuccessfulValidation = (): ValidatorFunction => async function (_value, _conf) { return Success(); }; -const testFailingValidation = (): ValidatorFunction => +const testFailingValidation = (): ValidatorFunction => async function (_value, _conf) { return Failure('test failed'); }; -const testMinimumValidation = (): ValidatorFunction => +const testMinimumValidation = (): ValidatorFunction => async function (value, _conf) { if (value > 2) { return Success(); diff --git a/tests/validators/bail.ts b/tests/validators/bail.ts index 92190da..97f5ccd 100644 --- a/tests/validators/bail.ts +++ b/tests/validators/bail.ts @@ -13,13 +13,13 @@ const conf: ValidatorConfiguration = { test('bail runs over each test if they are not failing', async () => { let i = 0; - const increment = (): ValidatorFunction => async () => { + const increment = (): ValidatorFunction => async () => { i += 1; return Success(); }; // To test whether it works with returning value - const increment2 = (): ValidatorFunction => async (value) => { + const increment2 = (): ValidatorFunction => async (value) => { i += 1; return Success(value); }; @@ -33,7 +33,7 @@ test('bail runs over each test if they are not failing', async () => { test('bail stops after first failing test', async () => { let i = 0; - const failIncrement = (): ValidatorFunction => async () => { + const failIncrement = (): ValidatorFunction => async () => { i += 1; return Failure('Incrementation failed.'); }; @@ -49,7 +49,7 @@ test('bail stops after first failing test', async () => { }); test('bail just passes to validate if the passed value is not an array', async () => { - const increment = (): ValidatorFunction => async (value) => { + const increment = (): ValidatorFunction => async (value) => { if (value) { return Success(); } else { diff --git a/tests/validators/either.ts b/tests/validators/either.ts index a6f06f5..68826f4 100644 --- a/tests/validators/either.ts +++ b/tests/validators/either.ts @@ -3,17 +3,17 @@ import either from '../../src/validators/either'; import validate from '../../src/validate'; import { Failure, Success, ValidatorFunction } from '../../src/types'; -const testSuccessfulValidation = (): ValidatorFunction => +const testSuccessfulValidation = (): ValidatorFunction => async function (_value, _conf) { return Success(); }; -const testFailingValidation = (i: number): ValidatorFunction => +const testFailingValidation = (i: number): ValidatorFunction => async function (_value, _conf) { return Failure(`test ${i} failed`); }; -const testTransformingValidation = (): ValidatorFunction => +const testTransformingValidation = (): ValidatorFunction => async function (value, _conf) { return Success(value + 1); }; @@ -34,14 +34,18 @@ test('either function passes if any of the two validation passes', async () => { test('either function resolves to first if the first is transformation', async () => { const value = 1; - const validateTest = validate(either([testTransformingValidation(), testSuccessfulValidation()])); + const validateTest = validate( + either([testTransformingValidation(), testSuccessfulValidation()]) + ); await expect(validateTest(value)).resolves.toEqual(value + 1); }); test('either function resolves to itself if the second one is a transformation', async () => { const value = 1; - const validateTest = validate(either([testSuccessfulValidation(), testTransformingValidation()])); + const validateTest = validate( + either([testSuccessfulValidation(), testTransformingValidation()]) + ); await expect(validateTest(value)).resolves.toEqual(value); }); diff --git a/tests/validators/optional.ts b/tests/validators/optional.ts index 7a5b9ec..ec67b36 100644 --- a/tests/validators/optional.ts +++ b/tests/validators/optional.ts @@ -12,7 +12,7 @@ const conf: ValidatorConfiguration = { test('optional validator if value is undefined, returns successfully without calling the inner validator', async () => { let i = 0; - const testValidation = (): ValidatorFunction => async (value) => { + const testValidation = (): ValidatorFunction => async (value) => { i += 1; if (value) { return Success(); @@ -47,7 +47,7 @@ test('optional validator if value is undefined, returns successfully without cal }); test('optional validator without it, undefined fails', async () => { - const testValidation = (): ValidatorFunction => async (value) => { + const testValidation = (): ValidatorFunction => async (value) => { if (value) { return Success(); } diff --git a/tests/validators/validateCondition.ts b/tests/validators/validateCondition.ts index 3b5ae04..8152c39 100644 --- a/tests/validators/validateCondition.ts +++ b/tests/validators/validateCondition.ts @@ -1,4 +1,4 @@ -import { describe, expect, test } from '@jest/globals'; +import { expect, test } from '@jest/globals'; import { ValidatorConfiguration } from '../../src/types'; import validateCondition from '../../src/validators/validateCondition'; From ce29d1480dd2a5c7ec5491d411f5afa9619a243d Mon Sep 17 00:00:00 2001 From: Grant Date: Sat, 3 Dec 2022 16:43:34 +0100 Subject: [PATCH 02/16] WIP: move all calls to asynchronous --- .prettierrc.json | 8 +- src/transformers/number/ceil.ts | 4 +- src/transformers/number/clamp.ts | 4 +- src/transformers/number/floor.ts | 4 +- src/transformers/number/round.ts | 4 +- src/transformers/number/toMultipleOf.ts | 4 +- src/transformers/string/lower.ts | 4 +- src/transformers/string/normalize.ts | 4 +- src/transformers/string/trim.ts | 4 +- src/transformers/string/truncate.ts | 4 +- src/transformers/string/upper.ts | 4 +- src/types.ts | 54 +++--- src/validate.ts | 197 +++++++++++++-------- src/validators/arrayOf.ts | 72 +++++--- src/validators/bail.ts | 55 +++--- src/validators/boolean/falsey.ts | 4 +- src/validators/boolean/isBool.ts | 4 +- src/validators/boolean/toBool.ts | 4 +- src/validators/boolean/truthy.ts | 4 +- src/validators/boolean/tryBool.ts | 4 +- src/validators/date/after.ts | 4 +- src/validators/date/before.ts | 6 +- src/validators/date/inRange.ts | 6 +- src/validators/date/isDate.ts | 4 +- src/validators/date/toDate.ts | 4 +- src/validators/date/tryDate.ts | 4 +- src/validators/either.ts | 48 ++--- src/validators/equals.ts | 4 +- src/validators/number/between.ts | 4 +- src/validators/number/closeTo.ts | 4 +- src/validators/number/gt.ts | 4 +- src/validators/number/gte.ts | 4 +- src/validators/number/isInt.ts | 4 +- src/validators/number/isMultipleOf.ts | 4 +- src/validators/number/isNumber.ts | 4 +- src/validators/number/lt.ts | 4 +- src/validators/number/lte.ts | 4 +- src/validators/number/toInt.ts | 4 +- src/validators/number/toNumber.ts | 4 +- src/validators/number/tryInt.ts | 4 +- src/validators/number/tryNumber.ts | 4 +- src/validators/oneOf.ts | 4 +- src/validators/optional.ts | 12 +- src/validators/string/betweenLength.ts | 4 +- src/validators/string/insensitiveEquals.ts | 4 +- src/validators/string/isEmail.ts | 4 +- src/validators/string/isString.ts | 4 +- src/validators/string/isUrl.ts | 4 +- src/validators/string/length.ts | 4 +- src/validators/string/maxLength.ts | 4 +- src/validators/string/minLength.ts | 4 +- src/validators/string/toString.ts | 4 +- src/validators/validateCondition.ts | 4 +- src/validators/validateRegex.ts | 4 +- 54 files changed, 368 insertions(+), 270 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index 0c4bb70..ec0d09c 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -2,5 +2,11 @@ "tabWidth": 4, "singleQuote": true, "printWidth": 100, - "semi": true + "semi": true, + "overrides": [ + { + "files": ["**/types.ts", "**/validate.ts"], + "options": { "printWidth": 1000 } + } + ] } diff --git a/src/transformers/number/ceil.ts b/src/transformers/number/ceil.ts index 85232f5..0ed09df 100644 --- a/src/transformers/number/ceil.ts +++ b/src/transformers/number/ceil.ts @@ -1,6 +1,6 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const ceil = (): ValidatorFunction => (value, conf) => { +const ceil = ():SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); } diff --git a/src/transformers/number/clamp.ts b/src/transformers/number/clamp.ts index 20a1573..828ef60 100644 --- a/src/transformers/number/clamp.ts +++ b/src/transformers/number/clamp.ts @@ -1,7 +1,7 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const clamp = - (min: number, max: number): ValidatorFunction => + (min: number, max: number):SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/transformers/number/floor.ts b/src/transformers/number/floor.ts index 9245d25..4786782 100644 --- a/src/transformers/number/floor.ts +++ b/src/transformers/number/floor.ts @@ -1,6 +1,6 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const floor = (): ValidatorFunction => (value, conf) => { +const floor = ():SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); } diff --git a/src/transformers/number/round.ts b/src/transformers/number/round.ts index 3913a23..cfce95b 100644 --- a/src/transformers/number/round.ts +++ b/src/transformers/number/round.ts @@ -1,6 +1,6 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const round = (): ValidatorFunction => (value, conf) => { +const round = ():SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); } diff --git a/src/transformers/number/toMultipleOf.ts b/src/transformers/number/toMultipleOf.ts index f4404cd..259fe88 100644 --- a/src/transformers/number/toMultipleOf.ts +++ b/src/transformers/number/toMultipleOf.ts @@ -1,7 +1,7 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const toMultipleOf = - (n: number, round = Math.round): ValidatorFunction => + (n: number, round = Math.round):SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/transformers/string/lower.ts b/src/transformers/string/lower.ts index d8bf34c..c4f3dc4 100644 --- a/src/transformers/string/lower.ts +++ b/src/transformers/string/lower.ts @@ -1,6 +1,6 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const lower = (): ValidatorFunction => (value, conf) => { +const lower = ():SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/transformers/string/normalize.ts b/src/transformers/string/normalize.ts index 0edd08e..30a844d 100644 --- a/src/transformers/string/normalize.ts +++ b/src/transformers/string/normalize.ts @@ -1,7 +1,7 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const normalize = - (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'): ValidatorFunction => + (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'):SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/transformers/string/trim.ts b/src/transformers/string/trim.ts index 9c9d427..8acdb60 100644 --- a/src/transformers/string/trim.ts +++ b/src/transformers/string/trim.ts @@ -1,6 +1,6 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const trim = (): ValidatorFunction => (value, conf) => { +const trim = ():SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/transformers/string/truncate.ts b/src/transformers/string/truncate.ts index e281386..1fb5fee 100644 --- a/src/transformers/string/truncate.ts +++ b/src/transformers/string/truncate.ts @@ -1,7 +1,7 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const truncate = - (n: number): ValidatorFunction => + (n: number):SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/transformers/string/upper.ts b/src/transformers/string/upper.ts index 77d3a5e..fa5a07e 100644 --- a/src/transformers/string/upper.ts +++ b/src/transformers/string/upper.ts @@ -1,6 +1,6 @@ -import { Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const upper = (): ValidatorFunction => (value, conf) => { +const upper = ():SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/types.ts b/src/types.ts index 3b82c53..d1bacb3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,35 +9,35 @@ export interface ValidatorConfiguration { original: any; parent: any; } -export interface ValidatorFunction { - (value: I, conf: ValidatorConfiguration): Promise; -} -export type ValidatorFunctionList1 = [ValidatorFunction] -export type ValidatorFunctionList2 = [ValidatorFunction, ValidatorFunction] -export type ValidatorFunctionList3 = [ValidatorFunction, ValidatorFunction, ValidatorFunction] -export type ValidatorFunctionList = - | ValidatorFunctionList1 - | ValidatorFunctionList2 - | ValidatorFunctionList3; - -export type ValueValidator = - | ValidatorFunctionList1 - | ValidatorFunctionList2 - | ValidatorFunctionList3 - | ValidatorFunction - | ValidatorObject; +export type SyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => O | undefined | void; +export type AsyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => Promise; +export type ValidatorFunction = SyncValidatorFunction | AsyncValidatorFunction; + +export type SyncValidatorFunctionList1 = [SyncValidatorFunction]; +export type SyncValidatorFunctionList2 = [SyncValidatorFunction, SyncValidatorFunction]; +export type SyncValidatorFunctionList3 = [SyncValidatorFunction, SyncValidatorFunction, SyncValidatorFunction]; +export type SyncValidatorFunctionList = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3; + +export type ValidatorFunctionList1 = [ValidatorFunction]; +export type ValidatorFunctionList2 = [ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList3 = [ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3; + +export type SyncValueValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunction | SyncValidatorObject; + +export type SyncValidatorObject = { + [key in keyof O]: SyncValueValidator; +}; + +export type ValueValidator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatorObject; export type ValidatorObject = { [key in keyof O]: ValueValidator; }; -export type Validator = - | ValidatorFunctionList1 - | ValidatorFunctionList2 - | ValidatorFunctionList3 - | ValidatorFunction - | ValidatorObject; +export type SyncValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunction | SyncValidatorObject; +export type Validator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatorObject; export interface FailureFunction { (v: T, conf: ValidatorConfiguration): string; @@ -45,12 +45,12 @@ export interface FailureFunction { export type InferValidator = T extends Validator ? O : never; -export const Success = function (t?: T): Promise { - return Promise.resolve(t); +export const Success = function (t?: T): T | undefined { + return t; }; -export const Ignore = function (): Promise { - return Promise.resolve(undefined); +export const Ignore = function (): undefined { + return undefined; }; export const Failure = function (t: string): never { diff --git a/src/validate.ts b/src/validate.ts index ccfb1e8..e97184e 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -1,80 +1,118 @@ -import { - Validator, - ValidatorConfiguration, - ValidatorFunction, - ValidatorFunctionList, - ValidatorFunctionList1, - ValidatorFunctionList2, - ValidatorFunctionList3, - ValidatorObject, - ValidatorState, -} from './types.js'; +import { SyncValidatorFunction, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; -const resolveValidatorList = function ( - validators: ValidatorFunctionList, - value: any, - conf: ValidatorConfiguration -): Promise { - return (validators as ValidatorFunction[]) - .reduce>>((previousPromise, validator) => { - return previousPromise.then(({ value, failures }) => - validator(value, conf).then( +function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; +function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; +function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): O | Promise { + const result = (validators as ValidatorFunction[]).reduce | Promise>>( + (previousState, validator) => { + if (isPromise(previousState)) { + return previousState.then(({ value, failures }) => { + const result = validator(value, conf); + if (isPromise(result)) { + return result.then( + (newValue) => ({ + value: typeof newValue !== 'undefined' ? newValue : value, + failures, + }), + (failure) => ({ + value, + failures: failures.concat(failure), + }) + ); + } + return { + value: typeof result !== 'undefined' ? result : value, + failures: failures, + }; + }); + } + const result = validator(value, conf); + if (isPromise(result)) { + return result.then( (newValue) => ({ value: typeof newValue !== 'undefined' ? newValue : value, - failures, + failures: previousState.failures, }), (failure) => ({ value, - failures: failures.concat(failure), + failures: previousState.failures.concat(failure), }) - ) - ); - }, Promise.resolve({ value, failures: [] })) - .then(({ value, failures }) => { + ); + } + return { + value: typeof result !== 'undefined' ? result : value, + failures: previousState.failures, + }; + }, + { value, failures: [] } as ValidatorState + ); + + if (isPromise(result)) { + return result.then(({ value, failures }) => { if (failures.length > 0) { throw failures; } return value as O; }); -}; + } -const resolveValidatorObject = function ( - validator: ValidatorObject, - testValue: any, - conf: ValidatorConfiguration -): Promise { + // TODO: handles multiple failures + if (result.failures.length > 0) { + throw result.failures; + } + return result.value as O; +} + +function resolveValidatorObject(validator: SyncValidatorObject, testValue: any, conf: ValidatorConfiguration): O; +function resolveValidatorObject(validator: ValidatorObject, testValue: any, conf: ValidatorConfiguration): Promise; +function resolveValidatorObject(validator: ValidatorObject, testValue: any, conf: ValidatorConfiguration): O | Promise { const keys = Object.keys(validator) as (keyof O)[]; - return Promise.all( - keys.map>>((i: keyof O) => - validate(validator[i as keyof O], { - ...conf, - name: i as string, - path: conf.path.concat(i as string), - parent: testValue, - })(testValue[i]).then( - (value) => ({ value: [i, value], failures: [] }), - (failures) => ({ value: [i, testValue[i]], failures }) - ) - ) - ).then((results) => { - let sanitizedObject: { [key in keyof O]?: O[key] } = {}; - let validationFailures: string[] = []; + const results = keys.map((key) => { + const result = validate(validator[key as keyof O], { + ...conf, + name: key as string, + path: conf.path.concat(key as string), + parent: testValue, + })(testValue[key]); + if (isPromise(result)) { + return result.then( + (value) => + ({ + value: [key, typeof result === 'undefined' ? testValue[key] : value], + failures: [], + } as ValidatorState<[keyof O, O[keyof O]]>), + (failure) => ({ value: [key, testValue[key]], failures: [failure] } as ValidatorState<[keyof O, O[keyof O]]>) + ); + } + return { + value: [key, typeof result === 'undefined' ? testValue[key] : result], + failures: [], + } as ValidatorState<[keyof O, O[keyof O]]>; + }); - results.forEach((result) => { - if (result.failures.length > 0) { - validationFailures = validationFailures.concat(result.failures); - } else { - if (typeof result.value[1] !== 'undefined') { - sanitizedObject[result.value[0]] = result.value[1]; - } + if (!isAllNonPromise(results)) { + return Promise.all(results).then((results) => { + const failures = results.flatMap((result) => result.failures); + if (failures.length > 0) { + throw failures; } + return Object.fromEntries(results.map(({ value }) => value)) as O; }); + } - if (validationFailures.length > 0) { - throw validationFailures; - } - return sanitizedObject as O; - }); + const failures = results.flatMap((result) => result.failures); + if (failures.length > 0) { + throw failures; + } + return Object.fromEntries(results.map(({ value }) => value)) as O; +} + +export const isPromise = (value: any): value is Promise => { + return typeof value === 'object' && value !== null && typeof value.then === 'function'; +}; + +export const isAllNonPromise = (value: (T | Promise)[]): value is T[] => { + return value.some(isPromise); }; const isValidatorFunctionList = (validator: Validator): validator is ValidatorFunctionList => { @@ -89,13 +127,18 @@ const isValidatorFunction = (validator: Validator): vali return typeof validator === 'function'; }; -export function validate(v: ValidatorFunction, c?: Partial): (val: I, c?: Partial) => Promise -export function validate(v: ValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => Promise -export function validate(v: ValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => Promise -export function validate(v: ValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => Promise -export function validate(v: ValidatorObject, c?: Partial): (val: I, c?: Partial) => Promise -export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => Promise -export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => Promise { +export function validate(v: SyncValidatorFunction, c?: Partial): (val: I, c?: Partial) => O; +export function validate(v: SyncValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => O; +export function validate(v: SyncValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => O; +export function validate(v: SyncValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => O; +export function validate(v: SyncValidatorObject, c?: Partial): (val: I, c?: Partial) => O; +export function validate(v: ValidatorFunction, c?: Partial): (val: I, c?: Partial) => Promise; +export function validate(v: ValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => Promise; +export function validate(v: ValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => Promise; +export function validate(v: ValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => Promise; +export function validate(v: ValidatorObject, c?: Partial): (val: I, c?: Partial) => Promise; +export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => O | Promise; +export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => O | Promise { return function (testValue: any, testConf?: Partial): Promise { // Set defaults to configuration const conf: ValidatorConfiguration = { @@ -121,14 +164,18 @@ export function validate(validator: Validator, validateC } else if (isValidatorFunction(validator)) { // It is a function, validate with it try { - return validator(testValue, conf) - .then((newValue) => (typeof newValue !== 'undefined' ? newValue : testValue)) - .catch((failures) => { - if (Array.isArray(failures)) { - return Promise.reject(failures); - } - return Promise.reject([failures]); - }); + const result = validator(testValue, conf); + if (isPromise(result)) { + return result + .then((newValue) => (typeof newValue !== 'undefined' ? newValue : testValue)) + .catch((failures) => { + if (Array.isArray(failures)) { + return Promise.reject(failures); + } + return Promise.reject([failures]); + }); + } + return result !== 'undefined' ? result : testValue; } catch (failures) { if (Array.isArray(failures)) { return Promise.reject(failures); @@ -140,6 +187,6 @@ export function validate(validator: Validator, validateC throw new Error('Validator should be an array, object or function.'); } }; -}; +} export default validate; diff --git a/src/validators/arrayOf.ts b/src/validators/arrayOf.ts index 35c3df8..0f90956 100644 --- a/src/validators/arrayOf.ts +++ b/src/validators/arrayOf.ts @@ -1,37 +1,65 @@ -import validate from '../validate.js'; -import { Validator, ValidatorFunction, ValidatorState } from '../types.js'; +import validate, { isAllNonPromise, isPromise } from '../validate.js'; +import { + Validator, + SyncValidatorFunction, + ValidatorState, + ValidatorFunction, + SyncValidator, + ValidatorConfiguration, +} from '../types.js'; -const arrayOf = - (validator: Validator): ValidatorFunction => - (testValues, conf) => { +function arrayOf( + validator: SyncValidator +): (val: I, c: ValidatorConfiguration) => O[]; +function arrayOf( + validator: Validator +): (val: I, c: ValidatorConfiguration) => Promise; +function arrayOf( + validator: Validator +): (val: I, c: ValidatorConfiguration) => O[] | Promise { + return (testValues, conf) => { // Array of one item should use that validation to every item in the array if (typeof testValues !== 'object' || !Array.isArray(testValues)) { throw `Field ${conf.name} should be an array.`; } - return Promise.all( - testValues.map>>((testValue, i) => - validate(validator, { + const results = testValues.map | Promise>>( + (testValue, i) => { + const result = validate(validator, { ...conf, name: `${conf.name}[${i}]`, path: conf.path.concat(i.toString()), parent: testValues, - })(testValue).then( - (value) => ({ value, failures: [] }), - (failures) => ({ value: testValue, failures }) - ) - ) - ).then((results) => { - let validationFailures = results.reduce( - (previousFailures, { failures }) => previousFailures.concat(failures), - [] - ); - if (validationFailures.length > 0) { - throw validationFailures; + })(testValue); + + if (isPromise(result)) { + return result.then( + (value) => ({ value, failures: [] }), + (failures) => ({ value: testValue, failures }) + ); + } + + // TODO: handles multiple failures + return { value: result, failures: [] }; } + ); - return results.map(({ value }) => value) as O[]; - }); + if (!isAllNonPromise(results)) { + return Promise.all(results).then((results) => { + const failures = results.flatMap((result) => result.failures); + if (failures.length > 0) { + throw failures; + } + return results.map(({ value }) => value); + }); + } + + const failures = results.flatMap((result) => result.failures); + if (failures.length > 0) { + throw failures; + } + return results.map(({ value }) => value); }; +} export default arrayOf; diff --git a/src/validators/bail.ts b/src/validators/bail.ts index cc2c83f..83436e4 100644 --- a/src/validators/bail.ts +++ b/src/validators/bail.ts @@ -1,29 +1,44 @@ -import { ValidatorFunction, ValidatorFunctionList, ValidatorState } from '../types.js'; -import validate from '../validate.js'; +import { + SyncValidatorFunction, + SyncValidatorFunctionList, + ValidatorConfiguration, + ValidatorState, +} from '../types.js'; +import validate, { isPromise } from '../validate.js'; -const bail = (validators: ValidatorFunctionList): ValidatorFunction => { +const bail = ( + validators: SyncValidatorFunctionList +): ((val: I, c: ValidatorConfiguration) => O | Promise) => { if (!Array.isArray(validators)) { // If not an array is passed, simply continue validation return validate(validators); } return (value, conf) => { - return (validators as ValidatorFunction[]) - .reduce>>((previousPromise, validator) => { - return previousPromise.then(({ value, failures }) => - failures.length > 0 - ? { value, failures } // Short-circuit for any error - : validator(value, conf).then( - (newValue) => ({ - value: typeof newValue !== 'undefined' ? newValue : value, - failures, - }), - (failure) => ({ - value, - failures: failures.concat(failure), - }) - ) - ); - }, Promise.resolve({ value, failures: [] })) + return (validators as SyncValidatorFunction[]) + .reduce | Promise>>( + (previousPromise, validator) => { + return previousPromise.then(({ value, failures }) => { + if (failures.length > 0) { + return { value, failures }; // Short-circuit for any error + } + const result = validator(value, conf); + if (isPromise(result)) { + return result.then( + (newValue) => ({ + value: typeof newValue !== 'undefined' ? newValue : value, + failures, + }), + (failure) => ({ + value, + failures: failures.concat(failure), + }) + ); + } + return result; + }); + }, + { value, failures: [] } + ) .then(({ value, failures }) => { if (failures.length > 0) { throw failures; diff --git a/src/validators/boolean/falsey.ts b/src/validators/boolean/falsey.ts index a075bd0..f01c854 100644 --- a/src/validators/boolean/falsey.ts +++ b/src/validators/boolean/falsey.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const falsey = (): ValidatorFunction => +const falsey = (): SyncValidatorFunction => validateCondition( (value) => !value, (_, conf) => `Field ${conf.name} should be falsey.` diff --git a/src/validators/boolean/isBool.ts b/src/validators/boolean/isBool.ts index 233a96c..1243c6f 100644 --- a/src/validators/boolean/isBool.ts +++ b/src/validators/boolean/isBool.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isBool = (): ValidatorFunction => +const isBool = (): SyncValidatorFunction => validateCondition( (v) => v === true || v === false, (_, conf) => `Field ${conf.name} should be a boolean.` diff --git a/src/validators/boolean/toBool.ts b/src/validators/boolean/toBool.ts index a0c976a..7236527 100644 --- a/src/validators/boolean/toBool.ts +++ b/src/validators/boolean/toBool.ts @@ -1,6 +1,6 @@ -import { Success, ValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; -const toBool = (): ValidatorFunction => (value) => { +const toBool = (): SyncValidatorFunction => (value) => { return Success(!!value); }; diff --git a/src/validators/boolean/truthy.ts b/src/validators/boolean/truthy.ts index 39f6ee5..ea2e64e 100644 --- a/src/validators/boolean/truthy.ts +++ b/src/validators/boolean/truthy.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const truthy = (): ValidatorFunction => +const truthy = (): SyncValidatorFunction => validateCondition( (val) => !!val, (_, conf) => `Field ${conf.name} should be truthy.` diff --git a/src/validators/boolean/tryBool.ts b/src/validators/boolean/tryBool.ts index 38e4967..9643798 100644 --- a/src/validators/boolean/tryBool.ts +++ b/src/validators/boolean/tryBool.ts @@ -1,6 +1,6 @@ -import { Failure, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; -const tryBool: (t?: any[], f?: any[]) => ValidatorFunction = +const tryBool: (t?: any[], f?: any[]) => SyncValidatorFunction = (truthy = [true, 1], falsey = [false, 0]) => (value, conf) => { if (truthy.indexOf(value) !== -1) { diff --git a/src/validators/date/after.ts b/src/validators/date/after.ts index a97a350..9f95655 100644 --- a/src/validators/date/after.ts +++ b/src/validators/date/after.ts @@ -1,9 +1,9 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const after: ( date: string | number | Date, opts?: { inclusive: boolean } -) => ValidatorFunction = +) => SyncValidatorFunction = (date, opts = { inclusive: false }) => (value, conf) => { if (!(value instanceof Date)) { diff --git a/src/validators/date/before.ts b/src/validators/date/before.ts index 44959ba..5cdd6e2 100644 --- a/src/validators/date/before.ts +++ b/src/validators/date/before.ts @@ -1,10 +1,10 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const before: ( date: string | number | Date, opts?: { inclusive?: boolean } -) => ValidatorFunction = - (date, opts = { inclusive: false }): ValidatorFunction => +) => SyncValidatorFunction = + (date, opts = { inclusive: false }): SyncValidatorFunction => (value, conf) => { if (!(value instanceof Date)) { return Ignore(); diff --git a/src/validators/date/inRange.ts b/src/validators/date/inRange.ts index bf1bc53..d80aba9 100644 --- a/src/validators/date/inRange.ts +++ b/src/validators/date/inRange.ts @@ -1,15 +1,15 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const inRange: ( minDate: string | number | Date, maxDate: string | number | Date, opts?: { minInclusive?: boolean; maxInclusive?: boolean } -) => ValidatorFunction = +) => SyncValidatorFunction = ( minDate, maxDate, opts = { minInclusive: false, maxInclusive: false } - ): ValidatorFunction => + ): SyncValidatorFunction => (value, conf) => { if (!(value instanceof Date)) { return Ignore(); diff --git a/src/validators/date/isDate.ts b/src/validators/date/isDate.ts index b609db8..74ff74a 100644 --- a/src/validators/date/isDate.ts +++ b/src/validators/date/isDate.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isDate = (): ValidatorFunction => +const isDate = (): SyncValidatorFunction => validateCondition( (value) => value instanceof Date && !Number.isNaN(value.getTime()), (_, conf) => `Field ${conf.name} should be a valid date.` diff --git a/src/validators/date/toDate.ts b/src/validators/date/toDate.ts index 1f34afd..0e34d9f 100644 --- a/src/validators/date/toDate.ts +++ b/src/validators/date/toDate.ts @@ -1,6 +1,6 @@ -import { Success, ValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; -const toDate = (): ValidatorFunction => (value, conf) => { +const toDate = (): SyncValidatorFunction => (value, conf) => { const parsed = value instanceof Date ? value : new Date(value); return Success(parsed); }; diff --git a/src/validators/date/tryDate.ts b/src/validators/date/tryDate.ts index 23ab2bb..dce2f48 100644 --- a/src/validators/date/tryDate.ts +++ b/src/validators/date/tryDate.ts @@ -1,6 +1,6 @@ -import { Failure, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; -const tryDate = (): ValidatorFunction => (value, conf) => { +const tryDate = (): SyncValidatorFunction => (value, conf) => { const parsed = value instanceof Date ? value : new Date(value); if (!Number.isNaN(parsed.getTime())) { return Success(parsed); diff --git a/src/validators/either.ts b/src/validators/either.ts index ec11d83..9ac7f3c 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -1,27 +1,29 @@ -import { InferValidator, Success, Validator, ValidatorFunction } from '../types.js'; +import { InferValidator, Success, Validator, ValidatorConfiguration } from '../types.js'; import validate from '../validate.js'; -const either = - >(validators: V[]): ValidatorFunction> => - (value, conf) => { - return Promise.allSettled( - validators.map( - (validator) => validate(validator, conf)(value, conf) as InferValidator - ) - ).then((results) => { - const fulfilledPromise = results.find( - (result: PromiseSettledResult): result is PromiseFulfilledResult => - result.status === 'fulfilled' - ); - if (fulfilledPromise) { - return Success(fulfilledPromise.value); - } - const rejectedPromises = results.filter( - (result: PromiseSettledResult): result is PromiseRejectedResult => - result.status === 'rejected' - ); - throw rejectedPromises.flatMap((result) => result.reason); - }); - }; +function either>( + validators: V[] +): (val: unknown, c: ValidatorConfiguration) => InferValidator | Promise> { + return (value, conf) => { + return Promise.allSettled( + validators.map( + (validator) => validate(validator, conf)(value, conf) as InferValidator + ) + ).then((results) => { + const fulfilledPromise = results.find( + (result: PromiseSettledResult): result is PromiseFulfilledResult => + result.status === 'fulfilled' + ); + if (fulfilledPromise) { + return Success(fulfilledPromise.value); + } + const rejectedPromises = results.filter( + (result: PromiseSettledResult): result is PromiseRejectedResult => + result.status === 'rejected' + ); + throw rejectedPromises.flatMap((result) => result.reason); + }); + }; +} export default either; diff --git a/src/validators/equals.ts b/src/validators/equals.ts index 7a60d2f..9ffbaa3 100644 --- a/src/validators/equals.ts +++ b/src/validators/equals.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../types.js'; +import { SyncValidatorFunction } from '../types.js'; import validateCondition from './validateCondition.js'; -const equals = (to: T): ValidatorFunction => +const equals = (to: T): SyncValidatorFunction => validateCondition( (value) => value === to, (_, conf) => `Field ${conf.name} should be equal to ${to}.` diff --git a/src/validators/number/between.ts b/src/validators/number/between.ts index de5243d..d39e0da 100644 --- a/src/validators/number/between.ts +++ b/src/validators/number/between.ts @@ -1,10 +1,10 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const between: ( min: number, max: number, opts?: { minInclusive?: boolean; maxInclusive?: boolean } -) => ValidatorFunction = +) => SyncValidatorFunction = (min, max, opts = { minInclusive: false, maxInclusive: false }) => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { diff --git a/src/validators/number/closeTo.ts b/src/validators/number/closeTo.ts index 93bdcbf..0830bfd 100644 --- a/src/validators/number/closeTo.ts +++ b/src/validators/number/closeTo.ts @@ -1,6 +1,6 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const closeTo: (v: number, e?: number) => ValidatorFunction = +const closeTo: (v: number, e?: number) => SyncValidatorFunction = (exactValue, epsilon = Number.EPSILON) => (value, conf) => { if (typeof value !== 'number') { diff --git a/src/validators/number/gt.ts b/src/validators/number/gt.ts index 5075b84..69a04d5 100644 --- a/src/validators/number/gt.ts +++ b/src/validators/number/gt.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const gt = - (min: number): ValidatorFunction => + (min: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/gte.ts b/src/validators/number/gte.ts index b14232a..ef21c5c 100644 --- a/src/validators/number/gte.ts +++ b/src/validators/number/gte.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const gte = - (min: number): ValidatorFunction => + (min: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/isInt.ts b/src/validators/number/isInt.ts index 74eca3b..7759a52 100644 --- a/src/validators/number/isInt.ts +++ b/src/validators/number/isInt.ts @@ -1,7 +1,7 @@ -import { Failure, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isInt = (): ValidatorFunction => +const isInt = (): SyncValidatorFunction => validateCondition( (value) => Number.isInteger(value), (_, conf) => `Field ${conf.name} should be an integer.` diff --git a/src/validators/number/isMultipleOf.ts b/src/validators/number/isMultipleOf.ts index ec11226..c3b4ddc 100644 --- a/src/validators/number/isMultipleOf.ts +++ b/src/validators/number/isMultipleOf.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const isMultipleOf = - (n: number): ValidatorFunction => + (n: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/isNumber.ts b/src/validators/number/isNumber.ts index 91337e6..1d7f7f6 100644 --- a/src/validators/number/isNumber.ts +++ b/src/validators/number/isNumber.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isNumber = (): ValidatorFunction => +const isNumber = (): SyncValidatorFunction => validateCondition( (value) => typeof value === 'number' && !Number.isNaN(value), (_, conf) => `Field ${conf.name} should be a number.` diff --git a/src/validators/number/lt.ts b/src/validators/number/lt.ts index 218ddc6..2a79701 100644 --- a/src/validators/number/lt.ts +++ b/src/validators/number/lt.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const lt = - (max: number): ValidatorFunction => + (max: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/lte.ts b/src/validators/number/lte.ts index 0ff9665..cca03c1 100644 --- a/src/validators/number/lte.ts +++ b/src/validators/number/lte.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const lte = - (max: number): ValidatorFunction => + (max: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { return Ignore(); diff --git a/src/validators/number/toInt.ts b/src/validators/number/toInt.ts index cfa6c01..bd30752 100644 --- a/src/validators/number/toInt.ts +++ b/src/validators/number/toInt.ts @@ -1,6 +1,6 @@ -import { Success, ValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; -const toInt = (): ValidatorFunction => (value) => { +const toInt = (): SyncValidatorFunction => (value) => { return Success(Number.parseInt(value as any)); }; diff --git a/src/validators/number/toNumber.ts b/src/validators/number/toNumber.ts index 40f4b3d..4126f07 100644 --- a/src/validators/number/toNumber.ts +++ b/src/validators/number/toNumber.ts @@ -1,6 +1,6 @@ -import { Success, ValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; -const toNumber = (): ValidatorFunction => (value, conf) => { +const toNumber = (): SyncValidatorFunction => (value, conf) => { return Success(Number.parseFloat(value as any)); }; diff --git a/src/validators/number/tryInt.ts b/src/validators/number/tryInt.ts index 28b7199..f74b9b5 100644 --- a/src/validators/number/tryInt.ts +++ b/src/validators/number/tryInt.ts @@ -1,6 +1,6 @@ -import { Failure, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; -const tryInt = (): ValidatorFunction => (value, conf) => { +const tryInt = (): SyncValidatorFunction => (value, conf) => { const parsed = Number.parseInt(value as any); if (!Number.isNaN(parsed)) { return Success(parsed); diff --git a/src/validators/number/tryNumber.ts b/src/validators/number/tryNumber.ts index cffc119..b7c25cc 100644 --- a/src/validators/number/tryNumber.ts +++ b/src/validators/number/tryNumber.ts @@ -1,6 +1,6 @@ -import { Failure, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; -const tryNumber = (): ValidatorFunction => (value, conf) => { +const tryNumber = (): SyncValidatorFunction => (value, conf) => { const parsed = Number.parseFloat(value as any); if (!Number.isNaN(parsed)) { return Success(parsed); diff --git a/src/validators/oneOf.ts b/src/validators/oneOf.ts index 803f9ae..d7f7119 100644 --- a/src/validators/oneOf.ts +++ b/src/validators/oneOf.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../types.js'; +import { SyncValidatorFunction } from '../types.js'; import validateCondition from './validateCondition.js'; -const oneOf = (items: T[]): ValidatorFunction => +const oneOf = (items: T[]): SyncValidatorFunction => validateCondition( (value) => items.indexOf(value) !== -1, (_, conf) => `Field ${conf.name} should be one of ${items.join(', ')}.` diff --git a/src/validators/optional.ts b/src/validators/optional.ts index c4a540a..234f730 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -1,15 +1,15 @@ import validate from '../validate.js'; -import { ValidatorFunction, Validator, Success } from '../types.js'; +import { Validator, Success, SyncValidator, ValidatorConfiguration } from '../types.js'; -const optional = - ( - validators: Validator - ): ValidatorFunction => - (value, conf) => { +function optional( + validators: Validator +): (val: I, c: ValidatorConfiguration) => O | undefined | Promise { + return (value, conf) => { if (typeof value === 'undefined') { return Success(); } return validate(validators, conf)(value); }; +} export default optional; diff --git a/src/validators/string/betweenLength.ts b/src/validators/string/betweenLength.ts index 36c1e57..5c49453 100644 --- a/src/validators/string/betweenLength.ts +++ b/src/validators/string/betweenLength.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const betweenLength = - (min: number, max: number): ValidatorFunction => + (min: number, max: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/insensitiveEquals.ts b/src/validators/string/insensitiveEquals.ts index a6d3191..967065d 100644 --- a/src/validators/string/insensitiveEquals.ts +++ b/src/validators/string/insensitiveEquals.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const insensitiveEquals = - (to: string): ValidatorFunction => + (to: string): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/isEmail.ts b/src/validators/string/isEmail.ts index d983639..80e2348 100644 --- a/src/validators/string/isEmail.ts +++ b/src/validators/string/isEmail.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateRegex from '../validateRegex.js'; -const isEmail = (): ValidatorFunction => +const isEmail = (): SyncValidatorFunction => validateRegex( /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/, (_, { name }) => `Field ${name} should be an email.` diff --git a/src/validators/string/isString.ts b/src/validators/string/isString.ts index 50db84b..a875ef7 100644 --- a/src/validators/string/isString.ts +++ b/src/validators/string/isString.ts @@ -1,7 +1,7 @@ -import { ValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; -const isString = (): ValidatorFunction => +const isString = (): SyncValidatorFunction => validateCondition( (value) => typeof value === 'string', (_, conf) => `Field ${conf.name} should be string.` diff --git a/src/validators/string/isUrl.ts b/src/validators/string/isUrl.ts index 835d64f..eaa939b 100644 --- a/src/validators/string/isUrl.ts +++ b/src/validators/string/isUrl.ts @@ -1,6 +1,6 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const isUrl = (): ValidatorFunction => (value, conf) => { +const isUrl = (): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); } diff --git a/src/validators/string/length.ts b/src/validators/string/length.ts index 3320d98..73bccbe 100644 --- a/src/validators/string/length.ts +++ b/src/validators/string/length.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const length = - (n: number): ValidatorFunction => + (n: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/maxLength.ts b/src/validators/string/maxLength.ts index 92e3bcf..6a94eeb 100644 --- a/src/validators/string/maxLength.ts +++ b/src/validators/string/maxLength.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const maxLength = - (max: number): ValidatorFunction => + (max: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/minLength.ts b/src/validators/string/minLength.ts index 0cd7114..8d98ea4 100644 --- a/src/validators/string/minLength.ts +++ b/src/validators/string/minLength.ts @@ -1,7 +1,7 @@ -import { Failure, Ignore, Success, ValidatorFunction } from '../../types.js'; +import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const minLength = - (min: number): ValidatorFunction => + (min: number): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'string') { return Ignore(); diff --git a/src/validators/string/toString.ts b/src/validators/string/toString.ts index 52b4bb9..4e1ad76 100644 --- a/src/validators/string/toString.ts +++ b/src/validators/string/toString.ts @@ -1,6 +1,6 @@ -import { Success, ValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; -const toString = (): ValidatorFunction => (value, conf) => { +const toString = (): SyncValidatorFunction => (value, conf) => { return Success('' + value); }; diff --git a/src/validators/validateCondition.ts b/src/validators/validateCondition.ts index a81848e..33a6fe3 100644 --- a/src/validators/validateCondition.ts +++ b/src/validators/validateCondition.ts @@ -3,7 +3,7 @@ import { FailureFunction, Success, ValidatorConfiguration, - ValidatorFunction, + SyncValidatorFunction, } from '../types.js'; interface ConditionFunction { @@ -13,7 +13,7 @@ interface ConditionFunction { const validateCondition = ( condition: ConditionFunction, errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` -): ValidatorFunction => { +): SyncValidatorFunction => { return function (field, conf) { if (condition(field, conf)) { return Success(); diff --git a/src/validators/validateRegex.ts b/src/validators/validateRegex.ts index 94239a5..2fce8c9 100644 --- a/src/validators/validateRegex.ts +++ b/src/validators/validateRegex.ts @@ -1,9 +1,9 @@ -import { Failure, FailureFunction, Ignore, Success, ValidatorFunction } from '../types.js'; +import { Failure, FailureFunction, Ignore, Success, SyncValidatorFunction } from '../types.js'; const validateRegex = ( regex: RegExp, errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` -): ValidatorFunction => { +): SyncValidatorFunction => { return function (field, conf) { if (typeof field !== 'string') { return Ignore(); From d7c6cfc535298f46e99f953c5660ea1aa9fe1255 Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 4 Dec 2022 01:37:44 +0100 Subject: [PATCH 03/16] Fix builds for the rest of the functions --- src/validators/bail.ts | 69 ++++++++++++++++++++++++++++++++-------- src/validators/either.ts | 51 ++++++++++++++++++----------- 2 files changed, 89 insertions(+), 31 deletions(-) diff --git a/src/validators/bail.ts b/src/validators/bail.ts index 83436e4..e35d7ff 100644 --- a/src/validators/bail.ts +++ b/src/validators/bail.ts @@ -2,24 +2,34 @@ import { SyncValidatorFunction, SyncValidatorFunctionList, ValidatorConfiguration, + ValidatorFunction, + ValidatorFunctionList, ValidatorState, } from '../types.js'; import validate, { isPromise } from '../validate.js'; -const bail = ( +function bail( validators: SyncValidatorFunctionList -): ((val: I, c: ValidatorConfiguration) => O | Promise) => { +): (val: I, c: ValidatorConfiguration) => O; +function bail( + validators: ValidatorFunctionList +): (val: I, c: ValidatorConfiguration) => Promise; +function bail( + validators: ValidatorFunctionList +): (val: I, c: ValidatorConfiguration) => O | Promise { if (!Array.isArray(validators)) { // If not an array is passed, simply continue validation return validate(validators); } return (value, conf) => { - return (validators as SyncValidatorFunction[]) - .reduce | Promise>>( - (previousPromise, validator) => { - return previousPromise.then(({ value, failures }) => { + const result = (validators as ValidatorFunction[]).reduce< + ValidatorState | Promise> + >( + (previousState, validator) => { + if (isPromise(previousState)) { + return previousState.then(({ value, failures }) => { if (failures.length > 0) { - return { value, failures }; // Short-circuit for any error + return previousState; } const result = validator(value, conf); if (isPromise(result)) { @@ -34,17 +44,50 @@ const bail = ( }) ); } - return result; + return { + value: typeof result !== 'undefined' ? result : value, + failures: failures, + }; }); - }, - { value, failures: [] } - ) - .then(({ value, failures }) => { + } + if (previousState.failures.length > 0) { + return previousState; + } + const result = validator(value, conf); + if (isPromise(result)) { + return result.then( + (newValue) => ({ + value: typeof newValue !== 'undefined' ? newValue : value, + failures: previousState.failures, + }), + (failure) => ({ + value, + failures: previousState.failures.concat(failure), + }) + ); + } + return { + value: typeof result !== 'undefined' ? result : value, + failures: previousState.failures, + }; + }, + { value, failures: [] } as ValidatorState + ); + + if (isPromise(result)) { + return result.then(({ value, failures }) => { if (failures.length > 0) { throw failures; } return value as O; }); + } + + // TODO: handles multiple failures + if (result.failures.length > 0) { + throw result.failures; + } + return result.value as O; }; -}; +} export default bail; diff --git a/src/validators/either.ts b/src/validators/either.ts index 9ac7f3c..d0344dc 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -1,28 +1,43 @@ import { InferValidator, Success, Validator, ValidatorConfiguration } from '../types.js'; -import validate from '../validate.js'; +import validate, { isAllNonPromise } from '../validate.js'; +function either>( + validators: V[] +): (val: unknown, c: ValidatorConfiguration) => InferValidator; +function either>( + validators: V[] +): (val: unknown, c: ValidatorConfiguration) => Promise>; function either>( validators: V[] ): (val: unknown, c: ValidatorConfiguration) => InferValidator | Promise> { return (value, conf) => { - return Promise.allSettled( - validators.map( - (validator) => validate(validator, conf)(value, conf) as InferValidator - ) - ).then((results) => { - const fulfilledPromise = results.find( - (result: PromiseSettledResult): result is PromiseFulfilledResult => - result.status === 'fulfilled' - ); - if (fulfilledPromise) { - return Success(fulfilledPromise.value); + try { + const results = validators.map((validator) => { + return validate(validator, conf)(value, conf) as + | InferValidator + | Promise>; + }); + + if (!isAllNonPromise(results)) { + return Promise.allSettled(results).then((results) => { + const fulfilledPromise = results.find( + (result: PromiseSettledResult): result is PromiseFulfilledResult => + result.status === 'fulfilled' + ); + if (fulfilledPromise) { + return fulfilledPromise.value; + } + const rejectedPromises = results.filter( + (result: PromiseSettledResult): result is PromiseRejectedResult => + result.status === 'rejected' + ); + throw rejectedPromises.flatMap((result) => result.reason); + }); } - const rejectedPromises = results.filter( - (result: PromiseSettledResult): result is PromiseRejectedResult => - result.status === 'rejected' - ); - throw rejectedPromises.flatMap((result) => result.reason); - }); + return value as InferValidator; + } catch (err) { + throw err; + } }; } From 7b5e97f749a46dd6b511f638d05fe2ab44713efb Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 4 Dec 2022 02:38:50 +0100 Subject: [PATCH 04/16] Fix tests apart from some type issues --- src/validate.ts | 14 ++++---- src/validators/arrayOf.ts | 10 +++--- src/validators/either.ts | 4 +-- src/validators/optional.ts | 6 ++++ tests/transformers/number/ceil.ts | 20 +++++------ tests/transformers/number/clamp.ts | 36 ++++++++++---------- tests/transformers/number/floor.ts | 18 +++++----- tests/transformers/number/round.ts | 20 +++++------ tests/transformers/number/toMultipleOf.ts | 30 ++++++++-------- tests/transformers/string/lower.ts | 26 +++++++------- tests/transformers/string/normalize.ts | 20 +++++------ tests/transformers/string/trim.ts | 24 ++++++------- tests/transformers/string/truncate.ts | 30 ++++++++-------- tests/transformers/string/upper.ts | 28 +++++++-------- tests/validate.ts | 8 ++--- tests/validators/boolean/falsey.ts | 14 ++++---- tests/validators/boolean/isBool.ts | 4 +-- tests/validators/boolean/toBool.ts | 26 +++++++------- tests/validators/boolean/truthy.ts | 12 +++---- tests/validators/boolean/tryBool.ts | 16 ++++----- tests/validators/date/after.ts | 26 +++++++------- tests/validators/date/before.ts | 26 +++++++------- tests/validators/date/inRange.ts | 32 ++++++++--------- tests/validators/date/isDate.ts | 2 +- tests/validators/equals.ts | 12 +++---- tests/validators/number/between.ts | 24 ++++++------- tests/validators/number/closeTo.ts | 20 +++++------ tests/validators/number/gt.ts | 18 +++++----- tests/validators/number/gte.ts | 20 +++++------ tests/validators/number/isInt.ts | 8 ++--- tests/validators/number/isMultipleOf.ts | 16 ++++----- tests/validators/number/isNumber.ts | 16 ++++----- tests/validators/number/lt.ts | 16 ++++----- tests/validators/number/lte.ts | 18 +++++----- tests/validators/number/toInt.ts | 34 +++++++++--------- tests/validators/number/toNumber.ts | 36 ++++++++++---------- tests/validators/number/tryInt.ts | 22 ++++++------ tests/validators/number/tryNumber.ts | 26 +++++++------- tests/validators/oneOf.ts | 22 ++++++------ tests/validators/string/betweenLength.ts | 28 +++++++-------- tests/validators/string/insensitiveEquals.ts | 24 ++++++------- tests/validators/string/isEmail.ts | 22 ++++++------ tests/validators/string/isString.ts | 4 +-- tests/validators/string/isUrl.ts | 32 ++++++++--------- tests/validators/string/length.ts | 22 ++++++------ tests/validators/string/maxLength.ts | 22 ++++++------ tests/validators/string/minLength.ts | 22 ++++++------ tests/validators/validateCondition.ts | 2 +- tests/validators/validateRegex.ts | 4 +-- 49 files changed, 474 insertions(+), 468 deletions(-) diff --git a/src/validate.ts b/src/validate.ts index e97184e..e91caeb 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -26,7 +26,7 @@ function resolveValidatorList(validators: ValidatorFunctionList ({ @@ -81,7 +81,7 @@ function resolveValidatorObject(validator: ValidatorObject, testValue: any value: [key, typeof result === 'undefined' ? testValue[key] : value], failures: [], } as ValidatorState<[keyof O, O[keyof O]]>), - (failure) => ({ value: [key, testValue[key]], failures: [failure] } as ValidatorState<[keyof O, O[keyof O]]>) + (failure) => ({ value: [key, testValue[key]], failures: Array.isArray(failure) ? failure : [failure] } as ValidatorState<[keyof O, O[keyof O]]>) ); } return { @@ -90,7 +90,7 @@ function resolveValidatorObject(validator: ValidatorObject, testValue: any } as ValidatorState<[keyof O, O[keyof O]]>; }); - if (!isAllNonPromise(results)) { + if (!hasNoPromise(results)) { return Promise.all(results).then((results) => { const failures = results.flatMap((result) => result.failures); if (failures.length > 0) { @@ -111,8 +111,8 @@ export const isPromise = (value: any): value is Promise => { return typeof value === 'object' && value !== null && typeof value.then === 'function'; }; -export const isAllNonPromise = (value: (T | Promise)[]): value is T[] => { - return value.some(isPromise); +export const hasNoPromise = (value: (T | Promise)[]): value is T[] => { + return !value.some(isPromise); }; const isValidatorFunctionList = (validator: Validator): validator is ValidatorFunctionList => { @@ -178,9 +178,9 @@ export function validate(validator: Validator, validateC return result !== 'undefined' ? result : testValue; } catch (failures) { if (Array.isArray(failures)) { - return Promise.reject(failures); + throw failures; } - return Promise.reject([failures]); + throw [failures]; } } else { // Shouldn't go on here diff --git a/src/validators/arrayOf.ts b/src/validators/arrayOf.ts index 0f90956..c39e694 100644 --- a/src/validators/arrayOf.ts +++ b/src/validators/arrayOf.ts @@ -1,4 +1,4 @@ -import validate, { isAllNonPromise, isPromise } from '../validate.js'; +import validate, { hasNoPromise, isPromise } from '../validate.js'; import { Validator, SyncValidatorFunction, @@ -10,13 +10,13 @@ import { function arrayOf( validator: SyncValidator -): (val: I, c: ValidatorConfiguration) => O[]; +): (val: unknown, c: ValidatorConfiguration) => O[]; function arrayOf( validator: Validator -): (val: I, c: ValidatorConfiguration) => Promise; +): (val: unknown, c: ValidatorConfiguration) => Promise; function arrayOf( validator: Validator -): (val: I, c: ValidatorConfiguration) => O[] | Promise { +): (val: unknown, c: ValidatorConfiguration) => O[] | Promise { return (testValues, conf) => { // Array of one item should use that validation to every item in the array if (typeof testValues !== 'object' || !Array.isArray(testValues)) { @@ -44,7 +44,7 @@ function arrayOf( } ); - if (!isAllNonPromise(results)) { + if (!hasNoPromise(results)) { return Promise.all(results).then((results) => { const failures = results.flatMap((result) => result.failures); if (failures.length > 0) { diff --git a/src/validators/either.ts b/src/validators/either.ts index d0344dc..1e65d68 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -1,5 +1,5 @@ import { InferValidator, Success, Validator, ValidatorConfiguration } from '../types.js'; -import validate, { isAllNonPromise } from '../validate.js'; +import validate, { hasNoPromise } from '../validate.js'; function either>( validators: V[] @@ -18,7 +18,7 @@ function either>( | Promise>; }); - if (!isAllNonPromise(results)) { + if (!hasNoPromise(results)) { return Promise.allSettled(results).then((results) => { const fulfilledPromise = results.find( (result: PromiseSettledResult): result is PromiseFulfilledResult => diff --git a/src/validators/optional.ts b/src/validators/optional.ts index 234f730..a96ae80 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -1,6 +1,12 @@ import validate from '../validate.js'; import { Validator, Success, SyncValidator, ValidatorConfiguration } from '../types.js'; +function optional( + validators: SyncValidator +): (val: I, c: ValidatorConfiguration) => O | undefined; +function optional( + validators: Validator +): (val: I, c: ValidatorConfiguration) => Promise; function optional( validators: Validator ): (val: I, c: ValidatorConfiguration) => O | undefined | Promise { diff --git a/tests/transformers/number/ceil.ts b/tests/transformers/number/ceil.ts index 4d9ce70..3d7ac47 100644 --- a/tests/transformers/number/ceil.ts +++ b/tests/transformers/number/ceil.ts @@ -12,19 +12,19 @@ const conf: ValidatorConfiguration = { test('ceil validator rounds up the number to the nearest integer', async () => { const validateCeil = ceil(); - await expect(validateCeil(5, conf)).resolves.toBe(5); - await expect(validateCeil(6.1, conf)).resolves.toBe(7); - await expect(validateCeil(6.5, conf)).resolves.toBe(7); - await expect(validateCeil(6.9, conf)).resolves.toBe(7); - await expect(validateCeil(7.999999999999901, conf)).resolves.toBe(8); + await expect(validateCeil(5, conf)).toBe(5); + await expect(validateCeil(6.1, conf)).toBe(7); + await expect(validateCeil(6.5, conf)).toBe(7); + await expect(validateCeil(6.9, conf)).toBe(7); + await expect(validateCeil(7.999999999999901, conf)).toBe(8); }); test('ceil ignores non-number inputs', async () => { const validateCeil = ceil(); - expect(validateCeil('6' as any, conf)).resolves.toBe(undefined); - await expect(validateCeil(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateCeil(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateCeil(null as any, conf)).resolves.toBe(undefined); - await expect(validateCeil({} as any, conf)).resolves.toBe(undefined); + expect(validateCeil('6' as any, conf)).toBe(undefined); + await expect(validateCeil(NaN as any, conf)).toBe(undefined); + await expect(validateCeil(undefined as any, conf)).toBe(undefined); + await expect(validateCeil(null as any, conf)).toBe(undefined); + await expect(validateCeil({} as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/number/clamp.ts b/tests/transformers/number/clamp.ts index c6ecdf4..1e2d994 100644 --- a/tests/transformers/number/clamp.ts +++ b/tests/transformers/number/clamp.ts @@ -12,37 +12,37 @@ const conf: ValidatorConfiguration = { test('clamp validator returns the number if it is between the two limits', async () => { const validateClamp = clamp(5, 7); - await expect(validateClamp(5, conf)).resolves.toBe(5); - await expect(validateClamp(5.5, conf)).resolves.toBe(5.5); - await expect(validateClamp(6, conf)).resolves.toBe(6); - await expect(validateClamp(7, conf)).resolves.toBe(7); + await expect(validateClamp(5, conf)).toBe(5); + await expect(validateClamp(5.5, conf)).toBe(5.5); + await expect(validateClamp(6, conf)).toBe(6); + await expect(validateClamp(7, conf)).toBe(7); }); test('clamp validator returns the closest limit if the value is outside the limit', async () => { const validateClamp = clamp(5, 7); - await expect(validateClamp(-Infinity, conf)).resolves.toBe(5); - await expect(validateClamp(-1000, conf)).resolves.toBe(5); - await expect(validateClamp(999, conf)).resolves.toBe(7); - await expect(validateClamp(Infinity, conf)).resolves.toBe(7); + await expect(validateClamp(-Infinity, conf)).toBe(5); + await expect(validateClamp(-1000, conf)).toBe(5); + await expect(validateClamp(999, conf)).toBe(7); + await expect(validateClamp(Infinity, conf)).toBe(7); }); test('clamp validator works with decimal limits too', async () => { const validateClamp = clamp(5.1, 6.9); - await expect(validateClamp(-1000, conf)).resolves.toBe(5.1); - await expect(validateClamp(5.1, conf)).resolves.toBe(5.1); - await expect(validateClamp(6, conf)).resolves.toBe(6); - await expect(validateClamp(6.3, conf)).resolves.toBe(6.3); - await expect(validateClamp(999, conf)).resolves.toBe(6.9); + await expect(validateClamp(-1000, conf)).toBe(5.1); + await expect(validateClamp(5.1, conf)).toBe(5.1); + await expect(validateClamp(6, conf)).toBe(6); + await expect(validateClamp(6.3, conf)).toBe(6.3); + await expect(validateClamp(999, conf)).toBe(6.9); }); test('clamp ignores non-number inputs', async () => { const validateClamp = clamp(5, 7); - await expect(validateClamp('6' as any, conf)).resolves.toBe(undefined); - await expect(validateClamp(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateClamp(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateClamp(null as any, conf)).resolves.toBe(undefined); - await expect(validateClamp({} as any, conf)).resolves.toBe(undefined); + await expect(validateClamp('6' as any, conf)).toBe(undefined); + await expect(validateClamp(NaN as any, conf)).toBe(undefined); + await expect(validateClamp(undefined as any, conf)).toBe(undefined); + await expect(validateClamp(null as any, conf)).toBe(undefined); + await expect(validateClamp({} as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/number/floor.ts b/tests/transformers/number/floor.ts index a8f352d..9019a85 100644 --- a/tests/transformers/number/floor.ts +++ b/tests/transformers/number/floor.ts @@ -12,18 +12,18 @@ const conf: ValidatorConfiguration = { test('floor validator rounds down the number to the nearest integer', async () => { const validateFloor = floor(); - await expect(validateFloor(5, conf)).resolves.toBe(5); - await expect(validateFloor(6.1, conf)).resolves.toBe(6); - await expect(validateFloor(6.9, conf)).resolves.toBe(6); - await expect(validateFloor(7.00000000001, conf)).resolves.toBe(7); + await expect(validateFloor(5, conf)).toBe(5); + await expect(validateFloor(6.1, conf)).toBe(6); + await expect(validateFloor(6.9, conf)).toBe(6); + await expect(validateFloor(7.00000000001, conf)).toBe(7); }); test('floor ignores non-number inputs', async () => { const validateFloor = floor(); - expect(validateFloor('6' as any, conf)).resolves.toBe(undefined); - await expect(validateFloor(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateFloor(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateFloor(null as any, conf)).resolves.toBe(undefined); - await expect(validateFloor({} as any, conf)).resolves.toBe(undefined); + expect(validateFloor('6' as any, conf)).toBe(undefined); + await expect(validateFloor(NaN as any, conf)).toBe(undefined); + await expect(validateFloor(undefined as any, conf)).toBe(undefined); + await expect(validateFloor(null as any, conf)).toBe(undefined); + await expect(validateFloor({} as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/number/round.ts b/tests/transformers/number/round.ts index ec3fbf4..2a480c0 100644 --- a/tests/transformers/number/round.ts +++ b/tests/transformers/number/round.ts @@ -12,19 +12,19 @@ const conf: ValidatorConfiguration = { test('round validator rounds the number to the nearest integer mathematically', async () => { const validateRound = round(); - await expect(validateRound(5, conf)).resolves.toBe(5); - await expect(validateRound(6.1, conf)).resolves.toBe(6); - await expect(validateRound(6.5, conf)).resolves.toBe(7); - await expect(validateRound(6.9, conf)).resolves.toBe(7); - await expect(validateRound(7.00000000001, conf)).resolves.toBe(7); + await expect(validateRound(5, conf)).toBe(5); + await expect(validateRound(6.1, conf)).toBe(6); + await expect(validateRound(6.5, conf)).toBe(7); + await expect(validateRound(6.9, conf)).toBe(7); + await expect(validateRound(7.00000000001, conf)).toBe(7); }); test('round ignores non-number inputs', async () => { const validateRound = round(); - expect(validateRound('6' as any, conf)).resolves.toBe(undefined); - await expect(validateRound(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateRound(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateRound(null as any, conf)).resolves.toBe(undefined); - await expect(validateRound({} as any, conf)).resolves.toBe(undefined); + expect(validateRound('6' as any, conf)).toBe(undefined); + await expect(validateRound(NaN as any, conf)).toBe(undefined); + await expect(validateRound(undefined as any, conf)).toBe(undefined); + await expect(validateRound(null as any, conf)).toBe(undefined); + await expect(validateRound({} as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/number/toMultipleOf.ts b/tests/transformers/number/toMultipleOf.ts index 2455a4c..2db4d9d 100644 --- a/tests/transformers/number/toMultipleOf.ts +++ b/tests/transformers/number/toMultipleOf.ts @@ -12,29 +12,29 @@ const conf: ValidatorConfiguration = { test('toMultipleOf validator rounds to the nearest multiple of n mathematically', async () => { const validateMultipleOfFive = toMultipleOf(5); - await expect(validateMultipleOfFive(5, conf)).resolves.toBe(5); - await expect(validateMultipleOfFive(6.1, conf)).resolves.toBe(5); - await expect(validateMultipleOfFive(7.5, conf)).resolves.toBe(10); - await expect(validateMultipleOfFive(10.00000000001, conf)).resolves.toBe(10); - await expect(validateMultipleOfFive(-7.5, conf)).resolves.toBe(-5); + await expect(validateMultipleOfFive(5, conf)).toBe(5); + await expect(validateMultipleOfFive(6.1, conf)).toBe(5); + await expect(validateMultipleOfFive(7.5, conf)).toBe(10); + await expect(validateMultipleOfFive(10.00000000001, conf)).toBe(10); + await expect(validateMultipleOfFive(-7.5, conf)).toBe(-5); }); test('toMultipleOf validator rounds to the nearest multiple of n with the given function', async () => { const validateMultipleOfFive = toMultipleOf(5, Math.floor); - await expect(validateMultipleOfFive(5, conf)).resolves.toBe(5); - await expect(validateMultipleOfFive(6.1, conf)).resolves.toBe(5); - await expect(validateMultipleOfFive(7.5, conf)).resolves.toBe(5); - await expect(validateMultipleOfFive(10.00000000001, conf)).resolves.toBe(10); - await expect(validateMultipleOfFive(-7.5, conf)).resolves.toBe(-10); + await expect(validateMultipleOfFive(5, conf)).toBe(5); + await expect(validateMultipleOfFive(6.1, conf)).toBe(5); + await expect(validateMultipleOfFive(7.5, conf)).toBe(5); + await expect(validateMultipleOfFive(10.00000000001, conf)).toBe(10); + await expect(validateMultipleOfFive(-7.5, conf)).toBe(-10); }); test('toMultipleOf ignores non-number inputs', async () => { const validateMultipleOfFive = toMultipleOf(5); - await expect(validateMultipleOfFive('10' as any, conf)).resolves.toBe(undefined); - await expect(validateMultipleOfFive(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateMultipleOfFive(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateMultipleOfFive(null as any, conf)).resolves.toBe(undefined); - await expect(validateMultipleOfFive({} as any, conf)).resolves.toBe(undefined); + await expect(validateMultipleOfFive('10' as any, conf)).toBe(undefined); + await expect(validateMultipleOfFive(NaN as any, conf)).toBe(undefined); + await expect(validateMultipleOfFive(undefined as any, conf)).toBe(undefined); + await expect(validateMultipleOfFive(null as any, conf)).toBe(undefined); + await expect(validateMultipleOfFive({} as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/string/lower.ts b/tests/transformers/string/lower.ts index b7a5323..b35bd65 100644 --- a/tests/transformers/string/lower.ts +++ b/tests/transformers/string/lower.ts @@ -12,27 +12,27 @@ const conf: ValidatorConfiguration = { test('lower validator changes every letter to the lowercase equivalent', async () => { const validateLower = lower(); - await expect(validateLower('asdasd', conf)).resolves.toBe('asdasd'); - await expect(validateLower('Asdasd', conf)).resolves.toBe('asdasd'); - await expect(validateLower('aSdaSD', conf)).resolves.toBe('asdasd'); + await expect(validateLower('asdasd', conf)).toBe('asdasd'); + await expect(validateLower('Asdasd', conf)).toBe('asdasd'); + await expect(validateLower('aSdaSD', conf)).toBe('asdasd'); }); test('lower validator works with locale-strings', async () => { const validateLower = lower(); - await expect(validateLower('mÄdchEn', conf)).resolves.toBe('mädchen'); - await expect(validateLower('cSütÖrtÖk', conf)).resolves.toBe('csütörtök'); + await expect(validateLower('mÄdchEn', conf)).toBe('mädchen'); + await expect(validateLower('cSütÖrtÖk', conf)).toBe('csütörtök'); }); test('lower if passed word is not a string, ignores', async () => { const validateLower = lower(); - await expect(validateLower(8 as any, conf)).resolves.toBe(undefined); - await expect(validateLower(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateLower(true as any, conf)).resolves.toBe(undefined); - await expect(validateLower([] as any, conf)).resolves.toBe(undefined); - await expect(validateLower(Array(8).fill('a') as any, conf)).resolves.toBe(undefined); - await expect(validateLower({} as any, conf)).resolves.toBe(undefined); - await expect(validateLower(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateLower(null as any, conf)).resolves.toBe(undefined); + await expect(validateLower(8 as any, conf)).toBe(undefined); + await expect(validateLower(NaN as any, conf)).toBe(undefined); + await expect(validateLower(true as any, conf)).toBe(undefined); + await expect(validateLower([] as any, conf)).toBe(undefined); + await expect(validateLower(Array(8).fill('a') as any, conf)).toBe(undefined); + await expect(validateLower({} as any, conf)).toBe(undefined); + await expect(validateLower(undefined as any, conf)).toBe(undefined); + await expect(validateLower(null as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/string/normalize.ts b/tests/transformers/string/normalize.ts index 366cbe1..f9b73f3 100644 --- a/tests/transformers/string/normalize.ts +++ b/tests/transformers/string/normalize.ts @@ -12,24 +12,24 @@ const conf: ValidatorConfiguration = { test('normalize validator normalizes the Unicode representation of a string', async () => { const validateNormalize = normalize(); - await expect(validateNormalize('\u006E\u0303', conf)).resolves.toBe('\u00F1'); // ñ + await expect(validateNormalize('\u006E\u0303', conf)).toBe('\u00F1'); // ñ }); test('normalize validator normalizes the string with another normalization form', async () => { const validateNormalize = normalize('NFD'); - await expect(validateNormalize('\u00F1', conf)).resolves.toBe('\u006E\u0303'); // ñ + await expect(validateNormalize('\u00F1', conf)).toBe('\u006E\u0303'); // ñ }); test('normalize if passed word is not a string, ignores', async () => { const validateNormalize = normalize(); - await expect(validateNormalize(8 as any, conf)).resolves.toBe(undefined); - await expect(validateNormalize(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateNormalize(true as any, conf)).resolves.toBe(undefined); - await expect(validateNormalize([] as any, conf)).resolves.toBe(undefined); - await expect(validateNormalize(Array(8).fill('a') as any, conf)).resolves.toBe(undefined); - await expect(validateNormalize({} as any, conf)).resolves.toBe(undefined); - await expect(validateNormalize(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateNormalize(null as any, conf)).resolves.toBe(undefined); + await expect(validateNormalize(8 as any, conf)).toBe(undefined); + await expect(validateNormalize(NaN as any, conf)).toBe(undefined); + await expect(validateNormalize(true as any, conf)).toBe(undefined); + await expect(validateNormalize([] as any, conf)).toBe(undefined); + await expect(validateNormalize(Array(8).fill('a') as any, conf)).toBe(undefined); + await expect(validateNormalize({} as any, conf)).toBe(undefined); + await expect(validateNormalize(undefined as any, conf)).toBe(undefined); + await expect(validateNormalize(null as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/string/trim.ts b/tests/transformers/string/trim.ts index 9e7ad57..d19525f 100644 --- a/tests/transformers/string/trim.ts +++ b/tests/transformers/string/trim.ts @@ -12,21 +12,21 @@ const conf: ValidatorConfiguration = { test('trim validator removes whitespace from the start and end', async () => { const validateTrim = trim(); - await expect(validateTrim(' asdasd ', conf)).resolves.toBe('asdasd'); - await expect(validateTrim(' asdasd\r\n\t', conf)).resolves.toBe('asdasd'); - await expect(validateTrim(' asd asd\t', conf)).resolves.toBe('asd asd'); - await expect(validateTrim(' asd\r\nasd\t', conf)).resolves.toBe('asd\r\nasd'); + await expect(validateTrim(' asdasd ', conf)).toBe('asdasd'); + await expect(validateTrim(' asdasd\r\n\t', conf)).toBe('asdasd'); + await expect(validateTrim(' asd asd\t', conf)).toBe('asd asd'); + await expect(validateTrim(' asd\r\nasd\t', conf)).toBe('asd\r\nasd'); }); test('trim if passed word is not a string, ignores', async () => { const validateTrim = trim(); - await expect(validateTrim(8 as any, conf)).resolves.toBe(undefined); - await expect(validateTrim(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateTrim(true as any, conf)).resolves.toBe(undefined); - await expect(validateTrim([] as any, conf)).resolves.toBe(undefined); - await expect(validateTrim(Array(8).fill('a') as any, conf)).resolves.toBe(undefined); - await expect(validateTrim({} as any, conf)).resolves.toBe(undefined); - await expect(validateTrim(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateTrim(null as any, conf)).resolves.toBe(undefined); + await expect(validateTrim(8 as any, conf)).toBe(undefined); + await expect(validateTrim(NaN as any, conf)).toBe(undefined); + await expect(validateTrim(true as any, conf)).toBe(undefined); + await expect(validateTrim([] as any, conf)).toBe(undefined); + await expect(validateTrim(Array(8).fill('a') as any, conf)).toBe(undefined); + await expect(validateTrim({} as any, conf)).toBe(undefined); + await expect(validateTrim(undefined as any, conf)).toBe(undefined); + await expect(validateTrim(null as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/string/truncate.ts b/tests/transformers/string/truncate.ts index 7fca89a..18cbfa0 100644 --- a/tests/transformers/string/truncate.ts +++ b/tests/transformers/string/truncate.ts @@ -12,34 +12,34 @@ const conf: ValidatorConfiguration = { test('truncate validator cuts the string to a maximum number of characters', async () => { const validateTruncate = truncate(6); - await expect(validateTruncate('123', conf)).resolves.toBe('123'); - await expect(validateTruncate('123456', conf)).resolves.toBe('123456'); - await expect(validateTruncate('123456789', conf)).resolves.toBe('123456'); + await expect(validateTruncate('123', conf)).toBe('123'); + await expect(validateTruncate('123456', conf)).toBe('123456'); + await expect(validateTruncate('123456789', conf)).toBe('123456'); }); test('truncate validator cuts from the end of the string if n is negative', async () => { const validateTruncate = truncate(-6); - await expect(validateTruncate('123', conf)).resolves.toBe('123'); - await expect(validateTruncate('123456', conf)).resolves.toBe('123456'); - await expect(validateTruncate('123456789', conf)).resolves.toBe('456789'); + await expect(validateTruncate('123', conf)).toBe('123'); + await expect(validateTruncate('123456', conf)).toBe('123456'); + await expect(validateTruncate('123456789', conf)).toBe('456789'); }); test('truncate validator returns empty if n is zero', async () => { const validateTruncate = truncate(0); - await expect(validateTruncate('123', conf)).resolves.toBe(''); + await expect(validateTruncate('123', conf)).toBe(''); }); test('truncate if passed word is not a string, ignores', async () => { const validateTruncate = truncate(6); - await expect(validateTruncate(8 as any, conf)).resolves.toBe(undefined); - await expect(validateTruncate(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateTruncate(true as any, conf)).resolves.toBe(undefined); - await expect(validateTruncate([] as any, conf)).resolves.toBe(undefined); - await expect(validateTruncate(Array(8).fill('a') as any, conf)).resolves.toBe(undefined); - await expect(validateTruncate({} as any, conf)).resolves.toBe(undefined); - await expect(validateTruncate(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateTruncate(null as any, conf)).resolves.toBe(undefined); + await expect(validateTruncate(8 as any, conf)).toBe(undefined); + await expect(validateTruncate(NaN as any, conf)).toBe(undefined); + await expect(validateTruncate(true as any, conf)).toBe(undefined); + await expect(validateTruncate([] as any, conf)).toBe(undefined); + await expect(validateTruncate(Array(8).fill('a') as any, conf)).toBe(undefined); + await expect(validateTruncate({} as any, conf)).toBe(undefined); + await expect(validateTruncate(undefined as any, conf)).toBe(undefined); + await expect(validateTruncate(null as any, conf)).toBe(undefined); }); diff --git a/tests/transformers/string/upper.ts b/tests/transformers/string/upper.ts index 3f1aa62..31ba2f1 100644 --- a/tests/transformers/string/upper.ts +++ b/tests/transformers/string/upper.ts @@ -12,27 +12,27 @@ const conf: ValidatorConfiguration = { test('upper validator changes every letter to the uppercase equivalent', async () => { const validateUpper = upper(); - await expect(validateUpper('asdasd', conf)).resolves.toBe('ASDASD'); - await expect(validateUpper('Asdasd', conf)).resolves.toBe('ASDASD'); - await expect(validateUpper('aSdaSD', conf)).resolves.toBe('ASDASD'); - await expect(validateUpper('ASDASD', conf)).resolves.toBe('ASDASD'); + await expect(validateUpper('asdasd', conf)).toBe('ASDASD'); + await expect(validateUpper('Asdasd', conf)).toBe('ASDASD'); + await expect(validateUpper('aSdaSD', conf)).toBe('ASDASD'); + await expect(validateUpper('ASDASD', conf)).toBe('ASDASD'); }); test('upper validator works with locale-strings', async () => { const validateUpper = upper(); - await expect(validateUpper('weiß', conf)).resolves.toBe('WEISS'); - await expect(validateUpper('cSütÖrtÖk', conf)).resolves.toBe('CSÜTÖRTÖK'); + await expect(validateUpper('weiß', conf)).toBe('WEISS'); + await expect(validateUpper('cSütÖrtÖk', conf)).toBe('CSÜTÖRTÖK'); }); test('upper if passed word is not a string, ignores', async () => { const validateUpper = upper(); - await expect(validateUpper(8 as any, conf)).resolves.toBe(undefined); - await expect(validateUpper(NaN as any, conf)).resolves.toBe(undefined); - await expect(validateUpper(true as any, conf)).resolves.toBe(undefined); - await expect(validateUpper([] as any, conf)).resolves.toBe(undefined); - await expect(validateUpper(Array(8).fill('a') as any, conf)).resolves.toBe(undefined); - await expect(validateUpper({} as any, conf)).resolves.toBe(undefined); - await expect(validateUpper(undefined as any, conf)).resolves.toBe(undefined); - await expect(validateUpper(null as any, conf)).resolves.toBe(undefined); + await expect(validateUpper(8 as any, conf)).toBe(undefined); + await expect(validateUpper(NaN as any, conf)).toBe(undefined); + await expect(validateUpper(true as any, conf)).toBe(undefined); + await expect(validateUpper([] as any, conf)).toBe(undefined); + await expect(validateUpper(Array(8).fill('a') as any, conf)).toBe(undefined); + await expect(validateUpper({} as any, conf)).toBe(undefined); + await expect(validateUpper(undefined as any, conf)).toBe(undefined); + await expect(validateUpper(null as any, conf)).toBe(undefined); }); diff --git a/tests/validate.ts b/tests/validate.ts index 370daf1..2e8e72b 100644 --- a/tests/validate.ts +++ b/tests/validate.ts @@ -2,17 +2,17 @@ import { describe, expect, test } from '@jest/globals'; import validate from '../src/validate'; import { Failure, Success, ValidatorFunction } from '../src/types'; -const testSuccessfulValidation = (): ValidatorFunction => +const testSuccessfulValidation = (): ValidatorFunction => async function (_value, _conf) { return Success(); }; -const testFailingValidation = (): ValidatorFunction => +const testFailingValidation = (): ValidatorFunction => async function (_value, _conf) { return Failure('test failed'); }; -const testTransformValidation = (): ValidatorFunction => +const testTransformValidation = (): ValidatorFunction => async function (value, _conf) { return Success(value + value); }; @@ -121,7 +121,7 @@ test('validate with object works with nested objects', async () => { test('validate with object throws array of error messages', async () => { const value = { key: 'asdasd', another: 'dsadas' }; const validateTest = validate({ - key: [testFailingValidation()], + key: testFailingValidation(), another: testFailingValidation(), }); diff --git a/tests/validators/boolean/falsey.ts b/tests/validators/boolean/falsey.ts index 6438dd2..66fe49c 100644 --- a/tests/validators/boolean/falsey.ts +++ b/tests/validators/boolean/falsey.ts @@ -12,13 +12,13 @@ const conf: ValidatorConfiguration = { test('falsey with false, zero, empty string or nullish returns success', async () => { const validateFalsey = falsey(); - await expect(validateFalsey(false, conf)).resolves.toBeUndefined(); - await expect(validateFalsey(0 as any, conf)).resolves.toBeUndefined(); - await expect(validateFalsey(-0 as any, conf)).resolves.toBeUndefined(); - await expect(validateFalsey('' as any, conf)).resolves.toBeUndefined(); - await expect(validateFalsey(null as any, conf)).resolves.toBeUndefined(); - await expect(validateFalsey(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateFalsey(NaN as any, conf)).resolves.toBeUndefined(); + await expect(validateFalsey(false, conf)).toBeUndefined(); + await expect(validateFalsey(0 as any, conf)).toBeUndefined(); + await expect(validateFalsey(-0 as any, conf)).toBeUndefined(); + await expect(validateFalsey('' as any, conf)).toBeUndefined(); + await expect(validateFalsey(null as any, conf)).toBeUndefined(); + await expect(validateFalsey(undefined as any, conf)).toBeUndefined(); + await expect(validateFalsey(NaN as any, conf)).toBeUndefined(); }); test('falsey with anything other fails', async () => { diff --git a/tests/validators/boolean/isBool.ts b/tests/validators/boolean/isBool.ts index 3dab677..9d85b52 100644 --- a/tests/validators/boolean/isBool.ts +++ b/tests/validators/boolean/isBool.ts @@ -12,8 +12,8 @@ const conf: ValidatorConfiguration = { test('isBool with true or false returns success', async () => { const validateBool = isBool(); - await expect(validateBool(true, conf)).resolves.toBeUndefined(); - await expect(validateBool(false, conf)).resolves.toBeUndefined(); + await expect(validateBool(true, conf)).toBeUndefined(); + await expect(validateBool(false, conf)).toBeUndefined(); }); test('isBool with anything other fails', async () => { diff --git a/tests/validators/boolean/toBool.ts b/tests/validators/boolean/toBool.ts index 332313a..49e1fd4 100644 --- a/tests/validators/boolean/toBool.ts +++ b/tests/validators/boolean/toBool.ts @@ -12,17 +12,17 @@ const conf: ValidatorConfiguration = { test('toBool converts everything to boolean', async () => { const sanitizeBool = toBool(); - await expect(sanitizeBool(true, conf)).resolves.toBe(true); - await expect(sanitizeBool(false, conf)).resolves.toBe(false); - await expect(sanitizeBool(0 as any, conf)).resolves.toBe(false); - await expect(sanitizeBool(-0 as any, conf)).resolves.toBe(false); - await expect(sanitizeBool(1 as any, conf)).resolves.toBe(true); - await expect(sanitizeBool(123 as any, conf)).resolves.toBe(true); - await expect(sanitizeBool(NaN as any, conf)).resolves.toBe(false); - await expect(sanitizeBool('' as any, conf)).resolves.toBe(false); - await expect(sanitizeBool('asd' as any, conf)).resolves.toBe(true); - await expect(sanitizeBool({} as any, conf)).resolves.toBe(true); - await expect(sanitizeBool([] as any, conf)).resolves.toBe(true); - await expect(sanitizeBool(null as any, conf)).resolves.toBe(false); - await expect(sanitizeBool(undefined as any, conf)).resolves.toBe(false); + await expect(sanitizeBool(true, conf)).toBe(true); + await expect(sanitizeBool(false, conf)).toBe(false); + await expect(sanitizeBool(0 as any, conf)).toBe(false); + await expect(sanitizeBool(-0 as any, conf)).toBe(false); + await expect(sanitizeBool(1 as any, conf)).toBe(true); + await expect(sanitizeBool(123 as any, conf)).toBe(true); + await expect(sanitizeBool(NaN as any, conf)).toBe(false); + await expect(sanitizeBool('' as any, conf)).toBe(false); + await expect(sanitizeBool('asd' as any, conf)).toBe(true); + await expect(sanitizeBool({} as any, conf)).toBe(true); + await expect(sanitizeBool([] as any, conf)).toBe(true); + await expect(sanitizeBool(null as any, conf)).toBe(false); + await expect(sanitizeBool(undefined as any, conf)).toBe(false); }); diff --git a/tests/validators/boolean/truthy.ts b/tests/validators/boolean/truthy.ts index f9d16bf..2c0f59d 100644 --- a/tests/validators/boolean/truthy.ts +++ b/tests/validators/boolean/truthy.ts @@ -12,12 +12,12 @@ const conf: ValidatorConfiguration = { test('truthy with other values returns success', async () => { const validateTruthy = truthy(); - await expect(validateTruthy(true, conf)).resolves.toBeUndefined(); - await expect(validateTruthy(1 as any, conf)).resolves.toBeUndefined(); - await expect(validateTruthy(-1 as any, conf)).resolves.toBeUndefined(); - await expect(validateTruthy('string' as any, conf)).resolves.toBeUndefined(); - await expect(validateTruthy({} as any, conf)).resolves.toBeUndefined(); - await expect(validateTruthy([] as any, conf)).resolves.toBeUndefined(); + await expect(validateTruthy(true, conf)).toBeUndefined(); + await expect(validateTruthy(1 as any, conf)).toBeUndefined(); + await expect(validateTruthy(-1 as any, conf)).toBeUndefined(); + await expect(validateTruthy('string' as any, conf)).toBeUndefined(); + await expect(validateTruthy({} as any, conf)).toBeUndefined(); + await expect(validateTruthy([] as any, conf)).toBeUndefined(); }); test('truthy with false, zero, empty string or nullish other fails', async () => { diff --git a/tests/validators/boolean/tryBool.ts b/tests/validators/boolean/tryBool.ts index 95f9eb0..e440d80 100644 --- a/tests/validators/boolean/tryBool.ts +++ b/tests/validators/boolean/tryBool.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('tryBool with with true, false, one and zero returns the correct value', async () => { const sanitizeBool = tryBool(); - await expect(sanitizeBool(true, conf)).resolves.toBe(true); - await expect(sanitizeBool(false, conf)).resolves.toBe(false); - await expect(sanitizeBool(1 as any, conf)).resolves.toBe(true); - await expect(sanitizeBool(0 as any, conf)).resolves.toBe(false); + await expect(sanitizeBool(true, conf)).toBe(true); + await expect(sanitizeBool(false, conf)).toBe(false); + await expect(sanitizeBool(1 as any, conf)).toBe(true); + await expect(sanitizeBool(0 as any, conf)).toBe(false); }); test('tryBool with other things fails', async () => { @@ -61,8 +61,8 @@ test('tryBool with other things fails', async () => { test('tryBool can be customized to accept other truthy or falsey values', async () => { const sanitizeBool = tryBool([true, 1, 'true', 600], [true, 1, 'false', null]); - await expect(sanitizeBool('true' as any, conf)).resolves.toBe(true); - await expect(sanitizeBool('false' as any, conf)).resolves.toBe(false); - await expect(sanitizeBool(600 as any, conf)).resolves.toBe(true); - await expect(sanitizeBool(null as any, conf)).resolves.toBe(false); + await expect(sanitizeBool('true' as any, conf)).toBe(true); + await expect(sanitizeBool('false' as any, conf)).toBe(false); + await expect(sanitizeBool(600 as any, conf)).toBe(true); + await expect(sanitizeBool(null as any, conf)).toBe(false); }); diff --git a/tests/validators/date/after.ts b/tests/validators/date/after.ts index fa226df..cdd3b56 100644 --- a/tests/validators/date/after.ts +++ b/tests/validators/date/after.ts @@ -13,19 +13,19 @@ test('after when the date is after the date returns success', async () => { const begin = new Date('2000-01-01'); const validateInRange = after(begin); - await expect(validateInRange(new Date('2000-01-02'), conf)).resolves.toBeUndefined(); - await expect(validateInRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); - await expect(validateInRange(new Date('2099-01-01'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2000-01-02'), conf)).toBeUndefined(); + await expect(validateInRange(new Date('2021-08-27'), conf)).toBeUndefined(); + await expect(validateInRange(new Date('2099-01-01'), conf)).toBeUndefined(); }); test('after definition can convert from string or number', async () => { const validateInStringRange = after('2000-01-01'); - await expect(validateInStringRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); + await expect(validateInStringRange(new Date('2021-08-27'), conf)).toBeUndefined(); const validateInNumberRange = after(946684800000); - await expect(validateInNumberRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); + await expect(validateInNumberRange(new Date('2021-08-27'), conf)).toBeUndefined(); }); test('after when the date is before or equal to the date, fails', async () => { @@ -55,18 +55,18 @@ test('after, when both inclusives are set, returns success for and upper lower l const begin = new Date('2000-01-01'); const validateInRange = after(begin, { inclusive: true }); - await expect(validateInRange(new Date('2000-01-01'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2000-01-01'), conf)).toBeUndefined(); }); test('after ignores non-date inputs', async () => { const begin = new Date('2000-01-01'); const validateInRange = after(begin); - await expect(validateInRange('string' as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(123 as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange({} as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange([] as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(null as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(undefined as any, conf)).resolves.toBeUndefined(); + await expect(validateInRange('string' as any, conf)).toBeUndefined(); + await expect(validateInRange(123 as any, conf)).toBeUndefined(); + await expect(validateInRange(NaN as any, conf)).toBeUndefined(); + await expect(validateInRange({} as any, conf)).toBeUndefined(); + await expect(validateInRange([] as any, conf)).toBeUndefined(); + await expect(validateInRange(null as any, conf)).toBeUndefined(); + await expect(validateInRange(undefined as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/date/before.ts b/tests/validators/date/before.ts index f04ef0f..e884f9a 100644 --- a/tests/validators/date/before.ts +++ b/tests/validators/date/before.ts @@ -13,19 +13,19 @@ test('before when the date is before the date returns success', async () => { const end = new Date('2099-12-31'); const validateInRange = before(end); - await expect(validateInRange(new Date('2000-01-02'), conf)).resolves.toBeUndefined(); - await expect(validateInRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); - await expect(validateInRange(new Date('2099-01-01'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2000-01-02'), conf)).toBeUndefined(); + await expect(validateInRange(new Date('2021-08-27'), conf)).toBeUndefined(); + await expect(validateInRange(new Date('2099-01-01'), conf)).toBeUndefined(); }); test('before definition can convert from string or number', async () => { const validateInStringRange = before('2099-12-31'); - await expect(validateInStringRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); + await expect(validateInStringRange(new Date('2021-08-27'), conf)).toBeUndefined(); const validateInNumberRange = before(4102358400000); - await expect(validateInNumberRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); + await expect(validateInNumberRange(new Date('2021-08-27'), conf)).toBeUndefined(); }); test('before when the date is after or equal to the date, fails', async () => { @@ -55,18 +55,18 @@ test('before, when inclusive is set, returns success for limit', async () => { const end = new Date('2099-12-31'); const validateInRange = before(end, { inclusive: true }); - await expect(validateInRange(new Date('2099-12-31'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2099-12-31'), conf)).toBeUndefined(); }); test('before ignores non-date inputs', async () => { const end = new Date('2099-12-31'); const validateInRange = before(end); - await expect(validateInRange('string' as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(123 as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange({} as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange([] as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(null as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(undefined as any, conf)).resolves.toBeUndefined(); + await expect(validateInRange('string' as any, conf)).toBeUndefined(); + await expect(validateInRange(123 as any, conf)).toBeUndefined(); + await expect(validateInRange(NaN as any, conf)).toBeUndefined(); + await expect(validateInRange({} as any, conf)).toBeUndefined(); + await expect(validateInRange([] as any, conf)).toBeUndefined(); + await expect(validateInRange(null as any, conf)).toBeUndefined(); + await expect(validateInRange(undefined as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/date/inRange.ts b/tests/validators/date/inRange.ts index 6012061..79a6442 100644 --- a/tests/validators/date/inRange.ts +++ b/tests/validators/date/inRange.ts @@ -14,19 +14,19 @@ test('inRange when the date is between the two dates returns success', async () const end = new Date('2099-12-31'); const validateInRange = inRange(begin, end); - await expect(validateInRange(new Date('2000-01-02'), conf)).resolves.toBeUndefined(); - await expect(validateInRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); - await expect(validateInRange(new Date('2099-01-01'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2000-01-02'), conf)).toBeUndefined(); + await expect(validateInRange(new Date('2021-08-27'), conf)).toBeUndefined(); + await expect(validateInRange(new Date('2099-01-01'), conf)).toBeUndefined(); }); test('inRange definition can convert from string or number', async () => { const validateInStringRange = inRange('2000-01-01', '2099-12-31'); - await expect(validateInStringRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); + await expect(validateInStringRange(new Date('2021-08-27'), conf)).toBeUndefined(); const validateInNumberRange = inRange(946684800000, 4102358400000); - await expect(validateInNumberRange(new Date('2021-08-27'), conf)).resolves.toBeUndefined(); + await expect(validateInNumberRange(new Date('2021-08-27'), conf)).toBeUndefined(); }); test('inRange when the date is before, after or equal to the two dates, fails', async () => { @@ -80,7 +80,7 @@ test('inRange, when minInclusive is set, returns success for lower limit and fai const end = new Date('2099-12-31'); const validateInRange = inRange(begin, end, { minInclusive: true }); - await expect(validateInRange(new Date('2000-01-01'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2000-01-01'), conf)).toBeUndefined(); try { await validateInRange(new Date('2099-12-31'), conf); @@ -104,7 +104,7 @@ test('inRange, when maxInclusive is set, fails for lower limit and returns succe ); } - await expect(validateInRange(new Date('2099-12-31'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2099-12-31'), conf)).toBeUndefined(); }); test('inRange, when both inclusives are set, returns success for and upper lower limit', async () => { @@ -112,8 +112,8 @@ test('inRange, when both inclusives are set, returns success for and upper lower const end = new Date('2099-12-31'); const validateInRange = inRange(begin, end, { minInclusive: true, maxInclusive: true }); - await expect(validateInRange(new Date('2000-01-01'), conf)).resolves.toBeUndefined(); - await expect(validateInRange(new Date('2099-12-31'), conf)).resolves.toBeUndefined(); + await expect(validateInRange(new Date('2000-01-01'), conf)).toBeUndefined(); + await expect(validateInRange(new Date('2099-12-31'), conf)).toBeUndefined(); }); test('inRange ignores non-date inputs', async () => { @@ -121,11 +121,11 @@ test('inRange ignores non-date inputs', async () => { const end = new Date('2099-12-31'); const validateInRange = inRange(begin, end); - await expect(validateInRange('string' as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(123 as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange({} as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange([] as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(null as any, conf)).resolves.toBeUndefined(); - await expect(validateInRange(undefined as any, conf)).resolves.toBeUndefined(); + await expect(validateInRange('string' as any, conf)).toBeUndefined(); + await expect(validateInRange(123 as any, conf)).toBeUndefined(); + await expect(validateInRange(NaN as any, conf)).toBeUndefined(); + await expect(validateInRange({} as any, conf)).toBeUndefined(); + await expect(validateInRange([] as any, conf)).toBeUndefined(); + await expect(validateInRange(null as any, conf)).toBeUndefined(); + await expect(validateInRange(undefined as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/date/isDate.ts b/tests/validators/date/isDate.ts index 48f903f..ee0539f 100644 --- a/tests/validators/date/isDate.ts +++ b/tests/validators/date/isDate.ts @@ -15,7 +15,7 @@ test('isDate when date is passed returns successfully', async () => { const dateString = '2021-08-27'; const date = new Date(dateString); - await expect(sanitizeDate(date, conf)).resolves.toBeUndefined(); + await expect(sanitizeDate(date, conf)).toBeUndefined(); }); test('isDate when invalid date is passed fails', async () => { diff --git a/tests/validators/equals.ts b/tests/validators/equals.ts index 5f20ad9..670d891 100644 --- a/tests/validators/equals.ts +++ b/tests/validators/equals.ts @@ -11,23 +11,23 @@ const conf: ValidatorConfiguration = { test('equals validator if the value is equals to the param, returns successfully', async () => { const validateStringEquality = equals('asdasd'); - await expect(validateStringEquality('asdasd', conf)).resolves.toBeUndefined(); + await expect(validateStringEquality('asdasd', conf)).toBeUndefined(); const validateNumberEquality = equals(100); - await expect(validateNumberEquality(100, conf)).resolves.toBeUndefined(); + await expect(validateNumberEquality(100, conf)).toBeUndefined(); const validateBoolEquality = equals(true); - await expect(validateBoolEquality(true, conf)).resolves.toBeUndefined(); + await expect(validateBoolEquality(true, conf)).toBeUndefined(); const obj = {}; const validateObjectEquality = equals(obj); - await expect(validateObjectEquality(obj, conf)).resolves.toBeUndefined(); + await expect(validateObjectEquality(obj, conf)).toBeUndefined(); const validateNullEquality = equals(null); - await expect(validateNullEquality(null, conf)).resolves.toBeUndefined(); + await expect(validateNullEquality(null, conf)).toBeUndefined(); const validateUndefinedEquality = equals(undefined); - await expect(validateUndefinedEquality(undefined, conf)).resolves.toBeUndefined(); + await expect(validateUndefinedEquality(undefined, conf)).toBeUndefined(); }); test('equals validator if the value is not equals, fails', async () => { diff --git a/tests/validators/number/between.ts b/tests/validators/number/between.ts index cfb7314..3cf2f39 100644 --- a/tests/validators/number/between.ts +++ b/tests/validators/number/between.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('between, when the number is between the two values, return success', async () => { const validateBetween = between(1, 10); - await expect(validateBetween(2, conf)).resolves.toBeUndefined(); - await expect(validateBetween(5, conf)).resolves.toBeUndefined(); - await expect(validateBetween(8, conf)).resolves.toBeUndefined(); + await expect(validateBetween(2, conf)).toBeUndefined(); + await expect(validateBetween(5, conf)).toBeUndefined(); + await expect(validateBetween(8, conf)).toBeUndefined(); }); test('between, when the number is not between or equal the two values, throws', async () => { @@ -60,7 +60,7 @@ test('between, when the number is not between or equal the two values, throws', test('between, when min inclusive is set, returns success for min and failure for max', async () => { const validateBetween = between(1, 10, { minInclusive: true }); - await expect(validateBetween(1, conf)).resolves.toBeUndefined(); + await expect(validateBetween(1, conf)).toBeUndefined(); try { await validateBetween(10, conf); @@ -72,7 +72,7 @@ test('between, when min inclusive is set, returns success for min and failure fo test('between, when max inclusive is set, returns failure for min and success for max', async () => { const validateBetween = between(1, 10, { maxInclusive: true }); - await expect(validateBetween(10, conf)).resolves.toBeUndefined(); + await expect(validateBetween(10, conf)).toBeUndefined(); try { await validateBetween(1, conf); @@ -84,16 +84,16 @@ test('between, when max inclusive is set, returns failure for min and success fo test('between, when both inclusive is set, returns success for both limits', async () => { const validateBetween = between(1, 10, { minInclusive: true, maxInclusive: true }); - await expect(validateBetween(1, conf)).resolves.toBeUndefined(); - await expect(validateBetween(10, conf)).resolves.toBeUndefined(); + await expect(validateBetween(1, conf)).toBeUndefined(); + await expect(validateBetween(10, conf)).toBeUndefined(); }); test('between ignores non-number inputs', async () => { const validateBetween = between(1, 10); - await expect(validateBetween('6' as any, conf)).resolves.toBeUndefined(); - await expect(validateBetween(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateBetween(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateBetween(null as any, conf)).resolves.toBeUndefined(); - await expect(validateBetween({} as any, conf)).resolves.toBeUndefined(); + await expect(validateBetween('6' as any, conf)).toBeUndefined(); + await expect(validateBetween(NaN as any, conf)).toBeUndefined(); + await expect(validateBetween(undefined as any, conf)).toBeUndefined(); + await expect(validateBetween(null as any, conf)).toBeUndefined(); + await expect(validateBetween({} as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/number/closeTo.ts b/tests/validators/number/closeTo.ts index 9057f98..7c911fd 100644 --- a/tests/validators/number/closeTo.ts +++ b/tests/validators/number/closeTo.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('closeTo when the two values are closer than an epsilon, returns the exact value', async () => { const validateCloseTo = closeTo(0.3); - await expect(validateCloseTo(0.3, conf)).resolves.toBe(0.3); - await expect(validateCloseTo(0.3 + 1e-16, conf)).resolves.toBe(0.3); - await expect(validateCloseTo(0.2 + 0.1, conf)).resolves.toBe(0.3); + await expect(validateCloseTo(0.3, conf)).toBe(0.3); + await expect(validateCloseTo(0.3 + 1e-16, conf)).toBe(0.3); + await expect(validateCloseTo(0.2 + 0.1, conf)).toBe(0.3); }); test('closeTo when the two values are farther than an epsilon, fails', async () => { @@ -48,10 +48,10 @@ test('closeTo when the two values are farther than an epsilon, fails', async () test('closeTo when can configure the epsilon', async () => { const validateCloseTo = closeTo(0.3, 0.001); - await expect(validateCloseTo(0.3, conf)).resolves.toBe(0.3); - await expect(validateCloseTo(0.3 + 1e-10, conf)).resolves.toBe(0.3); - await expect(validateCloseTo(0.2 + 0.1, conf)).resolves.toBe(0.3); - await expect(validateCloseTo(0.3 - 0.0001, conf)).resolves.toBe(0.3); + await expect(validateCloseTo(0.3, conf)).toBe(0.3); + await expect(validateCloseTo(0.3 + 1e-10, conf)).toBe(0.3); + await expect(validateCloseTo(0.2 + 0.1, conf)).toBe(0.3); + await expect(validateCloseTo(0.3 - 0.0001, conf)).toBe(0.3); try { await validateCloseTo(0.4, conf); @@ -63,7 +63,7 @@ test('closeTo when can configure the epsilon', async () => { test('closeTo when the passed value is not a number, ignores', async () => { const validateCloseTo = closeTo(0.3); - await expect(validateCloseTo('string' as any, conf)).resolves.toBeUndefined(); - await expect(validateCloseTo(null as any, conf)).resolves.toBeUndefined(); - await expect(validateCloseTo({} as any, conf)).resolves.toBeUndefined(); + await expect(validateCloseTo('string' as any, conf)).toBeUndefined(); + await expect(validateCloseTo(null as any, conf)).toBeUndefined(); + await expect(validateCloseTo({} as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/number/gt.ts b/tests/validators/number/gt.ts index 80f6659..61c71c5 100644 --- a/tests/validators/number/gt.ts +++ b/tests/validators/number/gt.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('gt when the number is greater returns success', async () => { const validateGreaterThanTen = gt(10); - await expect(validateGreaterThanTen(20, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanTen(500, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanTen(1000, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanTen(Infinity, conf)).resolves.toBeUndefined(); + await expect(validateGreaterThanTen(20, conf)).toBeUndefined(); + await expect(validateGreaterThanTen(500, conf)).toBeUndefined(); + await expect(validateGreaterThanTen(1000, conf)).toBeUndefined(); + await expect(validateGreaterThanTen(Infinity, conf)).toBeUndefined(); }); test('gt when the number is lower or equal fails', async () => { @@ -46,9 +46,9 @@ test('gt when the number is lower or equal fails', async () => { test('gt ignores non-number inputs', async () => { const validateGreaterThanTen = gt(10); - await expect(validateGreaterThanTen('6' as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanTen(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanTen(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanTen(null as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanTen({} as any, conf)).resolves.toBeUndefined(); + await expect(validateGreaterThanTen('6' as any, conf)).toBeUndefined(); + await expect(validateGreaterThanTen(NaN as any, conf)).toBeUndefined(); + await expect(validateGreaterThanTen(undefined as any, conf)).toBeUndefined(); + await expect(validateGreaterThanTen(null as any, conf)).toBeUndefined(); + await expect(validateGreaterThanTen({} as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/number/gte.ts b/tests/validators/number/gte.ts index 878ffdb..7b5a900 100644 --- a/tests/validators/number/gte.ts +++ b/tests/validators/number/gte.ts @@ -12,11 +12,11 @@ const conf: ValidatorConfiguration = { test('gte when the number is greater or equal returns success', async () => { const validateGreaterThanOrEqualToTen = gte(10); - await expect(validateGreaterThanOrEqualToTen(10, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(20, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(500, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(1000, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(Infinity, conf)).resolves.toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(10, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(20, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(500, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(1000, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(Infinity, conf)).toBeUndefined(); }); test('gte when the number is lower fails', async () => { @@ -42,9 +42,9 @@ test('gte when the number is lower fails', async () => { test('gte ignores non-number inputs', async () => { const validateGreaterThanOrEqualToTen = gte(10); - await expect(validateGreaterThanOrEqualToTen('6' as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(null as any, conf)).resolves.toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen({} as any, conf)).resolves.toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen('6' as any, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(NaN as any, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(undefined as any, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(null as any, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen({} as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/number/isInt.ts b/tests/validators/number/isInt.ts index f84aac9..447c01e 100644 --- a/tests/validators/number/isInt.ts +++ b/tests/validators/number/isInt.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('isInt, when integer is passed, returns success', async () => { const validateInteger = isInt(); - await expect(validateInteger(-1, conf)).resolves.toBeUndefined(); - await expect(validateInteger(0, conf)).resolves.toBeUndefined(); - await expect(validateInteger(123, conf)).resolves.toBeUndefined(); - await expect(validateInteger(1e10, conf)).resolves.toBeUndefined(); + await expect(validateInteger(-1, conf)).toBeUndefined(); + await expect(validateInteger(0, conf)).toBeUndefined(); + await expect(validateInteger(123, conf)).toBeUndefined(); + await expect(validateInteger(1e10, conf)).toBeUndefined(); }); test('isInt, when not an integer is passed, fails', async () => { diff --git a/tests/validators/number/isMultipleOf.ts b/tests/validators/number/isMultipleOf.ts index 4e2775c..5448868 100644 --- a/tests/validators/number/isMultipleOf.ts +++ b/tests/validators/number/isMultipleOf.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('isMultipleOf when the number is multiple of the given param returns success', async () => { const validateMultipleOfFive = isMultipleOf(5); - await expect(validateMultipleOfFive(10, conf)).resolves.toBeUndefined(); - await expect(validateMultipleOfFive(0, conf)).resolves.toBeUndefined(); - await expect(validateMultipleOfFive(-5, conf)).resolves.toBeUndefined(); + await expect(validateMultipleOfFive(10, conf)).toBeUndefined(); + await expect(validateMultipleOfFive(0, conf)).toBeUndefined(); + await expect(validateMultipleOfFive(-5, conf)).toBeUndefined(); }); test('isMultipleOf when the number is not the multiple of the given param fails', async () => { @@ -45,9 +45,9 @@ test('isMultipleOf when the number is not the multiple of the given param fails' test('isMultipleOf ignores non-number inputs', async () => { const validateMultipleOfFive = isMultipleOf(5); - await expect(validateMultipleOfFive('10' as any, conf)).resolves.toBeUndefined(); - await expect(validateMultipleOfFive(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateMultipleOfFive(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateMultipleOfFive(null as any, conf)).resolves.toBeUndefined(); - await expect(validateMultipleOfFive({} as any, conf)).resolves.toBeUndefined(); + await expect(validateMultipleOfFive('10' as any, conf)).toBeUndefined(); + await expect(validateMultipleOfFive(NaN as any, conf)).toBeUndefined(); + await expect(validateMultipleOfFive(undefined as any, conf)).toBeUndefined(); + await expect(validateMultipleOfFive(null as any, conf)).toBeUndefined(); + await expect(validateMultipleOfFive({} as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/number/isNumber.ts b/tests/validators/number/isNumber.ts index dc6068d..03046b9 100644 --- a/tests/validators/number/isNumber.ts +++ b/tests/validators/number/isNumber.ts @@ -12,14 +12,14 @@ const conf: ValidatorConfiguration = { test('isNumber, when number is passed, returns success', async () => { const validateNumber = isNumber(); - await expect(validateNumber(-1, conf)).resolves.toBeUndefined(); - await expect(validateNumber(0, conf)).resolves.toBeUndefined(); - await expect(validateNumber(123, conf)).resolves.toBeUndefined(); - await expect(validateNumber(1e10, conf)).resolves.toBeUndefined(); - await expect(validateNumber(123.45, conf)).resolves.toBeUndefined(); - await expect(validateNumber(1 / 10, conf)).resolves.toBeUndefined(); - await expect(validateNumber(Infinity, conf)).resolves.toBeUndefined(); - await expect(validateNumber(-Infinity, conf)).resolves.toBeUndefined(); + await expect(validateNumber(-1, conf)).toBeUndefined(); + await expect(validateNumber(0, conf)).toBeUndefined(); + await expect(validateNumber(123, conf)).toBeUndefined(); + await expect(validateNumber(1e10, conf)).toBeUndefined(); + await expect(validateNumber(123.45, conf)).toBeUndefined(); + await expect(validateNumber(1 / 10, conf)).toBeUndefined(); + await expect(validateNumber(Infinity, conf)).toBeUndefined(); + await expect(validateNumber(-Infinity, conf)).toBeUndefined(); }); test('isNumber, when not a number is passed, fails', async () => { diff --git a/tests/validators/number/lt.ts b/tests/validators/number/lt.ts index e5d3a8f..26c88e7 100644 --- a/tests/validators/number/lt.ts +++ b/tests/validators/number/lt.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('lt when the number is lower returns success', async () => { const validateLessThanTen = lt(10); - await expect(validateLessThanTen(0, conf)).resolves.toBeUndefined(); - await expect(validateLessThanTen(-5, conf)).resolves.toBeUndefined(); - await expect(validateLessThanTen(-Infinity, conf)).resolves.toBeUndefined(); + await expect(validateLessThanTen(0, conf)).toBeUndefined(); + await expect(validateLessThanTen(-5, conf)).toBeUndefined(); + await expect(validateLessThanTen(-Infinity, conf)).toBeUndefined(); }); test('lt when the number is greater or equal fails', async () => { @@ -40,9 +40,9 @@ test('lt when the number is greater or equal fails', async () => { test('lt ignores non-number inputs', async () => { const validateLessThanTen = lt(10); - await expect(validateLessThanTen('6' as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanTen(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanTen(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanTen(null as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanTen({} as any, conf)).resolves.toBeUndefined(); + await expect(validateLessThanTen('6' as any, conf)).toBeUndefined(); + await expect(validateLessThanTen(NaN as any, conf)).toBeUndefined(); + await expect(validateLessThanTen(undefined as any, conf)).toBeUndefined(); + await expect(validateLessThanTen(null as any, conf)).toBeUndefined(); + await expect(validateLessThanTen({} as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/number/lte.ts b/tests/validators/number/lte.ts index 05c574e..66aee71 100644 --- a/tests/validators/number/lte.ts +++ b/tests/validators/number/lte.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('lte when the number is less or equal returns success', async () => { const validateLessThanOrEqualToTen = lte(10); - await expect(validateLessThanOrEqualToTen(10, conf)).resolves.toBeUndefined(); - await expect(validateLessThanOrEqualToTen(0, conf)).resolves.toBeUndefined(); - await expect(validateLessThanOrEqualToTen(-5, conf)).resolves.toBeUndefined(); - await expect(validateLessThanOrEqualToTen(-Infinity, conf)).resolves.toBeUndefined(); + await expect(validateLessThanOrEqualToTen(10, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen(0, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen(-5, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen(-Infinity, conf)).toBeUndefined(); }); test('lte when the number is lower fails', async () => { @@ -36,9 +36,9 @@ test('lte when the number is lower fails', async () => { test('lte ignores non-number inputs', async () => { const validateLessThanOrEqualToTen = lte(10); - await expect(validateLessThanOrEqualToTen('6' as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanOrEqualToTen(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanOrEqualToTen(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanOrEqualToTen(null as any, conf)).resolves.toBeUndefined(); - await expect(validateLessThanOrEqualToTen({} as any, conf)).resolves.toBeUndefined(); + await expect(validateLessThanOrEqualToTen('6' as any, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen(NaN as any, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen(undefined as any, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen(null as any, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen({} as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/number/toInt.ts b/tests/validators/number/toInt.ts index 40687d8..02d1665 100644 --- a/tests/validators/number/toInt.ts +++ b/tests/validators/number/toInt.ts @@ -12,36 +12,36 @@ const conf: ValidatorConfiguration = { test('toInt, when number is passed, returns the value', async () => { const validateInteger = toInt(); - await expect(validateInteger(-1, conf)).resolves.toBe(-1); - await expect(validateInteger(0, conf)).resolves.toBe(0); - await expect(validateInteger(123, conf)).resolves.toBe(123); - await expect(validateInteger(1e10, conf)).resolves.toBe(1e10); + await expect(validateInteger(-1, conf)).toBe(-1); + await expect(validateInteger(0, conf)).toBe(0); + await expect(validateInteger(123, conf)).toBe(123); + await expect(validateInteger(1e10, conf)).toBe(1e10); }); test('toInt, when numeric string is passed, returns the parsed value', async () => { const validateInteger = toInt(); - await expect(validateInteger('-1' as any, conf)).resolves.toBe(-1); - await expect(validateInteger('0' as any, conf)).resolves.toBe(0); - await expect(validateInteger('123' as any, conf)).resolves.toBe(123); + await expect(validateInteger('-1' as any, conf)).toBe(-1); + await expect(validateInteger('0' as any, conf)).toBe(0); + await expect(validateInteger('123' as any, conf)).toBe(123); }); test('tryInt, when decimal value is passed, returns the value floored to the integer part', async () => { const validateInteger = toInt(); - await expect(validateInteger(1.1 as any, conf)).resolves.toBe(1); - await expect(validateInteger('1.1' as any, conf)).resolves.toBe(1); - await expect(validateInteger('123.99' as any, conf)).resolves.toBe(123); + await expect(validateInteger(1.1 as any, conf)).toBe(1); + await expect(validateInteger('1.1' as any, conf)).toBe(1); + await expect(validateInteger('123.99' as any, conf)).toBe(123); }); test('toInt, when not convertible value is passed, returns NaN', async () => { const validateInteger = toInt(); - await expect(validateInteger('string' as any, conf)).resolves.toBe(NaN); - await expect(validateInteger(Infinity, conf)).resolves.toBe(NaN); - await expect(validateInteger(-Infinity, conf)).resolves.toBe(NaN); - await expect(validateInteger(NaN as any, conf)).resolves.toBe(NaN); - await expect(validateInteger([] as any, conf)).resolves.toBe(NaN); - await expect(validateInteger({} as any, conf)).resolves.toBe(NaN); - await expect(validateInteger(null as any, conf)).resolves.toBe(NaN); + await expect(validateInteger('string' as any, conf)).toBe(NaN); + await expect(validateInteger(Infinity, conf)).toBe(NaN); + await expect(validateInteger(-Infinity, conf)).toBe(NaN); + await expect(validateInteger(NaN as any, conf)).toBe(NaN); + await expect(validateInteger([] as any, conf)).toBe(NaN); + await expect(validateInteger({} as any, conf)).toBe(NaN); + await expect(validateInteger(null as any, conf)).toBe(NaN); }); diff --git a/tests/validators/number/toNumber.ts b/tests/validators/number/toNumber.ts index 08a51e5..df00af7 100644 --- a/tests/validators/number/toNumber.ts +++ b/tests/validators/number/toNumber.ts @@ -12,32 +12,32 @@ const conf: ValidatorConfiguration = { test('toNumber, when number is passed, returns the value', async () => { const validateNumber = toNumber(); - await expect(validateNumber(-1, conf)).resolves.toBe(-1); - await expect(validateNumber(0, conf)).resolves.toBe(0); - await expect(validateNumber(123, conf)).resolves.toBe(123); - await expect(validateNumber(1e10, conf)).resolves.toBe(1e10); - await expect(validateNumber(123.45, conf)).resolves.toBe(123.45); - await expect(validateNumber(1 / 10, conf)).resolves.toBe(1 / 10); - await expect(validateNumber(Infinity, conf)).resolves.toBe(Infinity); - await expect(validateNumber(-Infinity, conf)).resolves.toBe(-Infinity); + await expect(validateNumber(-1, conf)).toBe(-1); + await expect(validateNumber(0, conf)).toBe(0); + await expect(validateNumber(123, conf)).toBe(123); + await expect(validateNumber(1e10, conf)).toBe(1e10); + await expect(validateNumber(123.45, conf)).toBe(123.45); + await expect(validateNumber(1 / 10, conf)).toBe(1 / 10); + await expect(validateNumber(Infinity, conf)).toBe(Infinity); + await expect(validateNumber(-Infinity, conf)).toBe(-Infinity); }); test('toNumber, when numeric string is passed, returns the parsed value', async () => { const validateNumber = toNumber(); - await expect(validateNumber('-1' as any, conf)).resolves.toBe(-1); - await expect(validateNumber('0' as any, conf)).resolves.toBe(0); - await expect(validateNumber('123' as any, conf)).resolves.toBe(123); - await expect(validateNumber('1e10' as any, conf)).resolves.toBe(1e10); - await expect(validateNumber('123.45' as any, conf)).resolves.toBe(123.45); + await expect(validateNumber('-1' as any, conf)).toBe(-1); + await expect(validateNumber('0' as any, conf)).toBe(0); + await expect(validateNumber('123' as any, conf)).toBe(123); + await expect(validateNumber('1e10' as any, conf)).toBe(1e10); + await expect(validateNumber('123.45' as any, conf)).toBe(123.45); }); test('toNumber, when not convertible value is passed, returns NaN', async () => { const validateNumber = toNumber(); - await expect(validateNumber('string' as any, conf)).resolves.toBe(NaN); - await expect(validateNumber(NaN as any, conf)).resolves.toBe(NaN); - await expect(validateNumber([] as any, conf)).resolves.toBe(NaN); - await expect(validateNumber({} as any, conf)).resolves.toBe(NaN); - await expect(validateNumber(null as any, conf)).resolves.toBe(NaN); + await expect(validateNumber('string' as any, conf)).toBe(NaN); + await expect(validateNumber(NaN as any, conf)).toBe(NaN); + await expect(validateNumber([] as any, conf)).toBe(NaN); + await expect(validateNumber({} as any, conf)).toBe(NaN); + await expect(validateNumber(null as any, conf)).toBe(NaN); }); diff --git a/tests/validators/number/tryInt.ts b/tests/validators/number/tryInt.ts index 106eff0..905a1a0 100644 --- a/tests/validators/number/tryInt.ts +++ b/tests/validators/number/tryInt.ts @@ -12,27 +12,27 @@ const conf: ValidatorConfiguration = { test('tryInt, when integer is passed, returns the value', async () => { const validateInteger = tryInt(); - await expect(validateInteger(-1, conf)).resolves.toBe(-1); - await expect(validateInteger(0, conf)).resolves.toBe(0); - await expect(validateInteger(123, conf)).resolves.toBe(123); - await expect(validateInteger(1e10, conf)).resolves.toBe(1e10); + await expect(validateInteger(-1, conf)).toBe(-1); + await expect(validateInteger(0, conf)).toBe(0); + await expect(validateInteger(123, conf)).toBe(123); + await expect(validateInteger(1e10, conf)).toBe(1e10); }); test('tryInt, when numeric string is passed, returns the parsed value', async () => { const validateInteger = tryInt(); - await expect(validateInteger('-1' as any, conf)).resolves.toBe(-1); - await expect(validateInteger('0' as any, conf)).resolves.toBe(0); - await expect(validateInteger('123' as any, conf)).resolves.toBe(123); + await expect(validateInteger('-1' as any, conf)).toBe(-1); + await expect(validateInteger('0' as any, conf)).toBe(0); + await expect(validateInteger('123' as any, conf)).toBe(123); }); test('tryInt, when decimal value is passed, returns the value floored to the integer part', async () => { const validateInteger = tryInt(); - await expect(validateInteger(1.1 as any, conf)).resolves.toBe(1); - await expect(validateInteger('1.1' as any, conf)).resolves.toBe(1); - await expect(validateInteger('123.99' as any, conf)).resolves.toBe(123); - await expect(validateInteger('-123.99' as any, conf)).resolves.toBe(-123); + await expect(validateInteger(1.1 as any, conf)).toBe(1); + await expect(validateInteger('1.1' as any, conf)).toBe(1); + await expect(validateInteger('123.99' as any, conf)).toBe(123); + await expect(validateInteger('-123.99' as any, conf)).toBe(-123); }); test('tryInt, when not an integer is passed, fails', async () => { diff --git a/tests/validators/number/tryNumber.ts b/tests/validators/number/tryNumber.ts index d6d0e0b..e9a073e 100644 --- a/tests/validators/number/tryNumber.ts +++ b/tests/validators/number/tryNumber.ts @@ -12,24 +12,24 @@ const conf: ValidatorConfiguration = { test('tryNumber, when number is passed, returns the value', async () => { const validateNumber = tryNumber(); - await expect(validateNumber(-1, conf)).resolves.toBe(-1); - await expect(validateNumber(0, conf)).resolves.toBe(0); - await expect(validateNumber(123, conf)).resolves.toBe(123); - await expect(validateNumber(1e10, conf)).resolves.toBe(1e10); - await expect(validateNumber(123.45, conf)).resolves.toBe(123.45); - await expect(validateNumber(1 / 10, conf)).resolves.toBe(1 / 10); - await expect(validateNumber(Infinity, conf)).resolves.toBe(Infinity); - await expect(validateNumber(-Infinity, conf)).resolves.toBe(-Infinity); + await expect(validateNumber(-1, conf)).toBe(-1); + await expect(validateNumber(0, conf)).toBe(0); + await expect(validateNumber(123, conf)).toBe(123); + await expect(validateNumber(1e10, conf)).toBe(1e10); + await expect(validateNumber(123.45, conf)).toBe(123.45); + await expect(validateNumber(1 / 10, conf)).toBe(1 / 10); + await expect(validateNumber(Infinity, conf)).toBe(Infinity); + await expect(validateNumber(-Infinity, conf)).toBe(-Infinity); }); test('tryNumber, when numeric string is passed, returns the parsed value', async () => { const validateNumber = tryNumber(); - await expect(validateNumber('-1' as any, conf)).resolves.toBe(-1); - await expect(validateNumber('0' as any, conf)).resolves.toBe(0); - await expect(validateNumber('123' as any, conf)).resolves.toBe(123); - await expect(validateNumber('1e10' as any, conf)).resolves.toBe(1e10); - await expect(validateNumber('123.45' as any, conf)).resolves.toBe(123.45); + await expect(validateNumber('-1' as any, conf)).toBe(-1); + await expect(validateNumber('0' as any, conf)).toBe(0); + await expect(validateNumber('123' as any, conf)).toBe(123); + await expect(validateNumber('1e10' as any, conf)).toBe(1e10); + await expect(validateNumber('123.45' as any, conf)).toBe(123.45); }); test('tryNumber, when not a number is passed, fails', async () => { diff --git a/tests/validators/oneOf.ts b/tests/validators/oneOf.ts index a8a3338..eff837e 100644 --- a/tests/validators/oneOf.ts +++ b/tests/validators/oneOf.ts @@ -11,26 +11,26 @@ const conf: ValidatorConfiguration = { test('oneOf validator if the value is one of the list, returns successfully', async () => { const validateStringEquality = oneOf(['one', 'two', 'three']); - await expect(validateStringEquality('one', conf)).resolves.toBeUndefined(); - await expect(validateStringEquality('two', conf)).resolves.toBeUndefined(); - await expect(validateStringEquality('three', conf)).resolves.toBeUndefined(); + await expect(validateStringEquality('one', conf)).toBeUndefined(); + await expect(validateStringEquality('two', conf)).toBeUndefined(); + await expect(validateStringEquality('three', conf)).toBeUndefined(); const validateNumberEquality = oneOf([100, 101, 102]); - await expect(validateNumberEquality(100, conf)).resolves.toBeUndefined(); - await expect(validateNumberEquality(101, conf)).resolves.toBeUndefined(); - await expect(validateNumberEquality(102, conf)).resolves.toBeUndefined(); + await expect(validateNumberEquality(100, conf)).toBeUndefined(); + await expect(validateNumberEquality(101, conf)).toBeUndefined(); + await expect(validateNumberEquality(102, conf)).toBeUndefined(); const validateBoolEquality = oneOf([true, false]); - await expect(validateBoolEquality(true, conf)).resolves.toBeUndefined(); - await expect(validateBoolEquality(false, conf)).resolves.toBeUndefined(); + await expect(validateBoolEquality(true, conf)).toBeUndefined(); + await expect(validateBoolEquality(false, conf)).toBeUndefined(); const obj = {}; const validateObjectEquality = oneOf([obj]); - await expect(validateObjectEquality(obj, conf)).resolves.toBeUndefined(); + await expect(validateObjectEquality(obj, conf)).toBeUndefined(); const validateNullEquality = oneOf([null, undefined]); - await expect(validateNullEquality(null, conf)).resolves.toBeUndefined(); - await expect(validateNullEquality(undefined, conf)).resolves.toBeUndefined(); + await expect(validateNullEquality(null, conf)).toBeUndefined(); + await expect(validateNullEquality(undefined, conf)).toBeUndefined(); }); test('oneOf validator if the value is not in the list, fails', async () => { diff --git a/tests/validators/string/betweenLength.ts b/tests/validators/string/betweenLength.ts index 0398149..4c5ada3 100644 --- a/tests/validators/string/betweenLength.ts +++ b/tests/validators/string/betweenLength.ts @@ -12,17 +12,17 @@ const conf: ValidatorConfiguration = { test('betweenLength if passed words length is between its limits, returns success', async () => { const validateLength = betweenLength(5, 10); - await expect(validateLength('smart', conf)).resolves.toBeUndefined(); - await expect(validateLength('serious', conf)).resolves.toBeUndefined(); - await expect(validateLength('attractive', conf)).resolves.toBeUndefined(); + await expect(validateLength('smart', conf)).toBeUndefined(); + await expect(validateLength('serious', conf)).toBeUndefined(); + await expect(validateLength('attractive', conf)).toBeUndefined(); }); test('betweenLength still works if the parameters are switched up', async () => { const validateLength = betweenLength(10, 5); - await expect(validateLength('smart', conf)).resolves.toBeUndefined(); - await expect(validateLength('serious', conf)).resolves.toBeUndefined(); - await expect(validateLength('attractive', conf)).resolves.toBeUndefined(); + await expect(validateLength('smart', conf)).toBeUndefined(); + await expect(validateLength('serious', conf)).toBeUndefined(); + await expect(validateLength('attractive', conf)).toBeUndefined(); }); test('betweenLength if passed word is shorter or longer, fails', async () => { @@ -44,12 +44,12 @@ test('betweenLength if passed word is shorter or longer, fails', async () => { test('betweenLength if passed word is not a string, ignores', async () => { const validateLength = betweenLength(5, 10); - await expect(validateLength(8 as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(true as any, conf)).resolves.toBeUndefined(); - await expect(validateLength([] as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).resolves.toBeUndefined(); - await expect(validateLength({} as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(null as any, conf)).resolves.toBeUndefined(); + await expect(validateLength(8 as any, conf)).toBeUndefined(); + await expect(validateLength(NaN as any, conf)).toBeUndefined(); + await expect(validateLength(true as any, conf)).toBeUndefined(); + await expect(validateLength([] as any, conf)).toBeUndefined(); + await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); + await expect(validateLength({} as any, conf)).toBeUndefined(); + await expect(validateLength(undefined as any, conf)).toBeUndefined(); + await expect(validateLength(null as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/string/insensitiveEquals.ts b/tests/validators/string/insensitiveEquals.ts index 8cf8c3a..0c5b446 100644 --- a/tests/validators/string/insensitiveEquals.ts +++ b/tests/validators/string/insensitiveEquals.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('insensitiveEquals, if the two strings are the same, returns successfully', async () => { const validateInsensitiveEquals = insensitiveEquals('AsdasD'); - await expect(validateInsensitiveEquals('asdasd', conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals('AsdasD', conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals('ASDASD', conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals('AsDaSd', conf)).resolves.toBeUndefined(); + await expect(validateInsensitiveEquals('asdasd', conf)).toBeUndefined(); + await expect(validateInsensitiveEquals('AsdasD', conf)).toBeUndefined(); + await expect(validateInsensitiveEquals('ASDASD', conf)).toBeUndefined(); + await expect(validateInsensitiveEquals('AsDaSd', conf)).toBeUndefined(); }); test('insensitiveEquals, if the two string are the same, fails', async () => { @@ -43,14 +43,14 @@ test('insensitiveEquals, if the two string are the same, fails', async () => { test('insensitiveEquals, if not a string is given, ignores', async () => { const validateInsensitiveEquals = insensitiveEquals('AsdasD'); - await expect(validateInsensitiveEquals(6 as any, conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals(true as any, conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals([] as any, conf)).resolves.toBeUndefined(); + await expect(validateInsensitiveEquals(6 as any, conf)).toBeUndefined(); + await expect(validateInsensitiveEquals(NaN as any, conf)).toBeUndefined(); + await expect(validateInsensitiveEquals(true as any, conf)).toBeUndefined(); + await expect(validateInsensitiveEquals([] as any, conf)).toBeUndefined(); await expect( validateInsensitiveEquals(['A', 's', 'd', 'a', 's', 'D'] as any, conf) - ).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals({} as any, conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateInsensitiveEquals(null as any, conf)).resolves.toBeUndefined(); + ).toBeUndefined(); + await expect(validateInsensitiveEquals({} as any, conf)).toBeUndefined(); + await expect(validateInsensitiveEquals(undefined as any, conf)).toBeUndefined(); + await expect(validateInsensitiveEquals(null as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/string/isEmail.ts b/tests/validators/string/isEmail.ts index e4069b0..a6cfede 100644 --- a/tests/validators/string/isEmail.ts +++ b/tests/validators/string/isEmail.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('isEmail, if valid email is given, returns successfully', async () => { const validateEmail = isEmail(); - await expect(validateEmail('support@gmail.com', conf)).resolves.toBeUndefined(); - await expect(validateEmail('cat@dog.ninja', conf)).resolves.toBeUndefined(); - await expect(validateEmail('asd@asd.asd', conf)).resolves.toBeUndefined(); + await expect(validateEmail('support@gmail.com', conf)).toBeUndefined(); + await expect(validateEmail('cat@dog.ninja', conf)).toBeUndefined(); + await expect(validateEmail('asd@asd.asd', conf)).toBeUndefined(); }); test('isEmail, if invalid email is given, fails', async () => { @@ -60,14 +60,14 @@ test('isEmail, if invalid email is given, fails', async () => { test('isEmail, if not a string is given, ignores', async () => { const validateEmail = isEmail(); - await expect(validateEmail(8 as any, conf)).resolves.toBeUndefined(); - await expect(validateEmail(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateEmail(true as any, conf)).resolves.toBeUndefined(); - await expect(validateEmail([] as any, conf)).resolves.toBeUndefined(); + await expect(validateEmail(8 as any, conf)).toBeUndefined(); + await expect(validateEmail(NaN as any, conf)).toBeUndefined(); + await expect(validateEmail(true as any, conf)).toBeUndefined(); + await expect(validateEmail([] as any, conf)).toBeUndefined(); await expect( validateEmail(['a', 's', 'd', '@', 'a', 's', 'd', '.', 'a', 's', 'd'] as any, conf) - ).resolves.toBeUndefined(); - await expect(validateEmail({} as any, conf)).resolves.toBeUndefined(); - await expect(validateEmail(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateEmail(null as any, conf)).resolves.toBeUndefined(); + ).toBeUndefined(); + await expect(validateEmail({} as any, conf)).toBeUndefined(); + await expect(validateEmail(undefined as any, conf)).toBeUndefined(); + await expect(validateEmail(null as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/string/isString.ts b/tests/validators/string/isString.ts index b5b5244..0826f1e 100644 --- a/tests/validators/string/isString.ts +++ b/tests/validators/string/isString.ts @@ -12,8 +12,8 @@ const conf: ValidatorConfiguration = { test('isString, when passed value is string returns success', async () => { const sanitizeString = isString(); - await expect(sanitizeString('string', conf)).resolves.toBeUndefined(); - await expect(sanitizeString('0', conf)).resolves.toBeUndefined(); + await expect(sanitizeString('string', conf)).toBeUndefined(); + await expect(sanitizeString('0', conf)).toBeUndefined(); }); test('isString, when passed value is not string, fails', async () => { diff --git a/tests/validators/string/isUrl.ts b/tests/validators/string/isUrl.ts index ae5371e..46e857e 100644 --- a/tests/validators/string/isUrl.ts +++ b/tests/validators/string/isUrl.ts @@ -12,16 +12,16 @@ const conf: ValidatorConfiguration = { test('isUrl, if valid url is given, returns successfully', async () => { const validateUrl = isUrl(); - await expect(validateUrl('https://google.com', conf)).resolves.toBeUndefined(); - await expect(validateUrl('https://google.com/', conf)).resolves.toBeUndefined(); - await expect(validateUrl('https://google.com:8443', conf)).resolves.toBeUndefined(); - await expect(validateUrl('https://google.com/search?q=name', conf)).resolves.toBeUndefined(); - await expect(validateUrl('https://google.com/#asdasd', conf)).resolves.toBeUndefined(); - await expect(validateUrl('mailto:asd@asd.asd', conf)).resolves.toBeUndefined(); - await expect(validateUrl('file:///etc/passwd', conf)).resolves.toBeUndefined(); + await expect(validateUrl('https://google.com', conf)).toBeUndefined(); + await expect(validateUrl('https://google.com/', conf)).toBeUndefined(); + await expect(validateUrl('https://google.com:8443', conf)).toBeUndefined(); + await expect(validateUrl('https://google.com/search?q=name', conf)).toBeUndefined(); + await expect(validateUrl('https://google.com/#asdasd', conf)).toBeUndefined(); + await expect(validateUrl('mailto:asd@asd.asd', conf)).toBeUndefined(); + await expect(validateUrl('file:///etc/passwd', conf)).toBeUndefined(); await expect( validateUrl('ftp://user:password@ftphost.com/directory', conf) - ).resolves.toBeUndefined(); + ).toBeUndefined(); }); test('isUrl, if invalid url is given, fails', async () => { @@ -49,14 +49,14 @@ test('isUrl, if invalid url is given, fails', async () => { test('isUrl, if not a string is given, ignores', async () => { const validateUrl = isUrl(); - await expect(validateUrl(8 as any, conf)).resolves.toBeUndefined(); - await expect(validateUrl(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateUrl(true as any, conf)).resolves.toBeUndefined(); - await expect(validateUrl([] as any, conf)).resolves.toBeUndefined(); + await expect(validateUrl(8 as any, conf)).toBeUndefined(); + await expect(validateUrl(NaN as any, conf)).toBeUndefined(); + await expect(validateUrl(true as any, conf)).toBeUndefined(); + await expect(validateUrl([] as any, conf)).toBeUndefined(); await expect( validateUrl(['a', 's', 'd', '@', 'a', 's', 'd', '.', 'a', 's', 'd'] as any, conf) - ).resolves.toBeUndefined(); - await expect(validateUrl({} as any, conf)).resolves.toBeUndefined(); - await expect(validateUrl(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateUrl(null as any, conf)).resolves.toBeUndefined(); + ).toBeUndefined(); + await expect(validateUrl({} as any, conf)).toBeUndefined(); + await expect(validateUrl(undefined as any, conf)).toBeUndefined(); + await expect(validateUrl(null as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/string/length.ts b/tests/validators/string/length.ts index 2833ca6..ccaf6e0 100644 --- a/tests/validators/string/length.ts +++ b/tests/validators/string/length.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('length if passed words length is the same, returns success', async () => { const validateLength = length(5); - await expect(validateLength('smart', conf)).resolves.toBeUndefined(); - await expect(validateLength('young', conf)).resolves.toBeUndefined(); - await expect(validateLength('brave', conf)).resolves.toBeUndefined(); + await expect(validateLength('smart', conf)).toBeUndefined(); + await expect(validateLength('young', conf)).toBeUndefined(); + await expect(validateLength('brave', conf)).toBeUndefined(); }); test('length if passed word is shorter or longer, fails', async () => { @@ -36,12 +36,12 @@ test('length if passed word is shorter or longer, fails', async () => { test('length if passed word is not a string, ignores', async () => { const validateLength = length(5); - await expect(validateLength(8 as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(true as any, conf)).resolves.toBeUndefined(); - await expect(validateLength([] as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).resolves.toBeUndefined(); - await expect(validateLength({} as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(null as any, conf)).resolves.toBeUndefined(); + await expect(validateLength(8 as any, conf)).toBeUndefined(); + await expect(validateLength(NaN as any, conf)).toBeUndefined(); + await expect(validateLength(true as any, conf)).toBeUndefined(); + await expect(validateLength([] as any, conf)).toBeUndefined(); + await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); + await expect(validateLength({} as any, conf)).toBeUndefined(); + await expect(validateLength(undefined as any, conf)).toBeUndefined(); + await expect(validateLength(null as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/string/maxLength.ts b/tests/validators/string/maxLength.ts index 4139e6b..cbef733 100644 --- a/tests/validators/string/maxLength.ts +++ b/tests/validators/string/maxLength.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('maxLength if passed words length is between its limits, returns success', async () => { const validateLength = maxLength(10); - await expect(validateLength('smart', conf)).resolves.toBeUndefined(); - await expect(validateLength('serious', conf)).resolves.toBeUndefined(); - await expect(validateLength('attractive', conf)).resolves.toBeUndefined(); + await expect(validateLength('smart', conf)).toBeUndefined(); + await expect(validateLength('serious', conf)).toBeUndefined(); + await expect(validateLength('attractive', conf)).toBeUndefined(); }); test('maxLength if passed word is longer, fails', async () => { @@ -36,12 +36,12 @@ test('maxLength if passed word is longer, fails', async () => { test('maxLength if passed word is not a string, ignores', async () => { const validateLength = maxLength(10); - await expect(validateLength(8 as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(true as any, conf)).resolves.toBeUndefined(); - await expect(validateLength([] as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).resolves.toBeUndefined(); - await expect(validateLength({} as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(null as any, conf)).resolves.toBeUndefined(); + await expect(validateLength(8 as any, conf)).toBeUndefined(); + await expect(validateLength(NaN as any, conf)).toBeUndefined(); + await expect(validateLength(true as any, conf)).toBeUndefined(); + await expect(validateLength([] as any, conf)).toBeUndefined(); + await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); + await expect(validateLength({} as any, conf)).toBeUndefined(); + await expect(validateLength(undefined as any, conf)).toBeUndefined(); + await expect(validateLength(null as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/string/minLength.ts b/tests/validators/string/minLength.ts index dca6e6b..e3d63af 100644 --- a/tests/validators/string/minLength.ts +++ b/tests/validators/string/minLength.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('minLength if passed words length is as at least long as the limit, returns success', async () => { const validateLength = minLength(5); - await expect(validateLength('smart', conf)).resolves.toBeUndefined(); - await expect(validateLength('serious', conf)).resolves.toBeUndefined(); - await expect(validateLength('attractive', conf)).resolves.toBeUndefined(); + await expect(validateLength('smart', conf)).toBeUndefined(); + await expect(validateLength('serious', conf)).toBeUndefined(); + await expect(validateLength('attractive', conf)).toBeUndefined(); }); test('minLength if passed word is shorter, fails', async () => { @@ -36,12 +36,12 @@ test('minLength if passed word is shorter, fails', async () => { test('minLength if passed word is not a string, ignores', async () => { const validateLength = minLength(5); - await expect(validateLength(8 as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(NaN as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(true as any, conf)).resolves.toBeUndefined(); - await expect(validateLength([] as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).resolves.toBeUndefined(); - await expect(validateLength({} as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(undefined as any, conf)).resolves.toBeUndefined(); - await expect(validateLength(null as any, conf)).resolves.toBeUndefined(); + await expect(validateLength(8 as any, conf)).toBeUndefined(); + await expect(validateLength(NaN as any, conf)).toBeUndefined(); + await expect(validateLength(true as any, conf)).toBeUndefined(); + await expect(validateLength([] as any, conf)).toBeUndefined(); + await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); + await expect(validateLength({} as any, conf)).toBeUndefined(); + await expect(validateLength(undefined as any, conf)).toBeUndefined(); + await expect(validateLength(null as any, conf)).toBeUndefined(); }); diff --git a/tests/validators/validateCondition.ts b/tests/validators/validateCondition.ts index 8152c39..caffeb0 100644 --- a/tests/validators/validateCondition.ts +++ b/tests/validators/validateCondition.ts @@ -6,7 +6,7 @@ const conf: ValidatorConfiguration = { name: 'object', original: {}, parent: {}, test('validateCondition function returns undefined if regex applies', async () => { const validateTest = validateCondition(() => true); - await expect(validateTest('', conf)).resolves.toBeUndefined(); + await expect(validateTest('', conf)).toBeUndefined(); }); test('validateCondition function throws error if regex fails', async () => { diff --git a/tests/validators/validateRegex.ts b/tests/validators/validateRegex.ts index 1d67fd6..92b76d5 100644 --- a/tests/validators/validateRegex.ts +++ b/tests/validators/validateRegex.ts @@ -6,7 +6,7 @@ const conf: ValidatorConfiguration = { name: 'object', original: {}, parent: {}, test('validateRegex function returns undefined if regex applies', async () => { const validateTest = validateRegex(/[a-z].*/); - await expect(validateTest('asdasd', conf)).resolves.toBeUndefined(); + await expect(validateTest('asdasd', conf)).toBeUndefined(); }); test('validateRegex function throws error if regex fails', async () => { @@ -20,5 +20,5 @@ test('validateRegex function throws error if regex fails', async () => { test('validateRegex function ignores if passed value is not a string', async () => { const validateTest = validateRegex(/[a-z].*/); - await expect(validateTest(123 as any, conf)).resolves.toBeUndefined(); + await expect(validateTest(123 as any, conf)).toBeUndefined(); }); From 99ca0ec8d49fddcbe024d4e4a6b55b63f9dcc260 Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 01:10:55 +0100 Subject: [PATCH 05/16] Refactor some types to handle edge cases --- src/types.ts | 19 ++++++------- src/validate.ts | 10 +++---- src/validators/oneOf.ts | 2 +- src/validators/validateCondition.ts | 42 +++++++++++++++++++++++------ 4 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/types.ts b/src/types.ts index d1bacb3..5a95abc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -11,12 +11,14 @@ export interface ValidatorConfiguration { } export type SyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => O | undefined | void; +// This is necessary so sync validators don't eat async validators (SyncValidatorFunction> instead of ValidatorFunction) +export type SyncValidatorFunctionInner = O extends Promise ? never : SyncValidatorFunction; export type AsyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => Promise; -export type ValidatorFunction = SyncValidatorFunction | AsyncValidatorFunction; +export type ValidatorFunction = SyncValidatorFunctionInner | AsyncValidatorFunction; -export type SyncValidatorFunctionList1 = [SyncValidatorFunction]; -export type SyncValidatorFunctionList2 = [SyncValidatorFunction, SyncValidatorFunction]; -export type SyncValidatorFunctionList3 = [SyncValidatorFunction, SyncValidatorFunction, SyncValidatorFunction]; +export type SyncValidatorFunctionList1 = [SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList2 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList3 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; export type SyncValidatorFunctionList = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3; export type ValidatorFunctionList1 = [ValidatorFunction]; @@ -24,19 +26,18 @@ export type ValidatorFunctionList2 = [ValidatorFunction, Validato export type ValidatorFunctionList3 = [ValidatorFunction, ValidatorFunction, ValidatorFunction]; export type ValidatorFunctionList = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3; -export type SyncValueValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunction | SyncValidatorObject; - +// Value validators are necessary, because we don't have generics in mapped types. +// Validator object values only support the return type of last validator function. +export type SyncValueValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunctionInner | SyncValidatorObject; export type SyncValidatorObject = { [key in keyof O]: SyncValueValidator; }; - export type ValueValidator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatorObject; - export type ValidatorObject = { [key in keyof O]: ValueValidator; }; -export type SyncValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunction | SyncValidatorObject; +export type SyncValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunctionInner | SyncValidatorObject; export type Validator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatorObject; export interface FailureFunction { diff --git a/src/validate.ts b/src/validate.ts index e91caeb..56e2ef8 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -1,4 +1,4 @@ -import { SyncValidatorFunction, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; +import { SyncValidatorFunction, SyncValidatorFunctionInner, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; @@ -68,7 +68,7 @@ function resolveValidatorObject(validator: ValidatorObject, testValue: any function resolveValidatorObject(validator: ValidatorObject, testValue: any, conf: ValidatorConfiguration): O | Promise { const keys = Object.keys(validator) as (keyof O)[]; const results = keys.map((key) => { - const result = validate(validator[key as keyof O], { + const result = validate(validator[key as keyof O] as any, { ...conf, name: key as string, path: conf.path.concat(key as string), @@ -127,19 +127,19 @@ const isValidatorFunction = (validator: Validator): vali return typeof validator === 'function'; }; -export function validate(v: SyncValidatorFunction, c?: Partial): (val: I, c?: Partial) => O; +export function validate(v: SyncValidatorFunctionInner, c?: Partial): (val: I, c?: Partial) => O; export function validate(v: SyncValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => O; export function validate(v: SyncValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => O; export function validate(v: SyncValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => O; -export function validate(v: SyncValidatorObject, c?: Partial): (val: I, c?: Partial) => O; export function validate(v: ValidatorFunction, c?: Partial): (val: I, c?: Partial) => Promise; export function validate(v: ValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => Promise; export function validate(v: ValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => Promise; export function validate(v: ValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => Promise; +export function validate(v: SyncValidatorObject, c?: Partial): (val: I, c?: Partial) => O; export function validate(v: ValidatorObject, c?: Partial): (val: I, c?: Partial) => Promise; export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => O | Promise; export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => O | Promise { - return function (testValue: any, testConf?: Partial): Promise { + return function (testValue: any, testConf) { // Set defaults to configuration const conf: ValidatorConfiguration = { name: 'object', diff --git a/src/validators/oneOf.ts b/src/validators/oneOf.ts index d7f7119..c0652d9 100644 --- a/src/validators/oneOf.ts +++ b/src/validators/oneOf.ts @@ -3,7 +3,7 @@ import validateCondition from './validateCondition.js'; const oneOf = (items: T[]): SyncValidatorFunction => validateCondition( - (value) => items.indexOf(value) !== -1, + (value) => items.indexOf(value as T) !== -1, (_, conf) => `Field ${conf.name} should be one of ${items.join(', ')}.` ); diff --git a/src/validators/validateCondition.ts b/src/validators/validateCondition.ts index 33a6fe3..ebd4083 100644 --- a/src/validators/validateCondition.ts +++ b/src/validators/validateCondition.ts @@ -4,23 +4,49 @@ import { Success, ValidatorConfiguration, SyncValidatorFunction, + AsyncValidatorFunction, } from '../types.js'; +import { isPromise } from '../validate.js'; -interface ConditionFunction { - (v: I, conf: ValidatorConfiguration): boolean; +interface SyncConditionFunction { + (v: unknown, conf: ValidatorConfiguration): boolean; } -const validateCondition = ( - condition: ConditionFunction, - errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` -): SyncValidatorFunction => { +interface AsyncConditionFunction { + (v: unknown, conf: ValidatorConfiguration): Promise; +} + +type ConditionFunction = SyncConditionFunction | AsyncConditionFunction; + +function validateCondition( + condition: SyncConditionFunction, + errorMsg?: FailureFunction +): SyncValidatorFunction; +function validateCondition( + condition: AsyncConditionFunction, + errorMsg?: FailureFunction +): AsyncValidatorFunction; +function validateCondition( + condition: ConditionFunction, + errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` +): (field: unknown, conf: ValidatorConfiguration) => O | undefined | Promise { return function (field, conf) { - if (condition(field, conf)) { + const result = condition(field, conf); + if (isPromise(result)) { + return result.then((result) => { + if (result) { + return Success(); + } else { + return Failure(errorMsg(field, conf)); + } + }); + } + if (result) { return Success(); } else { return Failure(errorMsg(field, conf)); } }; -}; +} export default validateCondition; From 53c1d7e9620df3ce0ccc488564a9032503b6373c Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 01:13:21 +0100 Subject: [PATCH 06/16] Add tests for TypeScript type checking --- tests/README.ts | 60 +++++--------- tests/types.ts | 153 +++++++++++++++++++++++++++++++++++ tests/validators/optional.ts | 7 +- 3 files changed, 175 insertions(+), 45 deletions(-) create mode 100644 tests/types.ts diff --git a/tests/README.ts b/tests/README.ts index 27ecb34..ed53b28 100644 --- a/tests/README.ts +++ b/tests/README.ts @@ -23,7 +23,12 @@ test('README: Validation functions', async () => { }, }); - const validatedUser = await validateUser({ + type ExpectedType = { + email: string; + password: string; + address: { city: string; street: string }; + }; + const validatedUser: ExpectedType = validateUser({ email: 'jdoe@example.net', password: 'asdasd69', address: { @@ -38,16 +43,6 @@ test('README: Validation functions', async () => { password: 'asdasd69', address: { city: 'Washington DC', street: 'Pennsylvania Avenue' }, }); - - // Let's check for the expected type with some TypeScript magic - type ExpectedType = { - email: string; - password: string; - address: { city: string; street: string }; - }; - type AssertExpectedType = T extends ExpectedType ? true : never; - // This line shouldn't compile if the type is wrong - const cond1: AssertExpectedType = true; }); test('README: Bring your own validator - isUniqueEmail starting', async () => { @@ -107,21 +102,16 @@ test('README: Bring your own validator - isUniqueEmail full', async () => { email: [isString(), isUniqueEmail()], }); - const validatedRegistration = await validateRegistration({ email: 'dsa@asd.asd' }); + type ExpectedType = { + email: string; + }; + const validatedRegistration: ExpectedType = await validateRegistration({ email: 'dsa@asd.asd' }); expect(validatedRegistration).toEqual({ email: 'dsa@asd.asd' }); try { await validateRegistration({ email: 'asd@asd.asd' }); } catch (err) { expect(err).toEqual(['This email already in use. Try your alternate address.']); } - - // Let's check for the expected type with some TypeScript magic - type ExpectedType = { - email: string; - }; - type AssertExpectedType = T extends ExpectedType ? true : never; - // This line shouldn't compile if the type is wrong - const cond1: AssertExpectedType = true; }); test('README: Sanitize and transform - hash', async () => { @@ -167,7 +157,11 @@ test('README: Sanitize and transform - hash', async () => { password: [isString(), minLength(8), hash()], }); - const validatedRegistration = await validateRegistration({ + type ExpectedType = { + email: string; + password: string; + }; + const validatedRegistration: ExpectedType = await validateRegistration({ email: 'asd2@asd.asd', password: 'asdasd69', }); @@ -176,15 +170,6 @@ test('README: Sanitize and transform - hash', async () => { email: 'asd2@asd.asd', password: '$2b$08$4S0b.0ut...', }); - - // Let's check for the expected type with some TypeScript magic - type ExpectedType = { - email: string; - password: string; - }; - type AssertExpectedType = T extends ExpectedType ? true : never; - // This line shouldn't compile if the type is wrong - const cond1: AssertExpectedType = true; }); test('README: Higher-order validators - confirmPassword', async () => { @@ -248,7 +233,11 @@ test('README: Higher-order validators - confirmPassword', async () => { }) ); - const validatedRegistration = await validateRegistration({ + type ExpectedType = { + email: string; + password: string; + }; + const validatedRegistration: ExpectedType = await validateRegistration({ email: 'asd2@asd.asd', password: 'asdasd69', password_confirm: 'asdasd69', @@ -258,13 +247,4 @@ test('README: Higher-order validators - confirmPassword', async () => { email: 'asd2@asd.asd', password: '$2b$08$4S0b.0ut...', }); - - // Let's check for the expected type with some TypeScript magic - type ExpectedType = { - email: string; - password: string; - }; - type AssertExpectedType = T extends ExpectedType ? true : never; - // This line shouldn't compile if the type is wrong - const cond1: AssertExpectedType = true; }); diff --git a/tests/types.ts b/tests/types.ts new file mode 100644 index 0000000..fc13e76 --- /dev/null +++ b/tests/types.ts @@ -0,0 +1,153 @@ +import { describe, expect, test } from '@jest/globals'; +import { SyncValidatorFunction, ValidatorFunction } from '../src/types'; +import validate from '../src/validate'; + +const isString: SyncValidatorFunction = (val, c) => { + if (typeof val === 'string') { + return val; + } else { + throw new Error('Not a string.'); + } +}; + +const toNumber: SyncValidatorFunction = (val, c) => { + return Number.parseInt(val); +}; + +const intoString: SyncValidatorFunction = (val, c) => { + return val.toString(); +}; + +const isStringP: ValidatorFunction = (val, c) => { + if (typeof val === 'string') return Promise.resolve(val); + else return Promise.reject(); +}; + +const toNumberP: ValidatorFunction = (val, c) => { + return Promise.resolve(Number.parseInt(val)); +}; + +const intoStringP: ValidatorFunction = (val, c) => { + return Promise.resolve(val.toString()); +}; + +test('sync validator function returns type without promise', () => { + const validateWithSyncFunction = validate(isString); + const vfn: string = validateWithSyncFunction(''); +}); +test('sync validator function array returns transformed type without promise', () => { + const validateWithSyncFunction1 = validate([isString]); + const vlist1: string = validateWithSyncFunction1(''); + + const validateWithSyncFunction2 = validate([isString, toNumber]); + const vlist2: number = validateWithSyncFunction2(''); + + const validateWithSyncFunction3 = validate([isString, toNumber, intoString]); + const vlist3: string = validateWithSyncFunction3(''); +}); +test('sync validator object returns object type without promise', () => { + const validateWithObject = validate({ a: [isString, toNumber, intoString], b: isString }); + const vobj: { a: string; b: string } = validateWithObject({ a: '', b: '' }); +}); +test('sync nested validator object return nested object without promise', () => { + const validateWithObject = validate({ a: { c: isString }, b: isString }); + const vdobj: { a: { c: string }; b: string } = validateWithObject({ a: { c: '' }, b: '' }); +}); + +test('async validator function returns type with promise', () => { + const validateWithAsyncFunction = validate(isStringP); + const vfnp: Promise = validateWithAsyncFunction(''); +}); +test('async validator function array returns type with promise', () => { + const validateWithAsyncFunction1 = validate([isStringP]); + const vlist1p: Promise = validateWithAsyncFunction1(''); + + const validateWithAsyncFunction2 = validate([isStringP, toNumberP]); + const vlist2p: Promise = validateWithAsyncFunction2(''); + + const validateWithAsyncFunction3 = validate([isStringP, toNumberP, intoStringP]); + const vlist3p: Promise = validateWithAsyncFunction3(''); +}); +test('async validator object returns object type with promise', () => { + const validateWithAsyncObject = validate({ a: [isStringP, toNumberP, intoStringP], b: isStringP }); + const vobjp: Promise<{ a: string; b: string }> = validateWithAsyncObject({ a: '', b: '' }); +}); +test('async nested validator object returns object type with promise', () => { + const validateWithAsyncNestedObject = validate({ a: { c: isStringP }, b: isStringP }); + const vdobjp: Promise<{ a: { c: string }; b: string }> = validateWithAsyncNestedObject({ a: { c: '' }, b: '' }); +}); + +test('mixed validator function array returns type with promise', () => { + const validateWithMixedFunction21 = validate([isString, toNumberP]); + const vlist2m1: Promise = validateWithMixedFunction21(''); + + const validateWithMixedFunction22 = validate([isStringP, toNumber]); + const vlist2m2: Promise = validateWithMixedFunction22(''); + + const validateWithMixedFunction31 = validate([isStringP, toNumber, intoStringP]); + const vlist3m1: Promise = validateWithMixedFunction31(''); + + const validateWithMixedFunction32 = validate([isStringP, toNumber, intoStringP]); + const vlist3m2: Promise = validateWithMixedFunction32(''); +}); +test('mixed validator object returns object type with promise', () => { + const validateWithMixedObject1 = validate({ a: [isString, toNumber, intoStringP], b: isStringP }); + const vobjm1: Promise<{ a: string; b: string }> = validateWithMixedObject1({ a: '', b: '' }); + + const validateWithMixedObject2 = validate({ a: [isStringP, toNumberP, intoString], b: isStringP }); + const vobjm2: Promise<{ a: string; b: string }> = validateWithMixedObject2({ a: '', b: '' }); + + const validateWithMixedObject3 = validate({ a: [isString, toNumber, intoString], b: isStringP }); + const vobjm3: Promise<{ a: string; b: string }> = validateWithMixedObject3({ a: '', b: '' }); + + const validateWithMixedObject4 = validate({ a: [isString, toNumber, intoStringP], b: isString }); + const vobjm4: Promise<{ a: string; b: string }> = validateWithMixedObject4({ a: '', b: '' }); +}); +test('mixed nested validator object returns object type with promise', () => { + const validateWithAsyncNestedObject1 = validate({ a: { c: isString }, b: isStringP }); + const vdobjm1: Promise<{ a: { c: string }; b: string }> = validateWithAsyncNestedObject1({ a: { c: '' }, b: '' }); + + const validateWithAsyncNestedObject2 = validate({ a: { c: isStringP }, b: isString }); + const vdobjm2: Promise<{ a: { c: string }; b: string }> = validateWithAsyncNestedObject2({ a: { c: '' }, b: '' }); +}); + + +test('inner sync validator function returns inner type', () => { + const validateWithSyncInnerFunction = validate(validate(isString)); + const vfnsi: string = validateWithSyncInnerFunction(''); +}); + +test('inner async validator function returns inner type', () => { + const validateWithInnerFunction = validate(validate(isStringP)); + const vfnai: Promise = validateWithInnerFunction(''); +}); +test('inner validator function array returns inner type', () => { + const validateWithInnerFunction11 = validate([validate(isString)]); + const vlist1i1: Promise = validateWithInnerFunction11(''); + + const validateWithInnerFunction12 = validate([validate(isStringP)]); + const vlist1i2: Promise = validateWithInnerFunction12(''); + + const validateWithInnerFunction13 = validate(validate([isStringP])); + const vlist1i3: Promise = validateWithInnerFunction13(''); +}); +test('inner validator object returns inner object type', () => { + const validateWithInnerObject1 = validate({ a: validate(isStringP), b: isStringP }); + const vobji1: Promise<{ a: string; b: string }> = validateWithInnerObject1({ a: '', b: '' }); + + const validateWithInnerObject2 = validate({ a: validate(isString), b: isStringP }); + const vobji2: Promise<{ a: string; b: string }> = validateWithInnerObject2({ a: '', b: '' }); + + const validateWithInnerObject3 = validate({ a: validate(isString), b: isString }); + const vobji3: { a: string; b: string } = validateWithInnerObject3({ a: '', b: '' }); +}); +test('inner nested validator object returns inner object type', () => { + const validateWithInnerNestedObject1 = validate({ a: { c: validate(isStringP) }, b: isStringP }); + const vdobji1: Promise<{ a: { c: string }; b: string }> = validateWithInnerNestedObject1({ a: { c: '' }, b: '' }); + + const validateWithInnerNestedObject2 = validate({ a: { c: validate(isString) }, b: isStringP }); + const vdobji2: Promise<{ a: { c: string }; b: string }> = validateWithInnerNestedObject2({ a: { c: '' }, b: '' }); + + const validateWithInnerNestedObject3 = validate({ a: { c: isStringP }, b: validate(isStringP) }); + const vdobji3: Promise<{ a: { c: string }; b: string }> = validateWithInnerNestedObject3({ a: { c: '' }, b: '' }); +}); \ No newline at end of file diff --git a/tests/validators/optional.ts b/tests/validators/optional.ts index ec67b36..bea5319 100644 --- a/tests/validators/optional.ts +++ b/tests/validators/optional.ts @@ -36,14 +36,11 @@ test('optional validator if value is undefined, returns successfully without cal expect(await validateListOptional({ field: 'string' })).toEqual({ field: 'string' }); expect(i).toEqual(2); - // Let's check for the expected type with some TypeScript magic - const validatedOptional = await validateFunctionOptional({ field: 'string' }); + // Let's check for the expected type type ExpectedType = { field: string | undefined; }; - type AssertExpectedType = T extends ExpectedType ? true : never; - // This line shouldn't compile if the type is wrong - const cond1: AssertExpectedType = true; + const validatedType: ExpectedType = await validateFunctionOptional({ field: 'string' }); }); test('optional validator without it, undefined fails', async () => { From 0a23bc96ce1c96bc5a5f18d40d9746f2e5f12a36 Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 02:03:37 +0100 Subject: [PATCH 07/16] Add validating function to fix some nested type issues --- src/types.ts | 4 ++++ src/validate.ts | 28 +++++++++++++++------------- tests/types.ts | 13 ++++++------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/types.ts b/src/types.ts index 5a95abc..98a2e98 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,6 +10,10 @@ export interface ValidatorConfiguration { parent: any; } +export type SyncValidatingFunction = O extends void | undefined ? never : (val: I, c?: Partial) => O; +export type AsyncValidatingFunction = (val: I, c?: Partial) => Promise; +export type ValidatingFunction = SyncValidatingFunction | AsyncValidatingFunction; + export type SyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => O | undefined | void; // This is necessary so sync validators don't eat async validators (SyncValidatorFunction> instead of ValidatorFunction) export type SyncValidatorFunctionInner = O extends Promise ? never : SyncValidatorFunction; diff --git a/src/validate.ts b/src/validate.ts index 56e2ef8..e45d248 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -1,4 +1,4 @@ -import { SyncValidatorFunction, SyncValidatorFunctionInner, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; +import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidatorFunctionInner, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, ValidatingFunction, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; @@ -127,18 +127,20 @@ const isValidatorFunction = (validator: Validator): vali return typeof validator === 'function'; }; -export function validate(v: SyncValidatorFunctionInner, c?: Partial): (val: I, c?: Partial) => O; -export function validate(v: SyncValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => O; -export function validate(v: SyncValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => O; -export function validate(v: SyncValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => O; -export function validate(v: ValidatorFunction, c?: Partial): (val: I, c?: Partial) => Promise; -export function validate(v: ValidatorFunctionList1, c?: Partial): (val: I, c?: Partial) => Promise; -export function validate(v: ValidatorFunctionList2, c?: Partial): (val: I, c?: Partial) => Promise; -export function validate(v: ValidatorFunctionList3, c?: Partial): (val: I, c?: Partial) => Promise; -export function validate(v: SyncValidatorObject, c?: Partial): (val: I, c?: Partial) => O; -export function validate(v: ValidatorObject, c?: Partial): (val: I, c?: Partial) => Promise; -export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => O | Promise; -export function validate(validator: Validator, validateConf?: Partial): (val: I, testConf?: Partial) => O | Promise { +export function validate(v: SyncValidatorFunctionInner, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatingFunction, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList1, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList2, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList3, c?: Partial): SyncValidatingFunction; +export function validate(v: ValidatorFunction, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatingFunction, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList1, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList2, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList3, c?: Partial): AsyncValidatingFunction; +export function validate(v: SyncValidatorObject, c?: Partial): SyncValidatingFunction; +export function validate(v: ValidatorObject, c?: Partial): AsyncValidatingFunction; +export function validate(validator: Validator, validateConf?: Partial): ValidatingFunction; +export function validate(validator: Validator, validateConf?: Partial): ValidatingFunction { return function (testValue: any, testConf) { // Set defaults to configuration const conf: ValidatorConfiguration = { diff --git a/tests/types.ts b/tests/types.ts index fc13e76..e7583ae 100644 --- a/tests/types.ts +++ b/tests/types.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from '@jest/globals'; -import { SyncValidatorFunction, ValidatorFunction } from '../src/types'; +import { SyncValidatorFunction, ValidatingFunction, ValidatorFunction } from '../src/types'; import validate from '../src/validate'; const isString: SyncValidatorFunction = (val, c) => { @@ -118,15 +118,13 @@ test('inner sync validator function returns inner type', () => { }); test('inner async validator function returns inner type', () => { - const validateWithInnerFunction = validate(validate(isStringP)); + const validatingFn: ValidatingFunction = validate(isStringP); + const validateWithInnerFunction = validate(validatingFn); const vfnai: Promise = validateWithInnerFunction(''); }); test('inner validator function array returns inner type', () => { const validateWithInnerFunction11 = validate([validate(isString)]); - const vlist1i1: Promise = validateWithInnerFunction11(''); - - const validateWithInnerFunction12 = validate([validate(isStringP)]); - const vlist1i2: Promise = validateWithInnerFunction12(''); + const vlist1i1: string = validateWithInnerFunction11(''); const validateWithInnerFunction13 = validate(validate([isStringP])); const vlist1i3: Promise = validateWithInnerFunction13(''); @@ -142,7 +140,8 @@ test('inner validator object returns inner object type', () => { const vobji3: { a: string; b: string } = validateWithInnerObject3({ a: '', b: '' }); }); test('inner nested validator object returns inner object type', () => { - const validateWithInnerNestedObject1 = validate({ a: { c: validate(isStringP) }, b: isStringP }); + const vf: ValidatingFunction = validate(isStringP); + const validateWithInnerNestedObject1 = validate({ a: { c: vf }, b: isStringP }); const vdobji1: Promise<{ a: { c: string }; b: string }> = validateWithInnerNestedObject1({ a: { c: '' }, b: '' }); const validateWithInnerNestedObject2 = validate({ a: { c: validate(isString) }, b: isStringP }); From 5dbe61edd4c5e19688a9c29c10ef40b5d86d246e Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 18:06:54 +0100 Subject: [PATCH 08/16] Remove undefined returning functions --- src/transformers/number/ceil.ts | 4 +- src/transformers/number/clamp.ts | 5 +-- src/transformers/number/floor.ts | 5 +-- src/transformers/number/round.ts | 5 +-- src/transformers/number/toMultipleOf.ts | 5 +-- src/transformers/string/lower.ts | 5 +-- src/transformers/string/normalize.ts | 5 +-- src/transformers/string/trim.ts | 5 +-- src/transformers/string/truncate.ts | 5 +-- src/transformers/string/upper.ts | 5 +-- src/types.ts | 16 +++---- src/validators/date/after.ts | 9 ++-- src/validators/date/before.ts | 10 ++--- src/validators/date/inRange.ts | 14 ++---- src/validators/number/between.ts | 8 +--- src/validators/number/closeTo.ts | 5 +-- src/validators/number/gt.ts | 8 +--- src/validators/number/gte.ts | 8 +--- src/validators/number/isMultipleOf.ts | 8 +--- src/validators/number/lt.ts | 8 +--- src/validators/number/lte.ts | 8 +--- src/validators/optional.ts | 17 ++------ src/validators/string/betweenLength.ts | 8 +--- src/validators/string/insensitiveEquals.ts | 7 +-- src/validators/string/isUrl.ts | 10 ++--- src/validators/string/length.ts | 8 +--- src/validators/string/maxLength.ts | 8 +--- src/validators/string/minLength.ts | 8 +--- src/validators/validateCondition.ts | 32 +++++++------- src/validators/validateRegex.ts | 13 +++--- tests/README.ts | 18 ++++---- tests/transformers/number/ceil.ts | 10 ----- tests/transformers/number/clamp.ts | 10 ----- tests/transformers/number/floor.ts | 10 ----- tests/transformers/number/round.ts | 10 ----- tests/transformers/number/toMultipleOf.ts | 10 ----- tests/transformers/string/lower.ts | 12 ----- tests/transformers/string/normalize.ts | 13 ------ tests/transformers/string/trim.ts | 13 ------ tests/transformers/string/truncate.ts | 13 ------ tests/transformers/string/upper.ts | 12 ----- tests/validate.ts | 4 +- tests/validators/arrayOf.ts | 6 +-- tests/validators/bail.ts | 8 ++-- tests/validators/boolean/falsey.ts | 24 +++++----- tests/validators/boolean/isBool.ts | 14 +++--- tests/validators/boolean/truthy.ts | 26 +++++------ tests/validators/date/after.ts | 25 +++-------- tests/validators/date/before.ts | 31 ++++--------- tests/validators/date/inRange.ts | 46 +++++++------------- tests/validators/date/isDate.ts | 8 ++-- tests/validators/either.ts | 4 +- tests/validators/equals.ts | 26 +++++------ tests/validators/number/between.ts | 24 +++------- tests/validators/number/closeTo.ts | 8 ---- tests/validators/number/gt.ts | 18 ++------ tests/validators/number/gte.ts | 20 +++------ tests/validators/number/isInt.ts | 8 ++-- tests/validators/number/isMultipleOf.ts | 15 ++----- tests/validators/number/isNumber.ts | 16 +++---- tests/validators/number/lt.ts | 16 ++----- tests/validators/number/lte.ts | 18 ++------ tests/validators/oneOf.ts | 38 ++++++++-------- tests/validators/optional.ts | 14 +++--- tests/validators/string/betweenLength.ts | 25 +++-------- tests/validators/string/insensitiveEquals.ts | 23 ++-------- tests/validators/string/isEmail.ts | 20 ++------- tests/validators/string/isString.ts | 4 +- tests/validators/string/isUrl.ts | 39 ++++++----------- tests/validators/string/length.ts | 19 ++------ tests/validators/string/maxLength.ts | 19 ++------ tests/validators/string/minLength.ts | 19 ++------ tests/validators/validateCondition.ts | 4 +- tests/validators/validateRegex.ts | 9 +--- 74 files changed, 284 insertions(+), 707 deletions(-) diff --git a/src/transformers/number/ceil.ts b/src/transformers/number/ceil.ts index 0ed09df..5220ac4 100644 --- a/src/transformers/number/ceil.ts +++ b/src/transformers/number/ceil.ts @@ -1,8 +1,8 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const ceil = ():SyncValidatorFunction => (value, conf) => { +const ceil = (): SyncValidatorFunction => (value, conf) => { if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); + return Ignore(value); } return Success(Math.ceil(value)); }; diff --git a/src/transformers/number/clamp.ts b/src/transformers/number/clamp.ts index 828ef60..db65ed8 100644 --- a/src/transformers/number/clamp.ts +++ b/src/transformers/number/clamp.ts @@ -1,11 +1,8 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const clamp = - (min: number, max: number):SyncValidatorFunction => + (min: number, max: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } if (min >= value) { return Success(min); } diff --git a/src/transformers/number/floor.ts b/src/transformers/number/floor.ts index 4786782..4eae500 100644 --- a/src/transformers/number/floor.ts +++ b/src/transformers/number/floor.ts @@ -1,9 +1,6 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const floor = ():SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } +const floor = (): SyncValidatorFunction => (value, conf) => { return Success(Math.floor(value)); }; diff --git a/src/transformers/number/round.ts b/src/transformers/number/round.ts index cfce95b..8cb5c2d 100644 --- a/src/transformers/number/round.ts +++ b/src/transformers/number/round.ts @@ -1,9 +1,6 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const round = ():SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } +const round = ():SyncValidatorFunction => (value, conf) => { return Success(Math.round(value)); }; diff --git a/src/transformers/number/toMultipleOf.ts b/src/transformers/number/toMultipleOf.ts index 259fe88..db8a63c 100644 --- a/src/transformers/number/toMultipleOf.ts +++ b/src/transformers/number/toMultipleOf.ts @@ -1,11 +1,8 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const toMultipleOf = - (n: number, round = Math.round):SyncValidatorFunction => + (n: number, round = Math.round): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } return Success(round(value / n) * n); }; diff --git a/src/transformers/string/lower.ts b/src/transformers/string/lower.ts index c4f3dc4..1e0648a 100644 --- a/src/transformers/string/lower.ts +++ b/src/transformers/string/lower.ts @@ -1,9 +1,6 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const lower = ():SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } +const lower = (): SyncValidatorFunction => (value, conf) => { return Success(value.toLocaleLowerCase()); }; diff --git a/src/transformers/string/normalize.ts b/src/transformers/string/normalize.ts index 30a844d..150aa55 100644 --- a/src/transformers/string/normalize.ts +++ b/src/transformers/string/normalize.ts @@ -1,11 +1,8 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const normalize = - (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'):SyncValidatorFunction => + (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } return Success(value.normalize(form)); }; diff --git a/src/transformers/string/trim.ts b/src/transformers/string/trim.ts index 8acdb60..6bf3298 100644 --- a/src/transformers/string/trim.ts +++ b/src/transformers/string/trim.ts @@ -1,9 +1,6 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const trim = ():SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } +const trim = ():SyncValidatorFunction => (value, conf) => { return Success(value.trim()); }; diff --git a/src/transformers/string/truncate.ts b/src/transformers/string/truncate.ts index 1fb5fee..1404cd3 100644 --- a/src/transformers/string/truncate.ts +++ b/src/transformers/string/truncate.ts @@ -1,11 +1,8 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; const truncate = - (n: number):SyncValidatorFunction => + (n: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } return Success(n >= 0 ? value.substr(0, n) : value.substr(n)); }; diff --git a/src/transformers/string/upper.ts b/src/transformers/string/upper.ts index fa5a07e..212cad0 100644 --- a/src/transformers/string/upper.ts +++ b/src/transformers/string/upper.ts @@ -1,9 +1,6 @@ import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const upper = ():SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } +const upper = ():SyncValidatorFunction => (value, conf) => { return Success(value.toLocaleUpperCase()); }; diff --git a/src/types.ts b/src/types.ts index 98a2e98..e77171b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,14 +10,14 @@ export interface ValidatorConfiguration { parent: any; } -export type SyncValidatingFunction = O extends void | undefined ? never : (val: I, c?: Partial) => O; +export type SyncValidatingFunction = (val: I, c?: Partial) => O; export type AsyncValidatingFunction = (val: I, c?: Partial) => Promise; export type ValidatingFunction = SyncValidatingFunction | AsyncValidatingFunction; -export type SyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => O | undefined | void; +export type SyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => O; // This is necessary so sync validators don't eat async validators (SyncValidatorFunction> instead of ValidatorFunction) export type SyncValidatorFunctionInner = O extends Promise ? never : SyncValidatorFunction; -export type AsyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => Promise; +export type AsyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => Promise; export type ValidatorFunction = SyncValidatorFunctionInner | AsyncValidatorFunction; export type SyncValidatorFunctionList1 = [SyncValidatorFunctionInner]; @@ -32,11 +32,11 @@ export type ValidatorFunctionList = ValidatorFunctionList1 | V // Value validators are necessary, because we don't have generics in mapped types. // Validator object values only support the return type of last validator function. -export type SyncValueValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunctionInner | SyncValidatorObject; +export type SyncValueValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunctionInner | SyncValidatingFunction | SyncValidatorObject; export type SyncValidatorObject = { [key in keyof O]: SyncValueValidator; }; -export type ValueValidator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatorObject; +export type ValueValidator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatingFunction | ValidatorObject; export type ValidatorObject = { [key in keyof O]: ValueValidator; }; @@ -50,12 +50,12 @@ export interface FailureFunction { export type InferValidator = T extends Validator ? O : never; -export const Success = function (t?: T): T | undefined { +export const Success = function (t: T): T { return t; }; -export const Ignore = function (): undefined { - return undefined; +export const Ignore = function (t: T): T { + return t; }; export const Failure = function (t: string): never { diff --git a/src/validators/date/after.ts b/src/validators/date/after.ts index 9f95655..3bfa59e 100644 --- a/src/validators/date/after.ts +++ b/src/validators/date/after.ts @@ -3,16 +3,13 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js' const after: ( date: string | number | Date, opts?: { inclusive: boolean } -) => SyncValidatorFunction = +) => SyncValidatorFunction = (date, opts = { inclusive: false }) => (value, conf) => { - if (!(value instanceof Date)) { - return Ignore(); - } - const min = date instanceof Date ? date : new Date(date); + if ((opts.inclusive && value >= min) || (!opts.inclusive && value > min)) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be after ${min.toString()}.`); diff --git a/src/validators/date/before.ts b/src/validators/date/before.ts index 5cdd6e2..20f29ed 100644 --- a/src/validators/date/before.ts +++ b/src/validators/date/before.ts @@ -3,17 +3,13 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js' const before: ( date: string | number | Date, opts?: { inclusive?: boolean } -) => SyncValidatorFunction = - (date, opts = { inclusive: false }): SyncValidatorFunction => +) => SyncValidatorFunction = + (date, opts = { inclusive: false }) => (value, conf) => { - if (!(value instanceof Date)) { - return Ignore(); - } - const max = date instanceof Date ? date : new Date(date); if ((opts.inclusive && value <= max) || (!opts.inclusive && value < max)) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be before ${max.toString()}.`); diff --git a/src/validators/date/inRange.ts b/src/validators/date/inRange.ts index d80aba9..15e9704 100644 --- a/src/validators/date/inRange.ts +++ b/src/validators/date/inRange.ts @@ -4,17 +4,9 @@ const inRange: ( minDate: string | number | Date, maxDate: string | number | Date, opts?: { minInclusive?: boolean; maxInclusive?: boolean } -) => SyncValidatorFunction = - ( - minDate, - maxDate, - opts = { minInclusive: false, maxInclusive: false } - ): SyncValidatorFunction => +) => SyncValidatorFunction = + (minDate, maxDate, opts = { minInclusive: false, maxInclusive: false }) => (value, conf) => { - if (!(value instanceof Date)) { - return Ignore(); - } - const min = minDate instanceof Date ? minDate : new Date(minDate); const max = maxDate instanceof Date ? maxDate : new Date(maxDate); @@ -22,7 +14,7 @@ const inRange: ( ((opts.minInclusive && value >= min) || (!opts.minInclusive && value > min)) && ((opts.maxInclusive && value <= max) || (!opts.maxInclusive && value < max)) ) { - return Success(); + return Success(value); } return Failure( diff --git a/src/validators/number/between.ts b/src/validators/number/between.ts index d39e0da..992fbe3 100644 --- a/src/validators/number/between.ts +++ b/src/validators/number/between.ts @@ -4,18 +4,14 @@ const between: ( min: number, max: number, opts?: { minInclusive?: boolean; maxInclusive?: boolean } -) => SyncValidatorFunction = +) => SyncValidatorFunction = (min, max, opts = { minInclusive: false, maxInclusive: false }) => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } - if ( ((opts.minInclusive && value >= min) || (!opts.minInclusive && value > min)) && ((opts.maxInclusive && value <= max) || (!opts.maxInclusive && value < max)) ) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be between ${min} and ${max}.`); diff --git a/src/validators/number/closeTo.ts b/src/validators/number/closeTo.ts index 0830bfd..79f8498 100644 --- a/src/validators/number/closeTo.ts +++ b/src/validators/number/closeTo.ts @@ -1,11 +1,8 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const closeTo: (v: number, e?: number) => SyncValidatorFunction = +const closeTo: (v: number, e?: number) => SyncValidatorFunction = (exactValue, epsilon = Number.EPSILON) => (value, conf) => { - if (typeof value !== 'number') { - return Ignore(); - } if (Math.abs(value - exactValue) < epsilon) { return Success(exactValue); } diff --git a/src/validators/number/gt.ts b/src/validators/number/gt.ts index 69a04d5..3da6deb 100644 --- a/src/validators/number/gt.ts +++ b/src/validators/number/gt.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const gt = - (min: number): SyncValidatorFunction => + (min: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } - if (value > min) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be greater than ${min}.`); diff --git a/src/validators/number/gte.ts b/src/validators/number/gte.ts index ef21c5c..30c24a5 100644 --- a/src/validators/number/gte.ts +++ b/src/validators/number/gte.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const gte = - (min: number): SyncValidatorFunction => + (min: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } - if (value >= min) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be greater than or equal to ${min}.`); diff --git a/src/validators/number/isMultipleOf.ts b/src/validators/number/isMultipleOf.ts index c3b4ddc..c15bb23 100644 --- a/src/validators/number/isMultipleOf.ts +++ b/src/validators/number/isMultipleOf.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const isMultipleOf = - (n: number): SyncValidatorFunction => + (n: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } - if (value % n === 0) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be the multiple of ${n}.`); diff --git a/src/validators/number/lt.ts b/src/validators/number/lt.ts index 2a79701..9cfb0f6 100644 --- a/src/validators/number/lt.ts +++ b/src/validators/number/lt.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const lt = - (max: number): SyncValidatorFunction => + (max: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } - if (value < max) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be less than ${max}.`); diff --git a/src/validators/number/lte.ts b/src/validators/number/lte.ts index cca03c1..49603ef 100644 --- a/src/validators/number/lte.ts +++ b/src/validators/number/lte.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const lte = - (max: number): SyncValidatorFunction => + (max: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(); - } - if (value <= max) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be less than or equal to ${max}.`); diff --git a/src/validators/optional.ts b/src/validators/optional.ts index a96ae80..9606561 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -1,20 +1,11 @@ -import validate from '../validate.js'; -import { Validator, Success, SyncValidator, ValidatorConfiguration } from '../types.js'; +import { Success, SyncValidatorFunction } from '../types.js'; -function optional( - validators: SyncValidator -): (val: I, c: ValidatorConfiguration) => O | undefined; -function optional( - validators: Validator -): (val: I, c: ValidatorConfiguration) => Promise; -function optional( - validators: Validator -): (val: I, c: ValidatorConfiguration) => O | undefined | Promise { +function optional(): SyncValidatorFunction { return (value, conf) => { if (typeof value === 'undefined') { - return Success(); + return Success(value); } - return validate(validators, conf)(value); + return Success(value); }; } diff --git a/src/validators/string/betweenLength.ts b/src/validators/string/betweenLength.ts index 5c49453..05b5313 100644 --- a/src/validators/string/betweenLength.ts +++ b/src/validators/string/betweenLength.ts @@ -1,16 +1,12 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const betweenLength = - (min: number, max: number): SyncValidatorFunction => + (min: number, max: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } - const minLength = Math.min(min, max); const maxLength = Math.max(min, max); if (minLength <= value.length && value.length <= maxLength) { - return Success(); + return Success(value); } return Failure( `Field ${conf.name} length should be between ${minLength} and ${maxLength} characters.` diff --git a/src/validators/string/insensitiveEquals.ts b/src/validators/string/insensitiveEquals.ts index 967065d..80e1df0 100644 --- a/src/validators/string/insensitiveEquals.ts +++ b/src/validators/string/insensitiveEquals.ts @@ -1,13 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const insensitiveEquals = - (to: string): SyncValidatorFunction => + (to: string): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } if (value.toLocaleLowerCase() === to.toLocaleLowerCase()) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} should be equal to ${to}.`); }; diff --git a/src/validators/string/isUrl.ts b/src/validators/string/isUrl.ts index eaa939b..9ef1083 100644 --- a/src/validators/string/isUrl.ts +++ b/src/validators/string/isUrl.ts @@ -1,13 +1,9 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; -const isUrl = (): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } - +const isUrl = (): SyncValidatorFunction => (value, conf) => { try { - const url = new URL(value); - return Success(); + new URL(value); + return Success(value); } catch { return Failure(`Field ${conf.name} should be an url.`); } diff --git a/src/validators/string/length.ts b/src/validators/string/length.ts index 73bccbe..c1f783a 100644 --- a/src/validators/string/length.ts +++ b/src/validators/string/length.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const length = - (n: number): SyncValidatorFunction => + (n: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } - if (value.length === n) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} length should be exactly ${n} characters.`); }; diff --git a/src/validators/string/maxLength.ts b/src/validators/string/maxLength.ts index 6a94eeb..2732e5f 100644 --- a/src/validators/string/maxLength.ts +++ b/src/validators/string/maxLength.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const maxLength = - (max: number): SyncValidatorFunction => + (max: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } - if (value.length <= max) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} length should be at most ${max} characters.`); }; diff --git a/src/validators/string/minLength.ts b/src/validators/string/minLength.ts index 8d98ea4..431d80c 100644 --- a/src/validators/string/minLength.ts +++ b/src/validators/string/minLength.ts @@ -1,14 +1,10 @@ import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; const minLength = - (min: number): SyncValidatorFunction => + (min: number): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'string') { - return Ignore(); - } - if (value.length >= min) { - return Success(); + return Success(value); } return Failure(`Field ${conf.name} length should be at least ${min} characters.`); }; diff --git a/src/validators/validateCondition.ts b/src/validators/validateCondition.ts index ebd4083..6335df2 100644 --- a/src/validators/validateCondition.ts +++ b/src/validators/validateCondition.ts @@ -3,46 +3,44 @@ import { FailureFunction, Success, ValidatorConfiguration, - SyncValidatorFunction, AsyncValidatorFunction, + SyncValidatorFunctionInner, } from '../types.js'; import { isPromise } from '../validate.js'; -interface SyncConditionFunction { +interface SyncConditionFunction { (v: unknown, conf: ValidatorConfiguration): boolean; } - -interface AsyncConditionFunction { +interface AsyncConditionFunction { (v: unknown, conf: ValidatorConfiguration): Promise; } +type ConditionFunction = SyncConditionFunction | AsyncConditionFunction; -type ConditionFunction = SyncConditionFunction | AsyncConditionFunction; - -function validateCondition( - condition: SyncConditionFunction, +function validateCondition( + condition: SyncConditionFunction, errorMsg?: FailureFunction -): SyncValidatorFunction; -function validateCondition( - condition: AsyncConditionFunction, +): SyncValidatorFunctionInner; +function validateCondition( + condition: AsyncConditionFunction, errorMsg?: FailureFunction -): AsyncValidatorFunction; -function validateCondition( - condition: ConditionFunction, +): AsyncValidatorFunction; +function validateCondition( + condition: ConditionFunction, errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` -): (field: unknown, conf: ValidatorConfiguration) => O | undefined | Promise { +): (value: unknown, conf: ValidatorConfiguration) => T | Promise { return function (field, conf) { const result = condition(field, conf); if (isPromise(result)) { return result.then((result) => { if (result) { - return Success(); + return Success(field as T); } else { return Failure(errorMsg(field, conf)); } }); } if (result) { - return Success(); + return Success(field as T); } else { return Failure(errorMsg(field, conf)); } diff --git a/src/validators/validateRegex.ts b/src/validators/validateRegex.ts index 2fce8c9..991e8cf 100644 --- a/src/validators/validateRegex.ts +++ b/src/validators/validateRegex.ts @@ -3,15 +3,12 @@ import { Failure, FailureFunction, Ignore, Success, SyncValidatorFunction } from const validateRegex = ( regex: RegExp, errorMsg: FailureFunction = (_, { name }) => `Field ${name} format is invalid.` -): SyncValidatorFunction => { - return function (field, conf) { - if (typeof field !== 'string') { - return Ignore(); - } - if (regex.test(field)) { - return Success(); +): SyncValidatorFunction => { + return function (value, conf) { + if (regex.test(value)) { + return Success(value); } else { - return Failure(errorMsg(field, conf)); + return Failure(errorMsg(value, conf)); } }; }; diff --git a/tests/README.ts b/tests/README.ts index ed53b28..ae5b227 100644 --- a/tests/README.ts +++ b/tests/README.ts @@ -59,7 +59,7 @@ test('README: Bring your own validator - isUniqueEmail starting', async () => { async function (email, conf) { const exists = await db.users.find({ email }); // User | null if (!exists) { - return; + return email; } throw 'This email already in use. Try your alternate address.'; }; @@ -89,11 +89,11 @@ test('README: Bring your own validator - isUniqueEmail full', async () => { const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { if (typeof email !== 'string') { - return Ignore(); + return Ignore(email); } const exists = await db.users.find({ email }); if (!exists) { - return Success(); + return Success(email); } return Failure('This email already in use. Try your alternate address.'); }; @@ -127,11 +127,11 @@ test('README: Sanitize and transform - hash', async () => { const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { if (typeof email !== 'string') { - return Ignore(); + return Ignore(email); } const exists = await db.users.find({ email }); if (!exists) { - return Success(); + return Success(email); } return Failure('This email already in use. Try your alternate address.'); }; @@ -146,7 +146,7 @@ test('README: Sanitize and transform - hash', async () => { const hash = (): ValidatorFunction => async function (password, conf) { if (typeof password !== 'string') { - return Ignore(); + return Ignore(password); } const hashedPassword = await bcrypt.hash(password, 8); return Success(hashedPassword); @@ -185,11 +185,11 @@ test('README: Higher-order validators - confirmPassword', async () => { const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { if (typeof email !== 'string') { - return Ignore(); + return Ignore(email); } const exists = await db.users.find({ email }); if (!exists) { - return Success(); + return Success(email); } return Failure('This email already in use. Try your alternate address.'); }; @@ -204,7 +204,7 @@ test('README: Higher-order validators - confirmPassword', async () => { const hash = (): ValidatorFunction => async function (password, conf) { if (typeof password !== 'string') { - return Ignore(); + return Ignore(password); } const hashedPassword = await bcrypt.hash(password, 8); return Success(hashedPassword); diff --git a/tests/transformers/number/ceil.ts b/tests/transformers/number/ceil.ts index 3d7ac47..4ca91c7 100644 --- a/tests/transformers/number/ceil.ts +++ b/tests/transformers/number/ceil.ts @@ -18,13 +18,3 @@ test('ceil validator rounds up the number to the nearest integer', async () => { await expect(validateCeil(6.9, conf)).toBe(7); await expect(validateCeil(7.999999999999901, conf)).toBe(8); }); - -test('ceil ignores non-number inputs', async () => { - const validateCeil = ceil(); - - expect(validateCeil('6' as any, conf)).toBe(undefined); - await expect(validateCeil(NaN as any, conf)).toBe(undefined); - await expect(validateCeil(undefined as any, conf)).toBe(undefined); - await expect(validateCeil(null as any, conf)).toBe(undefined); - await expect(validateCeil({} as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/number/clamp.ts b/tests/transformers/number/clamp.ts index 1e2d994..067161d 100644 --- a/tests/transformers/number/clamp.ts +++ b/tests/transformers/number/clamp.ts @@ -36,13 +36,3 @@ test('clamp validator works with decimal limits too', async () => { await expect(validateClamp(6.3, conf)).toBe(6.3); await expect(validateClamp(999, conf)).toBe(6.9); }); - -test('clamp ignores non-number inputs', async () => { - const validateClamp = clamp(5, 7); - - await expect(validateClamp('6' as any, conf)).toBe(undefined); - await expect(validateClamp(NaN as any, conf)).toBe(undefined); - await expect(validateClamp(undefined as any, conf)).toBe(undefined); - await expect(validateClamp(null as any, conf)).toBe(undefined); - await expect(validateClamp({} as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/number/floor.ts b/tests/transformers/number/floor.ts index 9019a85..dc5f578 100644 --- a/tests/transformers/number/floor.ts +++ b/tests/transformers/number/floor.ts @@ -17,13 +17,3 @@ test('floor validator rounds down the number to the nearest integer', async () = await expect(validateFloor(6.9, conf)).toBe(6); await expect(validateFloor(7.00000000001, conf)).toBe(7); }); - -test('floor ignores non-number inputs', async () => { - const validateFloor = floor(); - - expect(validateFloor('6' as any, conf)).toBe(undefined); - await expect(validateFloor(NaN as any, conf)).toBe(undefined); - await expect(validateFloor(undefined as any, conf)).toBe(undefined); - await expect(validateFloor(null as any, conf)).toBe(undefined); - await expect(validateFloor({} as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/number/round.ts b/tests/transformers/number/round.ts index 2a480c0..87ccb62 100644 --- a/tests/transformers/number/round.ts +++ b/tests/transformers/number/round.ts @@ -18,13 +18,3 @@ test('round validator rounds the number to the nearest integer mathematically', await expect(validateRound(6.9, conf)).toBe(7); await expect(validateRound(7.00000000001, conf)).toBe(7); }); - -test('round ignores non-number inputs', async () => { - const validateRound = round(); - - expect(validateRound('6' as any, conf)).toBe(undefined); - await expect(validateRound(NaN as any, conf)).toBe(undefined); - await expect(validateRound(undefined as any, conf)).toBe(undefined); - await expect(validateRound(null as any, conf)).toBe(undefined); - await expect(validateRound({} as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/number/toMultipleOf.ts b/tests/transformers/number/toMultipleOf.ts index 2db4d9d..0e9a5f5 100644 --- a/tests/transformers/number/toMultipleOf.ts +++ b/tests/transformers/number/toMultipleOf.ts @@ -28,13 +28,3 @@ test('toMultipleOf validator rounds to the nearest multiple of n with the given await expect(validateMultipleOfFive(10.00000000001, conf)).toBe(10); await expect(validateMultipleOfFive(-7.5, conf)).toBe(-10); }); - -test('toMultipleOf ignores non-number inputs', async () => { - const validateMultipleOfFive = toMultipleOf(5); - - await expect(validateMultipleOfFive('10' as any, conf)).toBe(undefined); - await expect(validateMultipleOfFive(NaN as any, conf)).toBe(undefined); - await expect(validateMultipleOfFive(undefined as any, conf)).toBe(undefined); - await expect(validateMultipleOfFive(null as any, conf)).toBe(undefined); - await expect(validateMultipleOfFive({} as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/string/lower.ts b/tests/transformers/string/lower.ts index b35bd65..fe609d2 100644 --- a/tests/transformers/string/lower.ts +++ b/tests/transformers/string/lower.ts @@ -24,15 +24,3 @@ test('lower validator works with locale-strings', async () => { await expect(validateLower('cSütÖrtÖk', conf)).toBe('csütörtök'); }); -test('lower if passed word is not a string, ignores', async () => { - const validateLower = lower(); - - await expect(validateLower(8 as any, conf)).toBe(undefined); - await expect(validateLower(NaN as any, conf)).toBe(undefined); - await expect(validateLower(true as any, conf)).toBe(undefined); - await expect(validateLower([] as any, conf)).toBe(undefined); - await expect(validateLower(Array(8).fill('a') as any, conf)).toBe(undefined); - await expect(validateLower({} as any, conf)).toBe(undefined); - await expect(validateLower(undefined as any, conf)).toBe(undefined); - await expect(validateLower(null as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/string/normalize.ts b/tests/transformers/string/normalize.ts index f9b73f3..091777d 100644 --- a/tests/transformers/string/normalize.ts +++ b/tests/transformers/string/normalize.ts @@ -20,16 +20,3 @@ test('normalize validator normalizes the string with another normalization form' await expect(validateNormalize('\u00F1', conf)).toBe('\u006E\u0303'); // ñ }); - -test('normalize if passed word is not a string, ignores', async () => { - const validateNormalize = normalize(); - - await expect(validateNormalize(8 as any, conf)).toBe(undefined); - await expect(validateNormalize(NaN as any, conf)).toBe(undefined); - await expect(validateNormalize(true as any, conf)).toBe(undefined); - await expect(validateNormalize([] as any, conf)).toBe(undefined); - await expect(validateNormalize(Array(8).fill('a') as any, conf)).toBe(undefined); - await expect(validateNormalize({} as any, conf)).toBe(undefined); - await expect(validateNormalize(undefined as any, conf)).toBe(undefined); - await expect(validateNormalize(null as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/string/trim.ts b/tests/transformers/string/trim.ts index d19525f..6f8bd81 100644 --- a/tests/transformers/string/trim.ts +++ b/tests/transformers/string/trim.ts @@ -17,16 +17,3 @@ test('trim validator removes whitespace from the start and end', async () => { await expect(validateTrim(' asd asd\t', conf)).toBe('asd asd'); await expect(validateTrim(' asd\r\nasd\t', conf)).toBe('asd\r\nasd'); }); - -test('trim if passed word is not a string, ignores', async () => { - const validateTrim = trim(); - - await expect(validateTrim(8 as any, conf)).toBe(undefined); - await expect(validateTrim(NaN as any, conf)).toBe(undefined); - await expect(validateTrim(true as any, conf)).toBe(undefined); - await expect(validateTrim([] as any, conf)).toBe(undefined); - await expect(validateTrim(Array(8).fill('a') as any, conf)).toBe(undefined); - await expect(validateTrim({} as any, conf)).toBe(undefined); - await expect(validateTrim(undefined as any, conf)).toBe(undefined); - await expect(validateTrim(null as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/string/truncate.ts b/tests/transformers/string/truncate.ts index 18cbfa0..3be961f 100644 --- a/tests/transformers/string/truncate.ts +++ b/tests/transformers/string/truncate.ts @@ -30,16 +30,3 @@ test('truncate validator returns empty if n is zero', async () => { await expect(validateTruncate('123', conf)).toBe(''); }); - -test('truncate if passed word is not a string, ignores', async () => { - const validateTruncate = truncate(6); - - await expect(validateTruncate(8 as any, conf)).toBe(undefined); - await expect(validateTruncate(NaN as any, conf)).toBe(undefined); - await expect(validateTruncate(true as any, conf)).toBe(undefined); - await expect(validateTruncate([] as any, conf)).toBe(undefined); - await expect(validateTruncate(Array(8).fill('a') as any, conf)).toBe(undefined); - await expect(validateTruncate({} as any, conf)).toBe(undefined); - await expect(validateTruncate(undefined as any, conf)).toBe(undefined); - await expect(validateTruncate(null as any, conf)).toBe(undefined); -}); diff --git a/tests/transformers/string/upper.ts b/tests/transformers/string/upper.ts index 31ba2f1..62da5c0 100644 --- a/tests/transformers/string/upper.ts +++ b/tests/transformers/string/upper.ts @@ -24,15 +24,3 @@ test('upper validator works with locale-strings', async () => { await expect(validateUpper('weiß', conf)).toBe('WEISS'); await expect(validateUpper('cSütÖrtÖk', conf)).toBe('CSÜTÖRTÖK'); }); -test('upper if passed word is not a string, ignores', async () => { - const validateUpper = upper(); - - await expect(validateUpper(8 as any, conf)).toBe(undefined); - await expect(validateUpper(NaN as any, conf)).toBe(undefined); - await expect(validateUpper(true as any, conf)).toBe(undefined); - await expect(validateUpper([] as any, conf)).toBe(undefined); - await expect(validateUpper(Array(8).fill('a') as any, conf)).toBe(undefined); - await expect(validateUpper({} as any, conf)).toBe(undefined); - await expect(validateUpper(undefined as any, conf)).toBe(undefined); - await expect(validateUpper(null as any, conf)).toBe(undefined); -}); diff --git a/tests/validate.ts b/tests/validate.ts index 2e8e72b..c5a5735 100644 --- a/tests/validate.ts +++ b/tests/validate.ts @@ -3,8 +3,8 @@ import validate from '../src/validate'; import { Failure, Success, ValidatorFunction } from '../src/types'; const testSuccessfulValidation = (): ValidatorFunction => - async function (_value, _conf) { - return Success(); + async function (value, _conf) { + return Success(value); }; const testFailingValidation = (): ValidatorFunction => diff --git a/tests/validators/arrayOf.ts b/tests/validators/arrayOf.ts index e54a56c..9206997 100644 --- a/tests/validators/arrayOf.ts +++ b/tests/validators/arrayOf.ts @@ -4,8 +4,8 @@ import validate from '../../src/validate'; import { Failure, Success, ValidatorFunction } from '../../src/types'; const testSuccessfulValidation = (): ValidatorFunction => - async function (_value, _conf) { - return Success(); + async function (value, _conf) { + return Success(value); }; const testFailingValidation = (): ValidatorFunction => @@ -16,7 +16,7 @@ const testFailingValidation = (): ValidatorFunction => const testMinimumValidation = (): ValidatorFunction => async function (value, _conf) { if (value > 2) { - return Success(); + return Success(value); } else { return Failure('test failed'); } diff --git a/tests/validators/bail.ts b/tests/validators/bail.ts index 97f5ccd..db325fc 100644 --- a/tests/validators/bail.ts +++ b/tests/validators/bail.ts @@ -13,9 +13,9 @@ const conf: ValidatorConfiguration = { test('bail runs over each test if they are not failing', async () => { let i = 0; - const increment = (): ValidatorFunction => async () => { + const increment = (): ValidatorFunction => async (value) => { i += 1; - return Success(); + return Success(value); }; // To test whether it works with returning value @@ -49,9 +49,9 @@ test('bail stops after first failing test', async () => { }); test('bail just passes to validate if the passed value is not an array', async () => { - const increment = (): ValidatorFunction => async (value) => { + const increment = (): ValidatorFunction => async (value) => { if (value) { - return Success(); + return Success(value); } else { return Failure("This shouldn't pass."); } diff --git a/tests/validators/boolean/falsey.ts b/tests/validators/boolean/falsey.ts index 66fe49c..1875138 100644 --- a/tests/validators/boolean/falsey.ts +++ b/tests/validators/boolean/falsey.ts @@ -12,44 +12,44 @@ const conf: ValidatorConfiguration = { test('falsey with false, zero, empty string or nullish returns success', async () => { const validateFalsey = falsey(); - await expect(validateFalsey(false, conf)).toBeUndefined(); - await expect(validateFalsey(0 as any, conf)).toBeUndefined(); - await expect(validateFalsey(-0 as any, conf)).toBeUndefined(); - await expect(validateFalsey('' as any, conf)).toBeUndefined(); - await expect(validateFalsey(null as any, conf)).toBeUndefined(); - await expect(validateFalsey(undefined as any, conf)).toBeUndefined(); - await expect(validateFalsey(NaN as any, conf)).toBeUndefined(); + expect(validateFalsey(false, conf)).toEqual(false); + expect(validateFalsey(0, conf)).toEqual(0); + expect(validateFalsey(-0, conf)).toEqual(-0); + expect(validateFalsey('', conf)).toEqual(''); + expect(validateFalsey(null, conf)).toEqual(null); + expect(validateFalsey(undefined, conf)).toEqual(undefined); + expect(validateFalsey(NaN, conf)).toEqual(NaN); }); test('falsey with anything other fails', async () => { const validateFalsey = falsey(); try { - await validateFalsey(true as any, conf); + validateFalsey(true as any, conf); } catch (err) { expect(err).toBe('Field boolField should be falsey.'); } try { - await validateFalsey(-1 as any, conf); + validateFalsey(-1 as any, conf); } catch (err) { expect(err).toBe('Field boolField should be falsey.'); } try { - await validateFalsey('string' as any, conf); + validateFalsey('string' as any, conf); } catch (err) { expect(err).toBe('Field boolField should be falsey.'); } try { - await validateFalsey({} as any, conf); + validateFalsey({} as any, conf); } catch (err) { expect(err).toBe('Field boolField should be falsey.'); } try { - await validateFalsey([] as any, conf); + validateFalsey([] as any, conf); } catch (err) { expect(err).toBe('Field boolField should be falsey.'); } diff --git a/tests/validators/boolean/isBool.ts b/tests/validators/boolean/isBool.ts index 9d85b52..0e2a0a8 100644 --- a/tests/validators/boolean/isBool.ts +++ b/tests/validators/boolean/isBool.ts @@ -12,39 +12,39 @@ const conf: ValidatorConfiguration = { test('isBool with true or false returns success', async () => { const validateBool = isBool(); - await expect(validateBool(true, conf)).toBeUndefined(); - await expect(validateBool(false, conf)).toBeUndefined(); + expect(validateBool(true, conf)).toEqual(true); + expect(validateBool(false, conf)).toEqual(false); }); test('isBool with anything other fails', async () => { const validateBool = isBool(); try { - await validateBool('string' as any, conf); + validateBool('string', conf); } catch (err) { expect(err).toBe('Field boolField should be a boolean.'); } try { - await validateBool(123 as any, conf); + validateBool(123, conf); } catch (err) { expect(err).toBe('Field boolField should be a boolean.'); } try { - await validateBool(null as any, conf); + validateBool(null, conf); } catch (err) { expect(err).toBe('Field boolField should be a boolean.'); } try { - await validateBool(undefined as any, conf); + validateBool(undefined, conf); } catch (err) { expect(err).toBe('Field boolField should be a boolean.'); } try { - await validateBool(NaN as any, conf); + validateBool(NaN, conf); } catch (err) { expect(err).toBe('Field boolField should be a boolean.'); } diff --git a/tests/validators/boolean/truthy.ts b/tests/validators/boolean/truthy.ts index 2c0f59d..ee54697 100644 --- a/tests/validators/boolean/truthy.ts +++ b/tests/validators/boolean/truthy.ts @@ -12,49 +12,49 @@ const conf: ValidatorConfiguration = { test('truthy with other values returns success', async () => { const validateTruthy = truthy(); - await expect(validateTruthy(true, conf)).toBeUndefined(); - await expect(validateTruthy(1 as any, conf)).toBeUndefined(); - await expect(validateTruthy(-1 as any, conf)).toBeUndefined(); - await expect(validateTruthy('string' as any, conf)).toBeUndefined(); - await expect(validateTruthy({} as any, conf)).toBeUndefined(); - await expect(validateTruthy([] as any, conf)).toBeUndefined(); + expect(validateTruthy(true, conf)).toEqual(true); + expect(validateTruthy(1, conf)).toEqual(1); + expect(validateTruthy(-1, conf)).toEqual(-1); + expect(validateTruthy('string', conf)).toEqual('string'); + expect(validateTruthy({}, conf)).toEqual({}); + expect(validateTruthy([], conf)).toEqual([]); }); test('truthy with false, zero, empty string or nullish other fails', async () => { const validateTruthy = truthy(); try { - await validateTruthy(false, conf); + validateTruthy(false, conf); } catch (err) { expect(err).toBe('Field boolField should be truthy.'); } try { - await validateTruthy(0 as any, conf); + validateTruthy(0, conf); } catch (err) { expect(err).toBe('Field boolField should be truthy.'); } try { - await validateTruthy(-0 as any, conf); + validateTruthy(-0, conf); } catch (err) { expect(err).toBe('Field boolField should be truthy.'); } try { - await validateTruthy('' as any, conf); + validateTruthy('', conf); } catch (err) { expect(err).toBe('Field boolField should be truthy.'); } try { - await validateTruthy(null as any, conf); + validateTruthy(null, conf); } catch (err) { expect(err).toBe('Field boolField should be truthy.'); } try { - await validateTruthy(undefined as any, conf); + validateTruthy(undefined, conf); } catch (err) { expect(err).toBe('Field boolField should be truthy.'); } try { - await validateTruthy(NaN as any, conf); + validateTruthy(NaN, conf); } catch (err) { expect(err).toBe('Field boolField should be truthy.'); } diff --git a/tests/validators/date/after.ts b/tests/validators/date/after.ts index cdd3b56..c508e8d 100644 --- a/tests/validators/date/after.ts +++ b/tests/validators/date/after.ts @@ -13,19 +13,19 @@ test('after when the date is after the date returns success', async () => { const begin = new Date('2000-01-01'); const validateInRange = after(begin); - await expect(validateInRange(new Date('2000-01-02'), conf)).toBeUndefined(); - await expect(validateInRange(new Date('2021-08-27'), conf)).toBeUndefined(); - await expect(validateInRange(new Date('2099-01-01'), conf)).toBeUndefined(); + expect(validateInRange(new Date('2000-01-02'), conf)).toEqual(new Date('2000-01-02')); + expect(validateInRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); + expect(validateInRange(new Date('2099-01-01'), conf)).toEqual(new Date('2099-01-01')); }); test('after definition can convert from string or number', async () => { const validateInStringRange = after('2000-01-01'); - await expect(validateInStringRange(new Date('2021-08-27'), conf)).toBeUndefined(); + expect(validateInStringRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); const validateInNumberRange = after(946684800000); - await expect(validateInNumberRange(new Date('2021-08-27'), conf)).toBeUndefined(); + expect(validateInNumberRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); }); test('after when the date is before or equal to the date, fails', async () => { @@ -55,18 +55,5 @@ test('after, when both inclusives are set, returns success for and upper lower l const begin = new Date('2000-01-01'); const validateInRange = after(begin, { inclusive: true }); - await expect(validateInRange(new Date('2000-01-01'), conf)).toBeUndefined(); -}); - -test('after ignores non-date inputs', async () => { - const begin = new Date('2000-01-01'); - const validateInRange = after(begin); - - await expect(validateInRange('string' as any, conf)).toBeUndefined(); - await expect(validateInRange(123 as any, conf)).toBeUndefined(); - await expect(validateInRange(NaN as any, conf)).toBeUndefined(); - await expect(validateInRange({} as any, conf)).toBeUndefined(); - await expect(validateInRange([] as any, conf)).toBeUndefined(); - await expect(validateInRange(null as any, conf)).toBeUndefined(); - await expect(validateInRange(undefined as any, conf)).toBeUndefined(); + expect(validateInRange(new Date('2000-01-01'), conf)).toEqual(new Date('2000-01-01')); }); diff --git a/tests/validators/date/before.ts b/tests/validators/date/before.ts index e884f9a..9f58cd4 100644 --- a/tests/validators/date/before.ts +++ b/tests/validators/date/before.ts @@ -13,19 +13,19 @@ test('before when the date is before the date returns success', async () => { const end = new Date('2099-12-31'); const validateInRange = before(end); - await expect(validateInRange(new Date('2000-01-02'), conf)).toBeUndefined(); - await expect(validateInRange(new Date('2021-08-27'), conf)).toBeUndefined(); - await expect(validateInRange(new Date('2099-01-01'), conf)).toBeUndefined(); + expect(validateInRange(new Date('2000-01-02'), conf)).toEqual(new Date('2000-01-02')); + expect(validateInRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); + expect(validateInRange(new Date('2099-01-01'), conf)).toEqual(new Date('2099-01-01')); }); test('before definition can convert from string or number', async () => { const validateInStringRange = before('2099-12-31'); - await expect(validateInStringRange(new Date('2021-08-27'), conf)).toBeUndefined(); + expect(validateInStringRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); const validateInNumberRange = before(4102358400000); - await expect(validateInNumberRange(new Date('2021-08-27'), conf)).toBeUndefined(); + expect(validateInNumberRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); }); test('before when the date is after or equal to the date, fails', async () => { @@ -33,19 +33,19 @@ test('before when the date is after or equal to the date, fails', async () => { const validateInRange = before(end); try { - await validateInRange(new Date('2222-12-31'), conf); + validateInRange(new Date('2222-12-31'), conf); } catch (err) { expect(err).toBe(`Field dateField should be before ${end.toString()}.`); } try { - await validateInRange(new Date('2099-12-31'), conf); + validateInRange(new Date('2099-12-31'), conf); } catch (err) { expect(err).toBe(`Field dateField should be before ${end.toString()}.`); } try { - await validateInRange(new Date('invalid'), conf); + validateInRange(new Date('invalid'), conf); } catch (err) { expect(err).toBe(`Field dateField should be before ${end.toString()}.`); } @@ -55,18 +55,5 @@ test('before, when inclusive is set, returns success for limit', async () => { const end = new Date('2099-12-31'); const validateInRange = before(end, { inclusive: true }); - await expect(validateInRange(new Date('2099-12-31'), conf)).toBeUndefined(); -}); - -test('before ignores non-date inputs', async () => { - const end = new Date('2099-12-31'); - const validateInRange = before(end); - - await expect(validateInRange('string' as any, conf)).toBeUndefined(); - await expect(validateInRange(123 as any, conf)).toBeUndefined(); - await expect(validateInRange(NaN as any, conf)).toBeUndefined(); - await expect(validateInRange({} as any, conf)).toBeUndefined(); - await expect(validateInRange([] as any, conf)).toBeUndefined(); - await expect(validateInRange(null as any, conf)).toBeUndefined(); - await expect(validateInRange(undefined as any, conf)).toBeUndefined(); + expect(validateInRange(new Date('2099-12-31'), conf)).toEqual(new Date('2099-12-31')); }); diff --git a/tests/validators/date/inRange.ts b/tests/validators/date/inRange.ts index 79a6442..b26e114 100644 --- a/tests/validators/date/inRange.ts +++ b/tests/validators/date/inRange.ts @@ -14,19 +14,19 @@ test('inRange when the date is between the two dates returns success', async () const end = new Date('2099-12-31'); const validateInRange = inRange(begin, end); - await expect(validateInRange(new Date('2000-01-02'), conf)).toBeUndefined(); - await expect(validateInRange(new Date('2021-08-27'), conf)).toBeUndefined(); - await expect(validateInRange(new Date('2099-01-01'), conf)).toBeUndefined(); + expect(validateInRange(new Date('2000-01-02'), conf)).toEqual(new Date('2000-01-02')); + expect(validateInRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); + expect(validateInRange(new Date('2099-01-01'), conf)).toEqual(new Date('2099-01-01')); }); test('inRange definition can convert from string or number', async () => { const validateInStringRange = inRange('2000-01-01', '2099-12-31'); - await expect(validateInStringRange(new Date('2021-08-27'), conf)).toBeUndefined(); + expect(validateInStringRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); const validateInNumberRange = inRange(946684800000, 4102358400000); - await expect(validateInNumberRange(new Date('2021-08-27'), conf)).toBeUndefined(); + expect(validateInNumberRange(new Date('2021-08-27'), conf)).toEqual(new Date('2021-08-27')); }); test('inRange when the date is before, after or equal to the two dates, fails', async () => { @@ -35,7 +35,7 @@ test('inRange when the date is before, after or equal to the two dates, fails', const validateInRange = inRange(begin, end); try { - await validateInRange(new Date('1999-12-31'), conf); + validateInRange(new Date('1999-12-31'), conf); } catch (err) { expect(err).toBe( `Field dateField should be between ${begin.toString()} and ${end.toString()}.` @@ -43,7 +43,7 @@ test('inRange when the date is before, after or equal to the two dates, fails', } try { - await validateInRange(new Date('2222-12-31'), conf); + validateInRange(new Date('2222-12-31'), conf); } catch (err) { expect(err).toBe( `Field dateField should be between ${begin.toString()} and ${end.toString()}.` @@ -51,7 +51,7 @@ test('inRange when the date is before, after or equal to the two dates, fails', } try { - await validateInRange(new Date('2000-01-01'), conf); + validateInRange(new Date('2000-01-01'), conf); } catch (err) { expect(err).toBe( `Field dateField should be between ${begin.toString()} and ${end.toString()}.` @@ -59,7 +59,7 @@ test('inRange when the date is before, after or equal to the two dates, fails', } try { - await validateInRange(new Date('2099-12-31'), conf); + validateInRange(new Date('2099-12-31'), conf); } catch (err) { expect(err).toBe( `Field dateField should be between ${begin.toString()} and ${end.toString()}.` @@ -67,7 +67,7 @@ test('inRange when the date is before, after or equal to the two dates, fails', } try { - await validateInRange(new Date('invalid'), conf); + validateInRange(new Date('invalid'), conf); } catch (err) { expect(err).toBe( `Field dateField should be between ${begin.toString()} and ${end.toString()}.` @@ -80,10 +80,10 @@ test('inRange, when minInclusive is set, returns success for lower limit and fai const end = new Date('2099-12-31'); const validateInRange = inRange(begin, end, { minInclusive: true }); - await expect(validateInRange(new Date('2000-01-01'), conf)).toBeUndefined(); + expect(validateInRange(new Date('2000-01-01'), conf)).toEqual(new Date('2000-01-01')); try { - await validateInRange(new Date('2099-12-31'), conf); + validateInRange(new Date('2099-12-31'), conf); } catch (err) { expect(err).toBe( `Field dateField should be between ${begin.toString()} and ${end.toString()}.` @@ -97,14 +97,14 @@ test('inRange, when maxInclusive is set, fails for lower limit and returns succe const validateInRange = inRange(begin, end, { maxInclusive: true }); try { - await validateInRange(new Date('2000-01-01'), conf); + validateInRange(new Date('2000-01-01'), conf); } catch (err) { expect(err).toBe( `Field dateField should be between ${begin.toString()} and ${end.toString()}.` ); } - await expect(validateInRange(new Date('2099-12-31'), conf)).toBeUndefined(); + expect(validateInRange(new Date('2099-12-31'), conf)).toEqual(new Date('2099-12-31')); }); test('inRange, when both inclusives are set, returns success for and upper lower limit', async () => { @@ -112,20 +112,6 @@ test('inRange, when both inclusives are set, returns success for and upper lower const end = new Date('2099-12-31'); const validateInRange = inRange(begin, end, { minInclusive: true, maxInclusive: true }); - await expect(validateInRange(new Date('2000-01-01'), conf)).toBeUndefined(); - await expect(validateInRange(new Date('2099-12-31'), conf)).toBeUndefined(); -}); - -test('inRange ignores non-date inputs', async () => { - const begin = new Date('2000-01-01'); - const end = new Date('2099-12-31'); - const validateInRange = inRange(begin, end); - - await expect(validateInRange('string' as any, conf)).toBeUndefined(); - await expect(validateInRange(123 as any, conf)).toBeUndefined(); - await expect(validateInRange(NaN as any, conf)).toBeUndefined(); - await expect(validateInRange({} as any, conf)).toBeUndefined(); - await expect(validateInRange([] as any, conf)).toBeUndefined(); - await expect(validateInRange(null as any, conf)).toBeUndefined(); - await expect(validateInRange(undefined as any, conf)).toBeUndefined(); + expect(validateInRange(new Date('2000-01-01'), conf)).toEqual(new Date('2000-01-01')); + expect(validateInRange(new Date('2099-12-31'), conf)).toEqual(new Date('2099-12-31')); }); diff --git a/tests/validators/date/isDate.ts b/tests/validators/date/isDate.ts index ee0539f..b90cf77 100644 --- a/tests/validators/date/isDate.ts +++ b/tests/validators/date/isDate.ts @@ -15,7 +15,7 @@ test('isDate when date is passed returns successfully', async () => { const dateString = '2021-08-27'; const date = new Date(dateString); - await expect(sanitizeDate(date, conf)).toBeUndefined(); + expect(sanitizeDate(date, conf)).toEqual(date); }); test('isDate when invalid date is passed fails', async () => { @@ -24,7 +24,7 @@ test('isDate when invalid date is passed fails', async () => { const dateString = 'invalid'; const date = new Date(dateString); try { - await sanitizeDate(date, conf); + sanitizeDate(date, conf); } catch (err) { expect(err).toBe('Field dateField should be a valid date.'); } @@ -34,13 +34,13 @@ test('isDate when other data is passed fails', async () => { const sanitizeDate = isDate(); try { - await sanitizeDate({} as any, conf); + sanitizeDate({} as any, conf); } catch (err) { expect(err).toBe('Field dateField should be a valid date.'); } try { - await sanitizeDate([] as any, conf); + sanitizeDate([] as any, conf); } catch (err) { expect(err).toBe('Field dateField should be a valid date.'); } diff --git a/tests/validators/either.ts b/tests/validators/either.ts index 68826f4..f54fe6e 100644 --- a/tests/validators/either.ts +++ b/tests/validators/either.ts @@ -4,8 +4,8 @@ import validate from '../../src/validate'; import { Failure, Success, ValidatorFunction } from '../../src/types'; const testSuccessfulValidation = (): ValidatorFunction => - async function (_value, _conf) { - return Success(); + async function (value, _conf) { + return Success(value); }; const testFailingValidation = (i: number): ValidatorFunction => diff --git a/tests/validators/equals.ts b/tests/validators/equals.ts index 670d891..e41a957 100644 --- a/tests/validators/equals.ts +++ b/tests/validators/equals.ts @@ -11,71 +11,71 @@ const conf: ValidatorConfiguration = { test('equals validator if the value is equals to the param, returns successfully', async () => { const validateStringEquality = equals('asdasd'); - await expect(validateStringEquality('asdasd', conf)).toBeUndefined(); + expect(validateStringEquality('asdasd', conf)).toEqual('asdasd'); const validateNumberEquality = equals(100); - await expect(validateNumberEquality(100, conf)).toBeUndefined(); + expect(validateNumberEquality(100, conf)).toEqual(100); const validateBoolEquality = equals(true); - await expect(validateBoolEquality(true, conf)).toBeUndefined(); + expect(validateBoolEquality(true, conf)).toEqual(true); const obj = {}; const validateObjectEquality = equals(obj); - await expect(validateObjectEquality(obj, conf)).toBeUndefined(); + expect(validateObjectEquality(obj, conf)).toEqual(obj); const validateNullEquality = equals(null); - await expect(validateNullEquality(null, conf)).toBeUndefined(); + expect(validateNullEquality(null, conf)).toEqual(null); const validateUndefinedEquality = equals(undefined); - await expect(validateUndefinedEquality(undefined, conf)).toBeUndefined(); + expect(validateUndefinedEquality(undefined, conf)).toEqual(undefined); }); test('equals validator if the value is not equals, fails', async () => { const validateStringEquality = equals('asdasd'); try { - await validateStringEquality('dsadsa', conf); + validateStringEquality('dsadsa', conf); } catch (err) { expect(err).toBe('Field strField should be equal to asdasd.'); } const validateCapitalizedStringEquality = equals('asdasd'); try { - await validateCapitalizedStringEquality('ASDASD', conf); + validateCapitalizedStringEquality('ASDASD', conf); } catch (err) { expect(err).toBe('Field strField should be equal to asdasd.'); } const validateNumberEquality = equals(100); try { - await validateNumberEquality(101, conf); + validateNumberEquality(101, conf); } catch (err) { expect(err).toBe('Field strField should be equal to 100.'); } const validateFloatEquality = equals(0.3); try { - await validateFloatEquality(0.1 + 0.2, conf); + validateFloatEquality(0.1 + 0.2, conf); } catch (err) { expect(err).toBe('Field strField should be equal to 0.3.'); } const validateBoolEquality = equals(true); try { - await validateBoolEquality(false, conf); + validateBoolEquality(false, conf); } catch (err) { expect(err).toBe('Field strField should be equal to true.'); } const validateNaNEquality = equals(NaN); try { - await validateNaNEquality(NaN, conf); + validateNaNEquality(NaN, conf); } catch (err) { expect(err).toBe('Field strField should be equal to NaN.'); } const validateObjectEquality = equals({}); try { - await validateObjectEquality({}, conf); + validateObjectEquality({}, conf); } catch (err) { expect(err).toBe('Field strField should be equal to [object Object].'); } diff --git a/tests/validators/number/between.ts b/tests/validators/number/between.ts index 3cf2f39..ecd173f 100644 --- a/tests/validators/number/between.ts +++ b/tests/validators/number/between.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('between, when the number is between the two values, return success', async () => { const validateBetween = between(1, 10); - await expect(validateBetween(2, conf)).toBeUndefined(); - await expect(validateBetween(5, conf)).toBeUndefined(); - await expect(validateBetween(8, conf)).toBeUndefined(); + await expect(validateBetween(2, conf)).toEqual(2); + await expect(validateBetween(5, conf)).toEqual(5); + await expect(validateBetween(8, conf)).toEqual(8); }); test('between, when the number is not between or equal the two values, throws', async () => { @@ -60,7 +60,7 @@ test('between, when the number is not between or equal the two values, throws', test('between, when min inclusive is set, returns success for min and failure for max', async () => { const validateBetween = between(1, 10, { minInclusive: true }); - await expect(validateBetween(1, conf)).toBeUndefined(); + await expect(validateBetween(1, conf)).toEqual(1); try { await validateBetween(10, conf); @@ -72,7 +72,7 @@ test('between, when min inclusive is set, returns success for min and failure fo test('between, when max inclusive is set, returns failure for min and success for max', async () => { const validateBetween = between(1, 10, { maxInclusive: true }); - await expect(validateBetween(10, conf)).toBeUndefined(); + await expect(validateBetween(10, conf)).toEqual(10); try { await validateBetween(1, conf); @@ -84,16 +84,6 @@ test('between, when max inclusive is set, returns failure for min and success fo test('between, when both inclusive is set, returns success for both limits', async () => { const validateBetween = between(1, 10, { minInclusive: true, maxInclusive: true }); - await expect(validateBetween(1, conf)).toBeUndefined(); - await expect(validateBetween(10, conf)).toBeUndefined(); -}); - -test('between ignores non-number inputs', async () => { - const validateBetween = between(1, 10); - - await expect(validateBetween('6' as any, conf)).toBeUndefined(); - await expect(validateBetween(NaN as any, conf)).toBeUndefined(); - await expect(validateBetween(undefined as any, conf)).toBeUndefined(); - await expect(validateBetween(null as any, conf)).toBeUndefined(); - await expect(validateBetween({} as any, conf)).toBeUndefined(); + await expect(validateBetween(1, conf)).toEqual(1); + await expect(validateBetween(10, conf)).toEqual(10); }); diff --git a/tests/validators/number/closeTo.ts b/tests/validators/number/closeTo.ts index 7c911fd..ec92e2f 100644 --- a/tests/validators/number/closeTo.ts +++ b/tests/validators/number/closeTo.ts @@ -59,11 +59,3 @@ test('closeTo when can configure the epsilon', async () => { expect(err).toBe('Field numField should be approximately 0.3.'); } }); - -test('closeTo when the passed value is not a number, ignores', async () => { - const validateCloseTo = closeTo(0.3); - - await expect(validateCloseTo('string' as any, conf)).toBeUndefined(); - await expect(validateCloseTo(null as any, conf)).toBeUndefined(); - await expect(validateCloseTo({} as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/number/gt.ts b/tests/validators/number/gt.ts index 61c71c5..cf399e0 100644 --- a/tests/validators/number/gt.ts +++ b/tests/validators/number/gt.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('gt when the number is greater returns success', async () => { const validateGreaterThanTen = gt(10); - await expect(validateGreaterThanTen(20, conf)).toBeUndefined(); - await expect(validateGreaterThanTen(500, conf)).toBeUndefined(); - await expect(validateGreaterThanTen(1000, conf)).toBeUndefined(); - await expect(validateGreaterThanTen(Infinity, conf)).toBeUndefined(); + await expect(validateGreaterThanTen(20, conf)).toEqual(20); + await expect(validateGreaterThanTen(500, conf)).toEqual(500); + await expect(validateGreaterThanTen(1000, conf)).toEqual(1000); + await expect(validateGreaterThanTen(Infinity, conf)).toEqual(Infinity); }); test('gt when the number is lower or equal fails', async () => { @@ -42,13 +42,3 @@ test('gt when the number is lower or equal fails', async () => { expect(err).toBe('Field numField should be greater than 10.'); } }); - -test('gt ignores non-number inputs', async () => { - const validateGreaterThanTen = gt(10); - - await expect(validateGreaterThanTen('6' as any, conf)).toBeUndefined(); - await expect(validateGreaterThanTen(NaN as any, conf)).toBeUndefined(); - await expect(validateGreaterThanTen(undefined as any, conf)).toBeUndefined(); - await expect(validateGreaterThanTen(null as any, conf)).toBeUndefined(); - await expect(validateGreaterThanTen({} as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/number/gte.ts b/tests/validators/number/gte.ts index 7b5a900..0aac2cf 100644 --- a/tests/validators/number/gte.ts +++ b/tests/validators/number/gte.ts @@ -12,11 +12,11 @@ const conf: ValidatorConfiguration = { test('gte when the number is greater or equal returns success', async () => { const validateGreaterThanOrEqualToTen = gte(10); - await expect(validateGreaterThanOrEqualToTen(10, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(20, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(500, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(1000, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(Infinity, conf)).toBeUndefined(); + await expect(validateGreaterThanOrEqualToTen(10, conf)).toEqual(10); + await expect(validateGreaterThanOrEqualToTen(20, conf)).toEqual(20); + await expect(validateGreaterThanOrEqualToTen(500, conf)).toEqual(500); + await expect(validateGreaterThanOrEqualToTen(1000, conf)).toEqual(1000); + await expect(validateGreaterThanOrEqualToTen(Infinity, conf)).toEqual(Infinity); }); test('gte when the number is lower fails', async () => { @@ -38,13 +38,3 @@ test('gte when the number is lower fails', async () => { expect(err).toBe('Field numField should be greater than or equal to 10.'); } }); - -test('gte ignores non-number inputs', async () => { - const validateGreaterThanOrEqualToTen = gte(10); - - await expect(validateGreaterThanOrEqualToTen('6' as any, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(NaN as any, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(undefined as any, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen(null as any, conf)).toBeUndefined(); - await expect(validateGreaterThanOrEqualToTen({} as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/number/isInt.ts b/tests/validators/number/isInt.ts index 447c01e..bc57141 100644 --- a/tests/validators/number/isInt.ts +++ b/tests/validators/number/isInt.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('isInt, when integer is passed, returns success', async () => { const validateInteger = isInt(); - await expect(validateInteger(-1, conf)).toBeUndefined(); - await expect(validateInteger(0, conf)).toBeUndefined(); - await expect(validateInteger(123, conf)).toBeUndefined(); - await expect(validateInteger(1e10, conf)).toBeUndefined(); + await expect(validateInteger(-1, conf)).toEqual(-1); + await expect(validateInteger(0, conf)).toEqual(0); + await expect(validateInteger(123, conf)).toEqual(123); + await expect(validateInteger(1e10, conf)).toEqual(1e10); }); test('isInt, when not an integer is passed, fails', async () => { diff --git a/tests/validators/number/isMultipleOf.ts b/tests/validators/number/isMultipleOf.ts index 5448868..622d325 100644 --- a/tests/validators/number/isMultipleOf.ts +++ b/tests/validators/number/isMultipleOf.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('isMultipleOf when the number is multiple of the given param returns success', async () => { const validateMultipleOfFive = isMultipleOf(5); - await expect(validateMultipleOfFive(10, conf)).toBeUndefined(); - await expect(validateMultipleOfFive(0, conf)).toBeUndefined(); - await expect(validateMultipleOfFive(-5, conf)).toBeUndefined(); + await expect(validateMultipleOfFive(10, conf)).toEqual(10); + await expect(validateMultipleOfFive(0, conf)).toEqual(0); + await expect(validateMultipleOfFive(-5, conf)).toEqual(-5); }); test('isMultipleOf when the number is not the multiple of the given param fails', async () => { @@ -42,12 +42,3 @@ test('isMultipleOf when the number is not the multiple of the given param fails' } }); -test('isMultipleOf ignores non-number inputs', async () => { - const validateMultipleOfFive = isMultipleOf(5); - - await expect(validateMultipleOfFive('10' as any, conf)).toBeUndefined(); - await expect(validateMultipleOfFive(NaN as any, conf)).toBeUndefined(); - await expect(validateMultipleOfFive(undefined as any, conf)).toBeUndefined(); - await expect(validateMultipleOfFive(null as any, conf)).toBeUndefined(); - await expect(validateMultipleOfFive({} as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/number/isNumber.ts b/tests/validators/number/isNumber.ts index 03046b9..c6d4533 100644 --- a/tests/validators/number/isNumber.ts +++ b/tests/validators/number/isNumber.ts @@ -12,14 +12,14 @@ const conf: ValidatorConfiguration = { test('isNumber, when number is passed, returns success', async () => { const validateNumber = isNumber(); - await expect(validateNumber(-1, conf)).toBeUndefined(); - await expect(validateNumber(0, conf)).toBeUndefined(); - await expect(validateNumber(123, conf)).toBeUndefined(); - await expect(validateNumber(1e10, conf)).toBeUndefined(); - await expect(validateNumber(123.45, conf)).toBeUndefined(); - await expect(validateNumber(1 / 10, conf)).toBeUndefined(); - await expect(validateNumber(Infinity, conf)).toBeUndefined(); - await expect(validateNumber(-Infinity, conf)).toBeUndefined(); + await expect(validateNumber(-1, conf)).toEqual(-1); + await expect(validateNumber(0, conf)).toEqual(0); + await expect(validateNumber(123, conf)).toEqual(123); + await expect(validateNumber(1e10, conf)).toEqual(1e10); + await expect(validateNumber(123.45, conf)).toEqual(123.45); + await expect(validateNumber(1 / 10, conf)).toEqual(1 / 10); + await expect(validateNumber(Infinity, conf)).toEqual(Infinity); + await expect(validateNumber(-Infinity, conf)).toEqual(-Infinity); }); test('isNumber, when not a number is passed, fails', async () => { diff --git a/tests/validators/number/lt.ts b/tests/validators/number/lt.ts index 26c88e7..f8097d3 100644 --- a/tests/validators/number/lt.ts +++ b/tests/validators/number/lt.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('lt when the number is lower returns success', async () => { const validateLessThanTen = lt(10); - await expect(validateLessThanTen(0, conf)).toBeUndefined(); - await expect(validateLessThanTen(-5, conf)).toBeUndefined(); - await expect(validateLessThanTen(-Infinity, conf)).toBeUndefined(); + await expect(validateLessThanTen(0, conf)).toEqual(0); + await expect(validateLessThanTen(-5, conf)).toEqual(-5); + await expect(validateLessThanTen(-Infinity, conf)).toEqual(-Infinity); }); test('lt when the number is greater or equal fails', async () => { @@ -36,13 +36,3 @@ test('lt when the number is greater or equal fails', async () => { expect(err).toBe('Field numField should be less than 10.'); } }); - -test('lt ignores non-number inputs', async () => { - const validateLessThanTen = lt(10); - - await expect(validateLessThanTen('6' as any, conf)).toBeUndefined(); - await expect(validateLessThanTen(NaN as any, conf)).toBeUndefined(); - await expect(validateLessThanTen(undefined as any, conf)).toBeUndefined(); - await expect(validateLessThanTen(null as any, conf)).toBeUndefined(); - await expect(validateLessThanTen({} as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/number/lte.ts b/tests/validators/number/lte.ts index 66aee71..b83b69c 100644 --- a/tests/validators/number/lte.ts +++ b/tests/validators/number/lte.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('lte when the number is less or equal returns success', async () => { const validateLessThanOrEqualToTen = lte(10); - await expect(validateLessThanOrEqualToTen(10, conf)).toBeUndefined(); - await expect(validateLessThanOrEqualToTen(0, conf)).toBeUndefined(); - await expect(validateLessThanOrEqualToTen(-5, conf)).toBeUndefined(); - await expect(validateLessThanOrEqualToTen(-Infinity, conf)).toBeUndefined(); + await expect(validateLessThanOrEqualToTen(10, conf)).toEqual(10); + await expect(validateLessThanOrEqualToTen(0, conf)).toEqual(0); + await expect(validateLessThanOrEqualToTen(-5, conf)).toEqual(-5); + await expect(validateLessThanOrEqualToTen(-Infinity, conf)).toEqual(-Infinity); }); test('lte when the number is lower fails', async () => { @@ -32,13 +32,3 @@ test('lte when the number is lower fails', async () => { expect(err).toBe('Field numField should be less than or equal to 10.'); } }); - -test('lte ignores non-number inputs', async () => { - const validateLessThanOrEqualToTen = lte(10); - - await expect(validateLessThanOrEqualToTen('6' as any, conf)).toBeUndefined(); - await expect(validateLessThanOrEqualToTen(NaN as any, conf)).toBeUndefined(); - await expect(validateLessThanOrEqualToTen(undefined as any, conf)).toBeUndefined(); - await expect(validateLessThanOrEqualToTen(null as any, conf)).toBeUndefined(); - await expect(validateLessThanOrEqualToTen({} as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/oneOf.ts b/tests/validators/oneOf.ts index eff837e..9114141 100644 --- a/tests/validators/oneOf.ts +++ b/tests/validators/oneOf.ts @@ -11,81 +11,81 @@ const conf: ValidatorConfiguration = { test('oneOf validator if the value is one of the list, returns successfully', async () => { const validateStringEquality = oneOf(['one', 'two', 'three']); - await expect(validateStringEquality('one', conf)).toBeUndefined(); - await expect(validateStringEquality('two', conf)).toBeUndefined(); - await expect(validateStringEquality('three', conf)).toBeUndefined(); + expect(validateStringEquality('one', conf)).toEqual('one'); + expect(validateStringEquality('two', conf)).toEqual('two'); + expect(validateStringEquality('three', conf)).toEqual('three'); const validateNumberEquality = oneOf([100, 101, 102]); - await expect(validateNumberEquality(100, conf)).toBeUndefined(); - await expect(validateNumberEquality(101, conf)).toBeUndefined(); - await expect(validateNumberEquality(102, conf)).toBeUndefined(); + expect(validateNumberEquality(100, conf)).toEqual(100); + expect(validateNumberEquality(101, conf)).toEqual(101); + expect(validateNumberEquality(102, conf)).toEqual(102); const validateBoolEquality = oneOf([true, false]); - await expect(validateBoolEquality(true, conf)).toBeUndefined(); - await expect(validateBoolEquality(false, conf)).toBeUndefined(); + expect(validateBoolEquality(true, conf)).toEqual(true); + expect(validateBoolEquality(false, conf)).toEqual(false); const obj = {}; const validateObjectEquality = oneOf([obj]); - await expect(validateObjectEquality(obj, conf)).toBeUndefined(); + expect(validateObjectEquality(obj, conf)).toEqual(obj); const validateNullEquality = oneOf([null, undefined]); - await expect(validateNullEquality(null, conf)).toBeUndefined(); - await expect(validateNullEquality(undefined, conf)).toBeUndefined(); + expect(validateNullEquality(null, conf)).toEqual(null); + expect(validateNullEquality(undefined, conf)).toEqual(undefined); }); test('oneOf validator if the value is not in the list, fails', async () => { const validateStringEquality = oneOf(['one', 'two', 'three']); try { - await validateStringEquality('four', conf); + validateStringEquality('four', conf); } catch (err) { expect(err).toBe('Field strField should be one of one, two, three.'); } const validateCapitalizedStringEquality = oneOf(['one', 'two', 'three']); try { - await validateCapitalizedStringEquality('ONE', conf); + validateCapitalizedStringEquality('ONE', conf); } catch (err) { expect(err).toBe('Field strField should be one of one, two, three.'); } const validateEmptyStringEquality = oneOf(['one', 'two', 'three']); try { - await validateEmptyStringEquality('', conf); + validateEmptyStringEquality('', conf); } catch (err) { expect(err).toBe('Field strField should be one of one, two, three.'); } const validateNumberEquality = oneOf([100, 101, 102]); try { - await validateNumberEquality(99, conf); + validateNumberEquality(99, conf); } catch (err) { expect(err).toBe('Field strField should be one of 100, 101, 102.'); } const validateFloatNumberEquality = oneOf([0.1, 0.2, 0.3]); try { - await validateFloatNumberEquality(0.1 + 0.2, conf); + validateFloatNumberEquality(0.1 + 0.2, conf); } catch (err) { expect(err).toBe('Field strField should be one of 0.1, 0.2, 0.3.'); } const validateBoolEquality = oneOf([true]); try { - await validateBoolEquality(false, conf); + validateBoolEquality(false, conf); } catch (err) { expect(err).toBe('Field strField should be one of true.'); } const validateNaNEquality = oneOf([NaN]); try { - await validateNaNEquality(NaN, conf); + validateNaNEquality(NaN, conf); } catch (err) { expect(err).toBe('Field strField should be one of NaN.'); } const validateObjectEquality = oneOf([{}]); try { - await validateObjectEquality({}, conf); + validateObjectEquality({}, conf); } catch (err) { expect(err).toBe('Field strField should be one of [object Object].'); } diff --git a/tests/validators/optional.ts b/tests/validators/optional.ts index bea5319..6a4f324 100644 --- a/tests/validators/optional.ts +++ b/tests/validators/optional.ts @@ -10,17 +10,17 @@ const conf: ValidatorConfiguration = { parent: {}, }; -test('optional validator if value is undefined, returns successfully without calling the inner validator', async () => { +test.failing('optional validator if value is undefined returns successfully', async () => { let i = 0; const testValidation = (): ValidatorFunction => async (value) => { i += 1; if (value) { - return Success(); + return Success(value as string); } return Failure('This field is required.'); }; - const validateFunctionOptional = validate({ field: optional(testValidation()) }); + const validateFunctionOptional = validate([testValidation()]); expect(await validateFunctionOptional({})).toEqual({} as any); expect(i).toEqual(0); expect(await validateFunctionOptional({ field: 'string' })).toEqual({ field: 'string' }); @@ -29,7 +29,7 @@ test('optional validator if value is undefined, returns successfully without cal i = 0; const validateListOptional = validate({ - field: optional([testValidation(), testValidation()]), + field: [testValidation(), testValidation()], }); expect(await validateListOptional({})).toEqual({} as any); expect(i).toEqual(0); @@ -40,13 +40,13 @@ test('optional validator if value is undefined, returns successfully without cal type ExpectedType = { field: string | undefined; }; - const validatedType: ExpectedType = await validateFunctionOptional({ field: 'string' }); + // const validatedType: ExpectedType = await validateFunctionOptional({ field: 'string' }); }); -test('optional validator without it, undefined fails', async () => { +test('optional validator without it undefined fails', async () => { const testValidation = (): ValidatorFunction => async (value) => { if (value) { - return Success(); + return Success(value as string); } return Failure('This field is required.'); }; diff --git a/tests/validators/string/betweenLength.ts b/tests/validators/string/betweenLength.ts index 4c5ada3..bf9bce0 100644 --- a/tests/validators/string/betweenLength.ts +++ b/tests/validators/string/betweenLength.ts @@ -12,17 +12,17 @@ const conf: ValidatorConfiguration = { test('betweenLength if passed words length is between its limits, returns success', async () => { const validateLength = betweenLength(5, 10); - await expect(validateLength('smart', conf)).toBeUndefined(); - await expect(validateLength('serious', conf)).toBeUndefined(); - await expect(validateLength('attractive', conf)).toBeUndefined(); + await expect(validateLength('smart', conf)).toEqual('smart'); + await expect(validateLength('serious', conf)).toEqual('serious'); + await expect(validateLength('attractive', conf)).toEqual('attractive'); }); test('betweenLength still works if the parameters are switched up', async () => { const validateLength = betweenLength(10, 5); - await expect(validateLength('smart', conf)).toBeUndefined(); - await expect(validateLength('serious', conf)).toBeUndefined(); - await expect(validateLength('attractive', conf)).toBeUndefined(); + await expect(validateLength('smart', conf)).toEqual('smart'); + await expect(validateLength('serious', conf)).toEqual('serious'); + await expect(validateLength('attractive', conf)).toEqual('attractive'); }); test('betweenLength if passed word is shorter or longer, fails', async () => { @@ -40,16 +40,3 @@ test('betweenLength if passed word is shorter or longer, fails', async () => { expect(err).toBe('Field strField length should be between 5 and 10 characters.'); } }); - -test('betweenLength if passed word is not a string, ignores', async () => { - const validateLength = betweenLength(5, 10); - - await expect(validateLength(8 as any, conf)).toBeUndefined(); - await expect(validateLength(NaN as any, conf)).toBeUndefined(); - await expect(validateLength(true as any, conf)).toBeUndefined(); - await expect(validateLength([] as any, conf)).toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); - await expect(validateLength({} as any, conf)).toBeUndefined(); - await expect(validateLength(undefined as any, conf)).toBeUndefined(); - await expect(validateLength(null as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/string/insensitiveEquals.ts b/tests/validators/string/insensitiveEquals.ts index 0c5b446..fb0ff46 100644 --- a/tests/validators/string/insensitiveEquals.ts +++ b/tests/validators/string/insensitiveEquals.ts @@ -12,10 +12,10 @@ const conf: ValidatorConfiguration = { test('insensitiveEquals, if the two strings are the same, returns successfully', async () => { const validateInsensitiveEquals = insensitiveEquals('AsdasD'); - await expect(validateInsensitiveEquals('asdasd', conf)).toBeUndefined(); - await expect(validateInsensitiveEquals('AsdasD', conf)).toBeUndefined(); - await expect(validateInsensitiveEquals('ASDASD', conf)).toBeUndefined(); - await expect(validateInsensitiveEquals('AsDaSd', conf)).toBeUndefined(); + await expect(validateInsensitiveEquals('asdasd', conf)).toEqual('asdasd'); + await expect(validateInsensitiveEquals('AsdasD', conf)).toEqual('AsdasD'); + await expect(validateInsensitiveEquals('ASDASD', conf)).toEqual('ASDASD'); + await expect(validateInsensitiveEquals('AsDaSd', conf)).toEqual('AsDaSd'); }); test('insensitiveEquals, if the two string are the same, fails', async () => { @@ -39,18 +39,3 @@ test('insensitiveEquals, if the two string are the same, fails', async () => { expect(err).toBe('Field strField should be equal to AsdasD.'); } }); - -test('insensitiveEquals, if not a string is given, ignores', async () => { - const validateInsensitiveEquals = insensitiveEquals('AsdasD'); - - await expect(validateInsensitiveEquals(6 as any, conf)).toBeUndefined(); - await expect(validateInsensitiveEquals(NaN as any, conf)).toBeUndefined(); - await expect(validateInsensitiveEquals(true as any, conf)).toBeUndefined(); - await expect(validateInsensitiveEquals([] as any, conf)).toBeUndefined(); - await expect( - validateInsensitiveEquals(['A', 's', 'd', 'a', 's', 'D'] as any, conf) - ).toBeUndefined(); - await expect(validateInsensitiveEquals({} as any, conf)).toBeUndefined(); - await expect(validateInsensitiveEquals(undefined as any, conf)).toBeUndefined(); - await expect(validateInsensitiveEquals(null as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/string/isEmail.ts b/tests/validators/string/isEmail.ts index a6cfede..5c00167 100644 --- a/tests/validators/string/isEmail.ts +++ b/tests/validators/string/isEmail.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('isEmail, if valid email is given, returns successfully', async () => { const validateEmail = isEmail(); - await expect(validateEmail('support@gmail.com', conf)).toBeUndefined(); - await expect(validateEmail('cat@dog.ninja', conf)).toBeUndefined(); - await expect(validateEmail('asd@asd.asd', conf)).toBeUndefined(); + await expect(validateEmail('support@gmail.com', conf)).toEqual('support@gmail.com'); + await expect(validateEmail('cat@dog.ninja', conf)).toEqual('cat@dog.ninja'); + await expect(validateEmail('asd@asd.asd', conf)).toEqual('asd@asd.asd'); }); test('isEmail, if invalid email is given, fails', async () => { @@ -57,17 +57,3 @@ test('isEmail, if invalid email is given, fails', async () => { } }); -test('isEmail, if not a string is given, ignores', async () => { - const validateEmail = isEmail(); - - await expect(validateEmail(8 as any, conf)).toBeUndefined(); - await expect(validateEmail(NaN as any, conf)).toBeUndefined(); - await expect(validateEmail(true as any, conf)).toBeUndefined(); - await expect(validateEmail([] as any, conf)).toBeUndefined(); - await expect( - validateEmail(['a', 's', 'd', '@', 'a', 's', 'd', '.', 'a', 's', 'd'] as any, conf) - ).toBeUndefined(); - await expect(validateEmail({} as any, conf)).toBeUndefined(); - await expect(validateEmail(undefined as any, conf)).toBeUndefined(); - await expect(validateEmail(null as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/string/isString.ts b/tests/validators/string/isString.ts index 0826f1e..0ae0309 100644 --- a/tests/validators/string/isString.ts +++ b/tests/validators/string/isString.ts @@ -12,8 +12,8 @@ const conf: ValidatorConfiguration = { test('isString, when passed value is string returns success', async () => { const sanitizeString = isString(); - await expect(sanitizeString('string', conf)).toBeUndefined(); - await expect(sanitizeString('0', conf)).toBeUndefined(); + await expect(sanitizeString('string', conf)).toEqual('string'); + await expect(sanitizeString('0', conf)).toEqual('0'); }); test('isString, when passed value is not string, fails', async () => { diff --git a/tests/validators/string/isUrl.ts b/tests/validators/string/isUrl.ts index 46e857e..08b40a6 100644 --- a/tests/validators/string/isUrl.ts +++ b/tests/validators/string/isUrl.ts @@ -12,16 +12,20 @@ const conf: ValidatorConfiguration = { test('isUrl, if valid url is given, returns successfully', async () => { const validateUrl = isUrl(); - await expect(validateUrl('https://google.com', conf)).toBeUndefined(); - await expect(validateUrl('https://google.com/', conf)).toBeUndefined(); - await expect(validateUrl('https://google.com:8443', conf)).toBeUndefined(); - await expect(validateUrl('https://google.com/search?q=name', conf)).toBeUndefined(); - await expect(validateUrl('https://google.com/#asdasd', conf)).toBeUndefined(); - await expect(validateUrl('mailto:asd@asd.asd', conf)).toBeUndefined(); - await expect(validateUrl('file:///etc/passwd', conf)).toBeUndefined(); - await expect( - validateUrl('ftp://user:password@ftphost.com/directory', conf) - ).toBeUndefined(); + await expect(validateUrl('https://google.com', conf)).toEqual('https://google.com'); + await expect(validateUrl('https://google.com/', conf)).toEqual('https://google.com/'); + await expect(validateUrl('https://google.com:8443', conf)).toEqual('https://google.com:8443'); + await expect(validateUrl('https://google.com/search?q=name', conf)).toEqual( + 'https://google.com/search?q=name' + ); + await expect(validateUrl('https://google.com/#asdasd', conf)).toEqual( + 'https://google.com/#asdasd' + ); + await expect(validateUrl('mailto:asd@asd.asd', conf)).toEqual('mailto:asd@asd.asd'); + await expect(validateUrl('file:///etc/passwd', conf)).toEqual('file:///etc/passwd'); + await expect(validateUrl('ftp://user:password@ftphost.com/directory', conf)).toEqual( + 'ftp://user:password@ftphost.com/directory' + ); }); test('isUrl, if invalid url is given, fails', async () => { @@ -45,18 +49,3 @@ test('isUrl, if invalid url is given, fails', async () => { expect(err).toBe('Field strField should be an url.'); } }); - -test('isUrl, if not a string is given, ignores', async () => { - const validateUrl = isUrl(); - - await expect(validateUrl(8 as any, conf)).toBeUndefined(); - await expect(validateUrl(NaN as any, conf)).toBeUndefined(); - await expect(validateUrl(true as any, conf)).toBeUndefined(); - await expect(validateUrl([] as any, conf)).toBeUndefined(); - await expect( - validateUrl(['a', 's', 'd', '@', 'a', 's', 'd', '.', 'a', 's', 'd'] as any, conf) - ).toBeUndefined(); - await expect(validateUrl({} as any, conf)).toBeUndefined(); - await expect(validateUrl(undefined as any, conf)).toBeUndefined(); - await expect(validateUrl(null as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/string/length.ts b/tests/validators/string/length.ts index ccaf6e0..7679394 100644 --- a/tests/validators/string/length.ts +++ b/tests/validators/string/length.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('length if passed words length is the same, returns success', async () => { const validateLength = length(5); - await expect(validateLength('smart', conf)).toBeUndefined(); - await expect(validateLength('young', conf)).toBeUndefined(); - await expect(validateLength('brave', conf)).toBeUndefined(); + await expect(validateLength('smart', conf)).toEqual('smart'); + await expect(validateLength('young', conf)).toEqual('young'); + await expect(validateLength('brave', conf)).toEqual('brave'); }); test('length if passed word is shorter or longer, fails', async () => { @@ -32,16 +32,3 @@ test('length if passed word is shorter or longer, fails', async () => { expect(err).toBe('Field strField length should be exactly 5 characters.'); } }); - -test('length if passed word is not a string, ignores', async () => { - const validateLength = length(5); - - await expect(validateLength(8 as any, conf)).toBeUndefined(); - await expect(validateLength(NaN as any, conf)).toBeUndefined(); - await expect(validateLength(true as any, conf)).toBeUndefined(); - await expect(validateLength([] as any, conf)).toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); - await expect(validateLength({} as any, conf)).toBeUndefined(); - await expect(validateLength(undefined as any, conf)).toBeUndefined(); - await expect(validateLength(null as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/string/maxLength.ts b/tests/validators/string/maxLength.ts index cbef733..3868888 100644 --- a/tests/validators/string/maxLength.ts +++ b/tests/validators/string/maxLength.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('maxLength if passed words length is between its limits, returns success', async () => { const validateLength = maxLength(10); - await expect(validateLength('smart', conf)).toBeUndefined(); - await expect(validateLength('serious', conf)).toBeUndefined(); - await expect(validateLength('attractive', conf)).toBeUndefined(); + await expect(validateLength('smart', conf)).toEqual('smart'); + await expect(validateLength('serious', conf)).toEqual('serious'); + await expect(validateLength('attractive', conf)).toEqual('attractive'); }); test('maxLength if passed word is longer, fails', async () => { @@ -32,16 +32,3 @@ test('maxLength if passed word is longer, fails', async () => { expect(err).toBe('Field strField length should be at most 10 characters.'); } }); - -test('maxLength if passed word is not a string, ignores', async () => { - const validateLength = maxLength(10); - - await expect(validateLength(8 as any, conf)).toBeUndefined(); - await expect(validateLength(NaN as any, conf)).toBeUndefined(); - await expect(validateLength(true as any, conf)).toBeUndefined(); - await expect(validateLength([] as any, conf)).toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); - await expect(validateLength({} as any, conf)).toBeUndefined(); - await expect(validateLength(undefined as any, conf)).toBeUndefined(); - await expect(validateLength(null as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/string/minLength.ts b/tests/validators/string/minLength.ts index e3d63af..bfb0bff 100644 --- a/tests/validators/string/minLength.ts +++ b/tests/validators/string/minLength.ts @@ -12,9 +12,9 @@ const conf: ValidatorConfiguration = { test('minLength if passed words length is as at least long as the limit, returns success', async () => { const validateLength = minLength(5); - await expect(validateLength('smart', conf)).toBeUndefined(); - await expect(validateLength('serious', conf)).toBeUndefined(); - await expect(validateLength('attractive', conf)).toBeUndefined(); + await expect(validateLength('smart', conf)).toEqual('smart'); + await expect(validateLength('serious', conf)).toEqual('serious'); + await expect(validateLength('attractive', conf)).toEqual('attractive'); }); test('minLength if passed word is shorter, fails', async () => { @@ -32,16 +32,3 @@ test('minLength if passed word is shorter, fails', async () => { expect(err).toBe('Field strField length should be at least 5 characters.'); } }); - -test('minLength if passed word is not a string, ignores', async () => { - const validateLength = minLength(5); - - await expect(validateLength(8 as any, conf)).toBeUndefined(); - await expect(validateLength(NaN as any, conf)).toBeUndefined(); - await expect(validateLength(true as any, conf)).toBeUndefined(); - await expect(validateLength([] as any, conf)).toBeUndefined(); - await expect(validateLength(Array(8).fill('a') as any, conf)).toBeUndefined(); - await expect(validateLength({} as any, conf)).toBeUndefined(); - await expect(validateLength(undefined as any, conf)).toBeUndefined(); - await expect(validateLength(null as any, conf)).toBeUndefined(); -}); diff --git a/tests/validators/validateCondition.ts b/tests/validators/validateCondition.ts index caffeb0..b9b19e2 100644 --- a/tests/validators/validateCondition.ts +++ b/tests/validators/validateCondition.ts @@ -6,13 +6,13 @@ const conf: ValidatorConfiguration = { name: 'object', original: {}, parent: {}, test('validateCondition function returns undefined if regex applies', async () => { const validateTest = validateCondition(() => true); - await expect(validateTest('', conf)).toBeUndefined(); + expect(validateTest('', conf)).toEqual(''); }); test('validateCondition function throws error if regex fails', async () => { const validateTest = validateCondition(() => false); try { - await validateTest('', conf); + validateTest('', conf); } catch (err) { expect(err).not.toBeUndefined(); } diff --git a/tests/validators/validateRegex.ts b/tests/validators/validateRegex.ts index 92b76d5..eb50ed4 100644 --- a/tests/validators/validateRegex.ts +++ b/tests/validators/validateRegex.ts @@ -6,19 +6,14 @@ const conf: ValidatorConfiguration = { name: 'object', original: {}, parent: {}, test('validateRegex function returns undefined if regex applies', async () => { const validateTest = validateRegex(/[a-z].*/); - await expect(validateTest('asdasd', conf)).toBeUndefined(); + expect(validateTest('asdasd', conf)).toEqual('asdasd'); }); test('validateRegex function throws error if regex fails', async () => { const validateTest = validateRegex(/[a-z].*/); try { - await validateTest('123', conf); + validateTest('123', conf); } catch (err) { expect(err).not.toBeUndefined(); } }); - -test('validateRegex function ignores if passed value is not a string', async () => { - const validateTest = validateRegex(/[a-z].*/); - await expect(validateTest(123 as any, conf)).toBeUndefined(); -}); From cb1cd229ddfa502d4b272200233fefd015786aac Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 18:16:04 +0100 Subject: [PATCH 09/16] Remove all of ignore --- README.md | 14 +++----------- src/index.ts | 2 -- src/transformers/number/ceil.ts | 5 +---- src/transformers/number/clamp.ts | 2 +- src/transformers/number/floor.ts | 2 +- src/transformers/number/round.ts | 2 +- src/transformers/number/toMultipleOf.ts | 2 +- src/transformers/string/lower.ts | 2 +- src/transformers/string/normalize.ts | 2 +- src/transformers/string/trim.ts | 2 +- src/transformers/string/truncate.ts | 2 +- src/transformers/string/upper.ts | 2 +- src/types.ts | 4 ---- src/validators/date/after.ts | 2 +- src/validators/date/before.ts | 2 +- src/validators/date/inRange.ts | 2 +- src/validators/number/between.ts | 2 +- src/validators/number/closeTo.ts | 2 +- src/validators/number/gt.ts | 2 +- src/validators/number/gte.ts | 2 +- src/validators/number/isMultipleOf.ts | 2 +- src/validators/number/lt.ts | 2 +- src/validators/number/lte.ts | 2 +- src/validators/string/betweenLength.ts | 2 +- src/validators/string/insensitiveEquals.ts | 2 +- src/validators/string/isUrl.ts | 2 +- src/validators/string/length.ts | 2 +- src/validators/string/maxLength.ts | 2 +- src/validators/string/minLength.ts | 2 +- src/validators/validateRegex.ts | 2 +- tests/README.ts | 16 ---------------- 31 files changed, 30 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 5704a6a..3b1a5ae 100644 --- a/README.md +++ b/README.md @@ -106,16 +106,13 @@ const validateRegistration = validate({ What you might notice is the extra parentheses before the async part: in Dvali it is customary to wrap the validator in an extra function. This allows to be consistent with other validation functions that need parameters (`minLength` for example). -To make this `isUniqueEmail` validation function more expressive, we can use the `Success`, `Failure` and `Ignore` macros, exported from the library: +To make this `isUniqueEmail` validation function more expressive, we can use the `Success` and `Failure` macros, exported from the library: ```js -import validate, { Success, Failure, Ignore } from 'dvali'; +import validate, { Success, Failure } from 'dvali'; const isUniqueEmail = () => async function (email, conf) { - if (typeof email !== 'string') { - return Ignore(); - } const exists = await db.users.find({ email }); if (!exists) { return Success(); @@ -124,8 +121,6 @@ const isUniqueEmail = () => }; ``` -Why use this `Ignore` call? Composability is very important in Dvali, one function should only do one thing (but do that thing well). In this case, we let the `isString` function handle whether the email is a string, and our function only proceeds if it's valid. This is useful in cases like optional fields, when we want to the validation to pass, even if the tested value is undefined. - To make writing validation functions easier, there are several helpers in the core library for example `validateCondition` for testing simple conditions, or `validateRegex` for testing against a regular expression. Before writing your own validation function for everything, check these out! ### Sanitize and transform @@ -136,13 +131,10 @@ To go forth with our registration theme, check this feature out with a sanitizat ```js import bcrypt from 'bcrypt'; -import validate, { isString, minLength, Ignore, Success } from 'dvali'; +import validate, { isString, minLength, Success } from 'dvali'; const hash = () => async function (password, conf) { - if (typeof password !== 'string') { - return Ignore(); - } const hashedPassword = await bcrypt.hash(password, 8); return Success(hashedPassword); // ... or just return the Promise: diff --git a/src/index.ts b/src/index.ts index f9418c1..4bcc335 100644 --- a/src/index.ts +++ b/src/index.ts @@ -69,7 +69,6 @@ import upper from './transformers/string/upper.js'; import { Failure, - Ignore, FailureFunction, Success, Validator, @@ -90,7 +89,6 @@ export type { export { Failure, - Ignore, Success, validate, arrayOf, diff --git a/src/transformers/number/ceil.ts b/src/transformers/number/ceil.ts index 5220ac4..7fe1096 100644 --- a/src/transformers/number/ceil.ts +++ b/src/transformers/number/ceil.ts @@ -1,9 +1,6 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const ceil = (): SyncValidatorFunction => (value, conf) => { - if (typeof value !== 'number' || Number.isNaN(value)) { - return Ignore(value); - } return Success(Math.ceil(value)); }; diff --git a/src/transformers/number/clamp.ts b/src/transformers/number/clamp.ts index db65ed8..95aa5f0 100644 --- a/src/transformers/number/clamp.ts +++ b/src/transformers/number/clamp.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const clamp = (min: number, max: number): SyncValidatorFunction => diff --git a/src/transformers/number/floor.ts b/src/transformers/number/floor.ts index 4eae500..96042af 100644 --- a/src/transformers/number/floor.ts +++ b/src/transformers/number/floor.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const floor = (): SyncValidatorFunction => (value, conf) => { return Success(Math.floor(value)); diff --git a/src/transformers/number/round.ts b/src/transformers/number/round.ts index 8cb5c2d..0853380 100644 --- a/src/transformers/number/round.ts +++ b/src/transformers/number/round.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const round = ():SyncValidatorFunction => (value, conf) => { return Success(Math.round(value)); diff --git a/src/transformers/number/toMultipleOf.ts b/src/transformers/number/toMultipleOf.ts index db8a63c..281f8c7 100644 --- a/src/transformers/number/toMultipleOf.ts +++ b/src/transformers/number/toMultipleOf.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const toMultipleOf = (n: number, round = Math.round): SyncValidatorFunction => diff --git a/src/transformers/string/lower.ts b/src/transformers/string/lower.ts index 1e0648a..aa7397e 100644 --- a/src/transformers/string/lower.ts +++ b/src/transformers/string/lower.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const lower = (): SyncValidatorFunction => (value, conf) => { return Success(value.toLocaleLowerCase()); diff --git a/src/transformers/string/normalize.ts b/src/transformers/string/normalize.ts index 150aa55..89a444b 100644 --- a/src/transformers/string/normalize.ts +++ b/src/transformers/string/normalize.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const normalize = (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'): SyncValidatorFunction => diff --git a/src/transformers/string/trim.ts b/src/transformers/string/trim.ts index 6bf3298..af730cf 100644 --- a/src/transformers/string/trim.ts +++ b/src/transformers/string/trim.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const trim = ():SyncValidatorFunction => (value, conf) => { return Success(value.trim()); diff --git a/src/transformers/string/truncate.ts b/src/transformers/string/truncate.ts index 1404cd3..b102d3c 100644 --- a/src/transformers/string/truncate.ts +++ b/src/transformers/string/truncate.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const truncate = (n: number): SyncValidatorFunction => diff --git a/src/transformers/string/upper.ts b/src/transformers/string/upper.ts index 212cad0..9c08c8b 100644 --- a/src/transformers/string/upper.ts +++ b/src/transformers/string/upper.ts @@ -1,4 +1,4 @@ -import { Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Success, SyncValidatorFunction } from '../../types.js'; const upper = ():SyncValidatorFunction => (value, conf) => { return Success(value.toLocaleUpperCase()); diff --git a/src/types.ts b/src/types.ts index e77171b..cd17d0a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -54,10 +54,6 @@ export const Success = function (t: T): T { return t; }; -export const Ignore = function (t: T): T { - return t; -}; - export const Failure = function (t: string): never { throw t; }; diff --git a/src/validators/date/after.ts b/src/validators/date/after.ts index 3bfa59e..3443016 100644 --- a/src/validators/date/after.ts +++ b/src/validators/date/after.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const after: ( date: string | number | Date, diff --git a/src/validators/date/before.ts b/src/validators/date/before.ts index 20f29ed..2ae1530 100644 --- a/src/validators/date/before.ts +++ b/src/validators/date/before.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const before: ( date: string | number | Date, diff --git a/src/validators/date/inRange.ts b/src/validators/date/inRange.ts index 15e9704..9142768 100644 --- a/src/validators/date/inRange.ts +++ b/src/validators/date/inRange.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const inRange: ( minDate: string | number | Date, diff --git a/src/validators/number/between.ts b/src/validators/number/between.ts index 992fbe3..378bc7d 100644 --- a/src/validators/number/between.ts +++ b/src/validators/number/between.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const between: ( min: number, diff --git a/src/validators/number/closeTo.ts b/src/validators/number/closeTo.ts index 79f8498..e88ad61 100644 --- a/src/validators/number/closeTo.ts +++ b/src/validators/number/closeTo.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const closeTo: (v: number, e?: number) => SyncValidatorFunction = (exactValue, epsilon = Number.EPSILON) => diff --git a/src/validators/number/gt.ts b/src/validators/number/gt.ts index 3da6deb..e4d3021 100644 --- a/src/validators/number/gt.ts +++ b/src/validators/number/gt.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const gt = (min: number): SyncValidatorFunction => diff --git a/src/validators/number/gte.ts b/src/validators/number/gte.ts index 30c24a5..ad17630 100644 --- a/src/validators/number/gte.ts +++ b/src/validators/number/gte.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const gte = (min: number): SyncValidatorFunction => diff --git a/src/validators/number/isMultipleOf.ts b/src/validators/number/isMultipleOf.ts index c15bb23..4a2414d 100644 --- a/src/validators/number/isMultipleOf.ts +++ b/src/validators/number/isMultipleOf.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const isMultipleOf = (n: number): SyncValidatorFunction => diff --git a/src/validators/number/lt.ts b/src/validators/number/lt.ts index 9cfb0f6..82a028a 100644 --- a/src/validators/number/lt.ts +++ b/src/validators/number/lt.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const lt = (max: number): SyncValidatorFunction => diff --git a/src/validators/number/lte.ts b/src/validators/number/lte.ts index 49603ef..2008e31 100644 --- a/src/validators/number/lte.ts +++ b/src/validators/number/lte.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const lte = (max: number): SyncValidatorFunction => diff --git a/src/validators/string/betweenLength.ts b/src/validators/string/betweenLength.ts index 05b5313..e3d1f8e 100644 --- a/src/validators/string/betweenLength.ts +++ b/src/validators/string/betweenLength.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const betweenLength = (min: number, max: number): SyncValidatorFunction => diff --git a/src/validators/string/insensitiveEquals.ts b/src/validators/string/insensitiveEquals.ts index 80e1df0..25aee60 100644 --- a/src/validators/string/insensitiveEquals.ts +++ b/src/validators/string/insensitiveEquals.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const insensitiveEquals = (to: string): SyncValidatorFunction => diff --git a/src/validators/string/isUrl.ts b/src/validators/string/isUrl.ts index 9ef1083..8f56b82 100644 --- a/src/validators/string/isUrl.ts +++ b/src/validators/string/isUrl.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const isUrl = (): SyncValidatorFunction => (value, conf) => { try { diff --git a/src/validators/string/length.ts b/src/validators/string/length.ts index c1f783a..fdc5852 100644 --- a/src/validators/string/length.ts +++ b/src/validators/string/length.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const length = (n: number): SyncValidatorFunction => diff --git a/src/validators/string/maxLength.ts b/src/validators/string/maxLength.ts index 2732e5f..21b35d9 100644 --- a/src/validators/string/maxLength.ts +++ b/src/validators/string/maxLength.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const maxLength = (max: number): SyncValidatorFunction => diff --git a/src/validators/string/minLength.ts b/src/validators/string/minLength.ts index 431d80c..5b40378 100644 --- a/src/validators/string/minLength.ts +++ b/src/validators/string/minLength.ts @@ -1,4 +1,4 @@ -import { Failure, Ignore, Success, SyncValidatorFunction } from '../../types.js'; +import { Failure, Success, SyncValidatorFunction } from '../../types.js'; const minLength = (min: number): SyncValidatorFunction => diff --git a/src/validators/validateRegex.ts b/src/validators/validateRegex.ts index 991e8cf..dd35857 100644 --- a/src/validators/validateRegex.ts +++ b/src/validators/validateRegex.ts @@ -1,4 +1,4 @@ -import { Failure, FailureFunction, Ignore, Success, SyncValidatorFunction } from '../types.js'; +import { Failure, FailureFunction, Success, SyncValidatorFunction } from '../types.js'; const validateRegex = ( regex: RegExp, diff --git a/tests/README.ts b/tests/README.ts index ae5b227..bcbae67 100644 --- a/tests/README.ts +++ b/tests/README.ts @@ -6,7 +6,6 @@ import validate, { ValidatorFunction, Success, Failure, - Ignore, Validator, ValidatorObject, } from '../src/index'; @@ -88,9 +87,6 @@ test('README: Bring your own validator - isUniqueEmail full', async () => { const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { - if (typeof email !== 'string') { - return Ignore(email); - } const exists = await db.users.find({ email }); if (!exists) { return Success(email); @@ -126,9 +122,6 @@ test('README: Sanitize and transform - hash', async () => { const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { - if (typeof email !== 'string') { - return Ignore(email); - } const exists = await db.users.find({ email }); if (!exists) { return Success(email); @@ -145,9 +138,6 @@ test('README: Sanitize and transform - hash', async () => { const hash = (): ValidatorFunction => async function (password, conf) { - if (typeof password !== 'string') { - return Ignore(password); - } const hashedPassword = await bcrypt.hash(password, 8); return Success(hashedPassword); }; @@ -184,9 +174,6 @@ test('README: Higher-order validators - confirmPassword', async () => { const isUniqueEmail = (): ValidatorFunction => async function (email, conf) { - if (typeof email !== 'string') { - return Ignore(email); - } const exists = await db.users.find({ email }); if (!exists) { return Success(email); @@ -203,9 +190,6 @@ test('README: Higher-order validators - confirmPassword', async () => { const hash = (): ValidatorFunction => async function (password, conf) { - if (typeof password !== 'string') { - return Ignore(password); - } const hashedPassword = await bcrypt.hash(password, 8); return Success(hashedPassword); }; From dbb029e4084db95443f7c9e76b67a4e31effb828 Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 18:52:25 +0100 Subject: [PATCH 10/16] Remove Success and Failure from the code --- README.md | 25 +++++----------------- src/index.ts | 4 ---- src/transformers/number/ceil.ts | 4 ++-- src/transformers/number/clamp.ts | 8 +++---- src/transformers/number/floor.ts | 4 ++-- src/transformers/number/round.ts | 4 ++-- src/transformers/number/toMultipleOf.ts | 4 ++-- src/transformers/string/lower.ts | 4 ++-- src/transformers/string/normalize.ts | 4 ++-- src/transformers/string/trim.ts | 4 ++-- src/transformers/string/truncate.ts | 4 ++-- src/transformers/string/upper.ts | 4 ++-- src/types.ts | 8 ------- src/validators/boolean/toBool.ts | 4 ++-- src/validators/boolean/tryBool.ts | 8 +++---- src/validators/date/after.ts | 6 +++--- src/validators/date/before.ts | 6 +++--- src/validators/date/inRange.ts | 8 +++---- src/validators/date/toDate.ts | 4 ++-- src/validators/date/tryDate.ts | 6 +++--- src/validators/either.ts | 2 +- src/validators/number/between.ts | 6 +++--- src/validators/number/closeTo.ts | 6 +++--- src/validators/number/gt.ts | 6 +++--- src/validators/number/gte.ts | 6 +++--- src/validators/number/isInt.ts | 2 +- src/validators/number/isMultipleOf.ts | 6 +++--- src/validators/number/lt.ts | 6 +++--- src/validators/number/lte.ts | 6 +++--- src/validators/number/toInt.ts | 4 ++-- src/validators/number/toNumber.ts | 4 ++-- src/validators/number/tryInt.ts | 6 +++--- src/validators/number/tryNumber.ts | 6 +++--- src/validators/optional.ts | 6 +++--- src/validators/string/betweenLength.ts | 8 +++---- src/validators/string/insensitiveEquals.ts | 6 +++--- src/validators/string/isUrl.ts | 6 +++--- src/validators/string/length.ts | 6 +++--- src/validators/string/maxLength.ts | 6 +++--- src/validators/string/minLength.ts | 6 +++--- src/validators/string/toString.ts | 4 ++-- src/validators/validateCondition.ts | 10 ++++----- src/validators/validateRegex.ts | 6 +++--- tests/README.ts | 23 +++++++++----------- tests/validate.ts | 8 +++---- tests/validators/arrayOf.ts | 10 ++++----- tests/validators/bail.ts | 12 +++++------ tests/validators/either.ts | 8 +++---- tests/validators/optional.ts | 10 ++++----- 49 files changed, 144 insertions(+), 180 deletions(-) diff --git a/README.md b/README.md index 3b1a5ae..450cd32 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ const isUniqueEmail = () => async function (email, conf) { const exists = await db.users.find({ email }); // User | null if (!exists) { - return; + return email; // You have to return the original value } throw 'This email already in use. Try your alternate address.'; }; @@ -106,21 +106,6 @@ const validateRegistration = validate({ What you might notice is the extra parentheses before the async part: in Dvali it is customary to wrap the validator in an extra function. This allows to be consistent with other validation functions that need parameters (`minLength` for example). -To make this `isUniqueEmail` validation function more expressive, we can use the `Success` and `Failure` macros, exported from the library: - -```js -import validate, { Success, Failure } from 'dvali'; - -const isUniqueEmail = () => - async function (email, conf) { - const exists = await db.users.find({ email }); - if (!exists) { - return Success(); - } - return Failure('This email already in use. Try your alternate address.'); - }; -``` - To make writing validation functions easier, there are several helpers in the core library for example `validateCondition` for testing simple conditions, or `validateRegex` for testing against a regular expression. Before writing your own validation function for everything, check these out! ### Sanitize and transform @@ -131,12 +116,12 @@ To go forth with our registration theme, check this feature out with a sanitizat ```js import bcrypt from 'bcrypt'; -import validate, { isString, minLength, Success } from 'dvali'; +import validate, { isString, minLength } from 'dvali'; const hash = () => async function (password, conf) { const hashedPassword = await bcrypt.hash(password, 8); - return Success(hashedPassword); + return hashedPassword; // ... or just return the Promise: // return bcrypt.hash(password, 8); }; @@ -168,10 +153,10 @@ See the `confirmPassword` higher-order validator in action: const confirmPassword = (validators) => async function (user, conf) { if (user?.password_confirm === undefined) { - return Failure('You should confirm your password.'); + throw 'You should confirm your password.' } if (user.password_confirm !== user.password) { - return Failure('The two passwords do not match.'); + throw 'The two passwords do not match.' } return validate(validators)(user); }; diff --git a/src/index.ts b/src/index.ts index 4bcc335..84787f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -68,9 +68,7 @@ import truncate from './transformers/string/truncate.js'; import upper from './transformers/string/upper.js'; import { - Failure, FailureFunction, - Success, Validator, ValidatorConfiguration, ValidatorFunction, @@ -88,8 +86,6 @@ export type { }; export { - Failure, - Success, validate, arrayOf, bail, diff --git a/src/transformers/number/ceil.ts b/src/transformers/number/ceil.ts index 7fe1096..d816cdb 100644 --- a/src/transformers/number/ceil.ts +++ b/src/transformers/number/ceil.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const ceil = (): SyncValidatorFunction => (value, conf) => { - return Success(Math.ceil(value)); + return Math.ceil(value); }; export default ceil; diff --git a/src/transformers/number/clamp.ts b/src/transformers/number/clamp.ts index 95aa5f0..0e1703f 100644 --- a/src/transformers/number/clamp.ts +++ b/src/transformers/number/clamp.ts @@ -1,15 +1,15 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const clamp = (min: number, max: number): SyncValidatorFunction => (value, conf) => { if (min >= value) { - return Success(min); + return min; } if (max <= value) { - return Success(max); + return max; } - return Success(value); + return value; }; export default clamp; diff --git a/src/transformers/number/floor.ts b/src/transformers/number/floor.ts index 96042af..7e95410 100644 --- a/src/transformers/number/floor.ts +++ b/src/transformers/number/floor.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const floor = (): SyncValidatorFunction => (value, conf) => { - return Success(Math.floor(value)); + return Math.floor(value); }; export default floor; diff --git a/src/transformers/number/round.ts b/src/transformers/number/round.ts index 0853380..78e072c 100644 --- a/src/transformers/number/round.ts +++ b/src/transformers/number/round.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const round = ():SyncValidatorFunction => (value, conf) => { - return Success(Math.round(value)); + return Math.round(value); }; export default round; diff --git a/src/transformers/number/toMultipleOf.ts b/src/transformers/number/toMultipleOf.ts index 281f8c7..fae3bfc 100644 --- a/src/transformers/number/toMultipleOf.ts +++ b/src/transformers/number/toMultipleOf.ts @@ -1,9 +1,9 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const toMultipleOf = (n: number, round = Math.round): SyncValidatorFunction => (value, conf) => { - return Success(round(value / n) * n); + return round(value / n) * n; }; export default toMultipleOf; diff --git a/src/transformers/string/lower.ts b/src/transformers/string/lower.ts index aa7397e..bb0a894 100644 --- a/src/transformers/string/lower.ts +++ b/src/transformers/string/lower.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const lower = (): SyncValidatorFunction => (value, conf) => { - return Success(value.toLocaleLowerCase()); + return value.toLocaleLowerCase(); }; export default lower; diff --git a/src/transformers/string/normalize.ts b/src/transformers/string/normalize.ts index 89a444b..f2d4a7a 100644 --- a/src/transformers/string/normalize.ts +++ b/src/transformers/string/normalize.ts @@ -1,9 +1,9 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const normalize = (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'): SyncValidatorFunction => (value, conf) => { - return Success(value.normalize(form)); + return value.normalize(form); }; export default normalize; diff --git a/src/transformers/string/trim.ts b/src/transformers/string/trim.ts index af730cf..d01da36 100644 --- a/src/transformers/string/trim.ts +++ b/src/transformers/string/trim.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const trim = ():SyncValidatorFunction => (value, conf) => { - return Success(value.trim()); + return value.trim(); }; export default trim; diff --git a/src/transformers/string/truncate.ts b/src/transformers/string/truncate.ts index b102d3c..b7fddbb 100644 --- a/src/transformers/string/truncate.ts +++ b/src/transformers/string/truncate.ts @@ -1,9 +1,9 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const truncate = (n: number): SyncValidatorFunction => (value, conf) => { - return Success(n >= 0 ? value.substr(0, n) : value.substr(n)); + return n >= 0 ? value.substr(0, n) : value.substr(n); }; export default truncate; diff --git a/src/transformers/string/upper.ts b/src/transformers/string/upper.ts index 9c08c8b..d7c1687 100644 --- a/src/transformers/string/upper.ts +++ b/src/transformers/string/upper.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const upper = ():SyncValidatorFunction => (value, conf) => { - return Success(value.toLocaleUpperCase()); + return value.toLocaleUpperCase(); }; export default upper; diff --git a/src/types.ts b/src/types.ts index cd17d0a..66e884a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -49,11 +49,3 @@ export interface FailureFunction { } export type InferValidator = T extends Validator ? O : never; - -export const Success = function (t: T): T { - return t; -}; - -export const Failure = function (t: string): never { - throw t; -}; diff --git a/src/validators/boolean/toBool.ts b/src/validators/boolean/toBool.ts index 7236527..9e7130e 100644 --- a/src/validators/boolean/toBool.ts +++ b/src/validators/boolean/toBool.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const toBool = (): SyncValidatorFunction => (value) => { - return Success(!!value); + return !!value; }; export default toBool; diff --git a/src/validators/boolean/tryBool.ts b/src/validators/boolean/tryBool.ts index 9643798..bfdec05 100644 --- a/src/validators/boolean/tryBool.ts +++ b/src/validators/boolean/tryBool.ts @@ -1,15 +1,15 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const tryBool: (t?: any[], f?: any[]) => SyncValidatorFunction = (truthy = [true, 1], falsey = [false, 0]) => (value, conf) => { if (truthy.indexOf(value) !== -1) { - return Success(true); + return true; } if (falsey.indexOf(value) !== -1) { - return Success(false); + return false; } - throw Failure(`Field ${conf.name} cannot be converted to boolean.`); + throw `Field ${conf.name} cannot be converted to boolean.`; }; export default tryBool; diff --git a/src/validators/date/after.ts b/src/validators/date/after.ts index 3443016..ff4f133 100644 --- a/src/validators/date/after.ts +++ b/src/validators/date/after.ts @@ -1,4 +1,4 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const after: ( date: string | number | Date, @@ -9,10 +9,10 @@ const after: ( const min = date instanceof Date ? date : new Date(date); if ((opts.inclusive && value >= min) || (!opts.inclusive && value > min)) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be after ${min.toString()}.`); + throw `Field ${conf.name} should be after ${min.toString()}.` }; export default after; diff --git a/src/validators/date/before.ts b/src/validators/date/before.ts index 2ae1530..4d740b5 100644 --- a/src/validators/date/before.ts +++ b/src/validators/date/before.ts @@ -1,4 +1,4 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const before: ( date: string | number | Date, @@ -9,10 +9,10 @@ const before: ( const max = date instanceof Date ? date : new Date(date); if ((opts.inclusive && value <= max) || (!opts.inclusive && value < max)) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be before ${max.toString()}.`); + throw `Field ${conf.name} should be before ${max.toString()}.` }; export default before; diff --git a/src/validators/date/inRange.ts b/src/validators/date/inRange.ts index 9142768..54401d4 100644 --- a/src/validators/date/inRange.ts +++ b/src/validators/date/inRange.ts @@ -1,4 +1,4 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const inRange: ( minDate: string | number | Date, @@ -14,12 +14,10 @@ const inRange: ( ((opts.minInclusive && value >= min) || (!opts.minInclusive && value > min)) && ((opts.maxInclusive && value <= max) || (!opts.maxInclusive && value < max)) ) { - return Success(value); + return value; } - return Failure( - `Field ${conf.name} should be between ${min.toString()} and ${max.toString()}.` - ); + throw `Field ${conf.name} should be between ${min.toString()} and ${max.toString()}.`; }; export default inRange; diff --git a/src/validators/date/toDate.ts b/src/validators/date/toDate.ts index 0e34d9f..f146c67 100644 --- a/src/validators/date/toDate.ts +++ b/src/validators/date/toDate.ts @@ -1,8 +1,8 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const toDate = (): SyncValidatorFunction => (value, conf) => { const parsed = value instanceof Date ? value : new Date(value); - return Success(parsed); + return parsed; }; export default toDate; diff --git a/src/validators/date/tryDate.ts b/src/validators/date/tryDate.ts index dce2f48..6194f45 100644 --- a/src/validators/date/tryDate.ts +++ b/src/validators/date/tryDate.ts @@ -1,11 +1,11 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const tryDate = (): SyncValidatorFunction => (value, conf) => { const parsed = value instanceof Date ? value : new Date(value); if (!Number.isNaN(parsed.getTime())) { - return Success(parsed); + return parsed; } - return Failure(`Field ${conf.name} should be a valid date.`); + throw `Field ${conf.name} should be a valid date.` }; export default tryDate; diff --git a/src/validators/either.ts b/src/validators/either.ts index 1e65d68..73dd3c2 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -1,4 +1,4 @@ -import { InferValidator, Success, Validator, ValidatorConfiguration } from '../types.js'; +import { InferValidator, Validator, ValidatorConfiguration } from '../types.js'; import validate, { hasNoPromise } from '../validate.js'; function either>( diff --git a/src/validators/number/between.ts b/src/validators/number/between.ts index 378bc7d..1d26d1b 100644 --- a/src/validators/number/between.ts +++ b/src/validators/number/between.ts @@ -1,4 +1,4 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const between: ( min: number, @@ -11,10 +11,10 @@ const between: ( ((opts.minInclusive && value >= min) || (!opts.minInclusive && value > min)) && ((opts.maxInclusive && value <= max) || (!opts.maxInclusive && value < max)) ) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be between ${min} and ${max}.`); + throw `Field ${conf.name} should be between ${min} and ${max}.` }; export default between; diff --git a/src/validators/number/closeTo.ts b/src/validators/number/closeTo.ts index e88ad61..7eee39d 100644 --- a/src/validators/number/closeTo.ts +++ b/src/validators/number/closeTo.ts @@ -1,12 +1,12 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const closeTo: (v: number, e?: number) => SyncValidatorFunction = (exactValue, epsilon = Number.EPSILON) => (value, conf) => { if (Math.abs(value - exactValue) < epsilon) { - return Success(exactValue); + return exactValue; } - return Failure(`Field ${conf.name} should be approximately ${exactValue}.`); + throw `Field ${conf.name} should be approximately ${exactValue}.` }; export default closeTo; diff --git a/src/validators/number/gt.ts b/src/validators/number/gt.ts index e4d3021..78c9e27 100644 --- a/src/validators/number/gt.ts +++ b/src/validators/number/gt.ts @@ -1,13 +1,13 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const gt = (min: number): SyncValidatorFunction => (value, conf) => { if (value > min) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be greater than ${min}.`); + throw `Field ${conf.name} should be greater than ${min}.` }; export default gt; diff --git a/src/validators/number/gte.ts b/src/validators/number/gte.ts index ad17630..f8cc86c 100644 --- a/src/validators/number/gte.ts +++ b/src/validators/number/gte.ts @@ -1,13 +1,13 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const gte = (min: number): SyncValidatorFunction => (value, conf) => { if (value >= min) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be greater than or equal to ${min}.`); + throw `Field ${conf.name} should be greater than or equal to ${min}.` }; export default gte; diff --git a/src/validators/number/isInt.ts b/src/validators/number/isInt.ts index 7759a52..b89625b 100644 --- a/src/validators/number/isInt.ts +++ b/src/validators/number/isInt.ts @@ -1,4 +1,4 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; import validateCondition from '../validateCondition.js'; const isInt = (): SyncValidatorFunction => diff --git a/src/validators/number/isMultipleOf.ts b/src/validators/number/isMultipleOf.ts index 4a2414d..82e71ee 100644 --- a/src/validators/number/isMultipleOf.ts +++ b/src/validators/number/isMultipleOf.ts @@ -1,13 +1,13 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const isMultipleOf = (n: number): SyncValidatorFunction => (value, conf) => { if (value % n === 0) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be the multiple of ${n}.`); + throw `Field ${conf.name} should be the multiple of ${n}.` }; export default isMultipleOf; diff --git a/src/validators/number/lt.ts b/src/validators/number/lt.ts index 82a028a..d0e4c32 100644 --- a/src/validators/number/lt.ts +++ b/src/validators/number/lt.ts @@ -1,13 +1,13 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const lt = (max: number): SyncValidatorFunction => (value, conf) => { if (value < max) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be less than ${max}.`); + throw `Field ${conf.name} should be less than ${max}.` }; export default lt; diff --git a/src/validators/number/lte.ts b/src/validators/number/lte.ts index 2008e31..64e15ce 100644 --- a/src/validators/number/lte.ts +++ b/src/validators/number/lte.ts @@ -1,13 +1,13 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const lte = (max: number): SyncValidatorFunction => (value, conf) => { if (value <= max) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be less than or equal to ${max}.`); + throw `Field ${conf.name} should be less than or equal to ${max}.` }; export default lte; diff --git a/src/validators/number/toInt.ts b/src/validators/number/toInt.ts index bd30752..24df926 100644 --- a/src/validators/number/toInt.ts +++ b/src/validators/number/toInt.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const toInt = (): SyncValidatorFunction => (value) => { - return Success(Number.parseInt(value as any)); + return Number.parseInt(value as any); }; export default toInt; diff --git a/src/validators/number/toNumber.ts b/src/validators/number/toNumber.ts index 4126f07..2b7264b 100644 --- a/src/validators/number/toNumber.ts +++ b/src/validators/number/toNumber.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const toNumber = (): SyncValidatorFunction => (value, conf) => { - return Success(Number.parseFloat(value as any)); + return Number.parseFloat(value as any); }; export default toNumber; diff --git a/src/validators/number/tryInt.ts b/src/validators/number/tryInt.ts index f74b9b5..7496f11 100644 --- a/src/validators/number/tryInt.ts +++ b/src/validators/number/tryInt.ts @@ -1,11 +1,11 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const tryInt = (): SyncValidatorFunction => (value, conf) => { const parsed = Number.parseInt(value as any); if (!Number.isNaN(parsed)) { - return Success(parsed); + return parsed; } - return Failure(`Field ${conf.name} should be an integer.`); + throw `Field ${conf.name} should be an integer.` }; export default tryInt; diff --git a/src/validators/number/tryNumber.ts b/src/validators/number/tryNumber.ts index b7c25cc..e71b6b4 100644 --- a/src/validators/number/tryNumber.ts +++ b/src/validators/number/tryNumber.ts @@ -1,11 +1,11 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const tryNumber = (): SyncValidatorFunction => (value, conf) => { const parsed = Number.parseFloat(value as any); if (!Number.isNaN(parsed)) { - return Success(parsed); + return parsed; } - return Failure(`Field ${conf.name} should be numeric.`); + throw `Field ${conf.name} should be numeric.` }; export default tryNumber; diff --git a/src/validators/optional.ts b/src/validators/optional.ts index 9606561..4c4d353 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -1,11 +1,11 @@ -import { Success, SyncValidatorFunction } from '../types.js'; +import { SyncValidatorFunction } from '../types.js'; function optional(): SyncValidatorFunction { return (value, conf) => { if (typeof value === 'undefined') { - return Success(value); + return value; } - return Success(value); + return value; }; } diff --git a/src/validators/string/betweenLength.ts b/src/validators/string/betweenLength.ts index e3d1f8e..1110c94 100644 --- a/src/validators/string/betweenLength.ts +++ b/src/validators/string/betweenLength.ts @@ -1,4 +1,4 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const betweenLength = (min: number, max: number): SyncValidatorFunction => @@ -6,11 +6,9 @@ const betweenLength = const minLength = Math.min(min, max); const maxLength = Math.max(min, max); if (minLength <= value.length && value.length <= maxLength) { - return Success(value); + return value; } - return Failure( - `Field ${conf.name} length should be between ${minLength} and ${maxLength} characters.` - ); + throw `Field ${conf.name} length should be between ${minLength} and ${maxLength} characters.`; }; export default betweenLength; diff --git a/src/validators/string/insensitiveEquals.ts b/src/validators/string/insensitiveEquals.ts index 25aee60..15e8f2f 100644 --- a/src/validators/string/insensitiveEquals.ts +++ b/src/validators/string/insensitiveEquals.ts @@ -1,12 +1,12 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const insensitiveEquals = (to: string): SyncValidatorFunction => (value, conf) => { if (value.toLocaleLowerCase() === to.toLocaleLowerCase()) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} should be equal to ${to}.`); + throw `Field ${conf.name} should be equal to ${to}.` }; export default insensitiveEquals; diff --git a/src/validators/string/isUrl.ts b/src/validators/string/isUrl.ts index 8f56b82..5e89837 100644 --- a/src/validators/string/isUrl.ts +++ b/src/validators/string/isUrl.ts @@ -1,11 +1,11 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const isUrl = (): SyncValidatorFunction => (value, conf) => { try { new URL(value); - return Success(value); + return value; } catch { - return Failure(`Field ${conf.name} should be an url.`); + throw `Field ${conf.name} should be an url.` } }; export default isUrl; diff --git a/src/validators/string/length.ts b/src/validators/string/length.ts index fdc5852..43fa217 100644 --- a/src/validators/string/length.ts +++ b/src/validators/string/length.ts @@ -1,12 +1,12 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const length = (n: number): SyncValidatorFunction => (value, conf) => { if (value.length === n) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} length should be exactly ${n} characters.`); + throw `Field ${conf.name} length should be exactly ${n} characters.` }; export default length; diff --git a/src/validators/string/maxLength.ts b/src/validators/string/maxLength.ts index 21b35d9..e39e041 100644 --- a/src/validators/string/maxLength.ts +++ b/src/validators/string/maxLength.ts @@ -1,12 +1,12 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const maxLength = (max: number): SyncValidatorFunction => (value, conf) => { if (value.length <= max) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} length should be at most ${max} characters.`); + throw `Field ${conf.name} length should be at most ${max} characters.` }; export default maxLength; diff --git a/src/validators/string/minLength.ts b/src/validators/string/minLength.ts index 5b40378..e665980 100644 --- a/src/validators/string/minLength.ts +++ b/src/validators/string/minLength.ts @@ -1,12 +1,12 @@ -import { Failure, Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const minLength = (min: number): SyncValidatorFunction => (value, conf) => { if (value.length >= min) { - return Success(value); + return value; } - return Failure(`Field ${conf.name} length should be at least ${min} characters.`); + throw `Field ${conf.name} length should be at least ${min} characters.` }; export default minLength; diff --git a/src/validators/string/toString.ts b/src/validators/string/toString.ts index 4e1ad76..d33cb6e 100644 --- a/src/validators/string/toString.ts +++ b/src/validators/string/toString.ts @@ -1,7 +1,7 @@ -import { Success, SyncValidatorFunction } from '../../types.js'; +import { SyncValidatorFunction } from '../../types.js'; const toString = (): SyncValidatorFunction => (value, conf) => { - return Success('' + value); + return '' + value; }; export default toString; diff --git a/src/validators/validateCondition.ts b/src/validators/validateCondition.ts index 6335df2..37747dd 100644 --- a/src/validators/validateCondition.ts +++ b/src/validators/validateCondition.ts @@ -1,7 +1,5 @@ import { - Failure, FailureFunction, - Success, ValidatorConfiguration, AsyncValidatorFunction, SyncValidatorFunctionInner, @@ -33,16 +31,16 @@ function validateCondition( if (isPromise(result)) { return result.then((result) => { if (result) { - return Success(field as T); + return field as T; } else { - return Failure(errorMsg(field, conf)); + throw errorMsg(field, conf); } }); } if (result) { - return Success(field as T); + return field as T; } else { - return Failure(errorMsg(field, conf)); + throw errorMsg(field, conf); } }; } diff --git a/src/validators/validateRegex.ts b/src/validators/validateRegex.ts index dd35857..47c928e 100644 --- a/src/validators/validateRegex.ts +++ b/src/validators/validateRegex.ts @@ -1,4 +1,4 @@ -import { Failure, FailureFunction, Success, SyncValidatorFunction } from '../types.js'; +import { FailureFunction, SyncValidatorFunction } from '../types.js'; const validateRegex = ( regex: RegExp, @@ -6,9 +6,9 @@ const validateRegex = ( ): SyncValidatorFunction => { return function (value, conf) { if (regex.test(value)) { - return Success(value); + return value; } else { - return Failure(errorMsg(value, conf)); + throw errorMsg(value, conf) } }; }; diff --git a/tests/README.ts b/tests/README.ts index bcbae67..3caec04 100644 --- a/tests/README.ts +++ b/tests/README.ts @@ -4,9 +4,6 @@ import validate, { isEmail, minLength, ValidatorFunction, - Success, - Failure, - Validator, ValidatorObject, } from '../src/index'; @@ -89,9 +86,9 @@ test('README: Bring your own validator - isUniqueEmail full', async () => { async function (email, conf) { const exists = await db.users.find({ email }); if (!exists) { - return Success(email); + return email; } - return Failure('This email already in use. Try your alternate address.'); + throw 'This email already in use. Try your alternate address.' }; const validateRegistration = validate({ @@ -124,9 +121,9 @@ test('README: Sanitize and transform - hash', async () => { async function (email, conf) { const exists = await db.users.find({ email }); if (!exists) { - return Success(email); + return email; } - return Failure('This email already in use. Try your alternate address.'); + throw 'This email already in use. Try your alternate address.' }; // Mock bcrypt @@ -139,7 +136,7 @@ test('README: Sanitize and transform - hash', async () => { const hash = (): ValidatorFunction => async function (password, conf) { const hashedPassword = await bcrypt.hash(password, 8); - return Success(hashedPassword); + return hashedPassword; }; const validateRegistration = validate({ @@ -176,9 +173,9 @@ test('README: Higher-order validators - confirmPassword', async () => { async function (email, conf) { const exists = await db.users.find({ email }); if (!exists) { - return Success(email); + return email; } - return Failure('This email already in use. Try your alternate address.'); + throw 'This email already in use. Try your alternate address.' }; // Mock bcrypt @@ -191,7 +188,7 @@ test('README: Higher-order validators - confirmPassword', async () => { const hash = (): ValidatorFunction => async function (password, conf) { const hashedPassword = await bcrypt.hash(password, 8); - return Success(hashedPassword); + return hashedPassword; }; const confirmPassword = < @@ -202,10 +199,10 @@ test('README: Higher-order validators - confirmPassword', async () => { ): ValidatorFunction => async function (user, conf) { if (!user?.password_confirm) { - return Failure('You should confirm your password.'); + throw 'You should confirm your password.' } if (user.password_confirm !== user.password) { - return Failure('The two passwords do not match.'); + throw 'The two passwords do not match.' } return validate(validator)(user); }; diff --git a/tests/validate.ts b/tests/validate.ts index c5a5735..25d515f 100644 --- a/tests/validate.ts +++ b/tests/validate.ts @@ -1,20 +1,20 @@ import { describe, expect, test } from '@jest/globals'; import validate from '../src/validate'; -import { Failure, Success, ValidatorFunction } from '../src/types'; +import { ValidatorFunction } from '../src/types'; const testSuccessfulValidation = (): ValidatorFunction => async function (value, _conf) { - return Success(value); + return value; }; const testFailingValidation = (): ValidatorFunction => async function (_value, _conf) { - return Failure('test failed'); + throw 'test failed' }; const testTransformValidation = (): ValidatorFunction => async function (value, _conf) { - return Success(value + value); + return value + value; }; test('validate with function returns the value on success', async () => { diff --git a/tests/validators/arrayOf.ts b/tests/validators/arrayOf.ts index 9206997..6277625 100644 --- a/tests/validators/arrayOf.ts +++ b/tests/validators/arrayOf.ts @@ -1,24 +1,24 @@ import { describe, expect, test } from '@jest/globals'; import arrayOf from '../../src/validators/arrayOf'; import validate from '../../src/validate'; -import { Failure, Success, ValidatorFunction } from '../../src/types'; +import { ValidatorFunction } from '../../src/types'; const testSuccessfulValidation = (): ValidatorFunction => async function (value, _conf) { - return Success(value); + return value; }; const testFailingValidation = (): ValidatorFunction => async function (_value, _conf) { - return Failure('test failed'); + throw 'test failed' }; const testMinimumValidation = (): ValidatorFunction => async function (value, _conf) { if (value > 2) { - return Success(value); + return value; } else { - return Failure('test failed'); + throw 'test failed' } }; diff --git a/tests/validators/bail.ts b/tests/validators/bail.ts index db325fc..21f695f 100644 --- a/tests/validators/bail.ts +++ b/tests/validators/bail.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from '@jest/globals'; -import { Failure, Success, ValidatorConfiguration, ValidatorFunction } from '../../src/types'; +import { ValidatorConfiguration, ValidatorFunction } from '../../src/types'; import validate from '../../src/validate'; import bail from '../../src/validators/bail'; @@ -15,13 +15,13 @@ test('bail runs over each test if they are not failing', async () => { const increment = (): ValidatorFunction => async (value) => { i += 1; - return Success(value); + return value; }; // To test whether it works with returning value const increment2 = (): ValidatorFunction => async (value) => { i += 1; - return Success(value); + return value; }; const validateBail = validate(bail([increment(), increment2(), increment()])); @@ -35,7 +35,7 @@ test('bail stops after first failing test', async () => { const failIncrement = (): ValidatorFunction => async () => { i += 1; - return Failure('Incrementation failed.'); + throw 'Incrementation failed.' }; const validateBail = validate(bail([failIncrement(), failIncrement(), failIncrement()])); @@ -51,9 +51,9 @@ test('bail stops after first failing test', async () => { test('bail just passes to validate if the passed value is not an array', async () => { const increment = (): ValidatorFunction => async (value) => { if (value) { - return Success(value); + return value; } else { - return Failure("This shouldn't pass."); + throw "This shouldn't pass." } }; diff --git a/tests/validators/either.ts b/tests/validators/either.ts index f54fe6e..e1ad3d8 100644 --- a/tests/validators/either.ts +++ b/tests/validators/either.ts @@ -1,21 +1,21 @@ import { expect, test } from '@jest/globals'; import either from '../../src/validators/either'; import validate from '../../src/validate'; -import { Failure, Success, ValidatorFunction } from '../../src/types'; +import { ValidatorFunction } from '../../src/types'; const testSuccessfulValidation = (): ValidatorFunction => async function (value, _conf) { - return Success(value); + return value; }; const testFailingValidation = (i: number): ValidatorFunction => async function (_value, _conf) { - return Failure(`test ${i} failed`); + throw `test ${i} failed` }; const testTransformingValidation = (): ValidatorFunction => async function (value, _conf) { - return Success(value + 1); + return value + 1; }; test('either function passes if both of the two validation passes', async () => { diff --git a/tests/validators/optional.ts b/tests/validators/optional.ts index 6a4f324..6af5532 100644 --- a/tests/validators/optional.ts +++ b/tests/validators/optional.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from '@jest/globals'; -import { Failure, Success, ValidatorConfiguration, ValidatorFunction } from '../../src/types'; +import { ValidatorConfiguration, ValidatorFunction } from '../../src/types'; import validate from '../../src/validate'; import optional from '../../src/validators/optional'; @@ -15,9 +15,9 @@ test.failing('optional validator if value is undefined returns successfully', as const testValidation = (): ValidatorFunction => async (value) => { i += 1; if (value) { - return Success(value as string); + return value as string; } - return Failure('This field is required.'); + throw 'This field is required.' }; const validateFunctionOptional = validate([testValidation()]); @@ -46,9 +46,9 @@ test.failing('optional validator if value is undefined returns successfully', as test('optional validator without it undefined fails', async () => { const testValidation = (): ValidatorFunction => async (value) => { if (value) { - return Success(value as string); + return value as string; } - return Failure('This field is required.'); + throw 'This field is required.' }; const validateNotOptional = validate({ field: testValidation() }); From 9c6ffab519fb1e5ecd90c34b4a83062264ef7993 Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 19:43:36 +0100 Subject: [PATCH 11/16] Remove undefined checks from code --- src/validate.ts | 43 ++++++++++++++++++++++-------------------- src/validators/bail.ts | 9 ++++----- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/validate.ts b/src/validate.ts index e45d248..a67f158 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -10,10 +10,12 @@ function resolveValidatorList(validators: ValidatorFunctionList ({ - value: typeof newValue !== 'undefined' ? newValue : value, - failures, - }), + (newValue) => { + return { + value: newValue, + failures, + }; + }, (failure) => ({ value, failures: failures.concat(failure), @@ -21,7 +23,7 @@ function resolveValidatorList(validators: ValidatorFunctionList(validators: ValidatorFunctionList ({ - value: typeof newValue !== 'undefined' ? newValue : value, - failures: previousState.failures, - }), + (newValue) => { + return { + value: newValue, + failures: previousState.failures, + }; + }, (failure) => ({ value, failures: previousState.failures.concat(failure), @@ -40,7 +44,7 @@ function resolveValidatorList(validators: ValidatorFunctionList(validator: ValidatorObject, testValue: any return result.then( (value) => ({ - value: [key, typeof result === 'undefined' ? testValue[key] : value], + value: [key, value], failures: [], } as ValidatorState<[keyof O, O[keyof O]]>), (failure) => ({ value: [key, testValue[key]], failures: Array.isArray(failure) ? failure : [failure] } as ValidatorState<[keyof O, O[keyof O]]>) ); } return { - value: [key, typeof result === 'undefined' ? testValue[key] : result], + value: [key, result], failures: [], } as ValidatorState<[keyof O, O[keyof O]]>; }); @@ -168,15 +172,14 @@ export function validate(validator: Validator, validateC try { const result = validator(testValue, conf); if (isPromise(result)) { - return result - .then((newValue) => (typeof newValue !== 'undefined' ? newValue : testValue)) - .catch((failures) => { - if (Array.isArray(failures)) { - return Promise.reject(failures); - } - return Promise.reject([failures]); - }); + return result.catch((failures) => { + if (Array.isArray(failures)) { + return Promise.reject(failures); + } + return Promise.reject([failures]); + }); } + return result; return result !== 'undefined' ? result : testValue; } catch (failures) { if (Array.isArray(failures)) { diff --git a/src/validators/bail.ts b/src/validators/bail.ts index e35d7ff..a6415c6 100644 --- a/src/validators/bail.ts +++ b/src/validators/bail.ts @@ -1,5 +1,4 @@ import { - SyncValidatorFunction, SyncValidatorFunctionList, ValidatorConfiguration, ValidatorFunction, @@ -35,7 +34,7 @@ function bail( if (isPromise(result)) { return result.then( (newValue) => ({ - value: typeof newValue !== 'undefined' ? newValue : value, + value: newValue, failures, }), (failure) => ({ @@ -45,7 +44,7 @@ function bail( ); } return { - value: typeof result !== 'undefined' ? result : value, + value: result, failures: failures, }; }); @@ -57,7 +56,7 @@ function bail( if (isPromise(result)) { return result.then( (newValue) => ({ - value: typeof newValue !== 'undefined' ? newValue : value, + value: newValue, failures: previousState.failures, }), (failure) => ({ @@ -67,7 +66,7 @@ function bail( ); } return { - value: typeof result !== 'undefined' ? result : value, + value: result, failures: previousState.failures, }; }, From bf401e6b022b96d42510b61ecbadceeabb4da64a Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 11 Dec 2022 20:12:29 +0100 Subject: [PATCH 12/16] FIx optional code and tests --- src/types.ts | 5 +++-- src/validate.ts | 6 +++--- src/validators/optional.ts | 26 +++++++++++++++++++++++--- tests/validators/optional.ts | 36 +++++++++++++++++++----------------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/types.ts b/src/types.ts index 66e884a..1e7fab7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,9 +10,10 @@ export interface ValidatorConfiguration { parent: any; } -export type SyncValidatingFunction = (val: I, c?: Partial) => O; +export type SyncValidatingFunction = O extends Promise ? never : (val: I, c?: Partial) => O; +export type SyncValidatingFunctionInner = O extends Promise ? never : SyncValidatingFunction; export type AsyncValidatingFunction = (val: I, c?: Partial) => Promise; -export type ValidatingFunction = SyncValidatingFunction | AsyncValidatingFunction; +export type ValidatingFunction = SyncValidatingFunctionInner | AsyncValidatingFunction; export type SyncValidatorFunction = (value: I, conf: ValidatorConfiguration) => O; // This is necessary so sync validators don't eat async validators (SyncValidatorFunction> instead of ValidatorFunction) diff --git a/src/validate.ts b/src/validate.ts index a67f158..5450f1f 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -1,4 +1,4 @@ -import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidatorFunctionInner, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, ValidatingFunction, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; +import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidatingFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, ValidatingFunction, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; @@ -89,7 +89,7 @@ function resolveValidatorObject(validator: ValidatorObject, testValue: any ); } return { - value: [key, result], + value: [key, result] as [keyof O, O[keyof O]], failures: [], } as ValidatorState<[keyof O, O[keyof O]]>; }); @@ -132,7 +132,7 @@ const isValidatorFunction = (validator: Validator): vali }; export function validate(v: SyncValidatorFunctionInner, c?: Partial): SyncValidatingFunction; -export function validate(v: SyncValidatingFunction, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatingFunctionInner, c?: Partial): SyncValidatingFunction; export function validate(v: SyncValidatorFunctionList1, c?: Partial): SyncValidatingFunction; export function validate(v: SyncValidatorFunctionList2, c?: Partial): SyncValidatingFunction; export function validate(v: SyncValidatorFunctionList3, c?: Partial): SyncValidatingFunction; diff --git a/src/validators/optional.ts b/src/validators/optional.ts index 4c4d353..6f28925 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -1,11 +1,31 @@ -import { SyncValidatorFunction } from '../types.js'; +import { + AsyncValidatingFunction, + SyncValidatingFunction, + SyncValidator, + ValidatingFunction, + Validator, + ValidatorConfiguration, +} from '../types.js'; +import validate, { isPromise } from '../validate.js'; -function optional(): SyncValidatorFunction { +function optional( + validator: SyncValidator +): SyncValidatingFunction; +function optional( + validator: Validator +): AsyncValidatingFunction; +function optional( + validator: Validator +): (value: unknown, conf: ValidatorConfiguration) => T | undefined | Promise { return (value, conf) => { if (typeof value === 'undefined') { return value; } - return value; + const result = validate(validator)(value); + if (isPromise(result)) { + return result; + } + return result; }; } diff --git a/tests/validators/optional.ts b/tests/validators/optional.ts index 6af5532..b09b23e 100644 --- a/tests/validators/optional.ts +++ b/tests/validators/optional.ts @@ -1,35 +1,37 @@ import { describe, expect, test } from '@jest/globals'; -import { ValidatorConfiguration, ValidatorFunction } from '../../src/types'; +import { SyncValidatorFunction, ValidatorConfiguration, ValidatorFunction } from '../../src/types'; import validate from '../../src/validate'; import optional from '../../src/validators/optional'; -const conf: ValidatorConfiguration = { - name: 'optionalField', - original: {}, - path: [], - parent: {}, -}; - -test.failing('optional validator if value is undefined returns successfully', async () => { +test('optional sync validator if value is undefined returns successfully', async () => { let i = 0; - const testValidation = (): ValidatorFunction => async (value) => { + const testValidation = (): SyncValidatorFunction => (value) => { i += 1; if (value) { return value as string; } - throw 'This field is required.' + throw 'This field is required.'; }; - const validateFunctionOptional = validate([testValidation()]); - expect(await validateFunctionOptional({})).toEqual({} as any); + const validateFunctionOptional = validate(optional([testValidation()])); + expect(validateFunctionOptional(undefined)).toEqual(undefined); expect(i).toEqual(0); - expect(await validateFunctionOptional({ field: 'string' })).toEqual({ field: 'string' }); + expect(validateFunctionOptional({ field: 'string' })).toEqual({ field: 'string' }); expect(i).toEqual(1); +}); - i = 0; +test('optional validator if value is undefined returns successfully', async () => { + let i = 0; + const testValidation = (): ValidatorFunction => async (value) => { + i += 1; + if (value) { + return value as string; + } + throw 'This field is required.'; + }; const validateListOptional = validate({ - field: [testValidation(), testValidation()], + field: optional([testValidation(), testValidation()]), }); expect(await validateListOptional({})).toEqual({} as any); expect(i).toEqual(0); @@ -48,7 +50,7 @@ test('optional validator without it undefined fails', async () => { if (value) { return value as string; } - throw 'This field is required.' + throw 'This field is required.'; }; const validateNotOptional = validate({ field: testValidation() }); From 99ccc765deffcc8f9e97d19620ebce82542f8d75 Mon Sep 17 00:00:00 2001 From: Grant Date: Mon, 12 Dec 2022 00:42:37 +0100 Subject: [PATCH 13/16] Fix and improve tests to push above 99% --- src/types.ts | 5 +- src/validate.ts | 4 +- src/validators/arrayOf.ts | 44 ++++----- src/validators/bail.ts | 79 +++++++++------- src/validators/either.ts | 100 +++++++++++++------- tests/validators/arrayOf.ts | 67 ++++++++++--- tests/validators/bail.ts | 129 ++++++++++++++++++++++++-- tests/validators/either.ts | 81 +++++++++++++--- tests/validators/validateCondition.ts | 29 +++++- 9 files changed, 408 insertions(+), 130 deletions(-) diff --git a/src/types.ts b/src/types.ts index 1e7fab7..6a957db 100644 --- a/src/types.ts +++ b/src/types.ts @@ -49,4 +49,7 @@ export interface FailureFunction { (v: T, conf: ValidatorConfiguration): string; } -export type InferValidator = T extends Validator ? O : never; +export type InferValidator = T extends Validator ? O : never; + +type Inferred = InferValidator | SyncValidatingFunction>; +type Inferred2 = ValidatingFunction extends SyncValidator ? true : false; \ No newline at end of file diff --git a/src/validate.ts b/src/validate.ts index 5450f1f..4b4705f 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -3,11 +3,12 @@ import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidatingFunction function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): O | Promise { + // TODO: we probably should bail by default const result = (validators as ValidatorFunction[]).reduce | Promise>>( (previousState, validator) => { if (isPromise(previousState)) { return previousState.then(({ value, failures }) => { - const result = validator(value, conf); + const result: unknown = validator(value, conf); if (isPromise(result)) { return result.then( (newValue) => { @@ -180,6 +181,7 @@ export function validate(validator: Validator, validateC }); } return result; + // For some reason, without this it won't compile ??? return result !== 'undefined' ? result : testValue; } catch (failures) { if (Array.isArray(failures)) { diff --git a/src/validators/arrayOf.ts b/src/validators/arrayOf.ts index c39e694..948f25c 100644 --- a/src/validators/arrayOf.ts +++ b/src/validators/arrayOf.ts @@ -1,22 +1,20 @@ import validate, { hasNoPromise, isPromise } from '../validate.js'; import { Validator, - SyncValidatorFunction, ValidatorState, - ValidatorFunction, SyncValidator, ValidatorConfiguration, + SyncValidatingFunction, + AsyncValidatingFunction, } from '../types.js'; function arrayOf( validator: SyncValidator -): (val: unknown, c: ValidatorConfiguration) => O[]; +): SyncValidatingFunction; +function arrayOf(validator: Validator): AsyncValidatingFunction; function arrayOf( validator: Validator -): (val: unknown, c: ValidatorConfiguration) => Promise; -function arrayOf( - validator: Validator -): (val: unknown, c: ValidatorConfiguration) => O[] | Promise { +): (val: I[], c: ValidatorConfiguration) => O[] | Promise { return (testValues, conf) => { // Array of one item should use that validation to every item in the array if (typeof testValues !== 'object' || !Array.isArray(testValues)) { @@ -25,22 +23,26 @@ function arrayOf( const results = testValues.map | Promise>>( (testValue, i) => { - const result = validate(validator, { - ...conf, - name: `${conf.name}[${i}]`, - path: conf.path.concat(i.toString()), - parent: testValues, - })(testValue); + try { + const result = validate(validator, { + ...conf, + name: `${conf.name}[${i}]`, + path: conf.path.concat(i.toString()), + parent: testValues, + })(testValue); - if (isPromise(result)) { - return result.then( - (value) => ({ value, failures: [] }), - (failures) => ({ value: testValue, failures }) - ); - } + if (isPromise(result)) { + return result.then( + (value) => ({ value, failures: [] }), + (failures) => ({ value: testValue as any, failures }) + ); + } - // TODO: handles multiple failures - return { value: result, failures: [] }; + // TODO: handles multiple failures + return { value: result, failures: [] }; + } catch (failure) { + return { value: testValue as any, failures: failure as string[] }; + } } ); diff --git a/src/validators/bail.ts b/src/validators/bail.ts index a6415c6..4914c51 100644 --- a/src/validators/bail.ts +++ b/src/validators/bail.ts @@ -30,45 +30,59 @@ function bail( if (failures.length > 0) { return previousState; } - const result = validator(value, conf); - if (isPromise(result)) { - return result.then( - (newValue) => ({ - value: newValue, - failures, - }), - (failure) => ({ - value, - failures: failures.concat(failure), - }) - ); + try { + const result = validator(value, conf); + if (isPromise(result)) { + return result.then( + (newValue) => ({ + value: newValue, + failures, + }), + (failure) => ({ + value, + failures: failures.concat(failure), + }) + ); + } + return { + value: result, + failures: failures, + }; + } catch (err) { + return { + value, + failures: failures.concat(err as string[]), + }; } - return { - value: result, - failures: failures, - }; }); } if (previousState.failures.length > 0) { return previousState; } - const result = validator(value, conf); - if (isPromise(result)) { - return result.then( - (newValue) => ({ - value: newValue, - failures: previousState.failures, - }), - (failure) => ({ - value, - failures: previousState.failures.concat(failure), - }) - ); + try { + const result = validator(value, conf); + if (isPromise(result)) { + return result.then( + (newValue) => ({ + value: newValue, + failures: previousState.failures, + }), + (failure) => ({ + value, + failures: previousState.failures.concat(failure), + }) + ); + } + return { + value: result, + failures: previousState.failures, + }; + } catch (err) { + return { + value, + failures: previousState.failures.concat(err as string[]), + }; } - return { - value: result, - failures: previousState.failures, - }; }, { value, failures: [] } as ValidatorState ); @@ -82,7 +96,6 @@ function bail( }); } - // TODO: handles multiple failures if (result.failures.length > 0) { throw result.failures; } diff --git a/src/validators/either.ts b/src/validators/either.ts index 73dd3c2..708bf88 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -1,43 +1,73 @@ -import { InferValidator, Validator, ValidatorConfiguration } from '../types.js'; -import validate, { hasNoPromise } from '../validate.js'; +import { + AsyncValidatorFunction, + InferValidator, + SyncValidator, + SyncValidatorFunction, + SyncValidatorFunctionInner, + Validator, + ValidatorConfiguration, + ValidatorFunction, + ValidatorState, +} from '../types.js'; +import validate, { hasNoPromise, isPromise } from '../validate.js'; -function either>( - validators: V[] -): (val: unknown, c: ValidatorConfiguration) => InferValidator; -function either>( - validators: V[] -): (val: unknown, c: ValidatorConfiguration) => Promise>; -function either>( - validators: V[] -): (val: unknown, c: ValidatorConfiguration) => InferValidator | Promise> { +function either( + validators: [SyncValidator, SyncValidator] +): SyncValidatorFunctionInner; +function either( + validators: [Validator, Validator] +): ValidatorFunction; +function either( + validators: [Validator, Validator] +): (val: unknown, c: ValidatorConfiguration) => O1 | O2 | Promise { return (value, conf) => { - try { - const results = validators.map((validator) => { - return validate(validator, conf)(value, conf) as - | InferValidator - | Promise>; - }); - - if (!hasNoPromise(results)) { - return Promise.allSettled(results).then((results) => { - const fulfilledPromise = results.find( - (result: PromiseSettledResult): result is PromiseFulfilledResult => - result.status === 'fulfilled' + const results = validators.map((validator) => { + try { + const result = validate( + validator as Validator, + conf + )(value, conf) as O1 | O2 | Promise; + if (isPromise(result)) { + return result.then( + (value) => + ({ + value, + failures: [], + } as ValidatorState), + (failure) => + ({ + value, + failures: failure, + } as ValidatorState) ); - if (fulfilledPromise) { - return fulfilledPromise.value; - } - const rejectedPromises = results.filter( - (result: PromiseSettledResult): result is PromiseRejectedResult => - result.status === 'rejected' - ); - throw rejectedPromises.flatMap((result) => result.reason); - }); + } + return { + value: result, + failures: [], + } as ValidatorState; + } catch (err) { + return { + value, + failures: err, + } as ValidatorState; } - return value as InferValidator; - } catch (err) { - throw err; + }); + + if (!hasNoPromise(results)) { + return Promise.all(results).then((results) => { + const successfulResult = results.find((result) => result.failures.length === 0); + if (typeof successfulResult === 'undefined') { + throw results.flatMap((result) => result.failures); + } + return successfulResult.value; + }); + } + + const successfulResult = results.find((result) => result.failures.length === 0); + if (typeof successfulResult === 'undefined') { + throw results.flatMap((result) => result.failures); } + return successfulResult.value; }; } diff --git a/tests/validators/arrayOf.ts b/tests/validators/arrayOf.ts index 6277625..6fd94ba 100644 --- a/tests/validators/arrayOf.ts +++ b/tests/validators/arrayOf.ts @@ -1,45 +1,84 @@ import { describe, expect, test } from '@jest/globals'; import arrayOf from '../../src/validators/arrayOf'; import validate from '../../src/validate'; -import { ValidatorFunction } from '../../src/types'; +import { SyncValidatorFunction, ValidatorFunction } from '../../src/types'; -const testSuccessfulValidation = (): ValidatorFunction => +const testSuccessfulValidation = (): SyncValidatorFunction => + function (value, _conf) { + return value; + }; + +const testSuccessfulValidationP = (): ValidatorFunction => async function (value, _conf) { return value; }; -const testFailingValidation = (): ValidatorFunction => +const testFailingValidation = (): SyncValidatorFunction => + function (_value, _conf) { + throw 'test failed'; + }; + +const testFailingValidationP = (): ValidatorFunction => async function (_value, _conf) { - throw 'test failed' + throw 'test failed'; }; -const testMinimumValidation = (): ValidatorFunction => +const testMinimumValidation = (): ValidatorFunction => async function (value, _conf) { if (value > 2) { return value; } else { - throw 'test failed' + throw 'test failed'; } }; -test('arrayOf function validates all items in an array', async () => { +test('arrayOf function validates all items in an array with sync validator', async () => { const value = [1, 2, 3]; const validateTest = validate(arrayOf(testSuccessfulValidation())); - await expect(validateTest(value)).resolves.toEqual(value); + const result: number[] = validateTest(value); + expect(result).toEqual(value); }); -test('arrayOf function validates objects', async () => { - const value = [{ key: 'asdasd' }, { key: 'dsadsa' }]; - const validateTest = validate(arrayOf(testSuccessfulValidation())); +test('arrayOf function validates all items in an array with async validator', async () => { + const value = [1, 2, 3]; + const validateTest = validate(arrayOf(testSuccessfulValidationP())); + + const result: Promise = validateTest(value); + await expect(result).resolves.toEqual(value); +}); + +test('arrayOf function validates objects with sync validator', async () => { + const value = [{ key: 1 }, { key: 2 }]; + const validateTest = validate(arrayOf({ key: testSuccessfulValidation() })); + + const result: { key: number }[] = validateTest(value); + expect(result).toEqual(value); +}); + +test('arrayOf function validates objects with async validator', async () => { + const value = [{ key: 1 }, { key: 2 }]; + const validateTest = validate(arrayOf({ key: testSuccessfulValidationP() })); - await expect(validateTest(value)).resolves.toEqual(value); + const result: Promise<{ key: number }[]> = validateTest(value); + await expect(result).resolves.toEqual(value); }); -test('arrayOf function throws error for every wrong item in array', async () => { +test('arrayOf function throws error for every wrong item in array with sync validator', async () => { const value = [1, 2, 3]; const validateTest = validate(arrayOf(testFailingValidation())); + try { + validateTest(value); + } catch (err) { + expect(err).toEqual(['test failed', 'test failed', 'test failed']); + } +}); + +test('arrayOf function throws error for every wrong item in array with async validator', async () => { + const value = [1, 2, 3]; + const validateTest = validate(arrayOf(testFailingValidationP())); + try { await validateTest(value); } catch (err) { @@ -63,7 +102,7 @@ test('arrayOf function throws error if given data is not an array', async () => const validateTest = validate(arrayOf(testSuccessfulValidation())); try { - await validateTest(value); + validateTest(value as any); } catch (err) { expect(err).not.toBeUndefined(); } diff --git a/tests/validators/bail.ts b/tests/validators/bail.ts index 21f695f..72ae1e7 100644 --- a/tests/validators/bail.ts +++ b/tests/validators/bail.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from '@jest/globals'; -import { ValidatorConfiguration, ValidatorFunction } from '../../src/types'; +import { SyncValidatorFunction, ValidatorConfiguration, ValidatorFunction } from '../../src/types'; import validate from '../../src/validate'; import bail from '../../src/validators/bail'; @@ -10,42 +10,153 @@ const conf: ValidatorConfiguration = { path: [], }; -test('bail runs over each test if they are not failing', async () => { +test('bail runs over each sync test if they are not failing', async () => { let i = 0; - const increment = (): ValidatorFunction => async (value) => { + const increment = (): SyncValidatorFunction => (value) => { i += 1; return value; }; - // To test whether it works with returning value - const increment2 = (): ValidatorFunction => async (value) => { + const validateBail = validate(bail([increment(), increment(), increment()])); + + expect(validateBail(null)).toBe(null); + expect(i).toBe(3); +}); + +test('bail runs over each async test if they are not failing', async () => { + let i = 0; + + const increment = (): ValidatorFunction => async (value) => { i += 1; return value; }; - const validateBail = validate(bail([increment(), increment2(), increment()])); + const validateBail = validate(bail([increment(), increment(), increment()])); await expect(validateBail(null)).resolves.toBe(null); expect(i).toBe(3); }); -test('bail stops after first failing test', async () => { +test('bail runs over each mixed test if they are not failing', async () => { + let i = 0; + + const increment = (): SyncValidatorFunction => (value) => { + i += 1; + return value; + }; + + const incrementP = (): ValidatorFunction => async (value) => { + i += 1; + return value; + }; + + const validateBail = validate(bail([increment(), incrementP()])); + + await expect(validateBail(null)).resolves.toBe(null); + expect(i).toBe(2); + + i = 0 + const validateBail2 = validate(bail([incrementP(), increment()])); + + await expect(validateBail2(null)).resolves.toBe(null); + expect(i).toBe(2); +}); + +test('bail stops after first failing sync test', async () => { + let i = 0; + + const increment = (): SyncValidatorFunction => (value) => { + i += 1; + return value; + }; + + const failIncrement = (): SyncValidatorFunction => () => { + i += 1; + throw 'Incrementation failed.' + }; + + const validateBail = validate(bail([increment(), failIncrement(), failIncrement()])); + + try { + validateBail(null); + } catch (err) { + expect(err).toEqual(['Incrementation failed.']); + } + expect(i).toBe(2); +}); + +test('bail stops after first failing async test', async () => { let i = 0; + const increment = (): ValidatorFunction => async (value) => { + i += 1; + return value; + }; + const failIncrement = (): ValidatorFunction => async () => { i += 1; throw 'Incrementation failed.' }; - const validateBail = validate(bail([failIncrement(), failIncrement(), failIncrement()])); + const validateBail = validate(bail([increment(), failIncrement(), failIncrement()])); try { await validateBail(null); } catch (err) { expect(err).toEqual(['Incrementation failed.']); } - expect(i).toBe(1); + expect(i).toBe(2); +}); + +test('bail stops after first failing test in mixed tests', async () => { + let i = 0; + + const increment = (): SyncValidatorFunction => (value) => { + i += 1; + return value; + }; + + const failIncrement = (): SyncValidatorFunction => () => { + i += 1; + throw 'Incrementation failed.' + }; + + const incrementP = (): ValidatorFunction => async (value) => { + i += 1; + return value; + }; + + const failIncrementP = (): ValidatorFunction => async () => { + i += 1; + throw 'Incrementation failed.' + }; + + const validateBail1 = validate(bail([increment(), failIncrementP(), failIncrement()])); + try { + await validateBail1(null); + } catch (err) { + expect(err).toEqual(['Incrementation failed.']); + } + expect(i).toBe(2); + + i = 0; + const validateBail2 = validate(bail([increment(), failIncrement(), failIncrementP()])); + try { + await validateBail2(null); + } catch (err) { + expect(err).toEqual(['Incrementation failed.']); + } + expect(i).toBe(2); + + i = 0; + const validateBail3 = validate(bail([incrementP(), failIncrement(), failIncrementP()])); + try { + await validateBail3(null); + } catch (err) { + expect(err).toEqual(['Incrementation failed.']); + } + expect(i).toBe(2); }); test('bail just passes to validate if the passed value is not an array', async () => { diff --git a/tests/validators/either.ts b/tests/validators/either.ts index e1ad3d8..2ff67ec 100644 --- a/tests/validators/either.ts +++ b/tests/validators/either.ts @@ -1,41 +1,83 @@ import { expect, test } from '@jest/globals'; import either from '../../src/validators/either'; import validate from '../../src/validate'; -import { ValidatorFunction } from '../../src/types'; +import { SyncValidatorFunction, ValidatorFunction } from '../../src/types'; -const testSuccessfulValidation = (): ValidatorFunction => +const testSuccessfulStringValidation = (): SyncValidatorFunction => + function (value, _conf) { + return value; + }; + +const testSuccessfulNumberValidation = (): SyncValidatorFunction => + function (value, _conf) { + return value; + }; + +const testSuccessfulStringValidationP = (): ValidatorFunction => + async function (value, _conf) { + return value; + }; + +const testSuccessfulNumberValidationP = (): ValidatorFunction => async function (value, _conf) { return value; }; -const testFailingValidation = (i: number): ValidatorFunction => +const testFailingValidation = (i: number): SyncValidatorFunction => + function (_value, _conf) { + throw `test ${i} failed`; + }; + +const testFailingValidationP = (i: number): ValidatorFunction => async function (_value, _conf) { - throw `test ${i} failed` + throw `test ${i} failed`; }; -const testTransformingValidation = (): ValidatorFunction => +const testTransformingValidation = (): ValidatorFunction => async function (value, _conf) { return value + 1; }; -test('either function passes if both of the two validation passes', async () => { +test('either function passes if both of the two sync validation passes', async () => { const value = 1; - const validateTest = validate(either([testSuccessfulValidation(), testSuccessfulValidation()])); + const validateTest = validate( + either([testSuccessfulNumberValidation(), testSuccessfulNumberValidation()]) + ); + const result: number = validateTest(value); + expect(result).toEqual(value); +}); - await expect(validateTest(value)).resolves.toEqual(value); +test('either function passes if both of the two async validation passes', async () => { + const value = 1; + const validateTest = validate( + either([testSuccessfulNumberValidationP(), testSuccessfulNumberValidationP()]) + ); + const result: Promise = validateTest(value); + await expect(result).resolves.toEqual(value); }); -test('either function passes if any of the two validation passes', async () => { +test('either function passes if either of the two sync validation passes', async () => { const value = 1; - const validateTest = validate(either([testSuccessfulValidation(), testFailingValidation(1)])); + const validateTest = validate(either([testSuccessfulNumberValidation(), testSuccessfulStringValidation()])); + const result = validateTest(value); + // TODO: this type doesn't work + // const result: string | number = validateTest(value); + expect(result).toEqual(value); +}); - await expect(validateTest(value)).resolves.toEqual(value); +test('either function passes if both of the two async validation passes', async () => { + const value = 1; + const validateTest = validate( + either([testSuccessfulNumberValidationP(), testSuccessfulStringValidationP()]) + ); + const result: Promise = validateTest(value); + await expect(result).resolves.toEqual(value); }); test('either function resolves to first if the first is transformation', async () => { const value = 1; const validateTest = validate( - either([testTransformingValidation(), testSuccessfulValidation()]) + either([testTransformingValidation(), testSuccessfulNumberValidationP()]) ); await expect(validateTest(value)).resolves.toEqual(value + 1); @@ -44,7 +86,7 @@ test('either function resolves to first if the first is transformation', async ( test('either function resolves to itself if the second one is a transformation', async () => { const value = 1; const validateTest = validate( - either([testSuccessfulValidation(), testTransformingValidation()]) + either([testSuccessfulNumberValidationP(), testTransformingValidation()]) ); await expect(validateTest(value)).resolves.toEqual(value); @@ -59,10 +101,21 @@ test('either function resolves the transformation only once if both are a transf await expect(validateTest(value)).resolves.toEqual(value + 1); }); -test('either function throws error if both of the two validation fails', async () => { +test('either function throws error if both of the two sync validation fails', async () => { const value = 1; const validateTest = validate(either([testFailingValidation(1), testFailingValidation(2)])); + try { + validateTest(value); + } catch (err) { + expect(err).toEqual(['test 1 failed', 'test 2 failed']); + } +}); + +test('either function throws error if both of the two async validation fails', async () => { + const value = 1; + const validateTest = validate(either([testFailingValidationP(1), testFailingValidationP(2)])); + try { await validateTest(value); } catch (err) { diff --git a/tests/validators/validateCondition.ts b/tests/validators/validateCondition.ts index b9b19e2..5a3cf68 100644 --- a/tests/validators/validateCondition.ts +++ b/tests/validators/validateCondition.ts @@ -4,12 +4,17 @@ import validateCondition from '../../src/validators/validateCondition'; const conf: ValidatorConfiguration = { name: 'object', original: {}, parent: {}, path: [] }; -test('validateCondition function returns undefined if regex applies', async () => { +test('validateCondition function returns value if condition applies', async () => { const validateTest = validateCondition(() => true); expect(validateTest('', conf)).toEqual(''); }); -test('validateCondition function throws error if regex fails', async () => { +test('validateCondition function returns value if async condition applies', async () => { + const validateTest = validateCondition(() => Promise.resolve(true)); + await expect(validateTest('', conf)).resolves.toEqual(''); +}); + +test('validateCondition function throws error if condition fails', async () => { const validateTest = validateCondition(() => false); try { validateTest('', conf); @@ -17,3 +22,23 @@ test('validateCondition function throws error if regex fails', async () => { expect(err).not.toBeUndefined(); } }); + +test('validateCondition function throws error if async condition fails', async () => { + const validateTest = validateCondition(() => Promise.resolve(false)); + try { + await validateTest('', conf); + } catch (err) { + expect(err).not.toBeUndefined(); + } +}); + +test('validateCondition function throws error if async condition fails', async () => { + const validateTest = validateCondition(() => { + throw 'Oh no.'; + }); + try { + validateTest('', conf); + } catch (err) { + expect(err).not.toBeUndefined(); + } +}); From 036b5cdf47ba961ce8ce26ae4678d38a74caf196 Mon Sep 17 00:00:00 2001 From: Grant Date: Mon, 2 Jan 2023 23:03:53 +0100 Subject: [PATCH 14/16] Remove any from number validators --- src/validators/number/toInt.ts | 2 +- src/validators/number/toNumber.ts | 2 +- src/validators/number/tryInt.ts | 2 +- src/validators/number/tryNumber.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/validators/number/toInt.ts b/src/validators/number/toInt.ts index 24df926..925a66a 100644 --- a/src/validators/number/toInt.ts +++ b/src/validators/number/toInt.ts @@ -1,7 +1,7 @@ import { SyncValidatorFunction } from '../../types.js'; const toInt = (): SyncValidatorFunction => (value) => { - return Number.parseInt(value as any); + return Number.parseInt(value as string); }; export default toInt; diff --git a/src/validators/number/toNumber.ts b/src/validators/number/toNumber.ts index 2b7264b..00210a9 100644 --- a/src/validators/number/toNumber.ts +++ b/src/validators/number/toNumber.ts @@ -1,7 +1,7 @@ import { SyncValidatorFunction } from '../../types.js'; const toNumber = (): SyncValidatorFunction => (value, conf) => { - return Number.parseFloat(value as any); + return Number.parseFloat(value as string); }; export default toNumber; diff --git a/src/validators/number/tryInt.ts b/src/validators/number/tryInt.ts index 7496f11..3cb320c 100644 --- a/src/validators/number/tryInt.ts +++ b/src/validators/number/tryInt.ts @@ -1,7 +1,7 @@ import { SyncValidatorFunction } from '../../types.js'; const tryInt = (): SyncValidatorFunction => (value, conf) => { - const parsed = Number.parseInt(value as any); + const parsed = Number.parseInt(value as string); if (!Number.isNaN(parsed)) { return parsed; } diff --git a/src/validators/number/tryNumber.ts b/src/validators/number/tryNumber.ts index e71b6b4..c38af70 100644 --- a/src/validators/number/tryNumber.ts +++ b/src/validators/number/tryNumber.ts @@ -1,7 +1,7 @@ import { SyncValidatorFunction } from '../../types.js'; const tryNumber = (): SyncValidatorFunction => (value, conf) => { - const parsed = Number.parseFloat(value as any); + const parsed = Number.parseFloat(value as string); if (!Number.isNaN(parsed)) { return parsed; } From edb0cae6f2f9890356e9dd252a697d47f39d69d6 Mon Sep 17 00:00:00 2001 From: Grant Date: Mon, 2 Jan 2023 23:04:14 +0100 Subject: [PATCH 15/16] Add TODOs where necessary --- package-lock.json | 2 +- package.json | 2 +- src/types.ts | 1 + src/validate.ts | 7 +++++-- src/validators/bail.ts | 1 + src/validators/either.ts | 3 --- src/validators/optional.ts | 1 - 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 09c7ee4..c9ef753 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "typescript": "^4.5.4" }, "engines": { - "node": "14<" + "node": ">=14" } }, "node_modules/@ampproject/remapping": { diff --git a/package.json b/package.json index 09b91da..b4d8c06 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "module": "./es/index.js", "types": "./dist/index.d.ts", "engines": { - "node": "14<" + "node": ">=14" }, "exports": { "require": "./dist/index.js", diff --git a/src/types.ts b/src/types.ts index 6a957db..fd8fb46 100644 --- a/src/types.ts +++ b/src/types.ts @@ -26,6 +26,7 @@ export type SyncValidatorFunctionList2 = [SyncValidatorFunctionInner = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; export type SyncValidatorFunctionList = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3; +// TODO: add more cases for longer validators export type ValidatorFunctionList1 = [ValidatorFunction]; export type ValidatorFunctionList2 = [ValidatorFunction, ValidatorFunction]; export type ValidatorFunctionList3 = [ValidatorFunction, ValidatorFunction, ValidatorFunction]; diff --git a/src/validate.ts b/src/validate.ts index 4b4705f..a44f09f 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -3,9 +3,10 @@ import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidatingFunction function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): O | Promise { - // TODO: we probably should bail by default + // TODO: we should bail by default const result = (validators as ValidatorFunction[]).reduce | Promise>>( (previousState, validator) => { + // TODO: refactor this to a unified function if (isPromise(previousState)) { return previousState.then(({ value, failures }) => { const result: unknown = validator(value, conf); @@ -181,7 +182,7 @@ export function validate(validator: Validator, validateC }); } return result; - // For some reason, without this it won't compile ??? + // TODO: For some reason, without this it won't compile ??? return result !== 'undefined' ? result : testValue; } catch (failures) { if (Array.isArray(failures)) { @@ -196,4 +197,6 @@ export function validate(validator: Validator, validateC }; } +// TODO: add identity transform function + export default validate; diff --git a/src/validators/bail.ts b/src/validators/bail.ts index 4914c51..87a4eb6 100644 --- a/src/validators/bail.ts +++ b/src/validators/bail.ts @@ -7,6 +7,7 @@ import { } from '../types.js'; import validate, { isPromise } from '../validate.js'; +// TODO: replace this with parallel validation function bail( validators: SyncValidatorFunctionList ): (val: I, c: ValidatorConfiguration) => O; diff --git a/src/validators/either.ts b/src/validators/either.ts index 708bf88..87a8fbd 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -1,8 +1,5 @@ import { - AsyncValidatorFunction, - InferValidator, SyncValidator, - SyncValidatorFunction, SyncValidatorFunctionInner, Validator, ValidatorConfiguration, diff --git a/src/validators/optional.ts b/src/validators/optional.ts index 6f28925..72ecedc 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -2,7 +2,6 @@ import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidator, - ValidatingFunction, Validator, ValidatorConfiguration, } from '../types.js'; From d0fd72b39f4eb717af69445526446d124e773ca5 Mon Sep 17 00:00:00 2001 From: Grant Date: Tue, 3 Jan 2023 01:27:27 +0100 Subject: [PATCH 16/16] Add more types for 24 validator list items --- .prettierrc.json | 6 +- src/index.ts | 4 +- src/types.ts | 161 ++++++++++++++++++++++++++++++++++--- src/validate.ts | 64 ++++++++++++--- src/validators/arrayOf.ts | 14 ++-- src/validators/bail.ts | 24 ++---- src/validators/either.ts | 22 ++--- src/validators/optional.ts | 20 +---- tests/types.ts | 6 ++ 9 files changed, 243 insertions(+), 78 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index ec0d09c..3204bbf 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -5,7 +5,11 @@ "semi": true, "overrides": [ { - "files": ["**/types.ts", "**/validate.ts"], + "files": [ + "src/types.ts", + "src/validate.ts", + "src/validators/bail.ts" + ], "options": { "printWidth": 1000 } } ] diff --git a/src/index.ts b/src/index.ts index 84787f9..139eb1c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -69,7 +69,7 @@ import upper from './transformers/string/upper.js'; import { FailureFunction, - Validator, + ValidatorInner, ValidatorConfiguration, ValidatorFunction, ValidatorObject, @@ -78,7 +78,7 @@ import { export type { FailureFunction, - Validator, + ValidatorInner as Validator, ValidatorConfiguration, ValidatorFunction, ValidatorObject, diff --git a/src/types.ts b/src/types.ts index fd8fb46..fd85e37 100644 --- a/src/types.ts +++ b/src/types.ts @@ -24,13 +24,102 @@ export type ValidatorFunction = SyncValidatorFunctionInner | AsyncVa export type SyncValidatorFunctionList1 = [SyncValidatorFunctionInner]; export type SyncValidatorFunctionList2 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner]; export type SyncValidatorFunctionList3 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; -export type SyncValidatorFunctionList = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3; +export type SyncValidatorFunctionList4 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList5 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList6 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList7 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList8 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList9 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList10 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList11 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList12 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList13 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList14 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList15 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList16 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList17 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList18 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList19 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList20 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList21 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList22 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList23 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList24 = [SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionInner]; +export type SyncValidatorFunctionList = + | SyncValidatorFunctionList1 + | SyncValidatorFunctionList2 + | SyncValidatorFunctionList3 + | SyncValidatorFunctionList4 + | SyncValidatorFunctionList5 + | SyncValidatorFunctionList6 + | SyncValidatorFunctionList7 + | SyncValidatorFunctionList8 + | SyncValidatorFunctionList9 + | SyncValidatorFunctionList10 + | SyncValidatorFunctionList11 + | SyncValidatorFunctionList12 + | SyncValidatorFunctionList13 + | SyncValidatorFunctionList14 + | SyncValidatorFunctionList15 + | SyncValidatorFunctionList16 + | SyncValidatorFunctionList17 + | SyncValidatorFunctionList18 + | SyncValidatorFunctionList19 + | SyncValidatorFunctionList20 + | SyncValidatorFunctionList21 + | SyncValidatorFunctionList22 + | SyncValidatorFunctionList23 + | SyncValidatorFunctionList24; -// TODO: add more cases for longer validators export type ValidatorFunctionList1 = [ValidatorFunction]; export type ValidatorFunctionList2 = [ValidatorFunction, ValidatorFunction]; export type ValidatorFunctionList3 = [ValidatorFunction, ValidatorFunction, ValidatorFunction]; -export type ValidatorFunctionList = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3; +export type ValidatorFunctionList4 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList5 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList6 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList7 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList8 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList9 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList10 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList11 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList12 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList13 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList14 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList15 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList16 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList17 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList18 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList19 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList20 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList21 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList22 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList23 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList24 = [ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction, ValidatorFunction]; +export type ValidatorFunctionList = + | ValidatorFunctionList1 + | ValidatorFunctionList2 + | ValidatorFunctionList3 + | ValidatorFunctionList4 + | ValidatorFunctionList5 + | ValidatorFunctionList6 + | ValidatorFunctionList7 + | ValidatorFunctionList8 + | ValidatorFunctionList9 + | ValidatorFunctionList10 + | ValidatorFunctionList11 + | ValidatorFunctionList12 + | ValidatorFunctionList13 + | ValidatorFunctionList14 + | ValidatorFunctionList15 + | ValidatorFunctionList16 + | ValidatorFunctionList17 + | ValidatorFunctionList18 + | ValidatorFunctionList19 + | ValidatorFunctionList20 + | ValidatorFunctionList21 + | ValidatorFunctionList22 + | ValidatorFunctionList23 + | ValidatorFunctionList24; // Value validators are necessary, because we don't have generics in mapped types. // Validator object values only support the return type of last validator function. @@ -38,19 +127,71 @@ export type SyncValueValidator = SyncValidatorFunctionList1 | SyncVal export type SyncValidatorObject = { [key in keyof O]: SyncValueValidator; }; -export type ValueValidator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatingFunction | ValidatorObject; +export type ValueValidator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatingFunction | ValidatorObject; export type ValidatorObject = { [key in keyof O]: ValueValidator; }; -export type SyncValidator = SyncValidatorFunctionList1 | SyncValidatorFunctionList2 | SyncValidatorFunctionList3 | SyncValidatorFunctionInner | SyncValidatorObject; -export type Validator = ValidatorFunctionList1 | ValidatorFunctionList2 | ValidatorFunctionList3 | ValidatorFunction | ValidatorObject; +export type SyncValidatorInner = + | SyncValidatorFunctionList1 + | SyncValidatorFunctionList2 + | SyncValidatorFunctionList3 + | SyncValidatorFunctionList4 + | SyncValidatorFunctionList5 + | SyncValidatorFunctionList6 + | SyncValidatorFunctionList7 + | SyncValidatorFunctionList8 + | SyncValidatorFunctionList9 + | SyncValidatorFunctionList10 + | SyncValidatorFunctionList11 + | SyncValidatorFunctionList12 + | SyncValidatorFunctionList13 + | SyncValidatorFunctionList14 + | SyncValidatorFunctionList15 + | SyncValidatorFunctionList16 + | SyncValidatorFunctionList17 + | SyncValidatorFunctionList18 + | SyncValidatorFunctionList19 + | SyncValidatorFunctionList20 + | SyncValidatorFunctionList21 + | SyncValidatorFunctionList22 + | SyncValidatorFunctionList23 + | SyncValidatorFunctionList24 + | SyncValidatorFunctionInner + | SyncValidatorObject; +export type ValidatorInner = + | ValidatorFunctionList1 + | ValidatorFunctionList2 + | ValidatorFunctionList3 + | ValidatorFunctionList4 + | ValidatorFunctionList5 + | ValidatorFunctionList6 + | ValidatorFunctionList7 + | ValidatorFunctionList8 + | ValidatorFunctionList9 + | ValidatorFunctionList10 + | ValidatorFunctionList11 + | ValidatorFunctionList12 + | ValidatorFunctionList13 + | ValidatorFunctionList14 + | ValidatorFunctionList15 + | ValidatorFunctionList16 + | ValidatorFunctionList17 + | ValidatorFunctionList18 + | ValidatorFunctionList19 + | ValidatorFunctionList20 + | ValidatorFunctionList21 + | ValidatorFunctionList22 + | ValidatorFunctionList23 + | ValidatorFunctionList24 + | ValidatorFunction + | ValidatorObject; + +export type SyncValidator = SyncValidatorInner; +export type Validator = ValidatorInner; export interface FailureFunction { (v: T, conf: ValidatorConfiguration): string; } -export type InferValidator = T extends Validator ? O : never; - -type Inferred = InferValidator | SyncValidatingFunction>; -type Inferred2 = ValidatingFunction extends SyncValidator ? true : false; \ No newline at end of file +export type InferValidator = T extends ValidatorInner ? O : never; diff --git a/src/validate.ts b/src/validate.ts index a44f09f..1a20c0d 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -1,9 +1,9 @@ -import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidatingFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList2, SyncValidatorFunctionList3, SyncValidatorObject, ValidatingFunction, Validator, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList2, ValidatorFunctionList3, ValidatorObject, ValidatorState } from './types.js'; +import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidatingFunctionInner, SyncValidatorFunctionInner, SyncValidatorFunctionList, SyncValidatorFunctionList1, SyncValidatorFunctionList10, SyncValidatorFunctionList11, SyncValidatorFunctionList12, SyncValidatorFunctionList13, SyncValidatorFunctionList14, SyncValidatorFunctionList15, SyncValidatorFunctionList16, SyncValidatorFunctionList17, SyncValidatorFunctionList18, SyncValidatorFunctionList19, SyncValidatorFunctionList2, SyncValidatorFunctionList20, SyncValidatorFunctionList21, SyncValidatorFunctionList22, SyncValidatorFunctionList23, SyncValidatorFunctionList24, SyncValidatorFunctionList3, SyncValidatorFunctionList4, SyncValidatorFunctionList5, SyncValidatorFunctionList6, SyncValidatorFunctionList7, SyncValidatorFunctionList8, SyncValidatorFunctionList9, SyncValidatorObject, ValidatingFunction, ValidatorInner, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorFunctionList1, ValidatorFunctionList10, ValidatorFunctionList11, ValidatorFunctionList12, ValidatorFunctionList13, ValidatorFunctionList14, ValidatorFunctionList15, ValidatorFunctionList16, ValidatorFunctionList17, ValidatorFunctionList18, ValidatorFunctionList19, ValidatorFunctionList2, ValidatorFunctionList20, ValidatorFunctionList21, ValidatorFunctionList22, ValidatorFunctionList23, ValidatorFunctionList24, ValidatorFunctionList3, ValidatorFunctionList4, ValidatorFunctionList5, ValidatorFunctionList6, ValidatorFunctionList7, ValidatorFunctionList8, ValidatorFunctionList9, ValidatorObject, ValidatorState } from './types.js'; -function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; -function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; -function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): O | Promise { - // TODO: we should bail by default +function resolveValidatorList(validators: SyncValidatorFunctionList, value: any, conf: ValidatorConfiguration): O; +function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): Promise; +function resolveValidatorList(validators: ValidatorFunctionList, value: any, conf: ValidatorConfiguration): O | Promise { + // TODO: we should bail by default const result = (validators as ValidatorFunction[]).reduce | Promise>>( (previousState, validator) => { // TODO: refactor this to a unified function @@ -74,7 +74,7 @@ function resolveValidatorObject(validator: ValidatorObject, testValue: any function resolveValidatorObject(validator: ValidatorObject, testValue: any, conf: ValidatorConfiguration): O | Promise { const keys = Object.keys(validator) as (keyof O)[]; const results = keys.map((key) => { - const result = validate(validator[key as keyof O] as any, { + const result = validate(validator[key as keyof O] as any, { ...conf, name: key as string, path: conf.path.concat(key as string), @@ -121,15 +121,15 @@ export const hasNoPromise = (value: (T | Promise)[]): value is T[] => { return !value.some(isPromise); }; -const isValidatorFunctionList = (validator: Validator): validator is ValidatorFunctionList => { +const isValidatorFunctionList = (validator: ValidatorInner): validator is ValidatorFunctionList => { return typeof validator === 'object' && Array.isArray(validator); }; -const isValidatorObject = (validator: Validator): validator is ValidatorObject => { +const isValidatorObject = (validator: ValidatorInner): validator is ValidatorObject => { return typeof validator === 'object' && !Array.isArray(validator); }; -const isValidatorFunction = (validator: Validator): validator is ValidatorFunction => { +const isValidatorFunction = (validator: ValidatorInner): validator is ValidatorFunction => { return typeof validator === 'function'; }; @@ -138,15 +138,57 @@ export function validate(v: SyncValidatingFunctionInner, c?: Partial export function validate(v: SyncValidatorFunctionList1, c?: Partial): SyncValidatingFunction; export function validate(v: SyncValidatorFunctionList2, c?: Partial): SyncValidatingFunction; export function validate(v: SyncValidatorFunctionList3, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList4, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList5, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList6, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList7, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList8, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList9, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList10, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList11, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList12, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList13, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList14, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList15, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList16, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList17, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList18, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList19, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList20, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList21, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList22, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList23, c?: Partial): SyncValidatingFunction; +export function validate(v: SyncValidatorFunctionList24, c?: Partial): SyncValidatingFunction export function validate(v: ValidatorFunction, c?: Partial): AsyncValidatingFunction; export function validate(v: ValidatingFunction, c?: Partial): AsyncValidatingFunction; export function validate(v: ValidatorFunctionList1, c?: Partial): AsyncValidatingFunction; export function validate(v: ValidatorFunctionList2, c?: Partial): AsyncValidatingFunction; export function validate(v: ValidatorFunctionList3, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList4, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList5, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList6, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList7, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList8, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList9, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList10, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList11, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList12, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList13, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList14, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList15, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList16, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList17, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList18, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList19, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList20, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList21, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList22, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList23, c?: Partial): AsyncValidatingFunction; +export function validate(v: ValidatorFunctionList24, c?: Partial): AsyncValidatingFunction export function validate(v: SyncValidatorObject, c?: Partial): SyncValidatingFunction; export function validate(v: ValidatorObject, c?: Partial): AsyncValidatingFunction; -export function validate(validator: Validator, validateConf?: Partial): ValidatingFunction; -export function validate(validator: Validator, validateConf?: Partial): ValidatingFunction { +export function validate(validator: ValidatorInner, validateConf?: Partial): ValidatingFunction; +export function validate(validator: ValidatorInner, validateConf?: Partial): ValidatingFunction { return function (testValue: any, testConf) { // Set defaults to configuration const conf: ValidatorConfiguration = { diff --git a/src/validators/arrayOf.ts b/src/validators/arrayOf.ts index 948f25c..92c3e84 100644 --- a/src/validators/arrayOf.ts +++ b/src/validators/arrayOf.ts @@ -1,19 +1,17 @@ import validate, { hasNoPromise, isPromise } from '../validate.js'; import { - Validator, ValidatorState, - SyncValidator, ValidatorConfiguration, SyncValidatingFunction, AsyncValidatingFunction, + SyncValidator, + Validator, } from '../types.js'; -function arrayOf( - validator: SyncValidator -): SyncValidatingFunction; -function arrayOf(validator: Validator): AsyncValidatingFunction; -function arrayOf( - validator: Validator +function arrayOf(validator: SyncValidator): SyncValidatingFunction; +function arrayOf(validator: Validator): AsyncValidatingFunction; +function arrayOf( + validator: Validator ): (val: I[], c: ValidatorConfiguration) => O[] | Promise { return (testValues, conf) => { // Array of one item should use that validation to every item in the array diff --git a/src/validators/bail.ts b/src/validators/bail.ts index 87a4eb6..6cae227 100644 --- a/src/validators/bail.ts +++ b/src/validators/bail.ts @@ -1,30 +1,16 @@ -import { - SyncValidatorFunctionList, - ValidatorConfiguration, - ValidatorFunction, - ValidatorFunctionList, - ValidatorState, -} from '../types.js'; +import { SyncValidatorFunctionList, ValidatorConfiguration, ValidatorFunction, ValidatorFunctionList, ValidatorState } from '../types.js'; import validate, { isPromise } from '../validate.js'; // TODO: replace this with parallel validation -function bail( - validators: SyncValidatorFunctionList -): (val: I, c: ValidatorConfiguration) => O; -function bail( - validators: ValidatorFunctionList -): (val: I, c: ValidatorConfiguration) => Promise; -function bail( - validators: ValidatorFunctionList -): (val: I, c: ValidatorConfiguration) => O | Promise { +function bail(validators: SyncValidatorFunctionList): (val: I, c: ValidatorConfiguration) => O; +function bail(validators: ValidatorFunctionList): (val: I, c: ValidatorConfiguration) => Promise; +function bail(validators: ValidatorFunctionList): (val: I, c: ValidatorConfiguration) => O | Promise { if (!Array.isArray(validators)) { // If not an array is passed, simply continue validation return validate(validators); } return (value, conf) => { - const result = (validators as ValidatorFunction[]).reduce< - ValidatorState | Promise> - >( + const result = (validators as ValidatorFunction[]).reduce | Promise>>( (previousState, validator) => { if (isPromise(previousState)) { return previousState.then(({ value, failures }) => { diff --git a/src/validators/either.ts b/src/validators/either.ts index 87a8fbd..18e4b57 100644 --- a/src/validators/either.ts +++ b/src/validators/either.ts @@ -1,29 +1,29 @@ import { - SyncValidator, SyncValidatorFunctionInner, - Validator, + SyncValidator, ValidatorConfiguration, ValidatorFunction, ValidatorState, + Validator, } from '../types.js'; import validate, { hasNoPromise, isPromise } from '../validate.js'; -function either( - validators: [SyncValidator, SyncValidator] +function either( + validators: [SyncValidator, SyncValidator] ): SyncValidatorFunctionInner; -function either( - validators: [Validator, Validator] +function either( + validators: [Validator, Validator] ): ValidatorFunction; -function either( - validators: [Validator, Validator] +function either( + validators: [Validator, Validator] ): (val: unknown, c: ValidatorConfiguration) => O1 | O2 | Promise { return (value, conf) => { const results = validators.map((validator) => { try { - const result = validate( - validator as Validator, + const result = validate(validator as Validator, conf)( + value, conf - )(value, conf) as O1 | O2 | Promise; + ) as O1 | O2 | Promise; if (isPromise(result)) { return result.then( (value) => diff --git a/src/validators/optional.ts b/src/validators/optional.ts index 72ecedc..24492da 100644 --- a/src/validators/optional.ts +++ b/src/validators/optional.ts @@ -1,21 +1,9 @@ -import { - AsyncValidatingFunction, - SyncValidatingFunction, - SyncValidator, - Validator, - ValidatorConfiguration, -} from '../types.js'; +import { AsyncValidatingFunction, SyncValidatingFunction, SyncValidator, ValidatorConfiguration, Validator } from '../types.js'; import validate, { isPromise } from '../validate.js'; -function optional( - validator: SyncValidator -): SyncValidatingFunction; -function optional( - validator: Validator -): AsyncValidatingFunction; -function optional( - validator: Validator -): (value: unknown, conf: ValidatorConfiguration) => T | undefined | Promise { +function optional(validator: SyncValidator): SyncValidatingFunction; +function optional(validator: Validator): AsyncValidatingFunction; +function optional(validator: Validator): (value: unknown, conf: ValidatorConfiguration) => T | undefined | Promise { return (value, conf) => { if (typeof value === 'undefined') { return value; diff --git a/tests/types.ts b/tests/types.ts index e7583ae..5f8ea6f 100644 --- a/tests/types.ts +++ b/tests/types.ts @@ -44,6 +44,9 @@ test('sync validator function array returns transformed type without promise', ( const validateWithSyncFunction3 = validate([isString, toNumber, intoString]); const vlist3: string = validateWithSyncFunction3(''); + + const validateWithSyncFunction24 = validate([toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString, toNumber, intoString]); + const vlist24: string = validateWithSyncFunction24(''); }); test('sync validator object returns object type without promise', () => { const validateWithObject = validate({ a: [isString, toNumber, intoString], b: isString }); @@ -67,6 +70,9 @@ test('async validator function array returns type with promise', () => { const validateWithAsyncFunction3 = validate([isStringP, toNumberP, intoStringP]); const vlist3p: Promise = validateWithAsyncFunction3(''); + + const validateWithSyncFunction24 = validate([toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP, toNumberP, intoStringP]); + const vlist24p: Promise = validateWithSyncFunction24(''); }); test('async validator object returns object type with promise', () => { const validateWithAsyncObject = validate({ a: [isStringP, toNumberP, intoStringP], b: isStringP });