npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

address-bd

v0.0.8

Published

Complete Bangladesh address data package with 8 divisions, 64 districts, and 495 upazilas. Bilingual support, fuzzy search, and SOLID architecture.

Downloads

210

Readme

address-bd

A complete, production-ready Bangladesh address data package for TypeScript/JavaScript. Provides access to all 8 divisions, 64 districts, and 495 upazilas with bilingual English/Bengali support, fuzzy search, and SOLID architecture.

🌐 Live Demo: https://address-bd.netlify.app/

Table of Contents


Features

Complete Data Coverage - All 8 divisions, 64 districts, and 495 upazilas of Bangladesh

🌐 Bilingual Support - English and Bengali (বাংলা) names for all locations

🔍 Powerful Search - Fuzzy search with Levenshtein distance, autocomplete, and type-ahead

🏗️ SOLID Architecture - Clean, maintainable code following SOLID principles

🎯 Type-Safe - Full TypeScript support with comprehensive type definitions

Zero Runtime Dependencies - Minimal bundle size

🔧 Highly Configurable - Extensive search and formatting options

📍 Geo Metadata - Coordinates, area, population, and literacy data for divisions


Installation

Install the package using your preferred package manager:

npm install address-bd
yarn add address-bd
pnpm add address-bd
bun add address-bd

Quick Start

import bdAddress from 'address-bd';

// Get all divisions
const divisions = await bdAddress.getAllDivisions();
console.log(divisions);
// [{ id: 1, name: 'Dhaka', bnName: 'ঢাকা', slug: 'dhaka', coordinates: {...}, ... }, ...]

// Search for locations
const results = await bdAddress.search('dhaka');
console.log(results);
// { divisions: [{item, score, matchedField}], districts: [...], upazilas: [...] }

// Get full address hierarchy
const address = await bdAddress.getFullAddress(1);
console.log(address.formatEnglish()); // "Savar, Dhaka, Dhaka"
console.log(address.formatBengali()); // "সাভার, ঢাকা, ঢাকা"

Configuration

Search Configuration

Customize default search behavior:

import { createSearchConfig, DEFAULT_SEARCH_CONFIG } from 'address-bd';

// View defaults
console.log(DEFAULT_SEARCH_CONFIG);
// { includeEnglish: true, includeBengali: true, includeSlug: true,
//   limit: 10, threshold: 0.3, caseSensitive: false,
//   types: ['division', 'district', 'upazila'] }

// Create custom configuration
const searchConfig = createSearchConfig({
    defaultLimit: 20, // More results
    defaultThreshold: 0.4, // Higher typo tolerance
    includeEnglish: true,
    includeBengali: true,
    includeSlug: false, // Exclude slug from search
    caseSensitive: false,
});

Address Configuration

Configure package-level settings:

import { getAddressConfig, DEFAULT_ADDRESS_CONFIG } from 'address-bd';

const addressConfig = getAddressConfig({
    debug: true, // Enable debug logging
    defaultLanguage: 'bn', // Default to Bengali
    defaultSeparator: ' - ', // Custom separator
});

Search Options (Per-Search)

Override options for individual searches:

import bdAddress from 'address-bd';

// Basic search with options
const results = await bdAddress.search('dhaka', {
    includeEnglish: true,
    includeBengali: true,
    includeSlug: true,
    limit: 10, // Max results per category
    threshold: 0.3, // Minimum similarity (0-1)
    caseSensitive: false,
    types: ['division', 'district', 'upazila'],
});

// Search only specific types
const divisionsOnly = await bdAddress.search('dhaka', {
    types: ['division'], // Only search divisions
});

// Bengali-only search
const bengali = await bdAddress.searchBengali('ঢাকা', { limit: 5 });

// Fuzzy search with higher typo tolerance
const fuzzy = await bdAddress.fuzzySearch('daka', { threshold: 0.4 });

Format Options

Customize address formatting:

import bdAddress from 'address-bd';

const address = await bdAddress.getFullAddress(1);

// Full control over formatting
const custom = bdAddress.formatAddress(address, {
    language: 'bn', // 'en' or 'bn'
    separator: ' | ', // Custom separator
    includeUpazila: true,
    includeDistrict: true,
    includeDivision: true,
});

// Partial address (exclude upazila)
const partial = bdAddress.formatAddress(address, {
    language: 'en',
    includeUpazila: false, // Skip upazila
    includeDistrict: true,
    includeDivision: true,
});

// Shorthand methods
bdAddress.formatAddressEnglish(address);
bdAddress.formatAddressBengali(address);

Complete Usage Examples

Data Access

import bdAddress from 'address-bd';

// Get all locations
const divisions = await bdAddress.getAllDivisions(); // 8 divisions
const districts = await bdAddress.getAllDistricts(); // 64 districts
const upazilas = await bdAddress.getAllUpazilas(); // 495 upazilas

// Find by ID
const division = await bdAddress.getDivisionById(1);
const district = await bdAddress.getDistrictById(1);
const upazila = await bdAddress.getUpazilaById(1);

// Find by slug (URL-friendly identifier)
const dhaka = await bdAddress.getDivisionBySlug('dhaka');
const sylhet = await bdAddress.getDistrictBySlug('sylhet');
const savar = await bdAddress.getUpazilaBySlug('savar');

// Find by name (works with both English and Bengali)
const div1 = await bdAddress.getDivisionByName('Dhaka');
const div2 = await bdAddress.getDivisionByName('ঢাকা');

// Access location properties
console.log(division.id); // 1
console.log(division.name); // 'Dhaka'
console.log(division.bnName); // 'ঢাকা'
console.log(division.slug); // 'dhaka'
console.log(division.coordinates); // { latitude: 23.7104, longitude: 90.4074 }
console.log(division.area); // 20143 (sq km)
console.log(division.population); // 161029969
console.log(division.literacy); // 70.2 (%)

Hierarchical Queries

import bdAddress from 'address-bd';

// Get districts in a division (by ID)
const dhakaDistricts = await bdAddress.getDistrictsByDivision(1);

// Get districts in a division (by slug)
const dhakaDistricts2 = await bdAddress.getDistrictsByDivisionSlug('dhaka');

// Get upazilas in a district (by ID)
const savarUpazilas = await bdAddress.getUpazilasByDistrict(1);

// Get upazilas in a district (by slug)
const savarUpazilas2 = await bdAddress.getUpazilasByDistrictSlug('savar');

// Get ALL upazilas in a division
const allDhakaUpazilas = await bdAddress.getUpazilasByDivision(1);

// Navigate up the hierarchy
const division = await bdAddress.getDivisionOfDistrict(1); // Get district's division
const district = await bdAddress.getDistrictOfUpazila(1); // Get upazila's district

// Get complete address hierarchy for an upazila
const fullAddress = await bdAddress.getFullAddress(1);
console.log(fullAddress.division); // Division object
console.log(fullAddress.district); // District object
console.log(fullAddress.upazila); // Upazila object

// Get full address by slug
const fullAddress2 = await bdAddress.getFullAddressBySlug('savar');

Search

import bdAddress from 'address-bd';

// Basic search - searches across all types
const results = await bdAddress.search('dhaka');
console.log(results);
// {
//   divisions: [{ item: Division, score: 1, matchedField: 'name' }],
//   districts: [{ item: District, score: 0.9, matchedField: 'name' }],
//   upazilas: [{ item: Upazila, score: 0.85, matchedField: 'name' }]
// }

// Quick search - returns first match only
const firstMatch = await bdAddress.quickSearch('dhaka');
if (firstMatch) {
    console.log(firstMatch.name); // 'Dhaka'
}

// Search specific types
const divisions = await bdAddress.searchDivisions('dhaka');
const districts = await bdAddress.searchDistricts('dhaka');
const upazilas = await bdAddress.searchUpazilas('dhaka');

// Fuzzy search - higher typo tolerance
const fuzzy = await bdAddress.fuzzySearch('daka'); // Finds "Dhaka"
const fuzzy2 = await bdAddress.fuzzySearch('daka', { threshold: 0.5 });

// Autocomplete - for dropdowns/typeahead
const suggestions = await bdAddress.autocomplete('dh');
// [{ name: 'Dhaka', bnName: 'ঢাকা', type: 'division', item: {...} }, ...]

// Language-specific searches
const english = await bdAddress.searchEnglish('dhaka');
const bengali = await bdAddress.searchBengali('ঢাকা');

// Advanced search with custom options
const custom = await bdAddress.search('dhaka', {
    includeEnglish: true,
    includeBengali: false, // English only
    includeSlug: false,
    limit: 5, // Fewer results
    threshold: 0.5, // Higher confidence
    types: ['district', 'upazila'], // Exclude divisions
});

// Access search result details
const searchResults = await bdAddress.search('dhaka');
searchResults.divisions.forEach((result) => {
    console.log(result.item.name); // 'Dhaka'
    console.log(result.score); // 1.0 (perfect match)
    console.log(result.matchedField); // 'name'
});

Address Formatting

import bdAddress from 'address-bd';

const address = await bdAddress.getFullAddress(1);

// English formatting
console.log(bdAddress.formatAddressEnglish(address));
// "Savar, Dhaka, Dhaka"

// Bengali formatting
console.log(bdAddress.formatAddressBengali(address));
// "সাভার, ঢাকা, ঢাকা"

// Custom formatting with options
const formatted = bdAddress.formatAddress(address, {
    language: 'en',
    separator: ' | ',
    includeUpazila: true,
    includeDistrict: true,
    includeDivision: true,
});
// "Savar | Dhaka | Dhaka"

// Partial address formats
const noUpazila = bdAddress.formatAddress(address, {
    language: 'en',
    includeUpazila: false,
    includeDistrict: true,
    includeDivision: true,
});
// "Dhaka, Dhaka"

const districtOnly = bdAddress.formatAddress(address, {
    language: 'bn',
    includeUpazila: false,
    includeDistrict: true,
    includeDivision: false,
});
// "ঢাকা"

// Using FullAddress entity methods directly
import { FullAddress } from 'address-bd';
const address2 = await bdAddress.getFullAddress(1);

address2.format({ language: 'en', separator: ', ' });
address2.formatEnglish();
address2.formatBengali();

Validation

import bdAddress from 'address-bd';

// Validate location IDs
const isValidDiv = await bdAddress.isValidDivision(1); // true
const isValidDiv2 = await bdAddress.isValidDivision(100); // false
const isValidDist = await bdAddress.isValidDistrict(1);
const isValidUp = await bdAddress.isValidUpazila(1);

// Validate hierarchical relationships
const inDiv = await bdAddress.isDistrictInDivision(1, 1);
// Is district #1 in division #1? => true

const inDist = await bdAddress.isUpazilaInDistrict(1, 1);
// Is upazila #1 in district #1? => true

const inDiv2 = await bdAddress.isUpazilaInDivision(1, 1);
// Is upazila #1 in division #1? => true

// Real-world validation example
async function validateAddress(upazilaId: number, divisionId: number) {
    const isValidUpazila = await bdAddress.isValidUpazila(upazilaId);
    if (!isValidUpazila) {
        throw new Error('Invalid upazila ID');
    }

    const inCorrectDivision = await bdAddress.isUpazilaInDivision(
        upazilaId,
        divisionId
    );
    if (!inCorrectDivision) {
        throw new Error('Upazila does not belong to the specified division');
    }

    return true;
}

Statistics

import bdAddress from 'address-bd';

// Get overall statistics
const stats = await bdAddress.getStats();
console.log(stats);
// {
//   totalDivisions: 8,
//   totalDistricts: 64,
//   totalUpazilas: 495,
//   divisionDistrictMap: { 1: 13, 2: 11, 3: 9, ... },
//   districtUpazilaMap: { 1: 12, 2: 14, ... }
// }

// Count operations
const districtCount = await bdAddress.getDistrictCount(1);
// How many districts in division #1? => 13

const upazilaCount = await bdAddress.getUpazilaCount(1);
// How many upazilas in district #1? => 12

const upazilaCountByDiv = await bdAddress.getUpazilaCountByDivision(1);
// How many total upazilas in division #1? => ~120

