first commit
This commit is contained in:
120
docs/localization/i18n/locale-data/src/countries/countries.md
Normal file
120
docs/localization/i18n/locale-data/src/countries/countries.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# countries
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Provides typed lookup functions over the static ISO 3166-1 alpha-2 country dataset (209 entries).
|
||||
The module is designed for high-frequency read access — data is held in a single frozen object
|
||||
(`COUNTRIES_DATA`) and all lookups run in O(1) or O(n) time with zero I/O. Every `getCountry`
|
||||
call emits an OTel counter increment, enabling production observability for cache-hit analysis
|
||||
and anomaly detection on invalid code injection attempts.
|
||||
|
||||
## Features
|
||||
|
||||
- **`getCountry(code)`** — O(1) lookup by ISO 3166-1 alpha-2 code; throws a typed
|
||||
`LocaleDataError` for unknown codes.
|
||||
- **`getAllCountries()`** — Returns the full `Record<string, CountryItem>` reference; O(1),
|
||||
no copy allocation.
|
||||
- **`getCountriesByContinent(continent)`** — Filters by two-letter continent code (`"EU"`, `"AS"`,
|
||||
`"AF"`, `"NA"`, `"SA"`, `"OC"`, `"AN"`); returns empty array for unknown codes.
|
||||
- **`getCountriesByCurrency(currency)`** — Matches against comma-separated ISO 4217 currency codes
|
||||
in each entry (e.g. `"CHE,CHF,CHW"`); returns empty array for unknown currencies.
|
||||
- **OTel instrumentation** — `locale_data.country.lookups` counter with `result: "found" | "not_found"`.
|
||||
- **Zod schemas** — `CountryCodeSchema` (2-char uppercase) and re-exported `CountryItemSchema`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { getCountry, getAllCountries } from "@suaveplan/locale-data/countries";
|
||||
|
||||
// Look up a single country
|
||||
const us = getCountry("US");
|
||||
console.log(us.name); // "United States"
|
||||
console.log(us.phone); // "1"
|
||||
console.log(us.emoji); // "🇺🇸"
|
||||
|
||||
// Get all countries
|
||||
const all = getAllCountries();
|
||||
console.log(Object.keys(all).length); // 209
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
getCountry,
|
||||
getCountriesByContinent,
|
||||
getCountriesByCurrency,
|
||||
} from "@suaveplan/locale-data/countries";
|
||||
import { LocaleDataError, LOCALE_DATA_CODES } from "@suaveplan/locale-data/errors";
|
||||
|
||||
// Error handling
|
||||
try {
|
||||
const country = getCountry("ZZ");
|
||||
} catch (err) {
|
||||
if (err instanceof LocaleDataError && err.code === LOCALE_DATA_CODES["COUNTRY.NOT_FOUND"]) {
|
||||
console.warn("Unknown country code");
|
||||
}
|
||||
}
|
||||
|
||||
// Filter by continent
|
||||
const europeanCountries = getCountriesByContinent("EU");
|
||||
console.log(europeanCountries.length); // ~40
|
||||
|
||||
// Find all Eurozone members (use single-currency entries + multi-currency)
|
||||
const eurozoneMembers = getCountriesByCurrency("EUR");
|
||||
console.log(eurozoneMembers.map((c) => c.name));
|
||||
|
||||
// Group by continent
|
||||
import { getAllCountries } from "@suaveplan/locale-data/countries";
|
||||
const byContinent = Object.entries(getAllCountries()).reduce<Record<string, string[]>>(
|
||||
(acc, [code, c]) => {
|
||||
(acc[c.continent] ??= []).push(code);
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `getCountry(code: string): CountryItem`
|
||||
|
||||
Look up a country by its ISO 3166-1 alpha-2 code.
|
||||
|
||||
- **Parameters:** `code` — case-sensitive two-letter code (e.g. `"US"`, `"DE"`).
|
||||
- **Returns:** The matching `CountryItem`.
|
||||
- **Throws:** `LocaleDataError` (`LOCALE_DATA/COUNTRY.NOT_FOUND`) when the code is not found.
|
||||
- **OTel:** Increments `locale_data.country.lookups` with `result: "found"` or `"not_found"`.
|
||||
|
||||
### `getAllCountries(): Record<string, CountryItem>`
|
||||
|
||||
Return the full 209-entry country map.
|
||||
|
||||
- **Returns:** A `Record<string, CountryItem>` — the same reference each call.
|
||||
- **Note:** Do not mutate the returned object.
|
||||
|
||||
### `getCountriesByContinent(continent: string): CountryItem[]`
|
||||
|
||||
Filter countries by continent code.
|
||||
|
||||
- **Parameters:** `continent` — `"EU"` | `"AS"` | `"AF"` | `"NA"` | `"SA"` | `"OC"` | `"AN"`.
|
||||
- **Returns:** Array of matching `CountryItem` values; empty array for unknown codes.
|
||||
|
||||
### `getCountriesByCurrency(currency: string): CountryItem[]`
|
||||
|
||||
Filter countries by ISO 4217 currency code.
|
||||
|
||||
- **Parameters:** `currency` — e.g. `"EUR"`, `"USD"`, `"CHF"`.
|
||||
- **Returns:** Array of matching `CountryItem` values; handles comma-separated multi-currency
|
||||
entries; empty array if no match.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Data is stored in `countries.data.ts` as a plain `Record<string, CountryItem>` const to keep the
|
||||
implementation file under the 300-line hard limit. The data file is excluded from coverage
|
||||
measurement because it contains no executable logic — only `export const`. The `getCountriesByCurrency`
|
||||
function splits on commas to support countries with composite currency fields like Switzerland
|
||||
(`"CHE,CHF,CHW"`), Bolivia (`"BOB,BOV"`), and Cuba (`"CUC,CUP"`).
|
||||
Reference in New Issue
Block a user