epic-geo
Version:
A simple geo information provider library.
153 lines (137 loc) • 4.5 kB
text/typescript
import { Countries, CountriesData, States } from "./countries";
import { CountryNames } from "./countryNames";
import { StateNames } from "./stateNames";
export interface InputCountry {
alpha2Code?: string;
alpha3Code?: string;
altSpellings?: string[];
area?: number | null;
borders?: string[];
callingCodes?: string[];
capital?: string | null;
currencies?: Array<{
code: string | null;
name: string | null;
symbol: string | null;
}>;
demonym?: string | null;
flag?: string | null;
gini?: number | null;
languages?: Array<{
iso639_1?: string | null;
iso639_2?: string | null;
name?: string | null;
nativeName?: string | null;
}>;
latlng?: [number, number] | null;
name?: string;
nativeName?: string | null;
numericCode?: string | null;
population?: number | null;
region?: string | null;
regionalBlocs?: Array<{
acronym: string;
name: string;
otherNames?: string[];
otherAcronyms?: string[];
}>;
subregion?: string | null;
timezones?: string[];
topLevelDomain?: string[];
translations?: {
br: string | null;
de: string | null;
es: string | null;
fa: string | null;
fr: string | null;
hr: string | null;
it: string | null;
ja: string | null;
nl: string | null;
pt: string | null;
};
cioc?: string | null;
states?: States;
}
export class EpicGeo {
protected CustomData: Record<string, InputCountry> = {};
public custom = (
countryName: ReturnType<CountryNames["get"]>[number],
data: InputCountry
) => {
this.CustomData[countryName] = data;
return this;
};
public countries = (): Countries => ({
...CountriesData,
...this.CustomData,
});
public country = (countryName: ReturnType<CountryNames["get"]>[number]) =>
this.countries()[countryName];
public countryList = (): Array<ReturnType<CountryNames["get"]>[number]> =>
Object.keys(this.countries()) as any;
public hasCountry = (name: string) =>
this.countryList()
.map((country) => country.toLowerCase())
.includes(name.toLowerCase() as any);
public states = (countryName?: ReturnType<CountryNames["get"]>[number]) =>
countryName
? this.countries()[countryName]?.states
: Object.values(this.countries())
.map((country) => country.states)
.reduce((p, c) => ({ ...p, ...c }), {});
public state = (
countryName: ReturnType<CountryNames["get"]>[number],
stateName: ReturnType<StateNames["get"]>[number]
) => this.states(countryName)?.[stateName];
public stateList = (): ReturnType<StateNames["get"]>[number] =>
Object.values(this.countries()).reduce(
(p, c) => [...p, ...Object.keys(c.states)],
[] as string[]
) as any;
public hasState = (
name: string,
countryName?: ReturnType<CountryNames["get"]>[number]
) =>
((countryName
? Object.keys(this.country(countryName)?.states || {})
: (this.stateList() as any)) as string[])
.map((state) => state.toLowerCase())
.includes(name.toLowerCase());
public cities = (
countryName?: ReturnType<CountryNames["get"]>[number],
stateName?: ReturnType<StateNames["get"]>[number]
) =>
countryName
? stateName
? this.state(countryName, stateName)?.cities || []
: Object.values(this.states(countryName))
.map((state) => state.cities)
.reduce((p, c) => p.concat(c), [])
: Object.values(this.states(countryName))
.map((state) => state.cities)
.reduce((p, c) => p.concat(c), []);
public cityList = () =>
Object.values(this.countries())
.map((country) =>
Object.values(country.states)
.map((state) => state?.cities || [])
.reduce((c, p) => c.concat(p), [])
)
.reduce((c, p) => c.concat(p), []);
public hasCity = (
name: string,
countryName?: ReturnType<CountryNames["get"]>[number],
stateName?: ReturnType<StateNames["get"]>[number]
) =>
(countryName
? stateName
? this.state(countryName, stateName)?.cities || []
: Object.values(this.states(countryName) || {})
.map((state) => state.cities)
.reduce((p, c) => p.concat(c), [])
: this.cityList()
)
.map((city) => city.toLowerCase())
.includes(name.toLowerCase());
}