// Use stats for pagination
const districtsInDhaka = await bdAddress.getDistrictsByDivision(1);
const totalDistricts = districtsInDhaka.length;
const pageSize = 10;
const totalPages = Math.ceil(totalDistricts / pageSize);

UI Helpers

import bdAddress from 'address-bd';

// Get names for dropdowns/arrays
const divisionNamesEn = await bdAddress.getDivisionNames('en');
// ['Dhaka', 'Chattogram', 'Sylhet', 'Rajshahi', 'Khulna', 'Barishal', 'Rangpur', 'Mymensingh']

const divisionNamesBn = await bdAddress.getDivisionNames('bn');
// ['ঢাকা', 'চট্টগ্রাম', 'সিলেট', 'রাজশাহী', 'খুলনা', 'বরিশাল', 'রংপুর', 'ময়মনসিংহ']

const districtNames = await bdAddress.getDistrictNames('en');
const upazilaNames = await bdAddress.getUpazilaNames('bn');

// Get options for select dropdowns
const divisionOptions = await bdAddress.getDivisionOptions();
// [{ value: 'dhaka', label: 'Dhaka', labelBn: 'ঢাকা' }, ...]

const districtOptions = await bdAddress.getDistrictOptions(1); // Filter by division
const upazilaOptions = await bdAddress.getUpazilaOptions(1); // Filter by district

const allDistrictOptions = await bdAddress.getDistrictOptions(); // All districts

Common Use Cases

Building Cascading Dropdowns

import bdAddress from 'address-bd';

// Frontend framework example (React)
async function LocationSelector() {
  const [selectedDivision, setSelectedDivision] = useState(null);
  const [selectedDistrict, setSelectedDistrict] = useState(null);
  const [selectedUpazila, setSelectedUpazila] = useState(null);

  // When division changes, load its districts
  const handleDivisionChange = async (divisionSlug) => {
    setSelectedDivision(divisionSlug);
    const districts = await bdAddress.getDistrictsByDivisionSlug(divisionSlug);
    return districts.map(d => ({ value: d.slug, label: d.name }));
  };

  // When district changes, load its upazilas
  const handleDistrictChange = async (districtSlug) => {
    setSelectedDistrict(districtSlug);
    const upazilas = await bdAddress.getUpazilasByDistrictSlug(districtSlug);
    return upazilas.map(u => ({ value: u.slug, label: u.name }));
  };

  // Get initial divisions
  const divisions = await bdAddress.getDivisionOptions();

  return (
    <select onChange={(e) => handleDivisionChange(e.target.value)}>
      {divisions.map(d => <option value={d.value}>{d.label}</option>)}
    </select>
  );
}

Type-Safe Enums

import {
    BangladeshDivision,
    BangladeshDistrict,
    BangladeshUpazila,
} from 'address-bd';

// Use enums for type-safe code
function processDivision(division: BangladeshDivision) {
    if (division === BangladeshDivision.DHAKA) {
        console.log('Processing Dhaka division');
    }
}

// Store in database with type safety
const userDivision = BangladeshDivision.DHAKA; // Type: 'dhaka'
const userDistrict = BangladeshDistrict.GAZIPUR; // Type: 'gazipur'

// Convert enum to search
const dhakaInfo = await bdAddress.getDivisionBySlug(BangladeshDivision.DHAKA);

Working with Coordinates & Metadata

import bdAddress from 'address-bd';

const division = await bdAddress.getDivisionById(1);

// Access coordinates
if (division.coordinates) {
    console.log(`Latitude: ${division.coordinates.latitude}`);
    console.log(`Longitude: ${division.coordinates.longitude}`);

    // Calculate distance (example with a distance library)
    // const distance = calculateDistance(..., division.coordinates);
}

// Access metadata
console.log(`Area: ${division.area} sq km`);
console.log(`Population: ${division.population?.toLocaleString()}`);
console.log(`Literacy: ${division.literacy}%`);

// Filter by criteria
const allDivisions = await bdAddress.getAllDivisions();
const largeDivisions = allDivisions.filter((d) => d.area && d.area > 20000);
const populousDivisions = allDivisions.filter(
    (d) => d.population && d.population > 30000000
);

