UNPKG

@yusifaliyevpro/countries

Version:

TypeScript wrapper for Rest Countries API to fetch country data by codes, capitals, or all countries with full typings.

501 lines (500 loc) 18.5 kB
//#region src/constants.ts const API_BASE_URL = "https://restcountries.com/v3.1"; //#endregion //#region src/helpers.ts function constructAPI({ route = "all", query = "", fields, status, codes, fullText }) { const base_url = new URL(API_BASE_URL); if (status !== void 0) route = "independent"; base_url.pathname += `/${route}/${query.toLowerCase()}`; if (status !== void 0) base_url.searchParams.set("status", String(status)); if (fullText !== void 0) base_url.searchParams.set("fullText", String(fullText)); if (codes) base_url.searchParams.append("codes", codes.toLowerCase()); fields = Array.from(new Set(fields)); if (fields && fields.length) base_url.searchParams.set("fields", fields.join(",")); return base_url; } function handleNotFoundError(ok) { if (!ok) console.error("Couldn't find any country that matches your query, if you think it is issue please submit it via github issues"); } function handleNetworkError(error) { console.warn("A network or REST Countries API side error happened while fetching data. Try again later."); console.warn("If this error persists, please verify the status of the REST Countries API. If the issue continues, feel free to report it on GitHub: https://github.com/yusifaliyevpro/countries"); console.error(error); } //#endregion //#region src/functions/getCountries.ts /** * Fetches all countries, optionally filtered by independence status, * and including only the specified fields. * * > **Note:** The `fields` parameter is required and you can only specify upto 10 fields, * as mandated by Alejandro Matos See: {@link https://gitlab.com/restcountries/restcountries/-/issues/265}. * * @param params - An object containing: * - `fields`: A required array of field names (keys from the `Country` type) to include in the response. * - `independent`: If true, only includes independent countries; if false, only dependent ones. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to an array of `CountryPicker<T>` objects with the requested fields, * or `null` if the request fails or no countries match the criteria. * * @example * // Get all countries with only the `name` and `area` fields * const countries = await getCountries({ fields: ["name", "area"] }); * * @example * // Get all independent countries with only the `name` and `area` fields * const independentCountries = await getCountries({ * independent: true, * fields: ["name", "area"] * }); */ async function getCountries({ independent, fields }, fetchOptions) { try { if (fields.length > 10) console.error("You can specify up to 10 fields only"); const api = constructAPI({ status: independent, fields }); const response = await fetch(api.toString(), fetchOptions); handleNotFoundError(response.ok); return response.ok ? await response.json() : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountriesByCodes.ts /** * Fetches countries by their codes (e.g., CCA2, CCA3, or CIOC), optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * * @param params - An object containing: * - `codes`: An array of country codes to fetch data for. CCA3 is recommended for precision. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to an array of `CountryPicker<T>` objects with the requested fields, * or `null` if the request fails or the countries are not found. * * @example * // Get countries by CCA3 codes with only `name` and `flags` fields * const countries = await getCountriesByCodes({ * codes: ["USA", "FRA", "JPN"], * fields: ["name", "flags"] * }); * * @example * // Get countries by CCA2 codes with all fields * const countries = await getCountriesByCodes({ codes: ["US", "FR", "JP"] }); */ async function getCountriesByCodes({ codes, fields }, fetchOptions) { try { const api = constructAPI({ route: "alpha", codes: codes.join(","), fields }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? await response.json() : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountriesByCurrency.ts /** * Fetches countries that use the specified currency, optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * * @param params - An object containing: * - `currency`: The currency code (e.g., "USD", "EUR", "JPY") used to filter countries. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to an array of `CountryPicker<T>` objects with the requested fields, * or `null` if the request fails or no countries use the specified currency. * * @example * // Get countries using the Euro with only `name` and `flags` fields * const euroCountries = await getCountriesByCurrency({ * currency: "EUR", * fields: ["name", "flags"] * }); * * @example * // Get countries using the Japanese Yen with all fields * const yenCountries = await getCountriesByCurrency({ currency: "JPY" }); */ async function getCountriesByCurrency({ currency, fields }, fetchOptions) { try { const api = constructAPI({ route: "currency", query: currency, fields }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? await response.json() : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountriesByLang.ts /** * Fetches countries where the specified language is officially or widely spoken, * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * * @param params - An object containing: * - `lang`: (e.g., "Spanish", "English", "Azerbaijani"). * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to an array of `CountryPicker<T>` objects with the requested fields, * or `null` if the request fails or no countries match the language criteria. * * @example * // Get countries where Spanish is spoken with `name` and `region` fields * const spanishSpeakingCountries = await getCountriesByLang({ * lang: "spa", * fields: ["name", "region"] * }); * * @example * // Get countries where English is spoken with all fields * const englishSpeakingCountries = await getCountriesByLang({ lang: "en" }); */ async function getCountriesByLang({ lang, fields }, fetchOptions) { try { const api = constructAPI({ route: "lang", query: lang, fields }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? await response.json() : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountriesByName.ts /** * Fetches countries that match a given name or partial name, * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * > Set `fullText` to `true` to require an exact, full-name match. * * @param params - An object containing: * - `name`: The country name or partial name to search for (e.g., "united"). * - `fullText`: Optional boolean to indicate whether to match full names exactly. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to an array of `CountryPicker<T>` objects with the requested fields, * or `null` if the request fails or no countries match the name. * * @example * // Search countries containing "united" with only `name` and `flags` fields * const results = await getCountriesByName({ * name: "united", * fields: ["name", "flags"] * }); * * @example * // Search for exact match of "Finland" with all fields * const country = await getCountriesByName({ name: "Finland", fullText: true }); */ async function getCountriesByName({ name, fullText, fields }, fetchOptions) { try { const api = constructAPI({ route: "name", query: name, fields, fullText }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? await response.json() : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountriesByRegion.ts /** * Fetches countries which belong to the specified world region, * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * * @param params - An object containing: * - `region`: The name of the region (e.g., "Asia", "Europe", "Africa") to filter countries by. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to an array of `CountryPicker<T>` objects with the requested fields, * or `null` if the request fails or the region is not found. * * @example * // Get Asian countries with only `name` and `population` fields * const asianCountries = await getCountriesByRegion({ * region: "Asia", * fields: ["name", "population"] * }); * * @example * // Get all fields for countries in Europe * const europeanCountries = await getCountriesByRegion({ region: "Europe" }); */ async function getCountriesByRegion({ region, fields }, fetchOptions) { try { const api = constructAPI({ route: "region", query: region, fields }); const response = await fetch(api.toString(), fetchOptions); handleNotFoundError(response.ok); return response.ok ? await response.json() : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountriesBySubregion.ts /** * Fetches countries that belong to the specified subregion, * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * * @param params - An object containing: * - `subregion`: The subregion name (e.g., "Southern Asia", "Northern Europe") to filter countries by. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to an array of `CountryPicker<T>` objects with the requested fields, * or `null` if the request fails or no countries match the subregion. * * @example * // Get countries in Northern Europe with only `name` and `population` fields * const nordicCountries = await getCountriesBySubregion({ * subregion: "Northern Europe", * fields: ["name", "population"] * }); * * @example * // Get all fields for countries in Southern Asia * const southAsianCountries = await getCountriesBySubregion({ subregion: "Southern Asia" }); */ async function getCountriesBySubregion({ subregion, fields }, fetchOptions) { try { const api = constructAPI({ route: "subregion", query: subregion, fields }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? await response.json() : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountryByCapital.ts /** * Fetches a single country by its capital city, * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * > Returns the first matching country or `null` if none is found. * * @param params - An object containing: * - `capital`: The name of the capital city to search for. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to a single `CountryPicker<T>` object with the requested fields, * or `null` if the request fails or no country matches the capital city. * * @example * // Get country by capital "Paris" with only `name` and `region` fields * const country = await getCountryByCapital({ * capital: "Paris", * fields: ["name", "region"] * }); * * @example * // Get all fields for the country with capital "Tokyo" * const japan = await getCountryByCapital({ capital: "Tokyo" }); */ async function getCountryByCapital({ capital, fields }, fetchOptions) { try { const api = constructAPI({ route: "capital", query: capital, fields }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? (await response.json())[0] : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountryByCode.ts /** * Fetches a single country by its code (e.g., CCA2, CCA3, or CIOC), * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * > Returns the first matching country or `null` if none is found. * * @param params - An object containing: * - `code`: The country code to fetch data for. CCA3 is recommended for precision. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to a single `CountryPicker<T>` object with the requested fields, * or `null` if the request fails or no country matches the code. * * @example * // Get country by CCA3 code "USA" with only `name` and `flags` fields * const usa = await getCountryByCode({ * code: "USA", * fields: ["name", "flags"] * }); * * @example * // Get all fields for the country with code "FRA" * const france = await getCountryByCode({ code: "FRA" }); */ async function getCountryByCode({ code, fields }, fetchOptions) { try { const api = constructAPI({ route: "alpha", query: code, fields }); const response = await fetch(api.toString(), fetchOptions); const data = await response.json(); return response.ok ? fields && !!fields.length ? data : data[0] : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountryByDemonym.ts /** * Fetches a single country by its demonym (the name for its residents), * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * > Returns the first matching country or `null` if none is found. * * @param params - An object containing: * - `demonym`: The demonym string to search for (e.g., "American", "French"). * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to a single `CountryPicker<T>` object with the requested fields, * or `null` if the request fails or no country matches the demonym. * * @example * // Get country by demonym "Canadian" with only `name` and `region` fields * const canada = await getCountryByDemonym({ * demonym: "Canadian", * fields: ["name", "region"] * }); * * @example * // Get all fields for the country with demonym "Brazilian" * const brazil = await getCountryByDemonym({ demonym: "Brazilian" }); */ async function getCountryByDemonym({ demonym, fields }, fetchOptions) { try { const api = constructAPI({ route: "demonym", query: demonym, fields }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? (await response.json())[0] : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/functions/getCountryByTranslation.ts /** * Fetches a single country by a translated country name, * optionally including only the specified fields. * * > **Note:** If `fields` is not provided, all available fields will be returned. * > Returns the first matching country or `null` if none is found. * * @param params - An object containing: * - `translation`: The translated name of the country to search for. * - `fields`: An optional array of field names (keys from the `Country` type) to include in the response. * * @param fetchOptions - Optional `RequestInit` object to customize the `fetch` request. * * @returns A promise that resolves to a single `CountryPicker<T>` object with the requested fields, * or `null` if the request fails or no country matches the translation. * * @example * // Get country by translation "Alemania" (German for Germany) with only `name` and `region` fields * const germany = await getCountryByTranslation({ * translation: "Alemania", * fields: ["name", "region"] * }); * * @example * // Get all fields for the country with translation "Espagne" (French for Spain) * const spain = await getCountryByTranslation({ translation: "Espagne" }); */ async function getCountryByTranslation({ translation, fields }, fetchOptions) { try { const api = constructAPI({ route: "translation", query: translation, fields }); const response = await fetch(api.toString(), fetchOptions); return response.ok ? (await response.json())[0] : null; } catch (error) { handleNetworkError(error); return null; } } //#endregion //#region src/index.ts const defineFields = (fields) => fields; //#endregion export { defineFields, getCountries, getCountriesByCodes, getCountriesByCurrency, getCountriesByLang, getCountriesByName, getCountriesByRegion, getCountriesBySubregion, getCountryByCapital, getCountryByCode, getCountryByDemonym, getCountryByTranslation }; //# sourceMappingURL=index.mjs.map