mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Add country continent mapping helper
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
import { validCountries } from './countryList';
|
||||
|
||||
export type Continent =
|
||||
| 'Africa'
|
||||
| 'Antarctica'
|
||||
| 'Asia'
|
||||
| 'Europe'
|
||||
| 'North America'
|
||||
| 'Oceania'
|
||||
| 'South America';
|
||||
|
||||
export type CountryToContinentMap = Record<string, Continent>;
|
||||
|
||||
export const countryToContinentMap = {
|
||||
'Afghanistan': 'Asia',
|
||||
'Aland Islands': 'Europe',
|
||||
'Albania': 'Europe',
|
||||
'Algeria': 'Africa',
|
||||
'American Samoa': 'Oceania',
|
||||
'Andorra': 'Europe',
|
||||
'Angola': 'Africa',
|
||||
'Anguilla': 'North America',
|
||||
'Antarctica': 'Antarctica',
|
||||
'Antigua and Barbuda': 'North America',
|
||||
'Argentina': 'South America',
|
||||
'Armenia': 'Asia',
|
||||
'Aruba': 'North America',
|
||||
'Ascension Island': 'Africa',
|
||||
'Ashmore and Cartier Islands': 'Oceania',
|
||||
'Australia': 'Oceania',
|
||||
'Austria': 'Europe',
|
||||
'Azerbaijan': 'Asia',
|
||||
'Bahamas, The': 'North America',
|
||||
'Bahrain': 'Asia',
|
||||
'Baker Island': 'Oceania',
|
||||
'Bangladesh': 'Asia',
|
||||
'Barbados': 'North America',
|
||||
'Bassas Da India': 'Africa',
|
||||
'Belarus': 'Europe',
|
||||
'Belgium': 'Europe',
|
||||
'Belize': 'North America',
|
||||
'Benin': 'Africa',
|
||||
'Bermuda': 'North America',
|
||||
'Bhutan': 'Asia',
|
||||
'Bolivia': 'South America',
|
||||
'Bonaire': 'North America',
|
||||
'Bosnia and Herzegovina': 'Europe',
|
||||
'Botswana': 'Africa',
|
||||
'Bouvet Island': 'Antarctica',
|
||||
'Brazil': 'South America',
|
||||
'British Indian Ocean Territory': 'Africa',
|
||||
'British Virgin Islands': 'North America',
|
||||
'Brunei': 'Asia',
|
||||
'Bulgaria': 'Europe',
|
||||
'Burkina Faso': 'Africa',
|
||||
'Burundi': 'Africa',
|
||||
'Cambodia': 'Asia',
|
||||
'Cameroon': 'Africa',
|
||||
'Canada': 'North America',
|
||||
'Cape Verde': 'Africa',
|
||||
'Cayman Islands': 'North America',
|
||||
'Central African Republic': 'Africa',
|
||||
'Chad': 'Africa',
|
||||
'Chile': 'South America',
|
||||
'China': 'Asia',
|
||||
'Christmas Island': 'Asia',
|
||||
'Clipperton Island': 'North America',
|
||||
'Cocos (Keeling) Islands': 'Asia',
|
||||
'Colombia': 'South America',
|
||||
'Comoros': 'Africa',
|
||||
'Congo, Democratic republic of the (prev. Zaire)': 'Africa',
|
||||
'Cook Islands': 'Oceania',
|
||||
'Coral Sea Islands': 'Oceania',
|
||||
'Costa Rica': 'North America',
|
||||
"Cote D'Ivoire": 'Africa',
|
||||
'Croatia': 'Europe',
|
||||
'Cuba': 'North America',
|
||||
'Curacao': 'North America',
|
||||
'Cyprus': 'Asia',
|
||||
'Czech Republic': 'Europe',
|
||||
'Denmark': 'Europe',
|
||||
'Djibouti': 'Africa',
|
||||
'Dominica': 'North America',
|
||||
'Dominican Republic': 'North America',
|
||||
'East Timor': 'Asia',
|
||||
'Ecuador': 'South America',
|
||||
'Egypt': 'Africa',
|
||||
'El Salvador': 'North America',
|
||||
'Equatorial Guinea': 'Africa',
|
||||
'Eritrea': 'Africa',
|
||||
'Estonia': 'Europe',
|
||||
'Ethiopia': 'Africa',
|
||||
'Europa Island': 'Africa',
|
||||
'Falkland Islands (Islas Malvinas)': 'South America',
|
||||
'Faroe Islands': 'Europe',
|
||||
'Fiji': 'Oceania',
|
||||
'Finland': 'Europe',
|
||||
'France': 'Europe',
|
||||
'French Guiana': 'South America',
|
||||
'French Polynesia': 'Oceania',
|
||||
'French Southern and Antarctic Lands': 'Antarctica',
|
||||
'Gabon': 'Africa',
|
||||
'Gambia, The': 'Africa',
|
||||
'Gaza Strip': 'Asia',
|
||||
'Georgia': 'Asia',
|
||||
'Germany': 'Europe',
|
||||
'Ghana': 'Africa',
|
||||
'Gibraltar': 'Europe',
|
||||
'Glorioso Islands': 'Africa',
|
||||
'Greece': 'Europe',
|
||||
'Greenland': 'North America',
|
||||
'Grenada': 'North America',
|
||||
'Guadeloupe': 'North America',
|
||||
'Guam': 'Oceania',
|
||||
'Guatemala': 'North America',
|
||||
'Guernsey': 'Europe',
|
||||
'Guinea': 'Africa',
|
||||
'Guinea-Bissau': 'Africa',
|
||||
'Guyana': 'South America',
|
||||
'Haiti': 'North America',
|
||||
'Heard Island and Mcdonald Islands': 'Antarctica',
|
||||
'Honduras': 'North America',
|
||||
'Hong Kong': 'Asia',
|
||||
'Howland Island': 'Oceania',
|
||||
'Hungary': 'Europe',
|
||||
'Iceland': 'Europe',
|
||||
'India': 'Asia',
|
||||
'Indonesia': 'Asia',
|
||||
'Iran': 'Asia',
|
||||
'Iraq': 'Asia',
|
||||
'Ireland': 'Europe',
|
||||
'Isle Of Man': 'Europe',
|
||||
'Israel': 'Asia',
|
||||
'Italy': 'Europe',
|
||||
'Jamaica': 'North America',
|
||||
'Jan Mayen': 'Europe',
|
||||
'Japan': 'Asia',
|
||||
'Jarvis Island': 'North America',
|
||||
'Jersey': 'Europe',
|
||||
'Jordan': 'Asia',
|
||||
'Juan De Nova Island': 'Africa',
|
||||
'Kazakhstan': 'Asia',
|
||||
'Kenya': 'Africa',
|
||||
'Kiribati': 'Oceania',
|
||||
'Kosovo': 'Europe',
|
||||
'Kuwait': 'Asia',
|
||||
'Kyrgyzstan': 'Asia',
|
||||
'Laos': 'Asia',
|
||||
'Latvia': 'Europe',
|
||||
'Lebanon': 'Asia',
|
||||
'Lesotho': 'Africa',
|
||||
'Liberia': 'Africa',
|
||||
'Libya': 'Africa',
|
||||
'Liechtenstein': 'Europe',
|
||||
'Lithuania': 'Europe',
|
||||
'Luxembourg': 'Europe',
|
||||
'Macau': 'Asia',
|
||||
'Madagascar': 'Africa',
|
||||
'Malawi': 'Africa',
|
||||
'Malaysia': 'Asia',
|
||||
'Maldives': 'Asia',
|
||||
'Mali': 'Africa',
|
||||
'Malta': 'Europe',
|
||||
'Marshall Islands': 'Oceania',
|
||||
'Martinique': 'North America',
|
||||
'Mauritania': 'Africa',
|
||||
'Mauritius': 'Africa',
|
||||
'Mayotte': 'Africa',
|
||||
'Mexico': 'North America',
|
||||
'Micronesia, Federated States of': 'Oceania',
|
||||
'Midway Islands': 'Oceania',
|
||||
'Moldova': 'Europe',
|
||||
'Monaco': 'Europe',
|
||||
'Mongolia': 'Asia',
|
||||
'Montenegro': 'Europe',
|
||||
'Montserrat': 'North America',
|
||||
'Morocco': 'Africa',
|
||||
'Mozambique': 'Africa',
|
||||
'Myanmar': 'Asia',
|
||||
'Namibia': 'Africa',
|
||||
'Nauru': 'Oceania',
|
||||
'Nepal': 'Asia',
|
||||
'Netherlands': 'Europe',
|
||||
'New Caledonia': 'Oceania',
|
||||
'New Zealand': 'Oceania',
|
||||
'Nicaragua': 'North America',
|
||||
'Niger': 'Africa',
|
||||
'Nigeria': 'Africa',
|
||||
'Niue': 'Oceania',
|
||||
"No Man's Land": 'Africa',
|
||||
'Norfolk Island': 'Oceania',
|
||||
'North Korea': 'Asia',
|
||||
'North Macedonia': 'Europe',
|
||||
'Northern Mariana Islands': 'Oceania',
|
||||
'Norway': 'Europe',
|
||||
'Oman': 'Asia',
|
||||
'Pakistan': 'Asia',
|
||||
'Palau': 'Oceania',
|
||||
'Palestine': 'Asia',
|
||||
'Panama': 'North America',
|
||||
'Papua New Guinea': 'Oceania',
|
||||
'Paracel Islands': 'Asia',
|
||||
'Paraguay': 'South America',
|
||||
'Peru': 'South America',
|
||||
'Philippines': 'Asia',
|
||||
'Pitcairn Islands': 'Oceania',
|
||||
'Poland': 'Europe',
|
||||
'Portugal': 'Europe',
|
||||
'Puerto Rico': 'North America',
|
||||
'Qatar': 'Asia',
|
||||
'Reunion': 'Africa',
|
||||
'Romania': 'Europe',
|
||||
'Russia': 'Europe',
|
||||
'Rwanda': 'Africa',
|
||||
'Saba': 'North America',
|
||||
'Saint Barthelemy': 'North America',
|
||||
'Saint Eustatius': 'North America',
|
||||
'Saint Helena': 'Africa',
|
||||
'Saint Kitts and Nevis': 'North America',
|
||||
'Saint Lucia': 'North America',
|
||||
'Saint Martin': 'North America',
|
||||
'Saint Pierre and Miquelon': 'North America',
|
||||
'Saint Vincent and the Grenadines': 'North America',
|
||||
'Samoa': 'Oceania',
|
||||
'San Marino': 'Europe',
|
||||
'Sao Tome and Principe': 'Africa',
|
||||
'Saudi Arabia': 'Asia',
|
||||
'Senegal': 'Africa',
|
||||
'Serbia': 'Europe',
|
||||
'Seychelles': 'Africa',
|
||||
'Sierra Leone': 'Africa',
|
||||
'Singapore': 'Asia',
|
||||
'Slovakia': 'Europe',
|
||||
'Slovenia': 'Europe',
|
||||
'Solomon Islands': 'Oceania',
|
||||
'Somalia': 'Africa',
|
||||
'South Africa': 'Africa',
|
||||
'South Georgia and the South Sandwich Islands': 'Antarctica',
|
||||
'South Korea': 'Asia',
|
||||
'South Sudan': 'Africa',
|
||||
'Spain': 'Europe',
|
||||
'Spratly Islands': 'Asia',
|
||||
'Sri Lanka': 'Asia',
|
||||
'Sudan': 'Africa',
|
||||
'Suriname': 'South America',
|
||||
'Svalbard': 'Europe',
|
||||
'Swaziland': 'Africa',
|
||||
'Sweden': 'Europe',
|
||||
'Switzerland': 'Europe',
|
||||
'Syria': 'Asia',
|
||||
'Taiwan': 'Asia',
|
||||
'Tajikistan': 'Asia',
|
||||
'Tanzania': 'Africa',
|
||||
'Thailand': 'Asia',
|
||||
'Togo': 'Africa',
|
||||
'Tokelau': 'Oceania',
|
||||
'Tonga': 'Oceania',
|
||||
'Trinidad and Tobago': 'North America',
|
||||
'Tromelin Island': 'Africa',
|
||||
'Tunisia': 'Africa',
|
||||
'Turkey': 'Asia',
|
||||
'Turkmenistan': 'Asia',
|
||||
'Turks and Caicos Islands': 'North America',
|
||||
'Tuvalu': 'Oceania',
|
||||
'Uganda': 'Africa',
|
||||
'Ukraine': 'Europe',
|
||||
'United Arab Emirates': 'Asia',
|
||||
'United Kingdom': 'Europe',
|
||||
'United States Minor Outlying Islands': 'Oceania',
|
||||
'United States of America': 'North America',
|
||||
'Uruguay': 'South America',
|
||||
'Uzbekistan': 'Asia',
|
||||
'Vanuatu': 'Oceania',
|
||||
'Vatican City': 'Europe',
|
||||
'Venezuela': 'South America',
|
||||
'Vietnam': 'Asia',
|
||||
'Virgin Islands': 'North America',
|
||||
'Wake Island': 'Oceania',
|
||||
'Wallis and Futuna': 'Oceania',
|
||||
'West Bank': 'Asia',
|
||||
'Western Sahara': 'Africa',
|
||||
'Yemen': 'Asia',
|
||||
'Zambia': 'Africa',
|
||||
'Zimbabwe': 'Africa',
|
||||
} as const satisfies CountryToContinentMap;
|
||||
|
||||
const normalizedCountryLookup = new Map<string, string>(
|
||||
validCountries.map(country => [country.toLowerCase(), country]),
|
||||
);
|
||||
|
||||
const continentAliases: Record<Continent, string[]> = {
|
||||
Africa: ['africa'],
|
||||
Antarctica: ['antarctica'],
|
||||
Asia: ['asia'],
|
||||
Europe: ['europe'],
|
||||
'North America': [
|
||||
'north america',
|
||||
'northern america',
|
||||
'central america',
|
||||
'caribbean',
|
||||
'america',
|
||||
'americas',
|
||||
],
|
||||
Oceania: ['oceania', 'australia', 'australasia', 'pacific'],
|
||||
'South America': ['south america', 'southern america', 'latin america', 'america', 'americas'],
|
||||
};
|
||||
|
||||
const normalize = (value: string | null | undefined) => value?.trim().toLowerCase() ?? '';
|
||||
|
||||
export const getContinentByCountry = (
|
||||
country: string | null | undefined,
|
||||
): Continent | undefined => {
|
||||
const normalizedCountry = normalize(country);
|
||||
if (!normalizedCountry) return undefined;
|
||||
|
||||
const canonicalCountry = normalizedCountryLookup.get(normalizedCountry);
|
||||
if (!canonicalCountry) return undefined;
|
||||
|
||||
return countryToContinentMap[canonicalCountry as keyof typeof countryToContinentMap];
|
||||
};
|
||||
|
||||
export const matchesCountryOrContinent = (
|
||||
country: string | null | undefined,
|
||||
filterValue: string | null | undefined,
|
||||
): boolean => {
|
||||
const normalizedFilter = normalize(filterValue);
|
||||
if (!normalizedFilter) return true;
|
||||
|
||||
const normalizedCountry = normalize(country);
|
||||
if (normalizedCountry.includes(normalizedFilter)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const continent = getContinentByCountry(country);
|
||||
if (!continent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalizedContinent = continent.toLowerCase();
|
||||
if (normalizedContinent.includes(normalizedFilter)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return continentAliases[continent].some(
|
||||
alias => alias.includes(normalizedFilter) || normalizedFilter.includes(alias),
|
||||
);
|
||||
};
|
||||
@@ -272,3 +272,7 @@ export const validCountries = [
|
||||
'Zambia',
|
||||
'Zimbabwe',
|
||||
]
|
||||
|
||||
export const validCountrySet = new Set(validCountries)
|
||||
|
||||
export const isValidCountry = (value: string): boolean => validCountrySet.has(value)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, it } from '@jest/globals'
|
||||
import { validCountries } from '../../shared/validators/countryList'
|
||||
import {
|
||||
countryToContinentMap,
|
||||
getContinentByCountry,
|
||||
matchesCountryOrContinent,
|
||||
} from '../../shared/validators/countryContinents'
|
||||
|
||||
describe('country continent mapping', () => {
|
||||
it('maps every valid country to a continent', () => {
|
||||
const missingCountries = validCountries.filter(
|
||||
country => !(country in countryToContinentMap)
|
||||
)
|
||||
|
||||
expect(missingCountries).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('resolves continents case-insensitively', () => {
|
||||
expect(getContinentByCountry(' canada ')).toBe('North America')
|
||||
expect(getContinentByCountry('BRAZIL')).toBe('South America')
|
||||
expect(getContinentByCountry('unknown')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('matches continent aliases and country names', () => {
|
||||
expect(matchesCountryOrContinent('Finland', 'Europe')).toBe(true)
|
||||
expect(matchesCountryOrContinent('Finland', 'eur')).toBe(true)
|
||||
expect(matchesCountryOrContinent('Finland', 'asia')).toBe(false)
|
||||
|
||||
expect(matchesCountryOrContinent('Mexico', 'central america')).toBe(true)
|
||||
expect(matchesCountryOrContinent('Brazil', 'latin america')).toBe(true)
|
||||
expect(matchesCountryOrContinent('Canada', 'americas')).toBe(true)
|
||||
expect(matchesCountryOrContinent('Kenya', 'afr')).toBe(true)
|
||||
|
||||
expect(matchesCountryOrContinent('Australia', 'oceania')).toBe(true)
|
||||
expect(matchesCountryOrContinent('Australia', 'pacific')).toBe(true)
|
||||
|
||||
expect(matchesCountryOrContinent('Kenya', 'oceania')).toBe(false)
|
||||
expect(matchesCountryOrContinent(null, 'Europe')).toBe(false)
|
||||
expect(matchesCountryOrContinent('Kenya', '')).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user