Handling Search Results

import bdAddress from 'address-bd';

const results = await bdAddress.search('dhaka');

// Process search results with scores
results.divisions.forEach((result) => {
    console.log(`Match: ${result.item.name}`);
    console.log(`Score: ${(result.score * 100).toFixed(1)}%`);
    console.log(`Matched in: ${result.matchedField}`);

    if (result.score > 0.9) {
        console.log('High confidence match!');
    } else if (result.score > 0.7) {
        console.log('Medium confidence match');
    }
});

// Get best match across all types
const allMatches = [
    ...results.divisions,
    ...results.districts,
    ...results.upazilas,
].sort((a, b) => b.score - a.score);

if (allMatches.length > 0) {
    const bestMatch = allMatches[0];
    console.log(`Best match: ${bestMatch.item.name} (${bestMatch.score})`);
}

Null Handling & Error Patterns

import bdAddress from 'address-bd';

// Safe navigation with null checks
const division = await bdAddress.getDivisionById(999);
if (division) {
    console.log(division.name);
} else {
    console.log('Division not found');
}

// Using optional chaining
const districtName = (await bdAddress.getDistrictById(1))?.name ?? 'Unknown';

// Validate before using
async function getSafeAddress(upazilaId: number) {
    const upazila = await bdAddress.getUpazilaById(upazilaId);

    if (!upazila) {
        throw new Error(`Upazila with ID ${upazilaId} not found`);
    }

    const district = await bdAddress.getDistrictById(upazila.districtId);
    if (!district) {
        throw new Error(`District not found for upazila ${upazilaId}`);
    }

    const division = await bdAddress.getDivisionById(district.divisionId);
    if (!division) {
        throw new Error(`Division not found for district ${district.id}`);
    }

    return { upazila, district, division };
}

// Usage with try-catch
try {
    const address = await getSafeAddress(1);
    console.log('Address is valid!');
} catch (error) {
    console.error('Invalid address:', error.message);
}

Entity Methods

import { Division, District, Upazila, FullAddress } from 'address-bd';

// Working with entities
const divisionData = { id: 1, name: 'Dhaka', bnName: 'ঢাকা', slug: 'dhaka' };
const division = Division.fromObject(divisionData);

// Value equality check
const div1 = await bdAddress.getDivisionById(1);
const div2 = Division.fromObject({ ...div1!.toObject() });
console.log(div1.equals(div2)); // true

// Convert to/from JSON
const json = division.toJSON();
const restored = Division.fromJSON(json);

// Convert to plain object
const plain = division.toObject();

// FullAddress entity methods
const address = await bdAddress.getFullAddress(1);
console.log(address.toString()); // "Savar, Dhaka, Dhaka"
console.log(address.formatEnglish()); // "Savar, Dhaka, Dhaka"
console.log(address.formatBengali()); // "সাভার, ঢাকা, ঢাকা"
console.log(address.equals(address)); // true

// Build FullAddress manually
const d = await bdAddress.getDivisionById(1);
const dist = await bdAddress.getDistrictById(1);
const u = await bdAddress.getUpazilaById(1);
if (d && dist && u) {
    const customAddress = FullAddress.create(d, dist, u);
}

API Reference

Data Access Methods

| Method | Returns | Description | | ------------------------- | --------------------------- | ------------------------ | | getAllDivisions() | Promise<Division[]> | All 8 divisions | | getAllDistricts() | Promise<District[]> | All 64 districts | | getAllUpazilas() | Promise<Upazila[]> | All 495 upazilas | | getDivisionById(id) | Promise<Division \| null> | Division by ID | | getDivisionBySlug(slug) | Promise<Division \| null> | Division by slug | | getDivisionByName(name) | Promise<Division \| null> | Division by name (EN/BN) | | getDistrictById(id) | Promise<District \| null> | District by ID | | getDistrictBySlug(slug) | Promise<District \| null> | District by slug | | getDistrictByName(name) | Promise<District \| null> | District by name (EN/BN) | | getUpazilaById(id) | Promise<Upazila \| null> | Upazila by ID | | getUpazilaBySlug(slug) | Promise<Upazila \| null> | Upazila by slug | | getUpazilaByName(name) | Promise<Upazila \| null> | Upazila by name (EN/BN) |

