Created
January 14, 2020 12:51
-
-
Save xamedow/a01782da3c0db52be4c3c0f24bed591e to your computer and use it in GitHub Desktop.
Validator helper functions
This file contains hidden or 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 { | |
__, | |
anyPass, | |
always, | |
allPass, | |
compose, | |
contains, | |
converge, | |
curry, | |
drop, | |
equals, | |
flip, | |
gt, | |
ifElse, | |
init, | |
is, | |
isEmpty, | |
isNil, | |
last, | |
map, | |
mergeAll, | |
modulo, | |
not, | |
product, | |
propEq, | |
toString, | |
propSatisfies, | |
sum, | |
take, | |
test, | |
when, | |
unapply, | |
zip, | |
} from 'ramda'; | |
/** | |
* Validator helper that determines if a prop is fulfilling given predicate function, | |
* therefore validating value under given key | |
* @param key | |
* @param message | |
* @param fn | |
* @returns {*} | |
*/ | |
export const validator = (key, message, fn) => ifElse( | |
propSatisfies(fn, key), | |
always, | |
always({ [key]: message }) | |
); | |
const isValidOrEmpty = (key, message, testFn) => validator( | |
key, | |
message, | |
ifElse(anyPass([isEmpty, isNil]), always(true), testFn) | |
); | |
export const branchValidator = (key, value, onTrue, onFalse = always(true)) => ifElse( | |
propEq(key, value), | |
onTrue, | |
onFalse | |
); | |
/** | |
* Required validator that checks if value from the given key is not null | |
* @param key {String} access key | |
* @param message {String} error message | |
* @returns {Function} accepts values object | |
*/ | |
export const required = (key, message) => validator( | |
key, | |
message, | |
compose(not, anyPass([isEmpty, isNil])) | |
); | |
const phoneReg = /^\+7 \([0-9]{3}\) [0-9]{3}-[0-9]{2}-[0-9]{2}$/; | |
export const isPhone = (key, message) => isValidOrEmpty(key, message, test(phoneReg)); | |
const cyrillicReg = /^[а-яА-Я]+((?![a-zA-Z0-9]).)*$/; | |
export const isCyrillic = (key, message) => isValidOrEmpty(key, message, test(cyrillicReg)); | |
export const isEmail = (key, message) => isValidOrEmpty(key, message, contains('@')); | |
/** | |
* Returns a function that applies given validators list to an object with key values | |
* @param validators {Array<Function>} validators list containing functions with key to validate | |
* and error message to pop when validation fails | |
* @returns {Function} | |
*/ | |
export const applyValidators = validators => converge( | |
unapply(mergeAll), | |
validators | |
); | |
// Control quotients list for INN validation | |
const q1 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8]; | |
const q2 = drop(1, q1); | |
const q3 = drop(2, q1); | |
/** | |
* Calculates sum of every element of a one array, | |
* multiplied by corresponding element of second array | |
*/ | |
const sumAndProduct = curry(compose(sum, map(product), zip)); | |
/** | |
* Checks if a value is greater than 9 then return 0, returns original value otherwise | |
*/ | |
const checkMagnitude = when(gt(__, 9), always(0)); | |
const DIVIDER = 11; | |
/** | |
* validates given inn sequence, by calculating checksum based on given quotients array | |
* @param index {Number} INN index at which control value will be compared to | |
* @param q {Array} quotient array for the step | |
* @returns {function(*=): *} | |
*/ | |
const compareChecksum = (index, q) => inn => compose( | |
equals(+inn[index]), | |
checkMagnitude, | |
flip(modulo)(DIVIDER), | |
sumAndProduct(q), | |
take(index) | |
)(inn); | |
// control step for IE INN length | |
const ieStep0 = ifElse(isNil, always, propEq('length', 12)); | |
// control step for the last but one IE INN digit | |
const ieStep1 = compareChecksum(10, q2); | |
// control step for the last IE INN digit | |
const ieStep2 = compareChecksum(11, q1); | |
// control step for Entity INN length | |
const entityStep0 = ifElse(isNil, always, propEq('length', 10)); | |
// control step for the last Entity INN digit | |
const entityStep1 = compareChecksum(9, q3); | |
export const isIEINNValid = (key, message) => isValidOrEmpty( | |
key, | |
message, | |
allPass([ieStep0, ieStep1, ieStep2]) | |
); | |
export const isEntityINNValid = (key, message) => isValidOrEmpty( | |
key, | |
message, | |
allPass([entityStep0, entityStep1]) | |
); | |
const ogrnStep0 = ifElse(isNil, always, propEq('length')); | |
/** | |
* последняя цифра остатка от деления значения огрн без последнего знака, | |
* должна быть равна последнему знаку | |
* @param divider | |
* @returns {function(*=): *} | |
*/ | |
const ogrnStep1 = divider => value => compose( | |
equals(last(value)), | |
last, | |
toString, | |
flip(modulo)(divider), | |
init, | |
)(value); | |
const isOgrnValid = (length, divider) => allPass([ | |
is(String), | |
ogrnStep0(length), | |
ogrnStep1(divider) | |
]); | |
export const isEntityOgrnValid = (key, message) => isValidOrEmpty( | |
key, | |
message, | |
isOgrnValid(13, 11) | |
); | |
export const isIeOgrnValid = (key, message) => isValidOrEmpty( | |
key, | |
message, | |
isOgrnValid(15, 13) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment