You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					344 lines
				
				10 KiB
			
		
		
			
		
	
	
					344 lines
				
				10 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								// This is a port of Google Android `libphonenumber`'s
							 | 
						||
| 
								 | 
							
								// `phonenumberutil.js` of December 31th, 2018.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// https://github.com/googlei18n/libphonenumber/commits/master/javascript/i18n/phonenumbers/phonenumberutil.js
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
									VALID_DIGITS,
							 | 
						||
| 
								 | 
							
									PLUS_CHARS,
							 | 
						||
| 
								 | 
							
									MIN_LENGTH_FOR_NSN,
							 | 
						||
| 
								 | 
							
									MAX_LENGTH_FOR_NSN
							 | 
						||
| 
								 | 
							
								} from './constants.js'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import ParseError from './ParseError.js'
							 | 
						||
| 
								 | 
							
								import Metadata from './metadata.js'
							 | 
						||
| 
								 | 
							
								import isViablePhoneNumber, { isViablePhoneNumberStart } from './helpers/isViablePhoneNumber.js'
							 | 
						||
| 
								 | 
							
								import extractExtension from './helpers/extension/extractExtension.js'
							 | 
						||
| 
								 | 
							
								import parseIncompletePhoneNumber from './parseIncompletePhoneNumber.js'
							 | 
						||
| 
								 | 
							
								import getCountryCallingCode from './getCountryCallingCode.js'
							 | 
						||
| 
								 | 
							
								import { isPossibleNumber } from './isPossibleNumber_.js'
							 | 
						||
| 
								 | 
							
								import { parseRFC3966 } from './helpers/RFC3966.js'
							 | 
						||
| 
								 | 
							
								import PhoneNumber from './PhoneNumber.js'
							 | 
						||
| 
								 | 
							
								import matchesEntirely from './helpers/matchesEntirely.js'
							 | 
						||
| 
								 | 
							
								import extractCountryCallingCode from './helpers/extractCountryCallingCode.js'
							 | 
						||
| 
								 | 
							
								import extractCountryCallingCodeFromInternationalNumberWithoutPlusSign from './helpers/extractCountryCallingCodeFromInternationalNumberWithoutPlusSign.js'
							 | 
						||
| 
								 | 
							
								import extractNationalNumber from './helpers/extractNationalNumber.js'
							 | 
						||
| 
								 | 
							
								import stripIddPrefix from './helpers/stripIddPrefix.js'
							 | 
						||
| 
								 | 
							
								import getCountryByCallingCode from './helpers/getCountryByCallingCode.js'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// We don't allow input strings for parsing to be longer than 250 chars.
							 | 
						||
| 
								 | 
							
								// This prevents malicious input from consuming CPU.
							 | 
						||
| 
								 | 
							
								const MAX_INPUT_STRING_LENGTH = 250
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This consists of the plus symbol, digits, and arabic-indic digits.
							 | 
						||
| 
								 | 
							
								const PHONE_NUMBER_START_PATTERN = new RegExp('[' + PLUS_CHARS + VALID_DIGITS + ']')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Regular expression of trailing characters that we want to remove.
							 | 
						||
| 
								 | 
							
								// A trailing `#` is sometimes used when writing phone numbers with extensions in US.
							 | 
						||
| 
								 | 
							
								// Example: "+1 (645) 123 1234-910#" number has extension "910".
							 | 
						||
| 
								 | 
							
								const AFTER_PHONE_NUMBER_END_PATTERN = new RegExp('[^' + VALID_DIGITS + '#' + ']+$')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const USE_NON_GEOGRAPHIC_COUNTRY_CODE = false
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Examples:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// ```js
							 | 
						||
| 
								 | 
							
								// parse('8 (800) 555-35-35', 'RU')
							 | 
						||
| 
								 | 
							
								// parse('8 (800) 555-35-35', 'RU', metadata)
							 | 
						||