Hierarchical Methods

| Method | Returns | Description | | ---------------------------------- | ------------------------------ | ------------------------------- | | getDistrictsByDivision(id) | Promise<District[]> | Districts in division (by ID) | | getDistrictsByDivisionSlug(slug) | Promise<District[]> | Districts in division (by slug) | | getUpazilasByDistrict(id) | Promise<Upazila[]> | Upazilas in district (by ID) | | getUpazilasByDistrictSlug(slug) | Promise<Upazila[]> | Upazilas in district (by slug) | | getUpazilasByDivision(id) | Promise<Upazila[]> | All upazilas in division | | getDivisionOfDistrict(id) | Promise<Division \| null> | Parent division of district | | getDistrictOfUpazila(id) | Promise<District \| null> | Parent district of upazila | | getFullAddress(upazilaId) | Promise<FullAddress \| null> | Complete address hierarchy | | getFullAddressBySlug(slug) | Promise<FullAddress \| null> | Address by upazila slug |

Search Methods

| Method | Returns | Description | | ---------------------------------- | ----------------------------------- | ------------------- | | search(query, options?) | Promise<LocationSearchResult> | Search all types | | quickSearch(query, options?) | Promise<AnyLocation \| null> | First match only | | searchDivisions(query, options?) | Promise<SearchResult<Division>[]> | Search divisions | | searchDistricts(query, options?) | Promise<SearchResult<District>[]> | Search districts | | searchUpazilas(query, options?) | Promise<SearchResult<Upazila>[]> | Search upazilas | | autocomplete(query, options?) | Promise<AutocompleteResult[]> | Prefix search | | fuzzySearch(query, options?) | Promise<LocationSearchResult> | High typo tolerance | | searchBengali(query, options?) | Promise<LocationSearchResult> | Bengali only | | searchEnglish(query, options?) | Promise<LocationSearchResult> | English only |

Validation Methods

| Method | Returns | Description | | ---------------------------------------------- | ------------------ | ------------------ | | isValidDivision(id) | Promise<boolean> | Check division ID | | isValidDistrict(id) | Promise<boolean> | Check district ID | | isValidUpazila(id) | Promise<boolean> | Check upazila ID | | isDistrictInDivision(districtId, divisionId) | Promise<boolean> | Check relationship | | isUpazilaInDistrict(upazilaId, districtId) | Promise<boolean> | Check relationship | | isUpazilaInDivision(upazilaId, divisionId) | Promise<boolean> | Check relationship |

Formatting Methods

| Method | Returns | Description | | ---------------------------------- | -------- | ------------------- | | formatAddress(address, options?) | string | Format with options | | formatAddressEnglish(address) | string | Format in English | | formatAddressBengali(address) | string | Format in Bengali |

Statistics Methods

| Method | Returns | Description | | --------------------------------------- | ------------------------ | --------------------------- | | getStats() | Promise<LocationStats> | Overall statistics | | getDistrictCount(divisionId) | Promise<number> | Count districts in division | | getUpazilaCount(districtId) | Promise<number> | Count upazilas in district | | getUpazilaCountByDivision(divisionId) | Promise<number> | Count upazilas in division |

UI Helper Methods

| Method | Returns | Description | | --------------------------------- | ------------------------- | --------------------------- | | getDivisionNames(language?) | Promise<string[]> | Division name array | | getDistrictNames(language?) | Promise<string[]> | District name array | | getUpazilaNames(language?) | Promise<string[]> | Upazila name array | | getDivisionOptions() | Promise<SelectOption[]> | Division dropdown options | | getDistrictOptions(divisionId?) | Promise<SelectOption[]> | District options (filtered) | | getUpazilaOptions(districtId?) | Promise<SelectOption[]> | Upazila options (filtered) |


Architecture

SOLID Principles

  • Single Responsibility - Each class has one reason to change
  • Open/Closed - Extensible via interfaces, closed for modification
  • Liskov Substitution - All implementations interchangeable
  • Interface Segregation - Focused, specific interfaces
  • Dependency Inversion - Depend on abstractions, not concretions

