UNPKG

vladdress

Version:

Lightweight Street Address Parser Written in TypeScript

184 lines (183 loc) 8.51 kB
"use strict"; exports.__esModule = true; exports.parseAddress = void 0; var strings_1 = require("./utils/strings"); var country_1 = require("./parsers/country"); var zip_code_1 = require("./parsers/zip-code"); var state_1 = require("./parsers/state"); var line2_1 = require("./parsers/line2"); var array_1 = require("./utils/array"); var city_state_1 = require("./parsers/city-state"); var po_box_1 = require("./parsers/po-box"); var street_address_1 = require("./parsers/street-address"); var no_suffix_1 = require("./parsers/no-suffix"); var parseAddress = function (address, options) { var _a, _b, _c, _d, _e, _f; if (!address) { throw new Error('parseAddress: Argument must be a non-empty string.'); } // Split the address by given delimiters, remove extraneous ones. var addressParts = address.split(/,|\t|\n/).map(strings_1.removeRepeatedSpaces).filter(function (s) { return !!s; }); // Check if the last section contains country reference (Just supports US/Canada for now) var countrySection = (_a = (0, array_1.getLastElement)(addressParts)) === null || _a === void 0 ? void 0 : _a.trim(); // If it does, remove it // TODO: Add the country code to the return if ((0, country_1.isValidCountryCode)(countrySection)) { addressParts = addressParts.slice(0, -1); } // Assume the last address section contains state, zip or both var stateZipString = (_b = (0, array_1.getLastElement)(addressParts)) === null || _b === void 0 ? void 0 : _b.trim(); var zipCode = (0, zip_code_1.parseZipCode)(stateZipString); var resultZipCode = (zipCode === null || zipCode === void 0 ? void 0 : zipCode.zip5) || (zipCode === null || zipCode === void 0 ? void 0 : zipCode.zipInternational); var resultZip4; if ((zipCode === null || zipCode === void 0 ? void 0 : zipCode.zip5) && zipCode.zip4) { resultZip4 = "".concat(zipCode.zip5, "-").concat(zipCode.zip4); } var cityStateString = zipCode === null || zipCode === void 0 ? void 0 : zipCode.trimmedString; // Parse and remove state if (cityStateString && cityStateString.length > 0) { // Check if anything is left of last section addressParts[addressParts.length - 1] = cityStateString; } else { addressParts.splice(-1, 1); cityStateString = (_c = addressParts[addressParts.length - 1]) === null || _c === void 0 ? void 0 : _c.trim(); } var stateInfo = (0, state_1.getStateInfo)(cityStateString); var resultStateAbbreviation = stateInfo.stateAbbreviation; var resultStateName = stateInfo.stateName; var cityString = stateInfo.trimmedString; if (!resultStateAbbreviation || !resultStateName || resultStateAbbreviation.length != 2) { throw new Error('Can not parse address. State not found.'); } // Parse and remove city/place name var placeString; if (cityString && cityString.length > 0) { addressParts[addressParts.length - 1] = cityString; placeString = (0, array_1.getLastElement)(addressParts); } else { addressParts.splice(-1, 1); placeString = (_d = addressParts[addressParts.length - 1]) === null || _d === void 0 ? void 0 : _d.trim(); } var placeNameResult = (0, city_state_1.parsePlaceName)(placeString, resultStateAbbreviation); var resultPlaceName = placeNameResult.placeName; if (!resultPlaceName) { throw new Error('No Place Name Specified'); } placeString = placeNameResult.placeString; // Parse the street data var streetString; if (placeString && placeString.length > 0) { addressParts[addressParts.length - 1] = placeString; } else { addressParts = addressParts.slice(0, -1); } var temporaryLine2; if (addressParts.length > 2) { throw new Error('Can not parse address. More than two address lines.'); } else if (addressParts.length === 2) { // check if the secondary data is first var line2Index = addressParts.findIndex(function (part) { var firstWord = part.substring(0, part.indexOf(' ')); return !!line2_1.usLine2Prefixes[firstWord]; }); var part = addressParts.splice(line2Index, 1)[0]; temporaryLine2 = part === null || part === void 0 ? void 0 : part.trim(); } if (addressParts.length === 0) { if (!(options === null || options === void 0 ? void 0 : options.allowPartialAddress)) { throw new Error('Can not parse address. Invalid street address data. Input string: ' + address); } var formattedAddress = makeFormattedAddress(resultStateAbbreviation, resultPlaceName); return { formattedAddress: formattedAddress, id: makeAddressId(formattedAddress), stateAbbreviation: resultStateAbbreviation, stateName: resultStateName, placeName: resultPlaceName, zipCode: resultZipCode, zipCodePlusFour: resultZip4 }; } streetString = (_e = addressParts[0]) === null || _e === void 0 ? void 0 : _e.trim(); if (!temporaryLine2) { var line2Type = (0, line2_1.validateUsLine2Type)(streetString); if (line2Type) { var upperSS = streetString.toUpperCase(); var idx = upperSS.indexOf(line2Type); temporaryLine2 = streetString === null || streetString === void 0 ? void 0 : streetString.substring(idx); streetString = (_f = streetString === null || streetString === void 0 ? void 0 : streetString.replace(temporaryLine2, "")) === null || _f === void 0 ? void 0 : _f.trim(); } } var resultAddressLine1; var resultStreetNumber; var resultStreetName; var resultStreetDirection; var resultStreetSuffix; var resultAddressLine2 = temporaryLine2; if ((0, po_box_1.matchesPOBox)(streetString)) { var res = (0, po_box_1.parsePOBox)(streetString); streetString = res.streetString; resultAddressLine1 = res.line1; } else if ((0, street_address_1.matchesStreetAddress)(streetString)) { var res = (0, street_address_1.parseStreetAddress)(streetString); resultAddressLine1 = res.line1; resultStreetNumber = res.streetNumber; resultStreetName = res.streetName; resultStreetDirection = res.streetDirection; resultStreetSuffix = res.streetSuffix; streetString = res.streetString; resultAddressLine2 || (resultAddressLine2 = res.line2); } else if ((0, no_suffix_1.matchesNoSuffix)(streetString)) { var res = (0, no_suffix_1.parseNoSuffix)(streetString); resultAddressLine1 = res.line1; resultAddressLine2 = res.line2; resultStreetName = res.streetName; resultStreetNumber = res.streetNumber; streetString = res.streetString; resultAddressLine2 || (resultAddressLine2 = res.line2); } else { throw new Error('Can not parse address. Invalid street address data. Input string: ' + address); } if (!resultAddressLine1) { throw new Error('Could not generate Address Line 1'); } var addressString = resultAddressLine1; if (resultAddressLine2) { addressString += ', ' + resultAddressLine2; } var resultFormattedAddress; if (addressString && resultPlaceName && resultStateAbbreviation) { resultFormattedAddress = makeFormattedAddress(resultStateAbbreviation, resultPlaceName, addressString, resultZipCode); } else { throw new Error('Required Address Parts Not Found.'); } return { zipCode: resultZipCode, zipCodePlusFour: resultZip4, stateAbbreviation: resultStateAbbreviation, stateName: resultStateName, placeName: resultPlaceName, addressLine1: resultAddressLine1, addressLine2: resultAddressLine2, streetNumber: resultStreetNumber, streetSuffix: resultStreetSuffix, streetDirection: resultStreetDirection, streetName: resultStreetName, id: makeAddressId(resultFormattedAddress), formattedAddress: resultFormattedAddress }; }; exports.parseAddress = parseAddress; var makeFormattedAddress = function (stateCode, placeName, line1, zipCode) { return (line1 ? (line1 + ", ") : '') + placeName + ", " + stateCode + (zipCode ? (" " + zipCode) : ''); }; var makeAddressId = function (formattedAddress) { return encodeURI(formattedAddress.replace(/[\s#/.,]+/g, '-').toLowerCase()); };