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
55 changes: 55 additions & 0 deletions DATA_REQUIREMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Country Data Requirements
Guide for adding a new country to the static Region Identifier dataset. Each supported country needs three JSON files plus a small code change.

## 1) Country config – `country/ISO3.json`
- Keys:
- `zipCodeFormat`: `"numeric"` or `"alpha"`.
- `zipCodeLength`: integer, required for numeric formats to pad/compare values (USA=5, AUS=4, DEU=5, etc.). Omit for alpha formats (CAN/GBR/NLD).
- Example:
```json
{ "zipCodeFormat": "numeric", "zipCodeLength": 5 }
```

## 2) Region names – `regionNames/ISO3.json`
- Plain object mapping ISO 3166-2 region codes (same codes used in `regions/*.json`) to display names in English.
- Example (`regionNames/AUS.json`):
```json
{
"AU-NSW": "New South Wales",
"AU-VIC": "Victoria"
}
```

## 3) Region mappings – `regions/ISO3.json`
Array of objects that map postal codes to ISO 3166-2 region codes. Formats already used in the repo:
- **Numeric intervals** (inclusive): objects with `low`, `high`, `region`. Values can be numbers or numeric strings if leading zeros matter. Example (`regions/AUS.json`):
```json
{ "region": "AU-NSW", "low": 1000, "high": 1999 }
```
- **Explicit codes**: objects with `low`, `region`, no `high`. Every postal code (or prefix) must be listed. Use strings to preserve zeros. Examples:
- Belgium lists every 4-digit code (`regions/BEL.json`).
- Spain lists 5-digit codes as strings (`regions/ESP.json`).
- Mexico lists 2-digit prefixes (`regions/MEX.json`).
- CAN/GBR use alpha prefixes (e.g., `"low": "X0A"` or `"low": "AB"`).
- **Discrete lists**: objects with `region` and `list` (array of codes). Numeric countries store numbers; matching uses `zipCodeLength` to pad leading zeros before comparison. Examples: USA (`list` of 5-digit numbers), RUS (per-region lists).

Additional format notes:
- Files can mix formats if needed. Order matters because the lookup stops at the first match.
- Intervals and lists are treated as inclusive ranges; for alpha codes only exact equality is used.
- Keep codes as strings when leading zeros are significant.

## 4) Code wiring
- Add the ISO3 code to `availableCountries` in `lib/region.js`; otherwise the static data is ignored and Google is used.
- If the country needs custom postal-code normalization, extend `validateZipCode` (see existing cases for GBR, CAN, NLD, MEX).

## 5) Testing
- Add test cases to `test/tests.js` under `countriesPostalCodes`: include the country ISO/name, a representative zip, expected region code, and set `usingGoogle: false`.
- Run `npm test` to execute Mocha tests.
- Optional: verify pretty-name lookups via `getNameFromCountryAndRegion` using the `regionNames` file.

## 6) Data quality checklist
- Region codes must be valid ISO 3166-2 for the country.
- `regionNames` should be English and cover every region code present in `regions/ISO3.json`.
- Postal-code coverage should include territories and edge prefixes (e.g., US territories, Canadian northern prefixes).
- Prefer ascending ordering of `regions` entries to keep matching predictable.
- Avoid empty mappings; placeholders (e.g., empty lists) will yield null regions and fall back to Google.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Utility module that provides an easy way to identify the region of the country d
- MEX
- NLD
- RUS
- SRB
- SWE
- USA

Expand Down
4 changes: 4 additions & 0 deletions country/SRB.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"zipCodeFormat": "numeric",
"zipCodeLength": 5
}
1 change: 1 addition & 0 deletions lib/region.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const availableCountries = new Set([
'MEX',
'NLD',
'RUS',
'SRB',
'SWE',
'USA',
'AUS',
Expand Down
27 changes: 27 additions & 0 deletions regionNames/SRB.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"RS-00": "Belgrade",
"RS-01": "North Bačka",
"RS-02": "Central Banat",
"RS-03": "North Banat",
"RS-04": "South Banat",
"RS-05": "West Bačka",
"RS-06": "South Bačka",
"RS-07": "Srem",
"RS-08": "Mačva",
"RS-09": "Kolubara",
"RS-10": "Podunavlje",
"RS-11": "Braničevo",
"RS-12": "Šumadija",
"RS-13": "Pomoravlje",
"RS-14": "Bor",
"RS-15": "Zaječar",
"RS-16": "Zlatibor",
"RS-17": "Moravica",
"RS-18": "Raška",
"RS-19": "Rasina",
"RS-20": "Nišava",
"RS-21": "Toplica",
"RS-22": "Pirot",
"RS-23": "Jablanica",
"RS-24": "Pčinja"
}
245 changes: 245 additions & 0 deletions regions/SRB.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
[
{
"region": "RS-00",
"low": 11000,
"high": 11299
},
{
"region": "RS-00",
"list": [
11306,
11307,
11308,
11309,
11351
]
},
{
"region": "RS-10",
"low": 11300,
"high": 11305
},
{
"region": "RS-10",
"low": 11310,
"high": 11325
},
{
"region": "RS-10",
"low": 11328,
"high": 11329
},
{
"region": "RS-10",
"list": [
11420,
11423,
11425,
11431,
11432
]
},
{
"region": "RS-00",
"low": 11400,
"high": 11419
},
{
"region": "RS-00",
"low": 11426,
"high": 11427
},
{
"region": "RS-00",
"list": [
11430,
11433
]
},
{
"region": "RS-00",
"low": 11450,
"high": 11462
},
{
"region": "RS-00",
"low": 11500,
"high": 11599
},
{
"region": "RS-02",
"list": [
11467
]
},
{
"region": "RS-11",
"low": 12000,
"high": 12399
},
{
"region": "RS-09",
"low": 14000,
"high": 14299
},
{
"region": "RS-08",
"low": 15000,
"high": 15399
},
{
"region": "RS-23",
"low": 16000,
"high": 16299
},
{
"region": "RS-24",
"low": 17500,
"high": 17599
},
{
"region": "RS-15",
"low": 18230,
"high": 18237
},
{
"region": "RS-20",
"low": 18000,
"high": 18229
},
{
"region": "RS-20",
"low": 18238,
"high": 18269
},
{
"region": "RS-22",
"low": 18300,
"high": 18359
},
{
"region": "RS-20",
"low": 18360,
"high": 18369
},
{
"region": "RS-21",
"low": 18400,
"high": 18499
},
{
"region": "RS-15",
"low": 19000,
"high": 19099
},
{
"region": "RS-15",
"low": 19200,
"high": 19209
},
{
"region": "RS-15",
"low": 19214,
"high": 19214
},
{
"region": "RS-15",
"low": 19227,
"high": 19228
},
{
"region": "RS-14",
"low": 19210,
"high": 19229
},
{
"region": "RS-15",
"low": 19233,
"high": 19235
},
{
"region": "RS-14",
"low": 19250,
"high": 19259
},
{
"region": "RS-14",
"low": 19300,
"high": 19335
},
{
"region": "RS-15",
"low": 19340,
"high": 19378
},
{
"region": "RS-06",
"low": 21000,
"high": 21499
},
{
"region": "RS-07",
"low": 22000,
"high": 22499
},
{
"region": "RS-02",
"low": 23100,
"high": 23299
},
{
"region": "RS-03",
"low": 23300,
"high": 23399
},
{
"region": "RS-01",
"low": 24000,
"high": 24399
},
{
"region": "RS-03",
"low": 24400,
"high": 24499
},
{
"region": "RS-05",
"low": 25000,
"high": 25299
},
{
"region": "RS-04",
"low": 26000,
"high": 26399
},
{
"region": "RS-16",
"low": 31000,
"high": 31399
},
{
"region": "RS-17",
"low": 32000,
"high": 32399
},
{
"region": "RS-12",
"low": 34000,
"high": 34399
},
{
"region": "RS-13",
"low": 35000,
"high": 35299
},
{
"region": "RS-18",
"low": 36000,
"high": 36399
},
{
"region": "RS-19",
"low": 37000,
"high": 37299
}
]
21 changes: 21 additions & 0 deletions test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,27 @@ const countriesPostalCodes = {
result: 'MX-CMX',
usingGoogle: false,
}],
'Serbia': [{
name: 'SRB',
zip: '11000',
result: 'RS-00',
usingGoogle: false,
}, {
name: 'SRB',
zip: '11320',
result: 'RS-10',
usingGoogle: false,
}, {
name: 'SRB',
zip: '18230',
result: 'RS-15',
usingGoogle: false,
}, {
name: 'SRB',
zip: '24430',
result: 'RS-03',
usingGoogle: false,
}],
'United States': [{
name: 'USA',
zip: '972022239',
Expand Down