# `AddressInput`
[🔗](https://github.com/nkezhaya/address_input/blob/main/lib/address_input.ex#L1)

High-level API for address metadata derived from the
[libaddressinput](https://github.com/google/libaddressinput) dataset.

The module loads a JSON dataset from `priv/metadata.json` (bundled with the
application) and exposes convenience functions for looking up normalized
[Country](`AddressInput.Country`) and [Subregion](`AddressInput.Subregion`)
structs.

## Primary entry points

- `countries/0` returns all available countries sorted by name. Each country
  includes parsed subregions.
- `get_country/1` returns a single country by ISO 3166-1 alpha-2 code (case
  insensitive), or `nil` if it is not present.
- `format_fields/1` extracts the fields present in a parsed address format.

## Country fields

A [Country](`AddressInput.Country`) includes:

- `id` - ISO 3166-1 alpha-2 code.
- `name` - localized display name from the dataset.
- `default_language` - language code used for labels.
- `required_fields` - list of required address components as atoms, derived
  from the dataset codes (`N`, `O`, `A`, `D`, `C`, `S`, `Z`, `X`).
- `subregion_type`, `sublocality_type`, `postal_code_type` - label hints.
- `postal_code_regex` - compiled regex for validating postal codes.
- `address_format` - parsed formatting template from the dataset (`fmt`).
- `local_address_format` - parsed local formatting template (`lfmt`) when present.
- `subregions` - list of [Subregion](`AddressInput.Subregion`) entries.

A [Subregion](`AddressInput.Subregion`) includes `id`, `iso_code`, and `name`.

## Example

    iex> AddressInput.get_country("US")
    %AddressInput.Country{
      id: "US",
      name: "UNITED STATES",
      default_language: "en",
      required_fields: [:address, :sublocality, :region, :postal_code],
      sublocality_type: "city",
      subregion_type: "state",
      postal_code_type: "zip",
      postal_code_regex: ~r/(\d{5})(?:[ -](\d{4}))?/,
      address_format: [{:field, :name}, :newline, ...],
      local_address_format: nil,
      subregions: [
        %AddressInput.Subregion{id: "AK", iso_code: "AK", name: "Alaska"},
        ...
      ]
    }
    "US"

# `address_format`

```elixir
@type address_format() :: [token()]
```

# `token`

```elixir
@type token() ::
  {:field, AddressInput.Country.field()} | {:text, String.t()} | :newline
```

# `countries`

```elixir
@spec countries() :: [AddressInput.Country.t()]
```

Returns the list of available countries as [Country](`AddressInput.Country`) structs.

# `format_fields`

```elixir
@spec format_fields(address_format()) :: [AddressInput.Country.field()]
```

Returns the fields present in a parsed address format, in template order.

These are the fields clients can render. Use the country's
`required_fields` to determine which of them must be validated.

## Example

    iex> country = AddressInput.get_country("IS")
    iex> AddressInput.format_fields(country.address_format)
    [:name, :organization, :address, :postal_code, :sublocality]

# `get_country`

```elixir
@spec get_country(String.t()) :: AddressInput.Country.t() | nil
```

Returns a [Country](`AddressInput.Country`) by ISO 3166-1 alpha-2 country code.

Returns `nil` when the country is not found.

# `parse_postal_code`

```elixir
@spec parse_postal_code(String.t(), String.t() | AddressInput.Country.t()) ::
  {:ok, String.t()} | :error
```

Returns `{:ok, postal_code}` if the postal code matches the expected format
for the given country. Otherwise, returns `:error`. The provided country must
be either a `%Country{}` or a string that resolves to one.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
