import {ValidationResult, ValidatorFunction} from './types' import {UniversalPath} from '../../util' /** Requires the given input value to be some form of affirmative boolean. */ function accepted(fieldName: string, inputValue: unknown): ValidationResult { if ( ['yes', 'Yes', 'YES', 1, true, 'true', 'True', 'TRUE'].includes(String(inputValue)) ) { return { valid: true } } return { valid: false, message: 'must be accepted', } } /** Requires the given input value to be some form of boolean. */ function boolean(fieldName: string, inputValue: unknown): ValidationResult { const boolish = ['true', 'True', 'TRUE', '1', 'false', 'False', 'FALSE', '0', true, false, 1, 0] if ( boolish.includes(String(inputValue)) ) { return { valid: true } } return { valid: false, message: 'must be true or false', } } /** Requires the input value to be of type string. */ function string(fieldName: string, inputValue: unknown): ValidationResult { if ( typeof inputValue === 'string' ) { return { valid: true } } return { valid: false, message: 'must be a string', } } /** Requires the given input value to be present and non-nullish. */ function required(fieldName: string, inputValue: unknown): ValidationResult { if ( typeof inputValue !== 'undefined' && inputValue !== null && inputValue !== '' ) { return { valid: true } } return { valid: false, message: 'is required', stopValidation: true, } } /** Alias of required(). */ function present(fieldName: string, inputValue: unknown): ValidationResult { return required(fieldName, inputValue) } /** Alias of required(). */ function filled(fieldName: string, inputValue: unknown): ValidationResult { return required(fieldName, inputValue) } /** Requires the given input value to be absent or nullish. */ function prohibited(fieldName: string, inputValue: unknown): ValidationResult { if ( typeof inputValue === 'undefined' || inputValue === null || inputValue === '' ) { return { valid: true } } return { valid: false, message: 'is not allowed', stopValidation: true, } } /** Alias of prohibited(). */ function absent(fieldName: string, inputValue: unknown): ValidationResult { return prohibited(fieldName, inputValue) } /** Alias of prohibited(). */ function empty(fieldName: string, inputValue: unknown): ValidationResult { return prohibited(fieldName, inputValue) } /** * Builds a validator function that requires the given input to be found in an array of values. * @param values */ function foundIn(values: any[]): ValidatorFunction { return (fieldName: string, inputValue: unknown): ValidationResult => { if ( values.includes(inputValue) ) { return { valid: true } } return { valid: false, message: `must be one of: ${values.join(', ')}`, } } } /** * Builds a validator function that requires the given input NOT to be found in an array of values. * @param values */ function notFoundIn(values: any[]): ValidatorFunction { return (fieldName: string, inputValue: unknown): ValidationResult => { if ( values.includes(inputValue) ) { return { valid: true } } return { valid: false, message: `must be one of: ${values.join(', ')}`, } } } /** Requires the input value to be number-like. */ function numeric(fieldName: string, inputValue: unknown): ValidationResult { if ( !isNaN(parseFloat(String(inputValue))) ) { return { valid: true } } return { valid: false, message: 'must be numeric', } } /** Requires the given input value to be integer-like. */ function integer(fieldName: string, inputValue: unknown): ValidationResult { if ( !isNaN(parseInt(String(inputValue), 10)) && parseInt(String(inputValue), 10) === parseFloat(String(inputValue)) ) { return { valid: true } } return { valid: false, message: 'must be an integer', } } /** Requires the given input value to be a UniversalPath. */ function file(fieldName: string, inputValue: unknown): ValidationResult { if ( inputValue instanceof UniversalPath ) { return { valid: true } } return { valid: false, message: 'must be a file', } } /** * A special validator function that marks a field as optional. * If the value of the field is nullish, no further validation rules will be applied. * If it is non-nullish, validation will continue. * @param fieldName * @param inputValue */ function optional(fieldName: string, inputValue: unknown): ValidationResult { if ( inputValue ?? true ) { return { valid: true, stopValidation: true, } } return { valid: true } } export const Is = { accepted, boolean, string, required, present, filled, prohibited, absent, empty, foundIn, notFoundIn, numeric, integer, file, optional, }