bd-geo-address 0.1.1
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/CHANGELOG.md +77 -0
- package/LICENSE +21 -0
- package/README.md +622 -0
- package/db/mongodb/bangladesh-address.json +29584 -0
- package/db/mysql/bangladesh-address.sql +3036 -0
- package/db/postgresql/bangladesh-address.sql +3034 -0
- package/db/sqlite/bangladesh-address.db +0 -0
- package/dist/index.d.mts +667 -0
- package/dist/index.d.ts +667 -0
- package/dist/index.js +29008 -0
- package/dist/index.mjs +28933 -0
- package/package.json +383 -0
package/README.md
ADDED
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
# bd-geo-address
|
|
2
|
+
|
|
3
|
+
> Bangladesh address library — division/district/upazila/thana lookup, FHIR geocode resolution, Bangla name support, postal codes, geolocation. Zero dependencies. Works on Node.js, React, Next.js, Vue, Angular, NestJS, Deno and Bun.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/bd-geo-address)
|
|
6
|
+
[](https://www.npmjs.com/package/bd-geo-address)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install bd-geo-address
|
|
16
|
+
# or
|
|
17
|
+
yarn add bd-geo-address
|
|
18
|
+
# or
|
|
19
|
+
pnpm add bd-geo-address
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
### Name-Based API
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { districtsOf, upazilasOf, isUpazila, isThana, DivisionName } from "bd-geo-address"
|
|
30
|
+
|
|
31
|
+
// All districts in Dhaka division
|
|
32
|
+
districtsOf(DivisionName.Dhaka)
|
|
33
|
+
// → ['Dhaka', 'Gazipur', 'Kishoreganj', 'Manikganj', 'Munshiganj', 'Narayanganj', ...]
|
|
34
|
+
|
|
35
|
+
// Upazilas of Tangail district
|
|
36
|
+
upazilasOf("Tangail")
|
|
37
|
+
// → [{ upazila: 'Tangail Sadar', upazilaBn: 'টাঙ্গাইল সদর', district: 'Tangail', ... }, ...]
|
|
38
|
+
|
|
39
|
+
// Correctly distinguishes upazilas from metropolitan thanas
|
|
40
|
+
isUpazila("Savar") // → true
|
|
41
|
+
isUpazila("Gulshan") // → false (Gulshan is a metropolitan thana)
|
|
42
|
+
isThana("Gulshan") // → true
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### FHIR Code API
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { resolveCode, toAddressString, toShortAddress } from "bd-geo-address"
|
|
49
|
+
|
|
50
|
+
// App stores FHIR geocode in the database, resolves at runtime
|
|
51
|
+
const address = resolveCode("30262530")
|
|
52
|
+
|
|
53
|
+
address?.formatted.en
|
|
54
|
+
// → 'Kafrul, Dhaka North City Corporation, Dhaka, Dhaka Division'
|
|
55
|
+
|
|
56
|
+
address?.formatted.bn
|
|
57
|
+
// → 'কাফরুল, ঢাকা উত্তর সিটি কর্পোরেশন, ঢাকা, ঢাকা বিভাগ'
|
|
58
|
+
|
|
59
|
+
toShortAddress("30262530") // → 'Kafrul, Dhaka'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## CommonJS Usage
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
const { allDivision, districtsOf, resolveCode, DivisionName } = require("bd-geo-address")
|
|
68
|
+
|
|
69
|
+
console.log(allDivision())
|
|
70
|
+
// → ['Dhaka', 'Chattogram', 'Mymensingh', 'Khulna', 'Rajshahi', 'Rangpur', 'Sylhet', 'Barisal']
|
|
71
|
+
|
|
72
|
+
console.log(resolveCode("30262530").formatted.short)
|
|
73
|
+
// → 'Kafrul, Dhaka'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## API Reference
|
|
79
|
+
|
|
80
|
+
### Division
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import {
|
|
84
|
+
allDivision, allDivisionBn,
|
|
85
|
+
divisionalDataOf, divisionalDataOfBn,
|
|
86
|
+
isValidDivision, isValidDivisionBn,
|
|
87
|
+
} from "bd-geo-address"
|
|
88
|
+
|
|
89
|
+
allDivision()
|
|
90
|
+
// → ['Dhaka', 'Chattogram', 'Mymensingh', 'Khulna', 'Rajshahi', 'Rangpur', 'Sylhet', 'Barisal']
|
|
91
|
+
|
|
92
|
+
allDivisionBn()
|
|
93
|
+
// → ['ঢাকা', 'চট্টগ্রাম', 'ময়মনসিংহ', 'খুলনা', 'রাজশাহী', 'রংপুর', 'সিলেট', 'বরিশাল']
|
|
94
|
+
|
|
95
|
+
divisionalDataOf("Sylhet")
|
|
96
|
+
// → { districts: ['Sylhet', 'Sunamganj', 'Habiganj', 'Moulvibazar'], upazilas: [...] }
|
|
97
|
+
|
|
98
|
+
divisionalDataOfBn("ঢাকা")
|
|
99
|
+
// → { districts: [...], upazilas: [...] }
|
|
100
|
+
|
|
101
|
+
isValidDivision("Dhaka") // → true
|
|
102
|
+
isValidDivision("InvalidName") // → false
|
|
103
|
+
isValidDivisionBn("ঢাকা") // → true
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### District
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import {
|
|
112
|
+
allDistricts, allDistrictsBn,
|
|
113
|
+
districtsOf, districtsOfBn,
|
|
114
|
+
isValidDistrict, isValidDistrictBn,
|
|
115
|
+
getDivisionOfDistrict, getDivisionOfDistrictBn,
|
|
116
|
+
} from "bd-geo-address"
|
|
117
|
+
|
|
118
|
+
allDistricts() // → all 64 district names in English
|
|
119
|
+
allDistrictsBn() // → all 64 district names in Bangla
|
|
120
|
+
|
|
121
|
+
districtsOf("Dhaka") // → ['Dhaka', 'Gazipur', 'Kishoreganj', ...]
|
|
122
|
+
districtsOfBn("ঢাকা") // → ['Dhaka', 'Gazipur', ...]
|
|
123
|
+
|
|
124
|
+
isValidDistrict("Tangail") // → true
|
|
125
|
+
isValidDistrict("Savar") // → false (upazila, not a district)
|
|
126
|
+
|
|
127
|
+
getDivisionOfDistrict("Tangail") // → 'Dhaka'
|
|
128
|
+
getDivisionOfDistrict("Cox's Bazar") // → 'Chattogram'
|
|
129
|
+
getDivisionOfDistrictBn("টাঙ্গাইল") // → 'Dhaka'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### Upazila
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import {
|
|
138
|
+
allUpazila, allUpazilaNames, allUpazilaNamesBn,
|
|
139
|
+
upazilasOf, upazilasOfBn,
|
|
140
|
+
upazilaNamesOf, upazilaNamesOfBn,
|
|
141
|
+
upazilasOfDivision, upazilasOfDivisionBn,
|
|
142
|
+
upazilaNamesOfDivision, upazilaNamesOfDivisionBn,
|
|
143
|
+
isUpazila, isUpazilabn,
|
|
144
|
+
getUpazila, getUpazilabn,
|
|
145
|
+
getDistrictOfUpazila, getDistrictOfUpazilabn,
|
|
146
|
+
upazilaData,
|
|
147
|
+
} from "bd-geo-address"
|
|
148
|
+
|
|
149
|
+
allUpazila() // → all 595 upazila names
|
|
150
|
+
|
|
151
|
+
upazilasOf("Tangail")
|
|
152
|
+
// → [{ upazila: 'Tangail Sadar', upazilaBn: 'টাঙ্গাইল সদর', district: 'Tangail', ... }, ...]
|
|
153
|
+
|
|
154
|
+
upazilaNamesOf("Tangail") // → ['Tangail Sadar', 'Basail', 'Bhuapur', ...]
|
|
155
|
+
upazilaNamesOfBn("টাঙ্গাইল") // → Bangla upazila names for Tangail
|
|
156
|
+
|
|
157
|
+
upazilasOfDivision("Sylhet") // → all upazilas in Sylhet division
|
|
158
|
+
|
|
159
|
+
isUpazila("Savar") // → true
|
|
160
|
+
isUpazila("Gulshan") // → false (metropolitan thana)
|
|
161
|
+
isUpazilabn("সাভার") // → true
|
|
162
|
+
|
|
163
|
+
getUpazila("Savar")
|
|
164
|
+
// → { upazila: 'Savar', upazilaBn: 'সাভার', district: 'Dhaka', division: 'Dhaka', ... }
|
|
165
|
+
|
|
166
|
+
// Disambiguate names that appear in multiple divisions:
|
|
167
|
+
getUpazila("Mohammadpur", "Khulna")
|
|
168
|
+
// → { upazila: 'Mohammadpur', district: 'Magura', division: 'Khulna', ... }
|
|
169
|
+
|
|
170
|
+
getDistrictOfUpazila("Savar") // → 'Dhaka'
|
|
171
|
+
getDistrictOfUpazilabn("সাভার") // → 'Dhaka'
|
|
172
|
+
|
|
173
|
+
upazilaData // raw Upazila[] constant — all 595 objects
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### Thana
|
|
179
|
+
|
|
180
|
+
The 26 metropolitan police thanas across Dhaka (15), Chattogram (6), Khulna (3), and Rajshahi (2).
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
import {
|
|
184
|
+
allThana, allThanaNames,
|
|
185
|
+
thanasOf, thanasOfBn,
|
|
186
|
+
thanaNamesOf, thanaNamesOfBn,
|
|
187
|
+
isThana, isThanabn,
|
|
188
|
+
getThana, getThanabn,
|
|
189
|
+
thanaData,
|
|
190
|
+
} from "bd-geo-address"
|
|
191
|
+
|
|
192
|
+
allThana() // → all 26 Thana objects
|
|
193
|
+
allThanaNames() // → ['Adabor', 'Badda', 'Banani', ..., 'Matihar']
|
|
194
|
+
|
|
195
|
+
thanasOf("Dhaka") // → 15 Dhaka thana objects
|
|
196
|
+
thanaNamesOf("Dhaka") // → ['Adabor', 'Badda', 'Banani', ...]
|
|
197
|
+
thanaNamesOfBn("ঢাকা") // → Bangla thana names
|
|
198
|
+
|
|
199
|
+
// isThana without district = true if it is a thana in any city
|
|
200
|
+
isThana("Gulshan") // → true
|
|
201
|
+
isThana("Kotwali", "Dhaka") // → true (disambiguate)
|
|
202
|
+
isThana("Kotwali", "Chattogram") // → true
|
|
203
|
+
isThanabn("গুলশান") // → true
|
|
204
|
+
|
|
205
|
+
getThana("Gulshan")
|
|
206
|
+
// → { thana: 'Gulshan', thanaBn: 'গুলশান', district: 'Dhaka', division: 'Dhaka', type: 'thana' }
|
|
207
|
+
|
|
208
|
+
getThana("Kotwali", "Chattogram")
|
|
209
|
+
// → { thana: 'Kotwali', district: 'Chattogram', ... }
|
|
210
|
+
|
|
211
|
+
thanaData // raw Thana[] constant — all 26 objects
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
| City | Thanas |
|
|
215
|
+
|------------|--------|
|
|
216
|
+
| Dhaka | 15 |
|
|
217
|
+
| Chattogram | 6 |
|
|
218
|
+
| Khulna | 3 |
|
|
219
|
+
| Rajshahi | 2 |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Search
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
import { searchLocations } from "bd-geo-address"
|
|
227
|
+
|
|
228
|
+
searchLocations("pur")
|
|
229
|
+
// → matches any division, district, upazila, or thana containing "pur"
|
|
230
|
+
// → [{ name: 'Rangpur', type: 'division' }, { name: 'Mirpur', type: 'thana', district: 'Dhaka' }, ...]
|
|
231
|
+
|
|
232
|
+
searchLocations("সিলেট")
|
|
233
|
+
// → Bangla search works the same way
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
### FHIR Code Resolution
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
import { resolveCode, resolveCodes } from "bd-geo-address"
|
|
242
|
+
|
|
243
|
+
resolveCode("30262530")
|
|
244
|
+
// {
|
|
245
|
+
// fhirCode: '30262530',
|
|
246
|
+
// thana: { code: '30262530', name: 'Kafrul', level: 'thana', ... },
|
|
247
|
+
// city_corp:{ name: 'Dhaka North City Corporation', ... },
|
|
248
|
+
// district: { name: 'Dhaka', ... },
|
|
249
|
+
// division: { name: 'Dhaka', ... },
|
|
250
|
+
// formatted: {
|
|
251
|
+
// en: 'Kafrul, Dhaka North City Corporation, Dhaka, Dhaka Division',
|
|
252
|
+
// bn: 'কাফরুল, ঢাকা উত্তর সিটি কর্পোরেশন, ঢাকা, ঢাকা বিভাগ',
|
|
253
|
+
// short: 'Kafrul, Dhaka',
|
|
254
|
+
// shortBn: 'কাফরুল, ঢাকা'
|
|
255
|
+
// },
|
|
256
|
+
// postal: { postalCode: '1216', postOfficeName: 'Kafrul', ... }
|
|
257
|
+
// }
|
|
258
|
+
|
|
259
|
+
resolveCodes(["30262530", "10040009", "INVALID"])
|
|
260
|
+
// → [BDAddress, BDAddress, null]
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### Address Formatting
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
import { toAddressString, toShortAddress, toCustomAddress } from "bd-geo-address"
|
|
269
|
+
|
|
270
|
+
toAddressString("30262530")
|
|
271
|
+
// → 'Kafrul, Dhaka North City Corporation, Dhaka, Dhaka Division'
|
|
272
|
+
|
|
273
|
+
toAddressString("30262530", "bn")
|
|
274
|
+
// → 'কাফরুল, ঢাকা উত্তর সিটি কর্পোরেশন, ঢাকা, ঢাকা বিভাগ'
|
|
275
|
+
|
|
276
|
+
toShortAddress("30262530") // → 'Kafrul, Dhaka'
|
|
277
|
+
toShortAddress("30262530", "bn") // → 'কাফরুল, ঢাকা'
|
|
278
|
+
|
|
279
|
+
toCustomAddress("30262530", ["thana", "district", "division"])
|
|
280
|
+
// → 'Kafrul, Dhaka, Dhaka Division'
|
|
281
|
+
|
|
282
|
+
toCustomAddress("30262530", ["thana", "district"], "bn")
|
|
283
|
+
// → 'কাফরুল, ঢাকা'
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### Lookup by FHIR Code
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
import { getByCode, findByName, findByNameBn, search, getAllByLevel } from "bd-geo-address"
|
|
292
|
+
|
|
293
|
+
getByCode("30") // → { code: '30', name: 'Dhaka', level: 'division', ... }
|
|
294
|
+
getByCode("INVALID") // → null
|
|
295
|
+
|
|
296
|
+
findByName("Dhaka") // → [division, district, ...]
|
|
297
|
+
findByName("Dhaka", "district") // → [{ name: 'Dhaka', level: 'district', ... }]
|
|
298
|
+
findByNameBn("ঢাকা") // → same but by Bangla name
|
|
299
|
+
|
|
300
|
+
search("Dhaka") // → English first, then Bangla fallback
|
|
301
|
+
|
|
302
|
+
getAllByLevel("division") // → all 8 division BDLocation objects
|
|
303
|
+
getAllByLevel("district") // → all 64 district BDLocation objects
|
|
304
|
+
getAllByLevel("upazila") // → all upazila BDLocation objects
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### Hierarchy
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
import { getParent, getChildren, getAllDescendants, getHierarchy } from "bd-geo-address"
|
|
313
|
+
|
|
314
|
+
getParent("1004") // → { code: '10', name: 'Barishal', level: 'division', ... }
|
|
315
|
+
getParent("10") // → null (divisions have no parent)
|
|
316
|
+
|
|
317
|
+
getChildren("10") // → all direct children of Barishal division
|
|
318
|
+
getAllDescendants("10") // → all locations under Barishal at any depth
|
|
319
|
+
getAllDescendants("10", "district") // → only districts
|
|
320
|
+
getAllDescendants("10", "upazila") // → only upazilas
|
|
321
|
+
|
|
322
|
+
getHierarchy("30262530")
|
|
323
|
+
// → BDAddress without the `formatted` field
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
### Validation
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
import { isValidCode, isValidName, isValidNameBn, isChildOf, getLevel } from "bd-geo-address"
|
|
332
|
+
|
|
333
|
+
isValidCode("30262530") // → true
|
|
334
|
+
isValidCode("INVALID") // → false
|
|
335
|
+
|
|
336
|
+
isValidName("Dhaka") // → true
|
|
337
|
+
isValidName("Dhaka", "division") // → true
|
|
338
|
+
isValidName("Dhaka", "upazila") // → false
|
|
339
|
+
isValidNameBn("ঢাকা", "division") // → true
|
|
340
|
+
|
|
341
|
+
isChildOf("10040009", "10") // → true (in Barishal division)
|
|
342
|
+
isChildOf("10040009", "1004") // → true (in Barguna district)
|
|
343
|
+
isChildOf("10040009", "30") // → false (not in Dhaka)
|
|
344
|
+
|
|
345
|
+
getLevel("10") // → 'division'
|
|
346
|
+
getLevel("1004") // → 'district'
|
|
347
|
+
getLevel("10040009") // → 'upazila'
|
|
348
|
+
getLevel("INVALID") // → null
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### Postal Codes
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
import {
|
|
357
|
+
getByPostalCode, getPostalCode, getPostalCodeBn,
|
|
358
|
+
getPostalCodesByArea, getFhirCodeFromPostal, resolvePostalCode,
|
|
359
|
+
} from "bd-geo-address"
|
|
360
|
+
|
|
361
|
+
getByPostalCode("8710")
|
|
362
|
+
// → { postalCode: '8710', postOfficeName: 'Amtali', upazilaName: 'Amtali', districtName: 'Barguna', ... }
|
|
363
|
+
|
|
364
|
+
getPostalCode("Amtali") // → '8710'
|
|
365
|
+
getFhirCodeFromPostal("8710") // → '10040009' (Amtali upazila FHIR code)
|
|
366
|
+
|
|
367
|
+
getPostalCodesByArea("Barguna", "district") // → all postal entries in Barguna district
|
|
368
|
+
getPostalCodesByArea("Barisal", "division") // → all postal entries in Barisal division
|
|
369
|
+
|
|
370
|
+
resolvePostalCode("8710")
|
|
371
|
+
// → full BDAddress for Amtali (same as resolveCode('10040009'))
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### Geolocation
|
|
377
|
+
|
|
378
|
+
> Coordinate data requires running `npm run build:coords` with HDX shapefiles.
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
import { getCoordinates, getNearestLocation, getLocationsWithinRadius } from "bd-geo-address"
|
|
382
|
+
|
|
383
|
+
getCoordinates("30") // → { lat: 23.8103, lng: 90.4125 }
|
|
384
|
+
getNearestLocation(23.7, 90.4) // → nearest BDLocation to the point
|
|
385
|
+
getNearestLocation(23.7, 90.4, "upazila") // → nearest upazila
|
|
386
|
+
getLocationsWithinRadius(23.7, 90.4, 50) // → all locations within 50 km
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## TypeScript Types
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
import type {
|
|
395
|
+
DivisionName, // enum
|
|
396
|
+
DistrictName, // string literal union of all 64 districts
|
|
397
|
+
LocationLevel, // 'division' | 'district' | 'city_corp' | 'municipality' | 'upazila' | 'thana' | 'union' | 'paurasava'
|
|
398
|
+
Upazila,
|
|
399
|
+
Thana,
|
|
400
|
+
SearchResult,
|
|
401
|
+
BDLocation,
|
|
402
|
+
BDAddress,
|
|
403
|
+
BDPostalEntry,
|
|
404
|
+
} from "bd-geo-address"
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**`BDAddress`** — resolved FHIR geocode result:
|
|
408
|
+
```ts
|
|
409
|
+
interface BDAddress {
|
|
410
|
+
fhirCode: string
|
|
411
|
+
division: BDLocation
|
|
412
|
+
district: BDLocation
|
|
413
|
+
city_corp?: BDLocation
|
|
414
|
+
municipality?: BDLocation
|
|
415
|
+
upazila?: BDLocation
|
|
416
|
+
thana?: BDLocation
|
|
417
|
+
union?: BDLocation
|
|
418
|
+
paurasava?: BDLocation
|
|
419
|
+
formatted: { en: string; bn: string; short: string; shortBn: string }
|
|
420
|
+
coordinates?: { lat: number; lng: number }
|
|
421
|
+
postal?: { postalCode: string; postOfficeName: string; postOfficeNameBn: string }
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**`DivisionName`** enum — use for IDE autocomplete:
|
|
426
|
+
```ts
|
|
427
|
+
import { DivisionName } from "bd-geo-address"
|
|
428
|
+
|
|
429
|
+
DivisionName.Dhaka // → 'Dhaka'
|
|
430
|
+
DivisionName.Chattogram // → 'Chattogram'
|
|
431
|
+
// Dhaka, Chattogram, Mymensingh, Khulna, Rajshahi, Rangpur, Sylhet, Barisal
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Framework Examples
|
|
437
|
+
|
|
438
|
+
### React — Cascade Location Picker
|
|
439
|
+
|
|
440
|
+
```tsx
|
|
441
|
+
import { useState } from "react"
|
|
442
|
+
import { allDivision, districtsOf, upazilasOf } from "bd-geo-address"
|
|
443
|
+
|
|
444
|
+
export function LocationPicker({ onChange }) {
|
|
445
|
+
const [division, setDivision] = useState("")
|
|
446
|
+
const [district, setDistrict] = useState("")
|
|
447
|
+
|
|
448
|
+
const districts = division ? districtsOf(division) : []
|
|
449
|
+
const upazilas = district ? upazilasOf(district) : []
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
<div>
|
|
453
|
+
<select onChange={e => { setDivision(e.target.value); setDistrict("") }}>
|
|
454
|
+
<option value="">Division</option>
|
|
455
|
+
{allDivision().map(d => <option key={d} value={d}>{d}</option>)}
|
|
456
|
+
</select>
|
|
457
|
+
<select onChange={e => setDistrict(e.target.value)} disabled={!division}>
|
|
458
|
+
<option value="">District</option>
|
|
459
|
+
{districts.map(d => <option key={d} value={d}>{d}</option>)}
|
|
460
|
+
</select>
|
|
461
|
+
<select onChange={e => onChange(e.target.value)} disabled={!district}>
|
|
462
|
+
<option value="">Upazila</option>
|
|
463
|
+
{upazilas.map(u => (
|
|
464
|
+
<option key={u.upazila} value={u.upazila}>{u.upazilaBn} ({u.upazila})</option>
|
|
465
|
+
))}
|
|
466
|
+
</select>
|
|
467
|
+
</div>
|
|
468
|
+
)
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Next.js — Server Component
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
import { resolveCode } from "bd-geo-address"
|
|
476
|
+
|
|
477
|
+
export default async function UserPage({ params }) {
|
|
478
|
+
const user = await fetchUser(params.id)
|
|
479
|
+
const address = resolveCode(user.locationCode)
|
|
480
|
+
|
|
481
|
+
return (
|
|
482
|
+
<div>
|
|
483
|
+
<p>{address?.formatted.en}</p>
|
|
484
|
+
<p>{address?.formatted.bn}</p>
|
|
485
|
+
</div>
|
|
486
|
+
)
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Vue 3
|
|
491
|
+
|
|
492
|
+
```vue
|
|
493
|
+
<template>
|
|
494
|
+
<select v-model="selectedDivision">
|
|
495
|
+
<option v-for="d in divisions" :key="d" :value="d">{{ d }}</option>
|
|
496
|
+
</select>
|
|
497
|
+
<select v-model="selectedDistrict">
|
|
498
|
+
<option v-for="d in districts" :key="d" :value="d">{{ d }}</option>
|
|
499
|
+
</select>
|
|
500
|
+
</template>
|
|
501
|
+
|
|
502
|
+
<script setup lang="ts">
|
|
503
|
+
import { ref, computed } from "vue"
|
|
504
|
+
import { allDivision, districtsOf } from "bd-geo-address"
|
|
505
|
+
|
|
506
|
+
const selectedDivision = ref("")
|
|
507
|
+
const divisions = allDivision()
|
|
508
|
+
const districts = computed(() =>
|
|
509
|
+
selectedDivision.value ? districtsOf(selectedDivision.value) : []
|
|
510
|
+
)
|
|
511
|
+
</script>
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Node.js / Express
|
|
515
|
+
|
|
516
|
+
```ts
|
|
517
|
+
import express from "express"
|
|
518
|
+
import { isValidCode, resolveCode, upazilasOf } from "bd-geo-address"
|
|
519
|
+
|
|
520
|
+
const app = express()
|
|
521
|
+
|
|
522
|
+
app.get("/address/:code", (req, res) => {
|
|
523
|
+
if (!isValidCode(req.params.code)) return res.status(400).json({ error: "Invalid geocode" })
|
|
524
|
+
res.json(resolveCode(req.params.code))
|
|
525
|
+
})
|
|
526
|
+
|
|
527
|
+
app.get("/upazilas/:district", (req, res) => {
|
|
528
|
+
res.json(upazilasOf(req.params.district))
|
|
529
|
+
})
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### NestJS
|
|
533
|
+
|
|
534
|
+
```ts
|
|
535
|
+
import { Injectable, BadRequestException } from "@nestjs/common"
|
|
536
|
+
import { resolveCode, isValidCode, BDAddress } from "bd-geo-address"
|
|
537
|
+
|
|
538
|
+
@Injectable()
|
|
539
|
+
export class LocationService {
|
|
540
|
+
resolve(fhirCode: string): BDAddress {
|
|
541
|
+
if (!isValidCode(fhirCode)) throw new BadRequestException("Invalid BD FHIR geocode")
|
|
542
|
+
return resolveCode(fhirCode)!
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
## Database Dumps
|
|
550
|
+
|
|
551
|
+
For PHP, Python, Java, Go, Ruby or any non-JS project, database dumps are included in the package.
|
|
552
|
+
|
|
553
|
+
| File | Format |
|
|
554
|
+
|------|--------|
|
|
555
|
+
| `db/mysql/bangladesh-address.sql` | MySQL 8.0+ |
|
|
556
|
+
| `db/postgresql/bangladesh-address.sql` | PostgreSQL 13+ |
|
|
557
|
+
| `db/sqlite/bangladesh-address.db` | SQLite 3 binary |
|
|
558
|
+
| `db/mongodb/bangladesh-address.json` | MongoDB insertMany-ready |
|
|
559
|
+
|
|
560
|
+
**Schema:**
|
|
561
|
+
- `divisions` — 8 rows (code, name, name_bn, lat, lng)
|
|
562
|
+
- `districts` — 64 rows (code, name, name_bn, division_code, lat, lng)
|
|
563
|
+
- `locations` — 1519 rows (all other FHIR locations: city corps, upazilas, unions, etc.)
|
|
564
|
+
- `thanas` — 26 metropolitan thanas
|
|
565
|
+
- `postal_codes` — 1343 postal code entries
|
|
566
|
+
|
|
567
|
+
**MySQL example:**
|
|
568
|
+
```bash
|
|
569
|
+
mysql -u root -p mydb < node_modules/bd-geo-address/db/mysql/bangladesh-address.sql
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
**PostgreSQL example:**
|
|
573
|
+
```bash
|
|
574
|
+
psql -U postgres mydb < node_modules/bd-geo-address/db/postgresql/bangladesh-address.sql
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
**SQLite example:**
|
|
578
|
+
```bash
|
|
579
|
+
cp node_modules/bd-geo-address/db/sqlite/bangladesh-address.db ./my-app.db
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
**MongoDB example:**
|
|
583
|
+
```js
|
|
584
|
+
const data = require("bd-geo-address/db/mongodb/bangladesh-address.json")
|
|
585
|
+
await db.collection("divisions").insertMany(data.divisions)
|
|
586
|
+
await db.collection("locations").insertMany(data.locations)
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## Data Coverage
|
|
592
|
+
|
|
593
|
+
| Level | Count |
|
|
594
|
+
|-------|-------|
|
|
595
|
+
| Divisions | 8 |
|
|
596
|
+
| Districts | 64 |
|
|
597
|
+
| City Corporations | 12 |
|
|
598
|
+
| Upazilas | 595 |
|
|
599
|
+
| Metropolitan Thanas | 26 |
|
|
600
|
+
| Unions | 848 |
|
|
601
|
+
| Postal codes | 1343 |
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Data Sources & Credits
|
|
606
|
+
|
|
607
|
+
- **FHIR geocodes** — [DGHS Bangladesh FHIR Server](https://fhir.dghs.gov.bd/core/CodeSystem-bd-geocodes.html)
|
|
608
|
+
- **Postal codes** — [saaiful/postcode-bd](https://github.com/saaiful/postcode-bd)
|
|
609
|
+
- **Coordinates** (optional) — [HDX Bangladesh Admin Boundaries](https://data.humdata.org/dataset/cod-ab-bgd)
|
|
610
|
+
- **Bangla names** — HDX shapefiles + manual curation
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## Contributing
|
|
615
|
+
|
|
616
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on fixing data, adding tests, or improving the API.
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
## License
|
|
621
|
+
|
|
622
|
+
[MIT](./LICENSE)
|