Skip to content

Instantly share code, notes, and snippets.

@xamedow
Created January 14, 2020 12:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xamedow/a01782da3c0db52be4c3c0f24bed591e to your computer and use it in GitHub Desktop.
Save xamedow/a01782da3c0db52be4c3c0f24bed591e to your computer and use it in GitHub Desktop.
Validator helper functions
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