UNPKG

phone

Version:

With a given country and phone number, validate and format the phone number to E.164 standard

138 lines (137 loc) 7.79 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.validatePhoneISO3166 = exports.findCountryPhoneDataByPhoneNumber = exports.findPossibleCountryPhoneData = exports.findExactCountryPhoneData = exports.findCountryPhoneDataByCountry = void 0; const country_phone_data_1 = __importDefault(require("../data/country_phone_data")); /** * @param {string=} country - country code alpha 2 or 3 * @returns {{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with, phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string, string, string, string], phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string], phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string], phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string, string], phone_number_lengths: [number]}|null} */ function findCountryPhoneDataByCountry(country) { // if no country provided, assume it's USA if (!country) { return country_phone_data_1.default.find(countryPhoneDatum => countryPhoneDatum.alpha3 === 'USA') || null; } if (country.length === 2) { return country_phone_data_1.default.find(countryPhoneDatum => country.toUpperCase() === countryPhoneDatum.alpha2) || null; } if (country.length === 3) { return country_phone_data_1.default.find(countryPhoneDatum => country.toUpperCase() === countryPhoneDatum.alpha3) || null; } return country_phone_data_1.default.find(countryPhoneDatum => country.toUpperCase() === countryPhoneDatum.country_name.toUpperCase()) || null; } exports.findCountryPhoneDataByCountry = findCountryPhoneDataByCountry; function findExactCountryPhoneData(phoneNumber, validateMobilePrefix, countryPhoneDatum) { // check if the phone number length match any one of the length config const phoneNumberLengthMatched = countryPhoneDatum.phone_number_lengths.some(length => { // as the phone number must include the country code, // but countryPhoneDatum.phone_number_lengths is the length without country code // therefore need to add back countryPhoneDatum.country_code.length to length return (countryPhoneDatum.country_code.length + length === phoneNumber.length); }); if (!phoneNumberLengthMatched) { return null; } // if no need to validate mobile prefix or the country data does not have mobile begin with // pick the current one as the answer directly if (!countryPhoneDatum.mobile_begin_with.length || !validateMobilePrefix) { return countryPhoneDatum; } // if the mobile begin with is correct, pick as the correct answer if (countryPhoneDatum.mobile_begin_with.some(beginWith => { return phoneNumber.match(new RegExp('^' + countryPhoneDatum.country_code + beginWith)); })) { return countryPhoneDatum; } return null; } exports.findExactCountryPhoneData = findExactCountryPhoneData; function findPossibleCountryPhoneData(phoneNumber, validateMobilePrefix, countryPhoneDatum) { // check if the phone number length match any one of the length config const phoneNumberLengthMatched = countryPhoneDatum.phone_number_lengths.some(length => { // the phone number must include the country code // countryPhoneDatum.phone_number_lengths is the length without country code // + 1 is assuming there is an unwanted trunk code prepended to the phone number return (countryPhoneDatum.country_code.length + length + 1 === phoneNumber.length); }); if (!phoneNumberLengthMatched) { return null; } // if no need to validate mobile prefix or the country data does not have mobile begin with // pick the current one as the answer directly if (!countryPhoneDatum.mobile_begin_with.length || !validateMobilePrefix) { return countryPhoneDatum; } // if the mobile begin with is correct, pick as the correct answer // match another \d for the unwanted trunk code prepended to the phone number if (countryPhoneDatum.mobile_begin_with.some(beginWith => { return phoneNumber.match(new RegExp('^' + countryPhoneDatum.country_code + '\\d?' + beginWith)); })) { return countryPhoneDatum; } } exports.findPossibleCountryPhoneData = findPossibleCountryPhoneData; /** * get country phone data by phone number * the phone number must include country code as the complete phone number includes the plus sign * @param phoneNumber * @param validateMobilePrefix * @returns {{exactCountryPhoneData: (*), possibleCountryPhoneData: (*)}} */ function findCountryPhoneDataByPhoneNumber(phoneNumber, validateMobilePrefix) { let exactCountryPhoneData; let possibleCountryPhoneData; for (const countryPhoneDatum of country_phone_data_1.default) { // if the country code is wrong, skip directly if (!phoneNumber.match(new RegExp('^' + countryPhoneDatum.country_code))) { continue; } // process only if exact match not found yet if (!exactCountryPhoneData) { exactCountryPhoneData = findExactCountryPhoneData(phoneNumber, validateMobilePrefix, countryPhoneDatum); } if (!possibleCountryPhoneData) { possibleCountryPhoneData = findPossibleCountryPhoneData(phoneNumber, validateMobilePrefix, countryPhoneDatum); } } return { exactCountryPhoneData, possibleCountryPhoneData }; } exports.findCountryPhoneDataByPhoneNumber = findCountryPhoneDataByPhoneNumber; /** * * @param {string} phone - phone number without plus sign, with or without country calling code * @param {Object} countryPhoneDatum - iso 3166 data * @param {String} countryPhoneDatum.country_code - country calling codes * @param {Array} countryPhoneDatum.phone_number_lengths - all available phone number lengths for this country * @param {Array} countryPhoneDatum.mobile_begin_with - mobile begin with number * @param {boolean} validateMobilePrefix - true if we skip mobile begin with checking * @param {boolean} plusSign - true if the input contains a plus sign * @returns {*|boolean} */ function validatePhoneISO3166(phone, countryPhoneDatum, validateMobilePrefix, plusSign) { if (!countryPhoneDatum.phone_number_lengths) { return false; } // remove country calling code from the phone number const phoneWithoutCountry = phone.replace(new RegExp('^' + countryPhoneDatum.country_code), ''); // if the phone number have +, countryPhoneDatum detected, // but the phone number does not have country calling code // then should consider the phone number as invalid if (plusSign && countryPhoneDatum && phoneWithoutCountry.length === phone.length) { return false; } const phone_number_lengths = countryPhoneDatum.phone_number_lengths; const mobile_begin_with = countryPhoneDatum.mobile_begin_with; const isLengthValid = phone_number_lengths.some(length => phoneWithoutCountry.length === length); // some country doesn't have mobile_begin_with const isBeginWithValid = mobile_begin_with.length ? mobile_begin_with.some(beginWith => phoneWithoutCountry.match(new RegExp('^' + beginWith))) : true; return isLengthValid && (!validateMobilePrefix || isBeginWithValid); } exports.validatePhoneISO3166 = validatePhoneISO3166;