All files / lib/validations/validate/card cardNumber.js

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42                                2x 2x   2x   2x 2x 194x   2x 15x 15x         15x 15x                
import {
  __,
  last,
  modulo,
  pipe,
  replace,
  toString,
  addIndex,
  reduceRight,
  eqBy,
  juxt,
  init,
  sum,
  split,
} from 'ramda'
 
const reduceRightIndexed = addIndex(reduceRight)
const clean = replace(/[^0-9]/g, '')
 
const mask = [0, 1, 2, 3, 4, -4, -3, -2, -1, 0]
 
const sameParity = eqBy(modulo(__, 2))
const finalSumReducer = (acc, digit, index, digits) =>
  acc + (sameParity(digits.length - 1, index) ? mask[digits[index]] : 0)
 
const validate = (cardNumber) => {
  const [withoutLastDigit, lastDigit] = juxt([init, last])(cardNumber)
  const finalSum = reduceRightIndexed(
    finalSumReducer,
    sum(withoutLastDigit),
    split('', withoutLastDigit)
  )
  const rest = 10 - (finalSum % 10)
  return (rest === 10 ? 0 : rest) === parseInt(lastDigit, 10)
}
 
export default pipe(
  toString,
  clean,
  validate
)