Skip to content

Instantly share code, notes, and snippets.

@elsangedy
Created August 2, 2018 16:23
Show Gist options
  • Save elsangedy/343e9ecf3129a6bd6ea8ef2c64ec43d3 to your computer and use it in GitHub Desktop.
Save elsangedy/343e9ecf3129a6bd6ea8ef2c64ec43d3 to your computer and use it in GitHub Desktop.
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