All files / components/phone-input phone-input-validator.ts

98.36% Statements 60/61
83.33% Branches 25/30
100% Functions 11/11
100% Lines 52/52

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 1062x                       2x   2x 4x 4x 3x     2x         758x 758x   25x   758x     2x 4x 3x 3x 1x   2x 2x 301x 1x 1x     1x     2x 4x 2x 2x 490x                           2x       4x 4x 4x 4x   2x     4x 4x 4x 4x   4x 2x 2x 2x 2x 2x 2x 2x 2x       4x 4x 4x 4x 4x   4x      
import {
    CountryCode,
    PhoneNumber,
    getCountries,
    getCountryCallingCode,
    parsePhoneNumber,
} from "libphonenumber-js/min";
 
interface MappingCache {
    [key: string]: string;
}
 
const callingCodeCountryCache: MappingCache = {};
 
export const formatPrefix = (prefix: string): string => {
    Iif (/^\+[0-9]{1,3}$/.test(prefix)) return prefix;
    if (prefix.length === 0) return "";
    return `+${prefix.replace(/[^0-9]/g, "")}`;
};
 
export const getCallingCodeForCountry = (
    country: string,
    fallback: string = ""
): string => {
    let callingCode: string;
    try {
        callingCode = getCountryCallingCode(country as CountryCode).valueOf();
    } catch (err) {
        callingCode = fallback;
    }
    return callingCode;
};
 
export const getCountryForCallingCode = (prefix: string): string => {
    if (typeof prefix !== "string" || prefix.length === 0) return "";
    const callingCode: string = prefix.replace(/[^0-9]/g, "").valueOf();
    if (callingCodeCountryCache[callingCode] !== undefined) {
        return callingCodeCountryCache[callingCode];
    }
    const countries = getCountries();
    for (let i = 0; i < countries.length; i++) {
        if (getCountryCallingCode(countries[i]).valueOf() === callingCode) {
            callingCodeCountryCache[callingCode] = countries[i].valueOf();
            return callingCodeCountryCache[callingCode];
        }
    }
    return "";
};
 
const fixCountryCode = (country: string): string => {
    if (typeof country !== "string" || country.length !== 2) return "";
    const countryCode: string = country.toUpperCase().valueOf();
    return getCountries()
        .map((value) => value.valueOf())
        .indexOf(countryCode) !== -1
        ? countryCode
        : "";
};
 
export interface PhoneNumberValidator {
    getCountry: () => string;
    getPrefix: () => string;
    getFormattedValue: () => string;
    getValidatedValue: () => string;
    isValid: () => boolean;
}
 
export const getValidator = (
    value: string = "",
    defaultCountry?: string
): PhoneNumberValidator => {
    const countryCode: CountryCode = defaultCountry as CountryCode;
    let phoneNumber: PhoneNumber | null = null;
    try {
        phoneNumber = parsePhoneNumber(value, countryCode);
    } catch (err) {
        phoneNumber = null;
    }
 
    let prefix: string = "";
    let formattedValue: string = value.replace(/[^+0-9 ]/g, "");
    let country: string = fixCountryCode(defaultCountry);
    let isValid: boolean = false;
 
    if (phoneNumber !== null && phoneNumber.country !== undefined) {
        prefix = formatPrefix(phoneNumber.countryCallingCode.valueOf());
        country = phoneNumber.country.valueOf();
        formattedValue = phoneNumber.formatInternational();
        isValid = phoneNumber.isValid();
    } else Eif (countryCode !== undefined) {
        prefix = formatPrefix(getCallingCodeForCountry(countryCode));
        Eif (formattedValue === "") {
            formattedValue = prefix;
        }
    }
 
    return {
        getPrefix: () => prefix,
        getCountry: () => country,
        isValid: () => isValid,
        getFormattedValue: () => formattedValue,
        getValidatedValue: () =>
            isValid ? formattedValue.replace(/\s/g, "") : "",
    };
};