86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
/**
|
|
* Validador de documentos brasileiros (CPF e CNPJ)
|
|
* Implementa algoritmo completo de validação de dígitos verificadores
|
|
*/
|
|
|
|
export function isValidCPF(cpf: string): boolean {
|
|
// Remove caracteres não numéricos
|
|
const cleaned = cpf.replace(/[^\d]/g, "");
|
|
|
|
// Verifica se tem 11 dígitos
|
|
if (cleaned.length !== 11) return false;
|
|
|
|
// Verifica se todos os dígitos são iguais (ex: 111.111.111-11)
|
|
if (/^(\d)\1+$/.test(cleaned)) return false;
|
|
|
|
// Valida primeiro dígito verificador
|
|
let sum = 0;
|
|
for (let i = 0; i < 9; i++) {
|
|
sum += parseInt(cleaned.charAt(i), 10) * (10 - i);
|
|
}
|
|
let remainder = (sum * 10) % 11;
|
|
if (remainder === 10 || remainder === 11) remainder = 0;
|
|
if (remainder !== parseInt(cleaned.charAt(9), 10)) return false;
|
|
|
|
// Valida segundo dígito verificador
|
|
sum = 0;
|
|
for (let i = 0; i < 10; i++) {
|
|
sum += parseInt(cleaned.charAt(i), 10) * (11 - i);
|
|
}
|
|
remainder = (sum * 10) % 11;
|
|
if (remainder === 10 || remainder === 11) remainder = 0;
|
|
if (remainder !== parseInt(cleaned.charAt(10), 10)) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
export function isValidCNPJ(cnpj: string): boolean {
|
|
// Remove caracteres não numéricos
|
|
const cleaned = cnpj.replace(/[^\d]/g, "");
|
|
|
|
// Verifica se tem 14 dígitos
|
|
if (cleaned.length !== 14) return false;
|
|
|
|
// Verifica se todos os dígitos são iguais
|
|
if (/^(\d)\1+$/.test(cleaned)) return false;
|
|
|
|
// Valida primeiro dígito verificador
|
|
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
let sum = 0;
|
|
for (let i = 0; i < 12; i++) {
|
|
sum += parseInt(cleaned.charAt(i), 10) * weights1[i];
|
|
}
|
|
let remainder = sum % 11;
|
|
const firstDigit = remainder < 2 ? 0 : 11 - remainder;
|
|
if (firstDigit !== parseInt(cleaned.charAt(12), 10)) return false;
|
|
|
|
// Valida segundo dígito verificador
|
|
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
sum = 0;
|
|
for (let i = 0; i < 13; i++) {
|
|
sum += parseInt(cleaned.charAt(i), 10) * weights2[i];
|
|
}
|
|
remainder = sum % 11;
|
|
const secondDigit = remainder < 2 ? 0 : 11 - remainder;
|
|
if (secondDigit !== parseInt(cleaned.charAt(13), 10)) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
export function isValidDocument(document: string): boolean {
|
|
const cleaned = document.replace(/[^\d]/g, "");
|
|
|
|
if (cleaned.length === 11) {
|
|
return isValidCPF(document);
|
|
} else if (cleaned.length === 14) {
|
|
return isValidCNPJ(document);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
export function normalizeDocument(document: string): string {
|
|
// Remove todos os caracteres não numéricos
|
|
return document.replace(/[^\d]/g, "");
|
|
}
|