UNPKG

@peralva/validate-cpf-cnpj

Version:
127 lines (120 loc) 3.67 kB
'use strict'; var calculateDigit = (data, multiplicationLimit) => { let result = ''; for (let iDigit = 1; iDigit <= 2; iDigit++) { let multiplication; let sum = 0; for (let iData = data.length - 1; iData >= 0; iData--) { if (!multiplication || (multiplicationLimit && multiplication > multiplicationLimit)) { multiplication = 2; } sum += multiplication * (data.charCodeAt(iData) - 48); multiplication++; } const digit = ((sum * 10) % 11) % 10; result += digit; data += digit; } return result; }; class CpfCnpjError extends Error { constructor(issue, errorMap) { let defaultError; if (issue.type === 'sequential') { defaultError = 'CPF cannot be sequential'; } else { defaultError = `${issue.type}: expected ${Array.isArray(issue.expected) ? issue.expected.join(' | ') : issue.expected}, received ${issue.received}`; } const _issue = { ...issue, defaultError, }; if (errorMap) { const resultErrorMap = errorMap(_issue); if (resultErrorMap) { super(resultErrorMap); } else { super(_issue.defaultError); } } else { super(defaultError); } this.issue = _issue; } } var getMask = (data) => data.length === 11 ? `${data.substring(0, 3)}.${data.substring(3, 6)}.${data.substring(6, 9)}-${data.substring(9)}` : `${data.substring(0, 2)}.${data.substring(2, 5)}.${data.substring(5, 8)}/${data.substring(8, 12)}-${data.substring(12)}`; var getCleanData = (data) => { let parsed = data.replace(/[^0-9A-Z]+/g, ''); const cpf = parsed.replace(/[^0-9]+/g, ''); if (cpf.length === 11) parsed = cpf; return parsed; }; var validateCpfCnpj = (data, { errorMap, clearData, } = { clearData: true, }) => { let parsed; if (clearData) { parsed = getCleanData(data); } else { parsed = data; } if (parsed.length !== 11 && parsed.length !== 14) { const issue = { type: 'length', expected: [11, 14], received: parsed.length, }; throw new CpfCnpjError({ ...issue, data: { received: data, parsed, }, }, errorMap); } const masked = getMask(parsed); if (parsed.length === 11) { const digitsSplited = parsed.split('').map((digit) => Number(digit)); if (digitsSplited.every((digit, index) => index === 0 || digit === digitsSplited[index - 1])) { throw new CpfCnpjError({ type: 'sequential', data: { received: data, parsed, masked, }, }, errorMap); } } const digits = parsed.substring(parsed.length - 2); const correct = calculateDigit(parsed.substring(0, parsed.length - 2), parsed.length === 14 ? 9 : undefined); if (digits !== correct) { const issue = { type: 'digits', expected: correct, received: digits, }; throw new CpfCnpjError({ ...issue, data: { received: data, parsed, masked, }, }, errorMap); } return { parsed, masked, }; }; exports.CpfCnpjError = CpfCnpjError; exports.validateCpfCnpj = validateCpfCnpj;