UNPKG

aamva-parser

Version:

Plugin to parse AAMVA Drivers License Data from the PDF417 barcode

194 lines (193 loc) 6.23 kB
import { Regex } from "../utils/regex"; import { FieldMapper } from "./fieldMapping"; import { IssuingCountry } from "../enums/issuingCountry"; import { Gender } from "../enums/gender"; import { EyeColor } from "../enums/eyeColor"; import { HairColor } from "../enums/hairColor"; import { Truncation } from "../enums/truncation"; import { NameSuffix } from "../enums/nameSuffix"; export class FieldParser { constructor(data, fieldMapper = new FieldMapper()) { this.regex = new Regex(); this.data = data; this.fieldMapper = fieldMapper; } parseString(key) { const identifier = this.fieldMapper.fieldFor(key); return this.regex.firstMatch(`${identifier}(.+)\\b`, this.data); } parseDouble(key) { const identifier = this.fieldMapper.fieldFor(key); const result = this.regex.firstMatch(`${identifier}(\\w+)\\b`, this.data); return result ? parseFloat(result) : null; } parseDate(field) { const dateString = this.parseString(field); if (!dateString || dateString.length !== 8) return null; // Ensure the string is 8 characters long const month = parseInt(dateString.slice(0, 2), 10); const day = parseInt(dateString.slice(2, 4), 10); const year = parseInt(dateString.slice(4, 8), 10); // Validate parsed components if (isNaN(month) || isNaN(day) || isNaN(year)) return null; // JavaScript Date constructor: new Date(year, monthIndex, day) // monthIndex is zero-based, so we subtract 1 from the month const parsedDate = new Date(year, month - 1, day); return isNaN(parsedDate.getTime()) ? null : parsedDate; } getDateFormat() { return "MMddyyyy"; } parseFirstName() { return this.parseString("firstName"); } parseLastName() { return this.parseString("lastName"); } parseMiddleName() { return this.parseString("middleName"); } parseExpirationDate() { return this.parseDate("expirationDate"); } parseIsExpired() { return (this.parseExpirationDate() !== null && new Date() > this.parseExpirationDate()); } parseIssueDate() { return this.parseDate("issueDate"); } parseDateOfBirth() { return this.parseDate("dateOfBirth"); } parseCountry() { const country = this.parseString("country"); switch (country) { case "USA": return IssuingCountry.UnitedStates; case "CAN": return IssuingCountry.Canada; default: return IssuingCountry.Unknown; } } parseTruncationStatus(field) { const truncation = this.parseString(field); switch (truncation) { case "T": return Truncation.Truncated; case "N": return Truncation.None; default: return Truncation.Unknown; } } parseGender() { const gender = this.parseString("gender"); switch (gender) { case "1": return Gender.Male; case "2": return Gender.Female; default: return Gender.Other; } } parseEyeColor() { const color = this.parseString("eyeColor"); switch (color) { case "BLK": return EyeColor.Black; case "BLU": return EyeColor.Blue; case "BRO": return EyeColor.Brown; case "GRY": return EyeColor.Gray; case "GRN": return EyeColor.Green; case "HAZ": return EyeColor.Hazel; case "MAR": return EyeColor.Maroon; case "PNK": return EyeColor.Pink; case "DIC": return EyeColor.Dichromatic; default: return EyeColor.Unknown; } } parseNameSuffix() { const suffix = this.parseString("suffix"); switch (suffix) { case "JR": return NameSuffix.Junior; case "SR": return NameSuffix.Senior; case "1ST": case "I": return NameSuffix.First; case "2ND": case "II": return NameSuffix.Second; case "3RD": case "III": return NameSuffix.Third; case "4TH": case "IV": return NameSuffix.Fourth; case "5TH": case "V": return NameSuffix.Fifth; case "6TH": case "VI": return NameSuffix.Sixth; case "7TH": case "VII": return NameSuffix.Seventh; case "8TH": case "VIII": return NameSuffix.Eighth; case "9TH": case "IX": return NameSuffix.Ninth; default: return NameSuffix.Unknown; } } parseHairColor() { const color = this.parseString("hairColor"); switch (color) { case "BAL": return HairColor.Bald; case "BLK": return HairColor.Black; case "BLN": return HairColor.Blond; case "BRO": return HairColor.Brown; case "GRY": return HairColor.Grey; case "RED": return HairColor.Red; case "SDY": return HairColor.Sandy; case "WHI": return HairColor.White; default: return HairColor.Unknown; } } parseHeight() { const heightString = this.parseString("height"); const height = this.parseDouble("height"); if (!heightString || !height) return null; return heightString.includes("cm") ? Math.round(height * FieldParser.INCHES_PER_CENTIMETER) : height; } } FieldParser.INCHES_PER_CENTIMETER = 0.393701;