@peralva/validate-cpf-cnpj
Version:
Validate CPF and CNPJ
124 lines (118 loc) • 3.62 kB
JavaScript
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,
};
};
export { CpfCnpjError, validateCpfCnpj };