Created
August 11, 2021 05:54
-
-
Save Radiergummi/bb31b7a74073359f9a835b4afed1d571 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Validates a value that isn't falsy. | |
* | |
* @param field | |
* @param message | |
*/ | |
export function required( | |
field?: string, | |
message?: string | Message<string>, | |
): Validator { | |
return validator( | |
( v?: string ) => !!v, | |
msg( field, message || `${ field } is required` ), | |
); | |
} | |
/** | |
* Validates a string is an email address. Please note that this validator is | |
* exceptionally forgiving by merely checking whether the value consists of | |
* "something", followed by an @ sign, followed by "something" dot "something". | |
* As validating email addresses is by and large pointless, this should be | |
* enough to ensure we receive something that mail can be sent to. | |
* | |
* @param field Name of the field under validation. | |
* @param message Message to show in case of an invalid value. | |
* @see https://stackoverflow.com/questions/46155 for more discussion. | |
*/ | |
export function email( | |
field?: string, | |
message?: string | Message<string>, | |
): Validator<string> { | |
return matches( /\S+@\S+\.\S+/, field, message || ( | |
() => `${ field } must be a valid email address` | |
) ); | |
} | |
export function website( | |
field?: string, | |
message?: string | Message<string>, | |
): Validator<string> { | |
return matches( | |
/^((http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/, | |
field, | |
message || ( | |
() => `${ field } must be a valid website` | |
), | |
); | |
} | |
/** | |
* Validates a string is shorter than a given amount of characters. | |
* | |
* @param expression Regular expression to match. | |
* @param field Name of the field under validation. | |
* @param message Message to show in case of an invalid value. | |
*/ | |
export function matches( | |
expression: string | RegExp | ValueFn<string | RegExp>, | |
field?: string, | |
message?: string | Message<string>, | |
): Validator<string> { | |
function unwrap( wrapped: string | RegExp | ValueFn<string | RegExp> ): RegExp { | |
const value = val( wrapped ); | |
return typeof value === 'string' | |
? new RegExp( value ) | |
: value; | |
} | |
return validator<string>( | |
( v?: string ) => ( | |
!!v && | |
unwrap( expression ).exec( v ) !== null | |
), | |
msg( field, message ), | |
); | |
} | |
/** | |
* Validates a string is shorter than a given amount of characters. | |
* | |
* @param characterAmount Maximum allowed number of characters. | |
* @param field Name of the field under validation. | |
* @param message Message to show in case of an invalid value. | |
*/ | |
export function shorterThan( | |
characterAmount: number | ValueFn<number>, | |
field?: string, | |
message?: string | Message<string>, | |
): Validator { | |
return validator( | |
( v?: string ) => ( | |
!v || ( | |
!!v && val<number>( characterAmount ) > v.length | |
) | |
), | |
msg( | |
field, | |
message || ( () => `${ field } must be shorter than ${ val<number>( characterAmount ) } characters.` ), | |
), | |
); | |
} | |
/** | |
* Validates a string is longer than a given amount of characters. | |
* | |
* @param characterAmount Minimum required number of characters. | |
* @param field Name of the field under validation. | |
* @param message Message to show in case of an invalid value. | |
*/ | |
export function longerThan( | |
characterAmount: number | ValueFn<number>, | |
field?: string, | |
message?: string | Message<string>, | |
): Validator { | |
return validator( | |
( v?: string ) => ( | |
!!v && | |
v.length > val<number>( characterAmount ) | |
), | |
msg( | |
field, | |
message || ( () => `${ field } must be longer than ${ val<number>( characterAmount ) } characters.` ), | |
), | |
); | |
} | |
/** | |
* Validates a string equals another string. | |
* | |
* @param value Value to compare against. | |
* @param field Name of the field under validation. | |
* @param message Message to show in case of an invalid value. | |
*/ | |
export function stringEquals( | |
value: string | ( () => string ), | |
field?: string, | |
message?: string | Message<string>, | |
): Validator { | |
return equals<string>( | |
value, | |
field, | |
message, | |
); | |
} | |
/** | |
* Validates a string equals another string if both are converted to lowercase | |
* characters only. | |
* | |
* @param value String to compare against. | |
* @param field Name of the field under validation. | |
* @param message Message to show in case of an invalid value. | |
*/ | |
export function lowerStringEquals( | |
value: string | ( () => string ), | |
field?: string, | |
message?: string | Message<string>, | |
): Validator { | |
return validator( | |
( v?: string ) => ( | |
!!v && | |
val<string>( value ).toLowerCase() === v.toLowerCase() | |
), | |
msg( field, message ), | |
); | |
} | |
export function truthy( | |
field?: string, | |
message?: string | Message<string>, | |
): Validator { | |
return validator( | |
( v?: any ) => typeof v === 'string' | |
? [ 'on', 'true', 'yes' ].includes( v.toLowerCase() ) | |
: !!v, | |
msg( field, message || `${ field } must be accepted` ), | |
); | |
} | |
/** | |
* Validates a value equals another value of a given type. | |
* | |
* @param value Value to compare against. | |
* @param field Name of the field under validation. | |
* @param message Message to show in case of an invalid value. | |
*/ | |
export function equals<T>( | |
value: T | ValueFn<T>, | |
field?: string, | |
message?: string | Message<T>, | |
): Validator<T> { | |
return validator<T>( | |
( v?: T ): boolean => ( | |
v === val<T>( value ) | |
), | |
msg<T>( field, message ), | |
); | |
} | |
/** | |
* Curries a validator function. | |
* | |
* @param predicate Predicate function to evaluate the value against. | |
* @param message Message function to generate an error function if | |
* validation fails. | |
* @return Validator<T> Validator function for the given predicate and message. | |
*/ | |
export function validator<T>( | |
predicate: Predicate<T>, | |
message: Message<T>, | |
): Validator<T> { | |
return ( v?: T ) => predicate( v ) || message( v ).trim(); | |
} | |
/** | |
* Evaluates value functions to comparison values or uses plain values otherwise | |
* if given. Both value function results and values must be of type T. | |
* | |
* @param value | |
* @return T | |
*/ | |
function val<T = any>( value: T | ValueFn<T> ): T { | |
return typeof value === 'function' | |
? ( value as ValueFn<T> )() | |
: value; | |
} | |
/** | |
* Converts plain string messages or missing values to a valid message function | |
* for a given value type T. | |
* | |
* @param field Name of the field under validation. | |
* @param message Given message handler as passed to the validator. | |
* @return Message<T> Valid message function. | |
*/ | |
function msg<T>( field?: string, message?: string | Message<T> ): Message<T> { | |
if ( !message ) { | |
return (): string => `${ field || 'Field' } is invalid`; | |
} | |
return typeof message === 'string' | |
? () => message | |
: message; | |
} | |
/** | |
* A value function for a given value type T that returns a value of type T. | |
* This may be used to pass dynamic comparison expressions to validators that | |
* should be evaluated at validation time instead of validator creation time. | |
*/ | |
type ValueFn<T> = () => T; | |
/** | |
* A predicate function for a given value type T that assesses whether a value | |
* is valid. If the value under validation has not been provided, the parameter | |
* will be undefined. The function returns a boolean true to indicate a valid | |
* value, or a boolean false to indicate an invalid value. | |
*/ | |
export type Predicate<T> = ( value: T | undefined ) => boolean; | |
/** | |
* A message function to generate an error message for a given invalid value of | |
* type T. It receives the field name and invalid value, if available, as its | |
* parameters, and returns an error message. | |
*/ | |
export type Message<T> = ( value: T | undefined ) => string; | |
/** | |
* A validator function for a given value type T. It either returns true, if the | |
* validator assessed a given value as valid, or a string message in case of an | |
* invalid value. | |
*/ | |
export type Validator<T = any> = ( v?: T ) => true | string; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment