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.
		
		
		
		
		
			
		
			
				
					540 lines
				
				15 KiB
			
		
		
			
		
	
	
					540 lines
				
				15 KiB
			| 
											3 years ago
										 | import compare from './tools/semver-compare.js' | ||
|  | 
 | ||
|  | // Added "possibleLengths" and renamed
 | ||
|  | // "country_phone_code_to_countries" to "country_calling_codes".
 | ||
|  | const V2 = '1.0.18' | ||
|  | 
 | ||
|  | // Added "idd_prefix" and "default_idd_prefix".
 | ||
|  | const V3 = '1.2.0' | ||
|  | 
 | ||
|  | // Moved `001` country code to "nonGeographic" section of metadata.
 | ||
|  | const V4 = '1.7.35' | ||
|  | 
 | ||
|  | const DEFAULT_EXT_PREFIX = ' ext. ' | ||
|  | 
 | ||
|  | const CALLING_CODE_REG_EXP = /^\d+$/ | ||
|  | 
 | ||
|  | /** | ||
|  |  * See: https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md
 | ||
|  |  */ | ||
|  | export default class Metadata { | ||
|  | 	constructor(metadata) { | ||
|  | 		validateMetadata(metadata) | ||
|  | 		this.metadata = metadata | ||
|  | 		setVersion.call(this, metadata) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getCountries() { | ||
|  | 		return Object.keys(this.metadata.countries).filter(_ => _ !== '001') | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getCountryMetadata(countryCode) { | ||
|  | 		return this.metadata.countries[countryCode] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nonGeographic() { | ||
|  | 		if (this.v1 || this.v2 || this.v3) return | ||
|  | 		// `nonGeographical` was a typo.
 | ||
|  | 		// It's present in metadata generated from `1.7.35` to `1.7.37`.
 | ||
|  | 		// The test case could be found by searching for "nonGeographical".
 | ||
|  | 		return this.metadata.nonGeographic || this.metadata.nonGeographical | ||
|  | 	} | ||
|  | 
 | ||
|  | 	hasCountry(country) { | ||
|  | 		return this.getCountryMetadata(country) !== undefined | ||
|  | 	} | ||
|  | 
 | ||
|  | 	hasCallingCode(callingCode) { | ||
|  | 		if (this.getCountryCodesForCallingCode(callingCode)) { | ||
|  | 			return true | ||
|  | 		} | ||
|  | 		if (this.nonGeographic()) { | ||
|  | 			if (this.nonGeographic()[callingCode]) { | ||
|  | 				return true | ||
|  | 			} | ||
|  | 		} else { | ||
|  | 			// A hacky workaround for old custom metadata (generated before V4).
 | ||
|  | 			const countryCodes = this.countryCallingCodes()[callingCode] | ||
|  | 			if (countryCodes && countryCodes.length === 1 && countryCodes[0] === '001') { | ||
|  | 				return true | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	isNonGeographicCallingCode(callingCode) { | ||
|  | 		if (this.nonGeographic()) { | ||
|  | 			return this.nonGeographic()[callingCode] ? true : false | ||
|  | 		} else { | ||
|  | 			return this.getCountryCodesForCallingCode(callingCode) ? false : true | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	country(countryCode) { | ||
|  | 		return this.selectNumberingPlan(countryCode) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	selectNumberingPlan(countryCode, callingCode) { | ||
|  | 		// Supports just passing `callingCode` as the first argument.
 | ||
|  | 		if (countryCode && CALLING_CODE_REG_EXP.test(countryCode)) { | ||
|  | 			callingCode = countryCode | ||
|  | 			countryCode = null | ||
|  | 		} | ||
|  | 		if (countryCode && countryCode !== '001') { | ||
|  | 			if (!this.hasCountry(countryCode)) { | ||
|  | 				throw new Error(`Unknown country: ${countryCode}`) | ||
|  | 			} | ||
|  | 			this.numberingPlan = new NumberingPlan(this.getCountryMetadata(countryCode), this) | ||
|  | 		} else if (callingCode) { | ||
|  | 			if (!this.hasCallingCode(callingCode)) { | ||
|  | 				throw new Error(`Unknown calling code: ${callingCode}`) | ||
|  | 			} | ||
|  | 			this.numberingPlan = new NumberingPlan(this.getNumberingPlanMetadata(callingCode), this) | ||
|  | 		} else { | ||
|  | 			this.numberingPlan = undefined | ||
|  | 		} | ||
|  | 		return this | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getCountryCodesForCallingCode(callingCode) { | ||
|  | 		const countryCodes = this.countryCallingCodes()[callingCode] | ||
|  | 		if (countryCodes) { | ||
|  | 			// Metadata before V4 included "non-geographic entity" calling codes
 | ||
|  | 			// inside `country_calling_codes` (for example, `"881":["001"]`).
 | ||
|  | 			// Now the semantics of `country_calling_codes` has changed:
 | ||
|  | 			// it's specifically for "countries" now.
 | ||
|  | 			// Older versions of custom metadata will simply skip parsing
 | ||
|  | 			// "non-geographic entity" phone numbers with new versions
 | ||
|  | 			// of this library: it's not considered a bug,
 | ||
|  | 			// because such numbers are extremely rare,
 | ||
|  | 			// and developers extremely rarely use custom metadata.
 | ||
|  | 			if (countryCodes.length === 1 && countryCodes[0].length === 3) { | ||
|  | 				return | ||
|  | 			} | ||
|  | 			return countryCodes | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getCountryCodeForCallingCode(callingCode) { | ||
|  | 		const countryCodes = this.getCountryCodesForCallingCode(callingCode) | ||
|  | 		if (countryCodes) { | ||
|  | 			return countryCodes[0] | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getNumberingPlanMetadata(callingCode) { | ||
|  | 		const countryCode = this.getCountryCodeForCallingCode(callingCode) | ||
|  | 		if (countryCode) { | ||
|  | 			return this.getCountryMetadata(countryCode) | ||
|  | 		} | ||
|  | 		if (this.nonGeographic()) { | ||
|  | 			const metadata = this.nonGeographic()[callingCode] | ||
|  | 			if (metadata) { | ||
|  | 				return metadata | ||
|  | 			} | ||
|  | 		} else { | ||
|  | 			// A hacky workaround for old custom metadata (generated before V4).
 | ||
|  | 			// In that metadata, there was no concept of "non-geographic" metadata
 | ||
|  | 			// so metadata for `001` country code was stored along with other countries.
 | ||
|  | 			// The test case can be found by searching for:
 | ||
|  | 			// "should work around `nonGeographic` metadata not existing".
 | ||
|  | 			const countryCodes = this.countryCallingCodes()[callingCode] | ||
|  | 			if (countryCodes && countryCodes.length === 1 && countryCodes[0] === '001') { | ||
|  | 				return this.metadata.countries['001'] | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	countryCallingCode() { | ||
|  | 		return this.numberingPlan.callingCode() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	IDDPrefix() { | ||
|  | 		return this.numberingPlan.IDDPrefix() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	defaultIDDPrefix() { | ||
|  | 		return this.numberingPlan.defaultIDDPrefix() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	nationalNumberPattern() { | ||
|  | 		return this.numberingPlan.nationalNumberPattern() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	possibleLengths() { | ||
|  | 		return this.numberingPlan.possibleLengths() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	formats() { | ||
|  | 		return this.numberingPlan.formats() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	nationalPrefixForParsing() { | ||
|  | 		return this.numberingPlan.nationalPrefixForParsing() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	nationalPrefixTransformRule() { | ||
|  | 		return this.numberingPlan.nationalPrefixTransformRule() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	leadingDigits() { | ||
|  | 		return this.numberingPlan.leadingDigits() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	hasTypes() { | ||
|  | 		return this.numberingPlan.hasTypes() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	type(type) { | ||
|  | 		return this.numberingPlan.type(type) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	ext() { | ||
|  | 		return this.numberingPlan.ext() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	countryCallingCodes() { | ||
|  | 		if (this.v1) return this.metadata.country_phone_code_to_countries | ||
|  | 		return this.metadata.country_calling_codes | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Deprecated.
 | ||
|  | 	chooseCountryByCountryCallingCode(callingCode) { | ||
|  | 		return this.selectNumberingPlan(callingCode) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	hasSelectedNumberingPlan() { | ||
|  | 		return this.numberingPlan !== undefined | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | class NumberingPlan { | ||
|  | 	constructor(metadata, globalMetadataObject) { | ||
|  | 		this.globalMetadataObject = globalMetadataObject | ||
|  | 		this.metadata = metadata | ||
|  | 		setVersion.call(this, globalMetadataObject.metadata) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	callingCode() { | ||
|  | 		return this.metadata[0] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Formatting information for regions which share
 | ||
|  | 	// a country calling code is contained by only one region
 | ||
|  | 	// for performance reasons. For example, for NANPA region
 | ||
|  | 	// ("North American Numbering Plan Administration",
 | ||
|  | 	//  which includes USA, Canada, Cayman Islands, Bahamas, etc)
 | ||
|  | 	// it will be contained in the metadata for `US`.
 | ||
|  | 	getDefaultCountryMetadataForRegion() { | ||
|  | 		return this.globalMetadataObject.getNumberingPlanMetadata(this.callingCode()) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Is always present.
 | ||
|  | 	IDDPrefix() { | ||
|  | 		if (this.v1 || this.v2) return | ||
|  | 		return this.metadata[1] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Is only present when a country supports multiple IDD prefixes.
 | ||
|  | 	defaultIDDPrefix() { | ||
|  | 		if (this.v1 || this.v2) return | ||
|  | 		return this.metadata[12] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nationalNumberPattern() { | ||
|  | 		if (this.v1 || this.v2) return this.metadata[1] | ||
|  | 		return this.metadata[2] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// "possible length" data is always present in Google's metadata.
 | ||
|  | 	possibleLengths() { | ||
|  | 		if (this.v1) return | ||
|  | 		return this.metadata[this.v2 ? 2 : 3] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	_getFormats(metadata) { | ||
|  | 		return metadata[this.v1 ? 2 : this.v2 ? 3 : 4] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// For countries of the same region (e.g. NANPA)
 | ||
|  | 	// formats are all stored in the "main" country for that region.
 | ||
|  | 	// E.g. "RU" and "KZ", "US" and "CA".
 | ||
|  | 	formats() { | ||
|  | 		const formats = this._getFormats(this.metadata) || this._getFormats(this.getDefaultCountryMetadataForRegion()) || [] | ||
|  | 		return formats.map(_ => new Format(_, this)) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nationalPrefix() { | ||
|  | 		return this.metadata[this.v1 ? 3 : this.v2 ? 4 : 5] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	_getNationalPrefixFormattingRule(metadata) { | ||
|  | 		return metadata[this.v1 ? 4 : this.v2 ? 5 : 6] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// For countries of the same region (e.g. NANPA)
 | ||
|  | 	// national prefix formatting rule is stored in the "main" country for that region.
 | ||
|  | 	// E.g. "RU" and "KZ", "US" and "CA".
 | ||
|  | 	nationalPrefixFormattingRule() { | ||
|  | 		return this._getNationalPrefixFormattingRule(this.metadata) || this._getNationalPrefixFormattingRule(this.getDefaultCountryMetadataForRegion()) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	_nationalPrefixForParsing() { | ||
|  | 		return this.metadata[this.v1 ? 5 : this.v2 ? 6 : 7] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nationalPrefixForParsing() { | ||
|  | 		// If `national_prefix_for_parsing` is not set explicitly,
 | ||
|  | 		// then infer it from `national_prefix` (if any)
 | ||
|  | 		return this._nationalPrefixForParsing() || this.nationalPrefix() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nationalPrefixTransformRule() { | ||
|  | 		return this.metadata[this.v1 ? 6 : this.v2 ? 7 : 8] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	_getNationalPrefixIsOptionalWhenFormatting() { | ||
|  | 		return !!this.metadata[this.v1 ? 7 : this.v2 ? 8 : 9] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// For countries of the same region (e.g. NANPA)
 | ||
|  | 	// "national prefix is optional when formatting" flag is
 | ||
|  | 	// stored in the "main" country for that region.
 | ||
|  | 	// E.g. "RU" and "KZ", "US" and "CA".
 | ||
|  | 	nationalPrefixIsOptionalWhenFormattingInNationalFormat() { | ||
|  | 		return this._getNationalPrefixIsOptionalWhenFormatting(this.metadata) || | ||
|  | 			this._getNationalPrefixIsOptionalWhenFormatting(this.getDefaultCountryMetadataForRegion()) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	leadingDigits() { | ||
|  | 		return this.metadata[this.v1 ? 8 : this.v2 ? 9 : 10] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	types() { | ||
|  | 		return this.metadata[this.v1 ? 9 : this.v2 ? 10 : 11] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	hasTypes() { | ||
|  | 		// Versions 1.2.0 - 1.2.4: can be `[]`.
 | ||
|  | 		/* istanbul ignore next */ | ||
|  | 		if (this.types() && this.types().length === 0) { | ||
|  | 			return false | ||
|  | 		} | ||
|  | 		// Versions <= 1.2.4: can be `undefined`.
 | ||
|  | 		// Version >= 1.2.5: can be `0`.
 | ||
|  | 		return !!this.types() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	type(type) { | ||
|  | 		if (this.hasTypes() && getType(this.types(), type)) { | ||
|  | 			return new Type(getType(this.types(), type), this) | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	ext() { | ||
|  | 		if (this.v1 || this.v2) return DEFAULT_EXT_PREFIX | ||
|  | 		return this.metadata[13] || DEFAULT_EXT_PREFIX | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | class Format { | ||
|  | 	constructor(format, metadata) { | ||
|  | 		this._format = format | ||
|  | 		this.metadata = metadata | ||
|  | 	} | ||
|  | 
 | ||
|  | 	pattern() { | ||
|  | 		return this._format[0] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	format() { | ||
|  | 		return this._format[1] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	leadingDigitsPatterns() { | ||
|  | 		return this._format[2] || [] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nationalPrefixFormattingRule() { | ||
|  | 		return this._format[3] || this.metadata.nationalPrefixFormattingRule() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nationalPrefixIsOptionalWhenFormattingInNationalFormat() { | ||
|  | 		return !!this._format[4] || this.metadata.nationalPrefixIsOptionalWhenFormattingInNationalFormat() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	nationalPrefixIsMandatoryWhenFormattingInNationalFormat() { | ||
|  | 		// National prefix is omitted if there's no national prefix formatting rule
 | ||
|  | 		// set for this country, or when the national prefix formatting rule
 | ||
|  | 		// contains no national prefix itself, or when this rule is set but
 | ||
|  | 		// national prefix is optional for this phone number format
 | ||
|  | 		// (and it is not enforced explicitly)
 | ||
|  | 		return this.usesNationalPrefix() && !this.nationalPrefixIsOptionalWhenFormattingInNationalFormat() | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Checks whether national prefix formatting rule contains national prefix.
 | ||
|  | 	usesNationalPrefix() { | ||
|  | 		return this.nationalPrefixFormattingRule() && | ||
|  | 			// Check that national prefix formatting rule is not a "dummy" one.
 | ||
|  | 			!FIRST_GROUP_ONLY_PREFIX_PATTERN.test(this.nationalPrefixFormattingRule()) | ||
|  | 			// In compressed metadata, `this.nationalPrefixFormattingRule()` is `0`
 | ||
|  | 			// when `national_prefix_formatting_rule` is not present.
 | ||
|  | 			// So, `true` or `false` are returned explicitly here, so that
 | ||
|  | 			// `0` number isn't returned.
 | ||
|  | 			? true | ||
|  | 			: false | ||
|  | 	} | ||
|  | 
 | ||
|  | 	internationalFormat() { | ||
|  | 		return this._format[5] || this.format() | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * A pattern that is used to determine if the national prefix formatting rule | ||
|  |  * has the first group only, i.e., does not start with the national prefix. | ||
|  |  * Note that the pattern explicitly allows for unbalanced parentheses. | ||
|  |  */ | ||
|  | const FIRST_GROUP_ONLY_PREFIX_PATTERN = /^\(?\$1\)?$/ | ||
|  | 
 | ||
|  | class Type { | ||
|  | 	constructor(type, metadata) { | ||
|  | 		this.type = type | ||
|  | 		this.metadata = metadata | ||
|  | 	} | ||
|  | 
 | ||
|  | 	pattern() { | ||
|  | 		if (this.metadata.v1) return this.type | ||
|  | 		return this.type[0] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	possibleLengths() { | ||
|  | 		if (this.metadata.v1) return | ||
|  | 		return this.type[1] || this.metadata.possibleLengths() | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | function getType(types, type) { | ||
|  | 	switch (type) { | ||
|  | 		case 'FIXED_LINE': | ||
|  | 			return types[0] | ||
|  | 		case 'MOBILE': | ||
|  | 			return types[1] | ||
|  | 		case 'TOLL_FREE': | ||
|  | 			return types[2] | ||
|  | 		case 'PREMIUM_RATE': | ||
|  | 			return types[3] | ||
|  | 		case 'PERSONAL_NUMBER': | ||
|  | 			return types[4] | ||
|  | 		case 'VOICEMAIL': | ||
|  | 			return types[5] | ||
|  | 		case 'UAN': | ||
|  | 			return types[6] | ||
|  | 		case 'PAGER': | ||
|  | 			return types[7] | ||
|  | 		case 'VOIP': | ||
|  | 			return types[8] | ||
|  | 		case 'SHARED_COST': | ||
|  | 			return types[9] | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | export function validateMetadata(metadata) { | ||
|  | 	if (!metadata) { | ||
|  | 		throw new Error('[libphonenumber-js] `metadata` argument not passed. Check your arguments.') | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// `country_phone_code_to_countries` was renamed to
 | ||
|  | 	// `country_calling_codes` in `1.0.18`.
 | ||
|  | 	if (!is_object(metadata) || !is_object(metadata.countries)) { | ||
|  | 		throw new Error(`[libphonenumber-js] \`metadata\` argument was passed but it's not a valid metadata. Must be an object having \`.countries\` child object property. Got ${is_object(metadata) ? 'an object of shape: { ' + Object.keys(metadata).join(', ') + ' }' : 'a ' + type_of(metadata) + ': ' + metadata}.`) | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // Babel transforms `typeof` into some "branches"
 | ||
|  | // so istanbul will show this as "branch not covered".
 | ||
|  | /* istanbul ignore next */ | ||
|  | const is_object = _ => typeof _ === 'object' | ||
|  | 
 | ||
|  | // Babel transforms `typeof` into some "branches"
 | ||
|  | // so istanbul will show this as "branch not covered".
 | ||
|  | /* istanbul ignore next */ | ||
|  | const type_of = _ => typeof _ | ||
|  | 
 | ||
|  | /** | ||
|  |  * Returns extension prefix for a country. | ||
|  |  * @param  {string} country | ||
|  |  * @param  {object} metadata | ||
|  |  * @return {string?} | ||
|  |  * @example | ||
|  |  * // Returns " ext. "
 | ||
|  |  * getExtPrefix("US") | ||
|  |  */ | ||
|  | export function getExtPrefix(country, metadata) { | ||
|  | 	metadata = new Metadata(metadata) | ||
|  | 	if (metadata.hasCountry(country)) { | ||
|  | 		return metadata.country(country).ext() | ||
|  | 	} | ||
|  | 	return DEFAULT_EXT_PREFIX | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Returns "country calling code" for a country. | ||
|  |  * Throws an error if the country doesn't exist or isn't supported by this library. | ||
|  |  * @param  {string} country | ||
|  |  * @param  {object} metadata | ||
|  |  * @return {string} | ||
|  |  * @example | ||
|  |  * // Returns "44"
 | ||
|  |  * getCountryCallingCode("GB") | ||
|  |  */ | ||
|  | export function getCountryCallingCode(country, metadata) { | ||
|  | 	metadata = new Metadata(metadata) | ||
|  | 	if (metadata.hasCountry(country)) { | ||
|  | 		return metadata.country(country).countryCallingCode() | ||
|  | 	} | ||
|  | 	throw new Error(`Unknown country: ${country}`) | ||
|  | } | ||
|  | 
 | ||
|  | export function isSupportedCountry(country, metadata) { | ||
|  | 	// metadata = new Metadata(metadata)
 | ||
|  | 	// return metadata.hasCountry(country)
 | ||
|  | 	return metadata.countries[country] !== undefined | ||
|  | } | ||
|  | 
 | ||
|  | function setVersion(metadata) { | ||
|  | 	const { version } = metadata | ||
|  | 	if (typeof version === 'number') { | ||
|  | 		this.v1 = version === 1 | ||
|  | 		this.v2 = version === 2 | ||
|  | 		this.v3 = version === 3 | ||
|  | 		this.v4 = version === 4 | ||
|  | 	} else { | ||
|  | 		if (!version) { | ||
|  | 			this.v1 = true | ||
|  | 		} else if (compare(version, V3) === -1) { | ||
|  | 			this.v2 = true | ||
|  | 		} else if (compare(version, V4) === -1) { | ||
|  | 			this.v3 = true | ||
|  | 		} else { | ||
|  | 			this.v4 = true | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // const ISO_COUNTRY_CODE = /^[A-Z]{2}$/
 | ||
|  | // function isCountryCode(countryCode) {
 | ||
|  | // 	return ISO_COUNTRY_CODE.test(countryCodeOrCountryCallingCode)
 | ||
|  | // }
 |