Design Patterns

| Pattern | Purpose | Location | | -------------------- | --------------------------- | ------------------------------ | | Repository | Data access abstraction | repositories/ | | Strategy | Pluggable search algorithms | services/search/strategies/ | | Factory | Object creation | factories/ | | Facade | Simplified public API | facades/bd-address.facade.ts | | Dependency Injection | Testable design | All services |

Directory Structure

src/
├── address/
│   ├── entities/          # Immutable value objects
│   ├── repositories/      # Data access layer
│   ├── services/          # Business logic
│   ├── types/             # Type definitions
│   └── utils/             # Pure functions
├── config/                # Configuration
├── facades/               # Public API
├── factories/             # Object creation
└── data/                  # JSON data files

Advanced Usage

Custom Facade Instance

import { BDAddressFactory } from 'address-bd';

// Create custom instance
const customFacade = BDAddressFactory.create();

// Or create with custom repositories (for testing)
import {
    DivisionRepository,
    DistrictRepository,
    UpazilaRepository,
} from 'address-bd';

const customFacade2 = BDAddressFactory.createWithRepositories(
    new DivisionRepository(),
    new DistrictRepository(),
    new UpazilaRepository()
);

Using Search Strategies Directly

import {
    LevenshteinStrategy,
    ExactMatchStrategy,
    AutocompleteStrategy,
    FuzzyStrategy,
} from 'address-bd';
import type { SearchOptions } from 'address-bd';

const options: SearchOptions = {
    includeEnglish: true,
    includeBengali: true,
    limit: 10,
    threshold: 0.3,
    caseSensitive: false,
};

// Use specific strategy
const fuzzyStrategy = new FuzzyStrategy<Division>();
const results = fuzzyStrategy.search('dhaka', divisions, options);

Working with Raw Data

import { LocationRepositoryFactory } from 'address-bd';

// Get repository instances
const divisionRepo = LocationRepositoryFactory.getDivisionRepository();
const districtRepo = LocationRepositoryFactory.getDistrictRepository();
const upazilaRepo = LocationRepositoryFactory.getUpazilaRepository();

// Use repositories directly
const allDivisions = await divisionRepo.findAll();
const dhakaDistricts = await districtRepo.findByDivision(1);
const savarUpazilas = await upazilaRepo.findByDistrict(1);

// Check existence
const exists = await divisionRepo.exists(1);

// Get counts
const count = await divisionRepo.count();

TypeScript Types

Key Types

import type {
    // Entities
    Division,
    District,
    Upazila,
    FullAddress,
    FullAddressData,

    // Base types
    Coordinates,
    BaseLocation,
    DivisionData,
    DistrictData,
    UpazilaData,

    // Search results
    SearchResult,
    LocationSearchResult,
    AnyLocation,
    LocationType,
    SelectOption,

    // Search configuration
    SearchOptions,
    DefaultSearchOptions,
    AutocompleteResult,

    // Statistics
    LocationStats,

    // Service interfaces
    ISearchService,
    IValidationService,
    IFormattingService,
    IStatisticsService,
    FormatOptions,

    // Repository interfaces
    IDivisionRepository,
    IDistrictRepository,
    IUpazilaRepository,
    ILocationRepository,
} from 'address-bd';

// Enums
import {
    BangladeshDivision,
    BangladeshDistrict,
    BangladeshUpazila,
} from 'address-bd';

Type Guards

import type { AnyLocation, Division, District, Upazila } from 'address-bd';

function isDivision(location: AnyLocation): location is Division {
    return 'area' in location; // Divisions have area property
}

function isDistrict(location: AnyLocation): location is District {
    return 'divisionId' in location && !('districtId' in location);
}

function isUpazila(location: AnyLocation): location is Upazila {
    return 'districtId' in location && 'area' in location === false;
}

// Usage
const location = await bdAddress.quickSearch('dhaka');
if (location) {
    if (isDivision(location)) {
        console.log(`Area: ${location.area} sq km`);
    }
}

License

by-nc-nd/4.0

This project is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).


Author