Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 45 additions & 16 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,28 @@ on:

jobs:
publish:
name: Publish to NuGet
name: Publish packages (NuGet.org + GitHub)
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
packages: write
actions: read

env:
SOLUTION_NAME: src/HawkN.Iso.Countries.Solution.sln
NUGET_ORG_USERNAME: HawkN113

## Iso.Countries package settings
## Iso.Countries package (Core)
PACKAGE_COUNTRIES_PROJECT_PATH: src/packages/HawkN.Iso.Countries/HawkN.Iso.Countries.csproj
PACKAGE_COUNTRIES_NUSPEC_FILE_PATH: HawkN.Iso.Countries.nuspec
PACKAGE_COUNTRIES_ID: HawkN.Iso.Countries

## Iso.Countries.Currencies package (Extension)
PACKAGE_COUNTRIES_CURRENCIES_PROJECT_PATH: src/packages/HawkN.Iso.Countries.Currencies/HawkN.Iso.Countries.Currencies.csproj
PACKAGE_COUNTRIES_CURRENCIES_NUSPEC_FILE_PATH: HawkN.Iso.Countries.Currencies.nuspec
PACKAGE_COUNTRIES_CURRENCIES_ID: HawkN.Iso.Countries.Currencies

OUTPUT_NUGET_DIR: nuget-packages
NUGET_SOURCE_URL: https://api.nuget.org/v3/index.json
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
Expand Down Expand Up @@ -50,17 +56,6 @@ jobs:
echo "CURRENT_VERSION=$VERSION" >> $GITHUB_ENV
shell: bash

- name: Check if package (${{ env.PACKAGE_COUNTRIES_ID }}) version already exists on NuGet.org
id: check_nuget
run: |
PACKAGE_COUNTRIES_ID_LOWER=$(echo "${{ env.PACKAGE_COUNTRIES_ID }}" | tr '[:upper:]' '[:lower:]')
STATUS_CODE=$(curl -s -o /dev/null -I -w "%{http_code}" "https://api.nuget.org/v3-flatcontainer/${PACKAGE_COUNTRIES_ID_LOWER}/${{ env.CURRENT_VERSION }}/index.json")
if [ "$STATUS_CODE" -eq 200 ]; then
echo "Error: Version ${{ env.CURRENT_VERSION }} already exists on NuGet.org!"
exit 1
fi
shell: bash

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_NAME }}

Expand All @@ -75,6 +70,15 @@ jobs:
/p:Version=${{ env.CURRENT_VERSION }} \
/p:ContinuousIntegrationBuild=true \
--output ${{ env.OUTPUT_NUGET_DIR }}

- name: Build and Pack (HawkN.Iso.Countries.Currencies) (Extension)
run: |
dotnet pack ${{ env.PACKAGE_COUNTRIES_CURRENCIES_PROJECT_PATH }} \
--configuration Release \
/p:NuspecFile=${{ env.PACKAGE_COUNTRIES_CURRENCIES_NUSPEC_FILE_PATH }} \
/p:Version=${{ env.CURRENT_VERSION }} \
/p:ContinuousIntegrationBuild=true \
--output ${{ env.OUTPUT_NUGET_DIR }}

- name: Generate Release Changelog
uses: orhun/git-cliff-action@v4
Expand Down Expand Up @@ -111,7 +115,9 @@ jobs:
uses: softprops/action-gh-release@v2
with:
body_path: CHANGELOG_RELEASE.md
files: ${{ env.OUTPUT_NUGET_DIR }}/${{ env.PACKAGE_COUNTRIES_ID }}.${{ env.CURRENT_VERSION }}.nupkg
files: |
${{ env.OUTPUT_NUGET_DIR }}/${{ env.PACKAGE_COUNTRIES_ID }}.${{ env.CURRENT_VERSION }}.nupkg
${{ env.OUTPUT_NUGET_DIR }}/${{ env.PACKAGE_COUNTRIES_CURRENCIES_ID }}.${{ env.CURRENT_VERSION }}.nupkg
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -126,5 +132,28 @@ jobs:
run: |
dotnet nuget push "${{ env.OUTPUT_NUGET_DIR }}/${{ env.PACKAGE_COUNTRIES_ID }}.${{ env.CURRENT_VERSION }}.nupkg" \
--api-key ${{steps.login.outputs.NUGET_API_KEY}} \
--source ${{ env.NUGET_SOURCE_URL }}
shell: bash
--source ${{ env.NUGET_SOURCE_URL }} \
--skip-duplicate
shell: bash

- name: Publish package (HawkN.Iso.Countries.Currencies) to NuGet.org (Trusted Publishing)
run: |
dotnet nuget push "${{ env.OUTPUT_NUGET_DIR }}/${{ env.PACKAGE_COUNTRIES_CURRENCIES_ID }}.${{ env.CURRENT_VERSION }}.nupkg" \
--api-key ${{steps.login.outputs.NUGET_API_KEY}} \
--source ${{ env.NUGET_SOURCE_URL }} \
--skip-duplicate
shell: bash

- name: Publish package (HawkN.Iso.Countries) to GitHub packages
run: |
dotnet nuget push "${{ env.OUTPUT_NUGET_DIR }}/${{ env.PACKAGE_COUNTRIES_ID }}.${{ env.CURRENT_VERSION }}.nupkg" \
--source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \
--api-key ${{ secrets.GITHUB_TOKEN }} \
--skip-duplicate

- name: Publish package (HawkN.Iso.Countries.Currencies) to GitHub Packages
run: |
dotnet nuget push "${{ env.OUTPUT_NUGET_DIR }}/${{ env.PACKAGE_COUNTRIES_CURRENCIES_ID }}.${{ env.CURRENT_VERSION }}.nupkg" \
--source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \
--api-key ${{ secrets.GITHUB_TOKEN }} \
--skip-duplicate
18 changes: 14 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,15 @@ jobs:

env:
SOLUTION_NAME: src/HawkN.Iso.Countries.Solution.sln
PACKAGE_COUNTRY_PROJECT_PATH: src/packages/HawkN.Iso.Countries/HawkN.Iso.Countries.csproj
PACKAGE_COUNTRY_NUSPEC_FILE_PATH: HawkN.Iso.Countries.nuspec

# Iso.Countries package (Core)
PACKAGE_COUNTRIES_PROJECT_PATH: src/packages/HawkN.Iso.Countries/HawkN.Iso.Countries.csproj
PACKAGE_COUNTRIES_NUSPEC_FILE_PATH: HawkN.Iso.Countries.nuspec

# Iso.Countries.Currencies package (Extensions)
PACKAGE_COUNTRIES_CURRENCIES_PROJECT_PATH: src/packages/HawkN.Iso.Countries.Currencies/HawkN.Iso.Countries.Currencies.csproj
PACKAGE_COUNTRIES_CURRENCIES_NUSPEC_FILE_PATH: HawkN.Iso.Countries.Currencies.nuspec

OUTPUT_NUGET_DIR: nuget-packages
ARTIFACTS_DIR: artifacts
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
Expand Down Expand Up @@ -72,7 +79,7 @@ jobs:
- name: Extract project version (HawkN.Iso.Countries)
id: get_version
run: |
VERSION=$(sed -n 's/.*<\(VersionPrefix\|Version\)>\([^<]*\)<\/\1>.*/\2/p' ${{ env.PACKAGE_COUNTRY_PROJECT_PATH }} | head -n 1)
VERSION=$(sed -n 's/.*<\(VersionPrefix\|Version\)>\([^<]*\)<\/\1>.*/\2/p' ${{ env.PACKAGE_COUNTRIES_PROJECT_PATH }} | head -n 1)
if [ -z "$VERSION" ]; then
VERSION=$(date +%Y%m%d)
fi
Expand All @@ -81,7 +88,10 @@ jobs:
shell: bash

- name: Validate package creation (HawkN.Iso.Countries)
run: dotnet pack ${{ env.PACKAGE_COUNTRY_PROJECT_PATH }} /p:NuspecFile=${{ env.PACKAGE_COUNTRY_NUSPEC_FILE_PATH }} /p:ContinuousIntegrationBuild=true --configuration Release --no-build --output ${{ env.OUTPUT_NUGET_DIR }}
run: dotnet pack ${{ env.PACKAGE_COUNTRIES_PROJECT_PATH }} /p:NuspecFile=${{ env.PACKAGE_COUNTRIES_NUSPEC_FILE_PATH }} /p:ContinuousIntegrationBuild=true --configuration Release --no-build --output ${{ env.OUTPUT_NUGET_DIR }}

- name: Validate package creation (HawkN.Iso.Countries.Currencies)
run: dotnet pack ${{ env.PACKAGE_COUNTRIES_CURRENCIES_PROJECT_PATH }} /p:NuspecFile=${{ env.PACKAGE_COUNTRIES_CURRENCIES_NUSPEC_FILE_PATH }} /p:ContinuousIntegrationBuild=true --configuration Release --no-build --output ${{ env.OUTPUT_NUGET_DIR }}

- name: Generate CHANGELOG.md
uses: orhun/git-cliff-action@v4
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@ src/packages/HawkN.Iso.Countries/obj/**
src/packages/HawkN.Iso.Countries/bin/**
src/packages/HawkN.Iso.Countries.Generators/obj/**
src/packages/HawkN.Iso.Countries.Generators/bin/**
src/packages/HawkN.Iso.Countries.Currencies/obj/**
src/packages/HawkN.Iso.Countries.Currencies/bin/**
src/packages/HawkN.Iso.Countries.Currencies.Generators/obj/**
src/packages/HawkN.Iso.Countries.Currencies.Generators/bin/**
src/tests/HawkN.Iso.Countries.Tests/obj/**
src/tests/HawkN.Iso.Countries.Tests/bin/**
src/tests/HawkN.Iso.Countries.Generators.Tests/obj/**
src/tests/HawkN.Iso.Countries.Generators.Tests/bin/**
src/tests/HawkN.Iso.Countries.Currencies.Tests/obj/**
src/tests/HawkN.Iso.Countries.Currencies.Tests/bin/**
src/tests/HawkN.Iso.Countries.Currencies.Generators.Tests/obj/**
src/tests/HawkN.Iso.Countries.Currencies.Generators.Tests/bin/**
src/samples/HawkN.Iso.Countries.Samples.Console/obj/**
src/samples/HawkN.Iso.Countries.Samples.Console/bin/**
src/samples/HawkN.Iso.Countries.Samples.WebApi/obj/**
Expand Down
92 changes: 76 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,48 @@
[![Build Status](https://img.shields.io/github/actions/workflow/status/HawkN113/HawkN.Iso.Countries/ci.yml?label=Build&style=flat-square)](https://github.com/HawkN113/HawkN.Iso.Countries/actions/workflows/ci.yml)
[![CodeQL Security](https://img.shields.io/github/actions/workflow/status/HawkN113/HawkN.Iso.Countries/codeql-analysis.yml?label=CodeQL%20Security&style=flat-square)](https://github.com/HawkN113/HawkN.Iso.Countries/actions/workflows/codeql-analysis.yml)
[![NuGet](https://img.shields.io/nuget/v/HawkN.Iso.Countries?label=HawkN.Iso.Countries&color=blue&style=flat-square)](https://www.nuget.org/packages/HawkN.Iso.Countries/)
[![Downloads](https://img.shields.io/nuget/dt/HawkN.Iso.Countries?logo=nuget&label=Downloads&color=brightgreen&style=flat-square&cacheSeconds=3600)](https://www.nuget.org/packages/HawkN.Iso.Countries/)
<br />
[![Downloads](https://img.shields.io/nuget/dt/HawkN.Iso.Countries?logo=nuget&label=&color=brightgreen&style=flat-square&cacheSeconds=3600)](https://www.nuget.org/packages/HawkN.Iso.Countries/)
[![NuGet](https://img.shields.io/nuget/v/HawkN.Iso.Countries.Currencies?label=HawkN.Iso.Countries.Currencies&color=blue&style=flat-square)](https://www.nuget.org/packages/HawkN.Iso.Countries.Currencies/)
[![Downloads](https://img.shields.io/nuget/dt/HawkN.Iso.Countries.Currencies?logo=nuget&label=&color=brightgreen&style=flat-square&cacheSeconds=3600)](https://www.nuget.org/packages/HawkN.Iso.Countries.Currencies/)

</br>

[![NuGet Trusted Publishing](https://img.shields.io/badge/NuGet-Trusted_Publishing-blue?logo=nuget&logoColor=white&style=flat-square)](https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing)
[![Target Framework](https://img.shields.io/badge/.NET-8.0-512bd4?logo=dotnet&style=flat-square)](https://dotnet.microsoft.com/download)
[![NuGet Ribbon](https://img.shields.io/badge/NuGet-Small_Size-success?logo=nuget&style=flat-square)](https://www.nuget.org/packages/HawkN.Iso.Countries/)
[![GitHub license](https://img.shields.io/github/license/HawkN113/HawkN.Iso.Countries?label=License&style=flat-square)](https://github.com/HawkN113/HawkN.Iso.Countries/blob/main/LICENSE)
[![Data: Unicode CLDR](https://img.shields.io/badge/data-Unicode%20CLDR-lightgrey.svg?label=Data%20license&style=flat-square)](https://unicode.org/license.html)
[![Data: ODbL](https://img.shields.io/badge/data-ODbL%201.0-orange.svg?label=Data%20license&style=flat-square)](https://opendatacommons.org/licenses/odbl/1-0/)

| ![HawkN.Iso.Countries](docs/img/HawkN.Iso.Countries.png) | **HawkN.Iso.Countries** provides ISO 3166-1 country codes (Alpha-2, Alpha-3), official names, numeric codes (UN M49), and validation services. |
|--------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

---

## Features
## Features
### HawkN.Iso.Countries (Core)
- **Comprehensive Country List** – Provides an up-to-date `ISO 3166-1` country data with numeric codes from `UN M49`.
- **Strongly Typed Codes** – `TwoLetterCode` and `ThreeLetterCode` enums are generated at compile-time.
- **Multiple Search Methods** – Lookup by Alpha-2, Alpha-3, Numeric code, or Country Name.
- **Advanced Validation** – Built-in `ValidationResult` providing detailed feedback for code and name verification.
- **Ultra-Fast Performance** – O(1) lookups via pre-indexed static dictionaries.
- **Lightweight & Dependency-Free** – Compatible with .NET 8 and above.

### HawkN.Iso.Countries.Currencies (Extension)
- **Primary and Secondary Currencies** – Get the main currency or all secondary currencies of a country.
- **Fast Lookups** – O(1) lookups using pre-indexed dictionaries and HashSet for secondary currencies.
- **Currency Validation** – Check if a country uses a given currency.
- **Seamless Integration** – Built to work with `HawkN.Iso.Countries` types (`CountryCode.TwoLetterCode`).
- **Lightweight & Dependency-Free** – Compatible with .NET 8 and above.

---

## Packages

| Package | Description |
|---------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
| [![NuGet](https://img.shields.io/nuget/v/HawkN.Iso.Countries?label=HawkN.Iso.Countries&color=blue&style=flat-square)](https://www.nuget.org/packages/HawkN.Iso.Countries/) | Main library with country models, validation services, and generated ISO enums (Alpha-2, Alpha-3). |
| Package | Description |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [![NuGet](https://img.shields.io/nuget/v/HawkN.Iso.Countries?label=HawkN.Iso.Countries&color=blue&style=flat-square)](https://www.nuget.org/packages/HawkN.Iso.Countries/) | Main library with country models, validation services, and generated ISO enums (Alpha-2, Alpha-3). |
| [![NuGet](https://img.shields.io/nuget/v/HawkN.Iso.Countries.Currencies?label=HawkN.Iso.Countries.Currencies&color=blue&style=flat-square)](https://www.nuget.org/packages/HawkN.Iso.Countries.Currencies/) | Provides ISO-based mapping of primary and secondary currencies for countries.It allows you to quickly retrieve the main currency, secondary currencies, all currencies, or check if a currency is used by a specific country. |

---

Expand All @@ -41,17 +56,29 @@ dotnet add package HawkN.Iso.Countries
````

### Required Namespaces

#### HawkN.Iso.Countries (Core)

```csharp
using HawkN.Iso.Countries;
using HawkN.Iso.Countries.Abstractions;
using HawkN.Iso.Countries.Models;
using HawkN.Iso.Countries.Extensions;
```

#### HawkN.Iso.Countries.Currencies (Extension)
```csharp
using HawkN.Iso.Countries;
using HawkN.Iso.Currencies;
using HawkN.Iso.Countries.Currencies.Extensions;
```
---

### Usage Example

#### Registration
#### HawkN.Iso.Countries (Core)

##### Registration
Register the service in your DI container:
```csharp
using var host = Host.CreateDefaultBuilder(args)
Expand All @@ -61,7 +88,7 @@ using var host = Host.CreateDefaultBuilder(args)
})
.Build();
```
#### Retrieval & Search
##### Retrieval & Search
The service provides O(1) lookups via pre-indexed dictionaries and efficient partial searching.
```csharp
var service = scope.ServiceProvider.GetRequiredService<ICountryCodeService>();
Expand Down Expand Up @@ -98,7 +125,7 @@ var suggestions = service.SearchByName("United")
// Returns: ["United Arab Emirates", "United Kingdom", "United States", ...]
```

#### Validation
##### Validation
Check if a code or name is valid and retrieve the model simultaneously:
```csharp
// Validate by Code
Expand All @@ -115,7 +142,7 @@ if (!nameResult.IsValid)
Console.WriteLine($"Error: {nameResult.Reason}");
}
```
#### Fluent String Extensions
##### Fluent String Extensions
```csharp
string input = "FRA";

Expand All @@ -136,7 +163,7 @@ if (validationResult.IsValid)
}
```

#### Emoji Flags Support
##### Emoji Flags Support
The library provides an easy way to display country flags using standard Unicode Emoji. This works without any external image assets and is perfect for lightweight UI components.

```csharp
Expand All @@ -149,6 +176,31 @@ Console.WriteLine($"{flag} {country.Name}");
// Output: 🇫🇮 Finland
```

#### HawkN.Iso.Countries.Currencies (Extension)

##### Currency mapping
```csharp
var country = CountryCode.TwoLetterCode.CH;

// Primary currency
var primary = country.GetPrimaryCurrency(); // CHF

// Secondary currencies
var secondary = country.GetSecondaryCurrencies();

// All currencies
var all = country.GetAllCurrencies();

// Check if used
bool usesChe = country.IsCurrencyUsedByCountry(CurrencyCode.CHE);
```

##### Validation
```csharp
// Check if used the currency
bool usesChe = country.IsCurrencyUsedByCountry(CurrencyCode.CHE);
```

---

### Supported countries
Expand Down Expand Up @@ -421,11 +473,19 @@ Last updated at `25.12.2025`.

## License

### Code License
The source code of `HawkN.Iso.Countries` is licensed under the [MIT License](LICENSE).
### Code
This project’s source code is licensed under the [MIT License](LICENSE).

### Data
This project uses data derived from the following sources:

- **Unicode Common Locale Data Repository (CLDR)**
Licensed under the [Unicode License Agreement](https://unicode.org/license.html).

- Country data (`ISO 3166-1` and `UN M49` numeric codes) is sourced from the [UN Statistics Division – M49 standard](https://unstats.un.org/unsd/methodology/m49/overview)

### Data License
Country data (`ISO 3166-1` and `UN M49` numeric codes) is sourced from the [UN Statistics Division – M49 standard](https://unstats.un.org/unsd/methodology/m49/overview)
The above data licenses are **permissive and compatible with MIT-licensed code**
when used for reference and code generation.

---

Expand Down Expand Up @@ -453,4 +513,4 @@ If you want to contribute code, feel free to submit a Pull Request.
### References
- [ISO 3166 Standard](https://www.iso.org/iso-3166-country-codes.html)
- [UN Statistics Division – M49 standard](https://unstats.un.org/unsd/methodology/m49/overview)
- [GitHub Repository](https://github.com/HawkN113/HawkN.Iso.Countries)
- [GitHub Repository](https://github.com/HawkN113/HawkN.Iso.Countries)
Loading