| 
								 | 
							
								// parse('8 (800) 555-35-35', { country: { default: 'RU' } })
							 | 
						||
| 
								 | 
							
								// parse('8 (800) 555-35-35', { country: { default: 'RU' } }, metadata)
							 | 
						||
| 
								 | 
							
								// parse('+7 800 555 35 35')
							 | 
						||
| 
								 | 
							
								// parse('+7 800 555 35 35', metadata)
							 | 
						||
| 
								 | 
							
								// ```
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								export default function parse(text, options, metadata) {
							 | 
						||
| 
								 | 
							
									// If assigning the `{}` default value is moved to the arguments above,
							 | 
						||
| 
								 | 
							
									// code coverage would decrease for some weird reason.
							 | 
						||
| 
								 | 
							
									options = options || {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									metadata = new Metadata(metadata)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Validate `defaultCountry`.
							 | 
						||
| 
								 | 
							
									if (options.defaultCountry && !metadata.hasCountry(options.defaultCountry)) {
							 | 
						||
| 
								 | 
							
										if (options.v2) {
							 | 
						||
| 
								 | 
							
											throw new ParseError('INVALID_COUNTRY')
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										throw new Error(`Unknown country: ${options.defaultCountry}`)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Parse the phone number.
							 | 
						||
| 
								 | 
							
									const { number: formattedPhoneNumber, ext, error } = parseInput(text, options.v2, options.extract)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// If the phone number is not viable then return nothing.
							 | 
						||
| 
								 | 
							
									if (!formattedPhoneNumber) {
							 | 
						||
| 
								 | 
							
										if (options.v2) {
							 | 
						||
| 
								 | 
							
											if (error === 'TOO_SHORT') {
							 | 
						||
| 
								 | 
							
												throw new ParseError('TOO_SHORT')
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											throw new ParseError('NOT_A_NUMBER')
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const {
							 | 
						||
| 
								 | 
							
										country,
							 | 
						||
| 
								 | 
							
										nationalNumber,
							 | 
						||
| 
								 | 
							
										countryCallingCode,
							 | 
						||
| 
								 | 
							
										carrierCode
							 | 
						||
| 
								 | 
							
									} = parsePhoneNumber(
							 | 
						||
| 
								 | 
							
										formattedPhoneNumber,
							 | 
						||
| 
								 | 
							
										options.defaultCountry,
							 | 
						||
| 
								 | 
							
										options.defaultCallingCode,
							 | 
						||
| 
								 | 
							
										metadata
							 | 
						||
| 
								 | 
							
									)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!metadata.hasSelectedNumberingPlan()) {
							 | 
						||
| 
								 | 
							
										if (options.v2) {
							 | 
						||
| 
								 | 
							
											throw new ParseError('INVALID_COUNTRY')
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Validate national (significant) number length.
							 | 
						||
| 
								 | 
							
									if (!nationalNumber || nationalNumber.length < MIN_LENGTH_FOR_NSN) {
							 | 
						||
| 
								 | 
							
										// Won't throw here because the regexp already demands length > 1.
							 | 
						||
| 
								 | 
							
										/* istanbul ignore if */
							 | 
						||
| 
								 | 
							
										if (options.v2) {
							 | 
						||
| 
								 | 
							
											throw new ParseError('TOO_SHORT')
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										// Google's demo just throws an error in this case.
							 | 
						||
| 
								 | 
							
										return {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Validate national (significant) number length.
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// A sidenote:
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// They say that sometimes national (significant) numbers
							 | 
						||
| 
								 | 
							
									// can be longer than `MAX_LENGTH_FOR_NSN` (e.g. in Germany).
							 | 
						||
| 
								 | 
							
									// https://github.com/googlei18n/libphonenumber/blob/7e1748645552da39c4e1ba731e47969d97bdb539/resources/phonenumber.proto#L36
							 | 
						||
| 
								 | 
							
									// Such numbers will just be discarded.
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									if (nationalNumber.length > MAX_LENGTH_FOR_NSN) {
							 | 
						||
| 
								 | 
							
										if (options.v2) {
							 | 
						||
| 
								 | 
							
											throw new ParseError('TOO_LONG')
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										// Google's demo just throws an error in this case.
							 | 
						||
| 
								 | 
							
										return {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (options.v2) {
							 | 
						||
| 
								 | 
							
										const phoneNumber = new PhoneNumber(
							 | 
						||
| 
								 | 
							
											countryCallingCode,
							 | 
						||
| 
								 | 
							
											nationalNumber,
							 | 
						||
| 
								 | 
							
											metadata.metadata
							 | 
						||
| 
								 | 
							
										)
							 | 
						||
| 
								 | 
							
										if (country) {
							 | 
						||
| 
								 | 
							
											phoneNumber.country = country
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (carrierCode) {
							 | 
						||
| 
								 | 
							
											phoneNumber.carrierCode = carrierCode
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (ext) {
							 | 
						||
| 
								 | 
							
											phoneNumber.ext = ext
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return phoneNumber
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Check if national phone number pattern matches the number.
							 | 
						||
| 
								 | 
							
									// National number pattern is different for each country,
							 | 
						||
| 
								 | 
							
									// even for those ones which are part of the "NANPA" group.
							 | 
						||
| 
								 | 
							
									const valid = (options.extended ? metadata.hasSelectedNumberingPlan() : country) ?
							 | 
						||
| 
								 | 
							
										matchesEntirely(nationalNumber, metadata.nationalNumberPattern()) :
							 | 
						||
| 
								 | 
							
										false
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!options.extended) {
							 | 
						||
| 
								 | 
							
										return valid ? result(country, nationalNumber, ext) : {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// isInternational: countryCallingCode !== undefined
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return {
							 | 
						||
| 
								 | 
							
										country,
							 | 
						||
| 
								 | 
							
										countryCallingCode,
							 | 
						||
| 
								 | 
							
										carrierCode,
							 | 
						||
| 
								 | 
							
										valid,
							 | 
						||
| 
								 | 
							
										possible: valid ? true : (
							 | 
						||
| 
								 | 
							
											options.extended === true &&
							 | 
						||
| 
								 | 
							
											metadata.possibleLengths() &&
							 | 
						||
| 
								 | 
							
											isPossibleNumber(nationalNumber, metadata) ? true : false
							 | 
						||
| 
								 | 
							
										),
							 | 
						||
| 
								 | 
							
										phone: nationalNumber,
							 | 
						||
| 
								 | 
							
										ext
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Extracts a formatted phone number from text.
							 | 
						||
| 
								 | 
							
								 * Doesn't guarantee that the extracted phone number
							 | 
						||
| 
								 | 
							
								 * is a valid phone number (for example, doesn't validate its length).
							 | 
						||
| 
								 | 
							
								 * @param  {string} text
							 | 
						||
| 
								 | 
							
								 * @param  {boolean} [extract] — If `false`, then will parse the entire `text` as a phone number.
							 | 
						||
| 
								 | 
							
								 * @param  {boolean} [throwOnError] — By default, it won't throw if the text is too long.
							 | 
						||
| 
								 | 
							
								 * @return {string}
							 | 
						||
| 
								 | 
							
								 * @example
							 | 
						||
| 
								 | 
							
								 * // Returns "(213) 373-4253".
							 | 
						||
| 
								 | 
							
								 * extractFormattedPhoneNumber("Call (213) 373-4253 for assistance.")
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function extractFormattedPhoneNumber(text, extract, throwOnError) {
							 | 
						||
| 
								 | 
							
									if (!text) {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (text.length > MAX_INPUT_STRING_LENGTH) {
							 | 
						||
| 
								 | 
							
										if (throwOnError) {
							 | 
						||
| 
								 | 
							
											throw new ParseError('TOO_LONG')
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (extract === false) {
							 | 
						||
| 
								 | 
							
										return text
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Attempt to extract a possible number from the string passed in
							 | 
						||
| 
								 | 
							
									const startsAt = text.search(PHONE_NUMBER_START_PATTERN)
							 | 
						||
| 
								 | 
							
									if (startsAt < 0) {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return text
							 | 
						||
| 
								 | 
							
										// Trim everything to the left of the phone number
							 | 
						||
| 
								 | 
							
										.slice(startsAt)
							 | 
						||
| 
								 | 
							
										// Remove trailing non-numerical characters
							 | 
						||
| 
								 | 
							
										.replace(AFTER_PHONE_NUMBER_END_PATTERN, '')
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @param  {string} text - Input.
							 | 
						||
| 
								 | 
							
								 * @param  {boolean} v2 - Legacy API functions don't pass `v2: true` flag.
							 | 
						||
| 
								 | 
							
								 * @param  {boolean} [extract] - Whether to extract a phone number from `text`, or attempt to parse the entire text as a phone number.
							 | 
						||
| 
								 | 
							
								 * @return {object} `{ ?number, ?ext }`.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function parseInput(text, v2, extract) {
							 | 
						||
| 
								 | 
							
									// Parse RFC 3966 phone number URI.
							 | 
						||
| 
								 | 
							
									if (text && text.indexOf('tel:') === 0) {
							 | 
						||
| 
								 | 
							
										return parseRFC3966(text)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									let number = extractFormattedPhoneNumber(text, extract, v2)
							 | 
						||
| 
								 | 
							
									// If the phone number is not viable, then abort.
							 | 
						||
| 
								 | 
							
									if (!number) {
							 | 
						||
| 
								 | 
							
										return {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (!isViablePhoneNumber(number)) {
							 | 
						||
| 
								 | 
							
										if (isViablePhoneNumberStart(number)) {
							 | 
						||
| 
								 | 
							
											return { error: 'TOO_SHORT' }
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Attempt to parse extension first, since it doesn't require region-specific
							 | 
						||
| 
								 | 
							
									// data and we want to have the non-normalised number here.
							 | 
						||
| 
								 | 
							
									const withExtensionStripped = extractExtension(number)
							 | 
						||
| 
								 | 
							
									if (withExtensionStripped.ext) {
							 | 
						||
| 
								 | 
							
										return withExtensionStripped
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return { number }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Creates `parse()` result object.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function result(country, nationalNumber, ext) {
							 | 
						||
| 
								 | 
							
									const result = {
							 | 
						||
| 
								 | 
							
										country,
							 | 
						||
| 
								 | 
							
										phone: nationalNumber
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (ext) {
							 | 
						||
| 
								 | 
							
										result.ext = ext
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return result
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Parses a viable phone number.
							 | 
						||
| 
								 | 
							
								 * @param {string} formattedPhoneNumber — Example: "(213) 373-4253".
							 | 
						||
| 
								 | 
							
								 * @param {string} [defaultCountry]
							 | 
						||
| 
								 | 
							
								 * @param {string} [defaultCallingCode]
							 | 
						||
| 
								 | 
							
								 * @param {Metadata} metadata
							 | 
						||
| 
								 | 
							
								 * @return {object} Returns `{ country: string?, countryCallingCode: string?, nationalNumber: string? }`.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function parsePhoneNumber(
							 | 
						||
| 
								 | 
							
									formattedPhoneNumber,
							 | 
						||
| 
								 | 
							
									defaultCountry,
							 | 
						||
| 
								 | 
							
									defaultCallingCode,
							 | 
						||
| 
								 | 
							
									metadata
							 | 
						||
| 
								 | 
							
								) {
							 | 
						||
| 
								 | 
							
									// Extract calling code from phone number.
							 | 
						||
| 
								 | 
							
									let { countryCallingCode, number } = extractCountryCallingCode(
							 | 
						||
| 
								 | 
							
										parseIncompletePhoneNumber(formattedPhoneNumber),
							 | 
						||
| 
								 | 
							
										defaultCountry,
							 | 
						||
| 
								 | 
							
										defaultCallingCode,
							 | 
						||
| 
								 | 
							
										metadata.metadata
							 | 
						||
| 
								 | 
							
									)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Choose a country by `countryCallingCode`.
							 | 
						||
| 
								 | 
							
									let country
							 | 
						||
| 
								 | 
							
									if (countryCallingCode) {
							 | 
						||
| 
								 | 
							
										metadata.selectNumberingPlan(countryCallingCode)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// If `formattedPhoneNumber` is in "national" format
							 | 
						||
| 
								 | 
							
									// then `number` is defined and `countryCallingCode` isn't.
							 | 
						||
| 
								 | 
							
									else if (number && (defaultCountry || defaultCallingCode)) {
							 | 
						||
| 
								 | 
							
										metadata.selectNumberingPlan(defaultCountry, defaultCallingCode)
							 | 
						||
| 
								 | 
							
										if (defaultCountry) {
							 | 
						||
| 
								 | 
							
											country = defaultCountry
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											/* istanbul ignore if */
							 | 
						||
| 
								 | 
							
											if (USE_NON_GEOGRAPHIC_COUNTRY_CODE) {
							 | 
						||
| 
								 | 
							
												if (metadata.isNonGeographicCallingCode(defaultCallingCode)) {
							 | 
						||
| 
								 | 
							
													country = '001'
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										countryCallingCode = defaultCallingCode || getCountryCallingCode(defaultCountry, metadata.metadata)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else return {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!number) {
							 | 
						||
| 
								 | 
							
										return { countryCallingCode }
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const {
							 | 
						||
| 
								 | 
							
										nationalNumber,
							 | 
						||
| 
								 | 
							
										carrierCode
							 | 
						||
| 
								 | 
							
									} = extractNationalNumber(
							 | 
						||
| 
								 | 
							
										parseIncompletePhoneNumber(number),
							 | 
						||
| 
								 | 
							
										metadata
							 | 
						||
| 
								 | 
							
									)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Sometimes there are several countries
							 | 
						||
| 
								 | 
							
									// corresponding to the same country phone code
							 | 
						||
| 
								 | 
							
									// (e.g. NANPA countries all having `1` country phone code).
							 | 
						||
| 
								 | 
							
									// Therefore, to reliably determine the exact country,
							 | 
						||
| 
								 | 
							
									// national (significant) number should have been parsed first.
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// When `metadata.json` is generated, all "ambiguous" country phone codes
							 | 
						||
| 
								 | 
							
									// get their countries populated with the full set of
							 | 
						||
| 
								 | 
							
									// "phone number type" regular expressions.
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									const exactCountry = getCountryByCallingCode(countryCallingCode, nationalNumber, metadata)
							 | 
						||
| 
								 | 
							
									if (exactCountry) {
							 | 
						||
| 
								 | 
							
										country = exactCountry
							 | 
						||
| 
								 | 
							
										/* istanbul ignore if */
							 | 
						||
| 
								 | 
							
										if (exactCountry === '001') {
							 | 
						||
| 
								 | 
							
											// Can't happen with `USE_NON_GEOGRAPHIC_COUNTRY_CODE` being `false`.
							 | 
						||
| 
								 | 
							
											// If `USE_NON_GEOGRAPHIC_COUNTRY_CODE` is set to `true` for some reason,
							 | 
						||
| 
								 | 
							
											// then remove the "istanbul ignore if".
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											metadata.country(country)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return {
							 | 
						||
| 
								 | 
							
										country,
							 | 
						||
| 
								 | 
							
										countryCallingCode,
							 | 
						||
| 
								 | 
							
										nationalNumber,
							 | 
						||
| 
								 | 
							
										carrierCode
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |