country-data-find
Version:
Information about countries - like their ISO (2/3) codes, names, and currencies.
189 lines (164 loc) • 5.63 kB
JavaScript
;
const CountryJSON = require('./data/Country.json');
const CountryArray = Object.values(CountryJSON);
// Optionally require Fuse.js for fuzzy search (must install: npm install fuse.js)
let Fuse;
try {
Fuse = require('fuse.js');
} catch (e) {
// If Fuse.js not installed, fuzzyFindCountry will throw an error
}
/** Utility: Normalize a string for search (case-insensitive, trim) */
function normalize(str) {
return typeof str === 'string' ? str.trim().toLowerCase() : '';
}
/** --- BASIC COUNTRY LOOKUPS --- **/
const Country = {
JSON: () => CountryJSON,
Array: () => CountryArray,
/** Find by any country name (partial, case-insensitive, any language) */
findCountry: (name) => {
if (!name) return null;
const nName = normalize(name);
return CountryArray.find(country =>
Object.values(country.LIST_OF_NAME)
.flat()
.some(n => normalize(n).includes(nName))
);
},
/** Find by ISO2 or ISO3 code */
findByCode: (code) => {
if (!code) return null;
const nCode = code.trim().toUpperCase();
return CountryArray.find(
c => c.ISO2_CODE === nCode || c.ISO3_CODE === nCode
);
},
/** Find ISO2 code from any name */
findISO2Code: (name) => {
const c = Country.findCountry(name);
return c ? c.ISO2_CODE : null;
},
/** Find ISO3 code from any name */
findISO3Code: (name) => {
const c = Country.findCountry(name);
return c ? c.ISO3_CODE : null;
},
/** Get all names of a country (all languages) by ISO2/ISO3 code */
getAllNames: (code) => {
const country = Country.findByCode(code);
if (!country) return [];
return Object.values(country.LIST_OF_NAME).flat();
},
/** List all countries' names in a specific language (default ENG) */
filterByLanguage: (lang = 'ENG') => {
return CountryArray.map(country => ({
code: country.ISO2_CODE,
name: country.LIST_OF_NAME[lang] || country.LIST_OF_NAME['ENG'] || []
}));
}
};
/** --- ADVANCED SEARCH FEATURES --- **/
/** Fuzzy country name search (requires fuse.js) */
function fuzzyFindCountry(name) {
if (!Fuse) throw new Error('fuzzyFindCountry requires fuse.js. Install with `npm install fuse.js`');
if (!name) return null;
// Prepare flat name list
const countryNames = CountryArray.flatMap(c =>
Object.entries(c.LIST_OF_NAME).flatMap(([lang, names]) =>
names.map(n => ({
name: n,
lang,
ISO2: c.ISO2_CODE,
ISO3: c.ISO3_CODE
}))
)
);
const fuse = new Fuse(countryNames, { keys: ['name'], threshold: 0.3 });
const result = fuse.search(name);
if (!result.length) return null;
// Return country object by ISO2 or ISO3 code
return Country.findByCode(result[0].item.ISO2 || result[0].item.ISO3);
}
/** Find all countries using a currency (by code or name) */
function findCountriesByCurrency(input) {
const nInput = normalize(input);
return CountryArray.filter(c =>
(c.CURRENCY || []).some(cur =>
(cur.CODE || []).some(code => normalize(code) === nInput) ||
(cur.NAME || []).some(name => normalize(name).includes(nInput))
)
);
}
/** Find by region/continent (requires REGION field in data) */
function findByRegion(region) {
const nRegion = normalize(region);
return CountryArray.filter(c =>
c.REGION && normalize(c.REGION) === nRegion
);
}
/** Find by phone code (requires PHONE_CODE field in data) */
function findByPhoneCode(phone) {
if (!phone) return [];
const nPhone = phone.replace(/^\+/, '');
return CountryArray.filter(c =>
Array.isArray(c.PHONE_CODE)
? c.PHONE_CODE.map(String).includes(nPhone)
: String(c.PHONE_CODE) === nPhone
);
}
/** Get country name in any language (first variant) */
function getCountryNameInLanguage(code, lang = 'ENG') {
const country = Country.findByCode(code);
if (!country) return null;
return (country.LIST_OF_NAME[lang] || [])[0] || null;
}
/** Autocomplete: find all countries whose names start with input (in a language) */
function autocompleteCountry(partial, lang = 'ENG') {
if (!partial) return [];
const nPartial = normalize(partial);
return CountryArray.filter(c =>
(c.LIST_OF_NAME[lang] || []).some(
name => normalize(name).startsWith(nPartial)
)
);
}
/** Generic flexible search: query by fields like { ISO2_CODE: 'LK' }, { 'CURRENCY.CODE': 'USD' } */
function findCountryFlexible(query = {}) {
return CountryArray.filter(country => {
return Object.entries(query).every(([key, value]) => {
if (key.startsWith('CURRENCY.')) {
const subKey = key.split('.')[1];
return (country.CURRENCY || []).some(cur =>
(cur[subKey] || []).includes(value)
);
}
if (country[key]) return country[key] === value;
return false;
});
});
}
/** Get flag emoji for ISO2 code */
function getFlagEmoji(iso2) {
if (!iso2 || typeof iso2 !== 'string' || iso2.length !== 2) return '';
return iso2
.toUpperCase()
.replace(/./g, c => String.fromCodePoint(0x1f1e6 + c.charCodeAt(0) - 65));
}
/** Validate if a string is a valid ISO2/ISO3 code */
function isValidCountryCode(code) {
return !!Country.findByCode(code);
}
/** Export all APIs */
module.exports = {
...Country,
fuzzyFindCountry,
findCountriesByCurrency,
findByRegion,
findByPhoneCode,
getCountryNameInLanguage,
autocompleteCountry,
findCountryFlexible,
getFlagEmoji,
isValidCountryCode,
};