postcode-format-validator 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +90 -0
- package/package.json +48 -0
- package/src/formats.js +380 -0
- package/src/index.d.ts +35 -0
- package/src/index.js +71 -0
- package/src/index.mjs +6 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# postcode-format-validator
|
|
2
|
+
|
|
3
|
+
A lightweight, zero-dependency JavaScript library to validate postcodes / postal codes for **100+ countries and territories** based on their official format definitions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install postcode-format-validator
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
const { validatePostcode } = require('postcode-format-validator');
|
|
15
|
+
|
|
16
|
+
validatePostcode('US', '10001'); // true
|
|
17
|
+
validatePostcode('US', '1000'); // false
|
|
18
|
+
validatePostcode('GB', 'SW1A 1AA'); // true
|
|
19
|
+
validatePostcode('CA', 'K1A 0B1'); // true
|
|
20
|
+
validatePostcode('DE', '10115'); // true
|
|
21
|
+
validatePostcode('JP', '100-0001'); // true
|
|
22
|
+
validatePostcode('IN', '110001'); // true
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### ES Module
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import { validatePostcode } from 'postcode-format-validator';
|
|
29
|
+
|
|
30
|
+
validatePostcode('FR', '75001'); // true
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API
|
|
34
|
+
|
|
35
|
+
### `validatePostcode(countryCode, postcode)`
|
|
36
|
+
|
|
37
|
+
| Parameter | Type | Description |
|
|
38
|
+
|---------------|----------|------------------------------------------------------------------|
|
|
39
|
+
| `countryCode` | `string` | ISO 3166-1 alpha-2 country/region code (case-insensitive) |
|
|
40
|
+
| `postcode` | `string` | The postcode / postal code to validate |
|
|
41
|
+
|
|
42
|
+
**Returns:** `boolean` — `true` if the postcode matches at least one accepted format for the country; `false` otherwise (including unknown countries).
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### `getFormats(countryCode)`
|
|
47
|
+
|
|
48
|
+
| Parameter | Type | Description |
|
|
49
|
+
|---------------|----------|------------------------------------------------------------------|
|
|
50
|
+
| `countryCode` | `string` | ISO country/region code (case-insensitive) |
|
|
51
|
+
|
|
52
|
+
**Returns:** `Array<{ format, regex, significantFigures }>` or `null` if the country is not supported.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### `getSupportedCountries()`
|
|
57
|
+
|
|
58
|
+
**Returns:** `string[]` — Sorted array of all supported ISO country/region codes.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Format Legend
|
|
63
|
+
|
|
64
|
+
The format strings use the following convention:
|
|
65
|
+
|
|
66
|
+
| Character | Meaning |
|
|
67
|
+
|-----------|-----------------|
|
|
68
|
+
| `9` | Any digit (0-9) |
|
|
69
|
+
| `A` | Any letter (A-Z, a-z) |
|
|
70
|
+
| ` ` (space) | Literal space |
|
|
71
|
+
| `-` | Literal hyphen |
|
|
72
|
+
|
|
73
|
+
### Examples
|
|
74
|
+
|
|
75
|
+
| Country | Format(s) | Example |
|
|
76
|
+
|---------|----------------------------------|----------------|
|
|
77
|
+
| US | `99999`, `99999-9999` | `10001`, `10001-1234` |
|
|
78
|
+
| GB | `A9 9AA`, `A99 9AA`, `A9A 9AA`, `AA9 9AA`, `AA99 9AA`, `AA9A 9AA` | `SW1A 1AA` |
|
|
79
|
+
| CA | `A9A 9A`, `A9A 9A9` | `K1A 0B1` |
|
|
80
|
+
| DE | `99999` | `10115` |
|
|
81
|
+
| JP | `999-9999` | `100-0001` |
|
|
82
|
+
| BR | `99999`, `99999-999`, `99999999` | `01310-100` |
|
|
83
|
+
|
|
84
|
+
## Supported Countries
|
|
85
|
+
|
|
86
|
+
AD, AM, AR, AS, AT, AU, AZ, BA, BD, BE, BG, BN, BR, BY, CA, CH, CN, CO, CU, CY, CZ, DE, DK, DZ, EC, EE, ES, FI, FM, FO, FR, GB, GE, GF, GG, GL, GP, GR, GU, HR, HU, IC, ID, IL, IN, IS, IT, JE, JP, KG, KH, KR, KV, KZ, LI, LT, LU, LV, MA, MC, MD, ME, MG, MH, MK, MN, MP, MQ, MV, MX, MY, NC, NL, NO, NZ, PG, PH, PK, PL, PR, PT, PW, RE, RO, RS, RU, SE, SG, SH, SI, SK, SM, SZ, TH, TN, TR, TW, UA, US, UZ, VI, XY, YT, ZA
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "postcode-format-validator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Validate postcodes/postal codes for 100+ countries worldwide based on official format definitions",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"module": "src/index.mjs",
|
|
7
|
+
"types": "src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"require": "./src/index.js",
|
|
11
|
+
"import": "./src/index.mjs",
|
|
12
|
+
"types": "./src/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "node test/index.test.js"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"postcode",
|
|
20
|
+
"postal-code",
|
|
21
|
+
"zipcode",
|
|
22
|
+
"zip-code",
|
|
23
|
+
"validation",
|
|
24
|
+
"format",
|
|
25
|
+
"country",
|
|
26
|
+
"postal",
|
|
27
|
+
"address",
|
|
28
|
+
"verify"
|
|
29
|
+
],
|
|
30
|
+
"author": "",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": ""
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": ""
|
|
38
|
+
},
|
|
39
|
+
"homepage": "",
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=10"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"src/",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
]
|
|
48
|
+
}
|
package/src/formats.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postcode format definitions by country code.
|
|
3
|
+
*
|
|
4
|
+
* Format legend (from the CSV source):
|
|
5
|
+
* 9 → any digit [0-9]
|
|
6
|
+
* A → any letter [A-Za-z]
|
|
7
|
+
* All other characters (spaces, dashes) are matched literally.
|
|
8
|
+
*
|
|
9
|
+
* Each country maps to an array of { format, regex, significantFigures }.
|
|
10
|
+
* Multiple entries mean the country accepts more than one valid format.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Convert a format string like "A9A 9A9" into a RegExp.
|
|
17
|
+
* @param {string} fmt
|
|
18
|
+
* @returns {RegExp}
|
|
19
|
+
*/
|
|
20
|
+
function formatToRegex(fmt) {
|
|
21
|
+
let pattern = '^';
|
|
22
|
+
for (const ch of fmt) {
|
|
23
|
+
if (ch === '9') {
|
|
24
|
+
pattern += '[0-9]';
|
|
25
|
+
} else if (ch === 'A') {
|
|
26
|
+
pattern += '[A-Za-z]';
|
|
27
|
+
} else {
|
|
28
|
+
// Escape any regex-special characters (e.g. dash is safe, but be cautious)
|
|
29
|
+
pattern += ch.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
pattern += '$';
|
|
33
|
+
return new RegExp(pattern);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Raw format data derived from postcode_formats.csv.
|
|
38
|
+
* Key = ISO country/region code (upper-case).
|
|
39
|
+
* Value = array of accepted formats.
|
|
40
|
+
*/
|
|
41
|
+
const POSTCODE_FORMATS = {
|
|
42
|
+
AD: [
|
|
43
|
+
{ format: '99999', significantFigures: 5 },
|
|
44
|
+
{ format: 'AA999', significantFigures: 5 },
|
|
45
|
+
],
|
|
46
|
+
AM: [
|
|
47
|
+
{ format: '9999', significantFigures: 4 },
|
|
48
|
+
],
|
|
49
|
+
AR: [
|
|
50
|
+
{ format: '9999', significantFigures: 4 },
|
|
51
|
+
],
|
|
52
|
+
AS: [
|
|
53
|
+
{ format: '99999', significantFigures: 5 },
|
|
54
|
+
],
|
|
55
|
+
AT: [
|
|
56
|
+
{ format: '9999', significantFigures: 4 },
|
|
57
|
+
],
|
|
58
|
+
AU: [
|
|
59
|
+
{ format: '9999', significantFigures: 4 },
|
|
60
|
+
],
|
|
61
|
+
AZ: [
|
|
62
|
+
{ format: '999999', significantFigures: 6 },
|
|
63
|
+
{ format: '9999', significantFigures: 4 },
|
|
64
|
+
],
|
|
65
|
+
BA: [
|
|
66
|
+
{ format: '99999', significantFigures: 5 },
|
|
67
|
+
],
|
|
68
|
+
BD: [
|
|
69
|
+
{ format: '9999', significantFigures: 4 },
|
|
70
|
+
],
|
|
71
|
+
BE: [
|
|
72
|
+
{ format: '9999', significantFigures: 4 },
|
|
73
|
+
],
|
|
74
|
+
BG: [
|
|
75
|
+
{ format: '9999', significantFigures: 4 },
|
|
76
|
+
],
|
|
77
|
+
BN: [
|
|
78
|
+
{ format: 'AA9999', significantFigures: 6 },
|
|
79
|
+
],
|
|
80
|
+
BR: [
|
|
81
|
+
{ format: '99999', significantFigures: 5 },
|
|
82
|
+
{ format: '99999-999', significantFigures: 5 },
|
|
83
|
+
{ format: '99999999', significantFigures: 5 },
|
|
84
|
+
],
|
|
85
|
+
BY: [
|
|
86
|
+
{ format: '999999', significantFigures: 6 },
|
|
87
|
+
],
|
|
88
|
+
CA: [
|
|
89
|
+
{ format: 'A9A 9A', significantFigures: 6 },
|
|
90
|
+
{ format: 'A9A 9A9', significantFigures: 6 },
|
|
91
|
+
],
|
|
92
|
+
CH: [
|
|
93
|
+
{ format: '9999', significantFigures: 4 },
|
|
94
|
+
],
|
|
95
|
+
CN: [
|
|
96
|
+
{ format: '999999', significantFigures: 6 },
|
|
97
|
+
],
|
|
98
|
+
CO: [
|
|
99
|
+
{ format: '999999', significantFigures: 6 },
|
|
100
|
+
],
|
|
101
|
+
CU: [
|
|
102
|
+
{ format: '99999', significantFigures: 5 },
|
|
103
|
+
],
|
|
104
|
+
CY: [
|
|
105
|
+
{ format: '9999', significantFigures: 4 },
|
|
106
|
+
],
|
|
107
|
+
CZ: [
|
|
108
|
+
{ format: '999 99', significantFigures: 6 },
|
|
109
|
+
],
|
|
110
|
+
DE: [
|
|
111
|
+
{ format: '99999', significantFigures: 5 },
|
|
112
|
+
],
|
|
113
|
+
DK: [
|
|
114
|
+
{ format: '9999', significantFigures: 4 },
|
|
115
|
+
],
|
|
116
|
+
DZ: [
|
|
117
|
+
{ format: '99999', significantFigures: 5 },
|
|
118
|
+
],
|
|
119
|
+
EC: [
|
|
120
|
+
{ format: '999999', significantFigures: 6 },
|
|
121
|
+
],
|
|
122
|
+
EE: [
|
|
123
|
+
{ format: '99999', significantFigures: 5 },
|
|
124
|
+
],
|
|
125
|
+
ES: [
|
|
126
|
+
{ format: '99999', significantFigures: 5 },
|
|
127
|
+
],
|
|
128
|
+
FI: [
|
|
129
|
+
{ format: '99999', significantFigures: 5 },
|
|
130
|
+
],
|
|
131
|
+
FM: [
|
|
132
|
+
{ format: '99999', significantFigures: 5 },
|
|
133
|
+
],
|
|
134
|
+
FO: [
|
|
135
|
+
{ format: '999', significantFigures: 3 },
|
|
136
|
+
],
|
|
137
|
+
FR: [
|
|
138
|
+
{ format: '99999', significantFigures: 5 },
|
|
139
|
+
],
|
|
140
|
+
GB: [
|
|
141
|
+
{ format: 'AA9A 9AA', significantFigures: 6 },
|
|
142
|
+
{ format: 'A99 9AA', significantFigures: 5 },
|
|
143
|
+
{ format: 'A9A 9AA', significantFigures: 5 },
|
|
144
|
+
{ format: 'A9 9AA', significantFigures: 4 },
|
|
145
|
+
{ format: 'AA99 9AA', significantFigures: 6 },
|
|
146
|
+
{ format: 'AA9 9AA', significantFigures: 5 },
|
|
147
|
+
],
|
|
148
|
+
GE: [
|
|
149
|
+
{ format: '9999', significantFigures: 4 },
|
|
150
|
+
],
|
|
151
|
+
GF: [
|
|
152
|
+
{ format: '99999', significantFigures: 5 },
|
|
153
|
+
],
|
|
154
|
+
GG: [
|
|
155
|
+
{ format: 'AA99 9AA', significantFigures: 4 },
|
|
156
|
+
{ format: 'AA9 9AA', significantFigures: 3 },
|
|
157
|
+
],
|
|
158
|
+
GL: [
|
|
159
|
+
{ format: '9999', significantFigures: 4 },
|
|
160
|
+
],
|
|
161
|
+
GP: [
|
|
162
|
+
{ format: '99999', significantFigures: 5 },
|
|
163
|
+
],
|
|
164
|
+
GR: [
|
|
165
|
+
{ format: '999 99', significantFigures: 6 },
|
|
166
|
+
],
|
|
167
|
+
GU: [
|
|
168
|
+
{ format: '99999', significantFigures: 5 },
|
|
169
|
+
{ format: '99999-9999', significantFigures: 5 },
|
|
170
|
+
],
|
|
171
|
+
HR: [
|
|
172
|
+
{ format: '99999', significantFigures: 5 },
|
|
173
|
+
],
|
|
174
|
+
HU: [
|
|
175
|
+
{ format: '9999', significantFigures: 4 },
|
|
176
|
+
],
|
|
177
|
+
IC: [
|
|
178
|
+
{ format: '99999', significantFigures: 5 },
|
|
179
|
+
],
|
|
180
|
+
ID: [
|
|
181
|
+
{ format: '99999', significantFigures: 5 },
|
|
182
|
+
],
|
|
183
|
+
IL: [
|
|
184
|
+
{ format: '9999999', significantFigures: 7 },
|
|
185
|
+
],
|
|
186
|
+
IN: [
|
|
187
|
+
{ format: '999999', significantFigures: 6 },
|
|
188
|
+
],
|
|
189
|
+
IS: [
|
|
190
|
+
{ format: '999', significantFigures: 3 },
|
|
191
|
+
],
|
|
192
|
+
IT: [
|
|
193
|
+
{ format: '99999', significantFigures: 5 },
|
|
194
|
+
],
|
|
195
|
+
JE: [
|
|
196
|
+
{ format: 'AA9 9AA', significantFigures: 3 },
|
|
197
|
+
],
|
|
198
|
+
JP: [
|
|
199
|
+
{ format: '999-9999', significantFigures: 8 },
|
|
200
|
+
],
|
|
201
|
+
KG: [
|
|
202
|
+
{ format: '999999', significantFigures: 6 },
|
|
203
|
+
],
|
|
204
|
+
KH: [
|
|
205
|
+
{ format: '99999', significantFigures: 5 },
|
|
206
|
+
],
|
|
207
|
+
KR: [
|
|
208
|
+
{ format: '99999', significantFigures: 5 },
|
|
209
|
+
],
|
|
210
|
+
KV: [
|
|
211
|
+
{ format: '99999', significantFigures: 5 },
|
|
212
|
+
],
|
|
213
|
+
KZ: [
|
|
214
|
+
{ format: '999999', significantFigures: 6 },
|
|
215
|
+
],
|
|
216
|
+
LI: [
|
|
217
|
+
{ format: '9999', significantFigures: 4 },
|
|
218
|
+
],
|
|
219
|
+
LT: [
|
|
220
|
+
{ format: '99999', significantFigures: 5 },
|
|
221
|
+
],
|
|
222
|
+
LU: [
|
|
223
|
+
{ format: '9999', significantFigures: 4 },
|
|
224
|
+
],
|
|
225
|
+
LV: [
|
|
226
|
+
{ format: '9999', significantFigures: 4 },
|
|
227
|
+
],
|
|
228
|
+
MA: [
|
|
229
|
+
{ format: '99999', significantFigures: 5 },
|
|
230
|
+
],
|
|
231
|
+
MC: [
|
|
232
|
+
{ format: '99999', significantFigures: 5 },
|
|
233
|
+
],
|
|
234
|
+
MD: [
|
|
235
|
+
{ format: '9999', significantFigures: 4 },
|
|
236
|
+
],
|
|
237
|
+
ME: [
|
|
238
|
+
{ format: '99999', significantFigures: 5 },
|
|
239
|
+
],
|
|
240
|
+
MG: [
|
|
241
|
+
{ format: '999', significantFigures: 3 },
|
|
242
|
+
],
|
|
243
|
+
MH: [
|
|
244
|
+
{ format: '99999', significantFigures: 5 },
|
|
245
|
+
],
|
|
246
|
+
MK: [
|
|
247
|
+
{ format: '9999', significantFigures: 4 },
|
|
248
|
+
],
|
|
249
|
+
MN: [
|
|
250
|
+
{ format: '999999', significantFigures: 6 },
|
|
251
|
+
{ format: '99999', significantFigures: 5 },
|
|
252
|
+
],
|
|
253
|
+
MP: [
|
|
254
|
+
{ format: '99999', significantFigures: 5 },
|
|
255
|
+
],
|
|
256
|
+
MQ: [
|
|
257
|
+
{ format: '99999', significantFigures: 5 },
|
|
258
|
+
],
|
|
259
|
+
MV: [
|
|
260
|
+
{ format: '99999', significantFigures: 5 },
|
|
261
|
+
{ format: '9999', significantFigures: 4 },
|
|
262
|
+
],
|
|
263
|
+
MX: [
|
|
264
|
+
{ format: '99999', significantFigures: 5 },
|
|
265
|
+
],
|
|
266
|
+
MY: [
|
|
267
|
+
{ format: '99999', significantFigures: 5 },
|
|
268
|
+
],
|
|
269
|
+
NC: [
|
|
270
|
+
{ format: '99999', significantFigures: 5 },
|
|
271
|
+
],
|
|
272
|
+
NL: [
|
|
273
|
+
{ format: '9999', significantFigures: 4 },
|
|
274
|
+
{ format: '9999 AA', significantFigures: 4 },
|
|
275
|
+
],
|
|
276
|
+
NO: [
|
|
277
|
+
{ format: '9999', significantFigures: 4 },
|
|
278
|
+
],
|
|
279
|
+
NZ: [
|
|
280
|
+
{ format: '9999', significantFigures: 4 },
|
|
281
|
+
],
|
|
282
|
+
PG: [
|
|
283
|
+
{ format: '999', significantFigures: 3 },
|
|
284
|
+
],
|
|
285
|
+
PH: [
|
|
286
|
+
{ format: '9999', significantFigures: 4 },
|
|
287
|
+
],
|
|
288
|
+
PK: [
|
|
289
|
+
{ format: '99999', significantFigures: 5 },
|
|
290
|
+
],
|
|
291
|
+
PL: [
|
|
292
|
+
{ format: '99-999', significantFigures: 6 },
|
|
293
|
+
],
|
|
294
|
+
PR: [
|
|
295
|
+
{ format: '99999', significantFigures: 5 },
|
|
296
|
+
],
|
|
297
|
+
PT: [
|
|
298
|
+
{ format: '9999-999', significantFigures: 8 },
|
|
299
|
+
],
|
|
300
|
+
PW: [
|
|
301
|
+
{ format: '99999', significantFigures: 5 },
|
|
302
|
+
],
|
|
303
|
+
RE: [
|
|
304
|
+
{ format: '99999', significantFigures: 5 },
|
|
305
|
+
],
|
|
306
|
+
RO: [
|
|
307
|
+
{ format: '999999', significantFigures: 6 },
|
|
308
|
+
],
|
|
309
|
+
RS: [
|
|
310
|
+
{ format: '99999', significantFigures: 5 },
|
|
311
|
+
],
|
|
312
|
+
RU: [
|
|
313
|
+
{ format: '999999', significantFigures: 6 },
|
|
314
|
+
],
|
|
315
|
+
SE: [
|
|
316
|
+
{ format: '999 99', significantFigures: 6 },
|
|
317
|
+
],
|
|
318
|
+
SG: [
|
|
319
|
+
{ format: '999999', significantFigures: 6 },
|
|
320
|
+
],
|
|
321
|
+
SH: [
|
|
322
|
+
{ format: 'AAAA 9AA', significantFigures: 8 },
|
|
323
|
+
],
|
|
324
|
+
SI: [
|
|
325
|
+
{ format: '9999', significantFigures: 4 },
|
|
326
|
+
],
|
|
327
|
+
SK: [
|
|
328
|
+
{ format: '999 99', significantFigures: 6 },
|
|
329
|
+
],
|
|
330
|
+
SM: [
|
|
331
|
+
{ format: '99999', significantFigures: 5 },
|
|
332
|
+
],
|
|
333
|
+
SZ: [
|
|
334
|
+
{ format: 'A999', significantFigures: 4 },
|
|
335
|
+
],
|
|
336
|
+
TH: [
|
|
337
|
+
{ format: '99999', significantFigures: 5 },
|
|
338
|
+
],
|
|
339
|
+
TN: [
|
|
340
|
+
{ format: '9999', significantFigures: 4 },
|
|
341
|
+
],
|
|
342
|
+
TR: [
|
|
343
|
+
{ format: '99999', significantFigures: 5 },
|
|
344
|
+
],
|
|
345
|
+
TW: [
|
|
346
|
+
{ format: '999', significantFigures: 3 },
|
|
347
|
+
{ format: '99999', significantFigures: 5 },
|
|
348
|
+
],
|
|
349
|
+
UA: [
|
|
350
|
+
{ format: '99999', significantFigures: 5 },
|
|
351
|
+
],
|
|
352
|
+
US: [
|
|
353
|
+
{ format: '99999', significantFigures: 5 },
|
|
354
|
+
{ format: '99999-9999', significantFigures: 5 },
|
|
355
|
+
],
|
|
356
|
+
UZ: [
|
|
357
|
+
{ format: '999999', significantFigures: 6 },
|
|
358
|
+
],
|
|
359
|
+
VI: [
|
|
360
|
+
{ format: '99999', significantFigures: 5 },
|
|
361
|
+
],
|
|
362
|
+
XY: [
|
|
363
|
+
{ format: '99999', significantFigures: 5 },
|
|
364
|
+
],
|
|
365
|
+
YT: [
|
|
366
|
+
{ format: '99999', significantFigures: 5 },
|
|
367
|
+
],
|
|
368
|
+
ZA: [
|
|
369
|
+
{ format: '9999', significantFigures: 4 },
|
|
370
|
+
],
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
// Pre-compile regex patterns for each format entry
|
|
374
|
+
for (const code of Object.keys(POSTCODE_FORMATS)) {
|
|
375
|
+
for (const entry of POSTCODE_FORMATS[code]) {
|
|
376
|
+
entry.regex = formatToRegex(entry.format);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
module.exports = { POSTCODE_FORMATS, formatToRegex };
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface PostcodeFormat {
|
|
2
|
+
/** The format pattern (e.g. "99999", "A9A 9A9"). 9 = digit, A = letter. */
|
|
3
|
+
format: string;
|
|
4
|
+
/** Pre-compiled regex for the format. */
|
|
5
|
+
regex: RegExp;
|
|
6
|
+
/** Number of significant figures in the format. */
|
|
7
|
+
significantFigures: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Validate a postcode against the known formats for a given country.
|
|
12
|
+
*
|
|
13
|
+
* @param countryCode ISO 3166-1 alpha-2 country/region code (case-insensitive).
|
|
14
|
+
* @param postcode The postcode / postal code to validate.
|
|
15
|
+
* @returns `true` if the postcode matches at least one accepted format; `false` otherwise.
|
|
16
|
+
*/
|
|
17
|
+
export declare function validatePostcode(countryCode: string, postcode: string): boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get the accepted postcode format(s) for a country.
|
|
21
|
+
*
|
|
22
|
+
* @param countryCode ISO country/region code (case-insensitive).
|
|
23
|
+
* @returns Array of format objects, or `null` if the country is not supported.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getFormats(countryCode: string): PostcodeFormat[] | null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* List all supported country codes.
|
|
29
|
+
*
|
|
30
|
+
* @returns Sorted array of ISO country/region codes.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getSupportedCountries(): string[];
|
|
33
|
+
|
|
34
|
+
/** Raw format data keyed by country code. */
|
|
35
|
+
export declare const POSTCODE_FORMATS: Record<string, PostcodeFormat[]>;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* postcode-validator
|
|
3
|
+
*
|
|
4
|
+
* Validate postcodes / postal codes for 100+ countries based on their
|
|
5
|
+
* official format definitions.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const { validatePostcode, getFormats, getSupportedCountries } = require('postcode-validator');
|
|
9
|
+
*
|
|
10
|
+
* validatePostcode('US', '10001'); // true
|
|
11
|
+
* validatePostcode('US', '1000'); // false
|
|
12
|
+
* validatePostcode('GB', 'SW1A 1AA'); // true
|
|
13
|
+
* validatePostcode('CA', 'K1A 0B1'); // true
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
const { POSTCODE_FORMATS, formatToRegex } = require('./formats');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Validate a postcode against the known formats for a given country.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} countryCode ISO 3166-1 alpha-2 country/region code (case-insensitive).
|
|
24
|
+
* @param {string} postcode The postcode / postal code to validate.
|
|
25
|
+
* @returns {boolean} `true` if the postcode matches at least one accepted format
|
|
26
|
+
* for the country; `false` otherwise (including unknown countries).
|
|
27
|
+
*/
|
|
28
|
+
function validatePostcode(countryCode, postcode) {
|
|
29
|
+
if (typeof countryCode !== 'string' || typeof postcode !== 'string') {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const code = countryCode.trim().toUpperCase();
|
|
34
|
+
const trimmed = postcode.trim();
|
|
35
|
+
|
|
36
|
+
const formats = POSTCODE_FORMATS[code];
|
|
37
|
+
if (!formats) {
|
|
38
|
+
return false; // Country not in our database
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return formats.some((entry) => entry.regex.test(trimmed));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the accepted postcode format(s) for a country.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} countryCode ISO country/region code (case-insensitive).
|
|
48
|
+
* @returns {Array<{ format: string, regex: RegExp, significantFigures: number }>|null}
|
|
49
|
+
* Array of format objects, or `null` if the country is not supported.
|
|
50
|
+
*/
|
|
51
|
+
function getFormats(countryCode) {
|
|
52
|
+
if (typeof countryCode !== 'string') return null;
|
|
53
|
+
const code = countryCode.trim().toUpperCase();
|
|
54
|
+
return POSTCODE_FORMATS[code] || null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* List all supported country codes.
|
|
59
|
+
*
|
|
60
|
+
* @returns {string[]} Sorted array of ISO country/region codes.
|
|
61
|
+
*/
|
|
62
|
+
function getSupportedCountries() {
|
|
63
|
+
return Object.keys(POSTCODE_FORMATS).sort();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
validatePostcode,
|
|
68
|
+
getFormats,
|
|
69
|
+
getSupportedCountries,
|
|
70
|
+
POSTCODE_FORMATS,
|
|
71
|
+
};
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import mod from './index.js';
|
|
2
|
+
export const validatePostcode = mod.validatePostcode;
|
|
3
|
+
export const getFormats = mod.getFormats;
|
|
4
|
+
export const getSupportedCountries = mod.getSupportedCountries;
|
|
5
|
+
export const POSTCODE_FORMATS = mod.POSTCODE_FORMATS;
|
|
6
|
+
export default mod;
|