UNPKG

@randyd45/curp-validation

Version:

a simple package for curp validation

125 lines (111 loc) 5.35 kB
import {CURPValueError, ExceptionCodes} from "./exceptions.js"; import {CURPChars} from "./enums.js"; import {altisonantes} from "./altisonantes.js"; const VOCALS = 'AEIOU'.split(''); const CONSONANTS = 'BCDFGHJKLMNÑPQRSTVWXYZ'.split(''); const CHARSET = 'AEIOUBCDFGHJKLMNPQRSTVWXYZ'.split('') const IGNORED_NAMES = ['MARIA', 'MA', 'MA.', 'JOSE', 'J', 'J.']; const IGNORED_WORDS = ['DA', 'DAS', 'DE', 'DEL', 'DER', 'DI', 'DIE', 'DD', 'EL', 'LA', 'LOS', 'LAS', 'LE', 'LES', 'MAC', 'MC', 'VAN', 'VON', 'Y']; const IGNORED_COMBINED = [...IGNORED_NAMES, ...IGNORED_WORDS] const accentMap = { 'Á': 'A', 'À': 'A', 'Ä': 'A', 'Â': 'A', 'Ā': 'A', 'Ă': 'A', 'Ą': 'A', 'É': 'E', 'È': 'E', 'Ë': 'E', 'Ê': 'E', 'Ē': 'E', 'Ĕ': 'E', 'Ę': 'E', 'Í': 'I', 'Ì': 'I', 'Ï': 'I', 'Î': 'I', 'Ī': 'I', 'Ĭ': 'I', 'Į': 'I', 'Ó': 'O', 'Ò': 'O', 'Ö': 'O', 'Ô': 'O', 'Ō': 'O', 'Ŏ': 'O', 'Ő': 'O', 'Ú': 'U', 'Ù': 'U', 'Ü': 'U', 'Û': 'U', 'Ū': 'U', 'Ŭ': 'U', 'Ů': 'U', 'Ű': 'U', 'Ų': 'U', 'Ý': 'Y', 'Ỳ': 'Y', 'Ÿ': 'Y', 'Ŷ': 'Y' }; export class CURP { constructor(curp) { this.curp = curp.toUpperCase(); } isFormatValid() { if (this.curp.length !== 18) return false; let re = /^([A-Z][AEIOUX][A-Z]{2}\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])[HM](?:AS|B[CS]|C[CLMSH]|D[FG]|G[TR]|HG|JC|M[CNS]|N[ETL]|OC|PL|Q[TR]|S[PLR]|T[CSL]|VZ|YN|ZS)[B-DF-HJ-NP-TV-Z]{3}[A-Z\d])(\d)$/; return re.test(this.curp); } isNameValid(name) { let pieces = name.toUpperCase().split(" "); if (pieces.length > 1 && IGNORED_NAMES.includes(pieces[0])) delete pieces[0]; let name_features = this.preProcessWord(name, IGNORED_COMBINED); return this.curp[CURPChars.NAME_CHAR] === name_features.letter && this.curp[CURPChars.NAME_CONSONANT] === name_features.consonant; } isFirstLastnameValid(lastname) { let curp_start = this.curp.toUpperCase().substring(0, 4); let lastname_features = this.preProcessWord(lastname, IGNORED_WORDS); let valid = this.curp[CURPChars.SURNAME_A_CHAR] === lastname_features.letter && this.curp[CURPChars.SURNAME_A_CONSONANT] === lastname_features.consonant; if (valid) { valid = this.curp[CURPChars.SURNAME_A_VOWEL] === lastname_features.vocal; if (altisonantes[curp_start]) { for (let i = 0; i < altisonantes[curp_start].length; i++) { valid = valid || altisonantes[curp_start][i] === lastname_features.vocal; } } } return valid; } isSecondLastnameValid(lastname) { let lastname_features = this.preProcessWord(lastname, IGNORED_WORDS); return this.curp[CURPChars.SURNAME_B_CHAR] === lastname_features.letter && this.curp[CURPChars.SURNAME_B_CONSONANT] === lastname_features.consonant; } preProcessWord(word, ignored_words) { let new_word = word.toUpperCase().split(''); for (let i = 0; i < new_word.length; i++) { if (accentMap[new_word[i]]) { new_word[i] = accentMap[new_word[i]]; } else if (new_word[i] === 'Ñ') { new_word[i] = 'X'; } else if (!CHARSET.find(item => item === new_word[i])) { new_word[i] = ' '; } } let pieces = new_word.join('').split(" "); new_word = pieces.filter(item => !ignored_words.find(iw => iw === item)); new_word.push(pieces[pieces.length - 1]); new_word = new_word[0]; let features = { letter: new_word[0], vocal: undefined, consonant: undefined, }; for (let i = 1; i < new_word.length; i++) { if (!features.vocal && VOCALS.find(item => item === new_word[i])) { features.vocal = new_word[i]; } else if (!features.consonant && CONSONANTS.find(item => item === new_word[i])) { features.consonant = new_word[i]; } if (features.vocal && features.consonant) return features } return new_word; } isBirthdayValid(year, month, day) { if (!(year === parseInt(this.curp[CURPChars.YEAR_0]+ "" + this.curp[CURPChars.YEAR_1]))) return false; if (!(month === parseInt(this.curp[CURPChars.MONTH_0] + "" + this.curp[CURPChars.MONTH_1]))) return false; return day === parseInt(this.curp[CURPChars.DAY_0] + "" + this.curp[CURPChars.DAY_1]); } extractBirthday(){ let homonym = this.curp[CURPChars.HOMONYMY]; let before_2k = homonym >= '0' && homonym <= '9'; let day = parseInt(this.curp[CURPChars.DAY_0] + this.curp[CURPChars.DAY_1]); let month = parseInt(this.curp[CURPChars.MONTH_0] + this.curp[CURPChars.MONTH_1]); let year = parseInt(this.curp[CURPChars.YEAR_0] + this.curp[CURPChars.YEAR_1]); let century = before_2k ? 19 : 20; year += century * 100; year = year > new Date().getFullYear() ? year - 100 : year; return { year: String(year).padStart(2, '0'), month: String(month).padStart(2, '0'), day: String(day).padStart(2, '0'), } } }