first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View 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"`).