Created
August 2, 2018 16:23
-
-
Save elsangedy/343e9ecf3129a6bd6ea8ef2c64ec43d3 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
import * as R from 'ramda' | |
const valid = (message, isValid) => message ? (isValid ? null : message) : isValid | |
const emailRegex = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/ | |
export const isEmail = (value, message) => valid(message, emailRegex.test(value)) | |
export const isNumber = (value, message) => valid(message, /^\d+$/.test(value)) | |
export const required = (value, message) => valid(message, !!value && value.trim() !== '') | |
export const min = (value, minimum, message) => valid(message, value.length >= minimum) | |
export const max = (value, maximum, message) => valid(message, value.length <= maximum) | |
export const REQUIRED = 'REQUIRED' | |
export const MIN = 'MIN' | |
export const MAX = 'MAX' | |
export const IS_EMAIL = 'IS_EMAIL' | |
export const IS_NUMBER = 'IS_NUMBER' | |
export const validation = (rule, value) => { | |
switch (rule.type) { | |
case REQUIRED: | |
return required(value, (rule.message || 'Required')) | |
case IS_EMAIL: | |
return isEmail(value, (rule.message || 'Invalid email address')) | |
case IS_NUMBER: | |
return isNumber(value, (rule.message || 'Invalid number')) | |
case MIN: | |
return min(value, rule.params, (rule.message || 'Number < ' + rule.params)) | |
case MAX: | |
return max(value, rule.params, (rule.message || 'Number > ' + rule.params)) | |
default: | |
return false | |
} | |
} | |
const removeNulls = R.when( | |
R.either(R.is(Array), R.is(Object)), | |
R.pipe( | |
R.reject(R.isNil), | |
R.map(x => removeNulls(x)) | |
) | |
) | |
const ruleStringToObject = (rule) => ({ type: rule }) | |
const ruleObjectToArray = (rule) => [rule] | |
const isString = R.is(String) | |
const isArray = Array.isArray | |
const isObject = (value) => R.and(R.is(Object, value), R.not(isArray(value))) | |
const whenStringFormatToObject = R.when(isString, ruleStringToObject) | |
const whenObjectFormatToArray = R.when(isObject, ruleObjectToArray) | |
const getRule = R.curry((fields, rule) => fields[rule]) | |
export const validate = (fields) => R.pipe( | |
R.keys, | |
R.reduce( | |
(acc, rule) => R.pipe( | |
getRule(fields), | |
whenStringFormatToObject, | |
whenObjectFormatToArray, | |
R.map(whenStringFormatToObject), | |
(item) => ({ ...acc, [rule]: item }) | |
)(rule), | |
{} | |
), | |
(fieldRules) => (values) => R.pipe( | |
R.keys, | |
R.reduce( | |
(acc, fieldRule) => R.pipe( | |
getRule(fieldRules), | |
R.reduce( | |
(acc2, rule) => R.pipe( | |
R.split('.'), | |
R.lensPath, | |
R.ifElse( | |
R.pipe(R.view(R.__, acc2), R.isNil), | |
(lens) => R.set(lens, validation(rule, R.view(lens, values)), acc2), | |
() => acc2 | |
) | |
)(fieldRule), | |
acc | |
) | |
)(fieldRule), | |
{} | |
), | |
removeNulls | |
)(fieldRules) | |
)(fields) | |
export default validate |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment