{"_id":"@derrick63/rwanda-admin-hierarchy","_rev":"5-f15176627d0306ae69a67971a16e82c6","name":"@derrick63/rwanda-admin-hierarchy","dist-tags":{"latest":"1.3.0"},"versions":{"1.0.0":{"name":"@derrick63/rwanda-admin-hierarchy","version":"1.0.0","keywords":["rwanda","administrative-data","administrative-divisions","province","district","sector","cell","village","geodata","dataset","kigali"],"author":{"url":"https://github.com/Derrick-MUGISHA","name":"Derrick Mugisha"},"license":"ISC","_id":"@derrick63/rwanda-admin-hierarchy@1.0.0","maintainers":[{"name":"derrick63","email":"derrickmugisha169@gmail.com"}],"homepage":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda#readme","bugs":{"url":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda/issues"},"dist":{"shasum":"0d93d731d58f71fc3c9c4a204733471caa44dede","tarball":"https://registry.npmjs.org/@derrick63/rwanda-admin-hierarchy/-/rwanda-admin-hierarchy-1.0.0.tgz","fileCount":9,"integrity":"sha512-I6e3z686bujY/f5jxKbLXclhvqBUjiDj4HFN9GX7hJTsLnxeS2CaVeA2M05C6FHK48SpVCM6a5Cs9ACm997MBQ==","signatures":[{"sig":"MEUCIQCC8BSuG5oV8ZwenitJe3U7Pg4r7SHop2qhnqajtOC+jgIgLFcHpF8Yt+6K0TB7+e+gH25i/Ql706ImJiAVxny0mAg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1524327},"main":"src/index.js","type":"commonjs","types":"src/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./data":"./data/rwanda-administrative.json","./package.json":"./package.json"},"gitHead":"fbca47d29497cbaa074d03015b6bdc3521cff5c1","scripts":{"test":"node --test","start":"node src/server.js","prepack":"npm run validate:data && npm test","build:data":"node scripts/build-json-from-pdf.js","validate:data":"node scripts/validate-data.js"},"_npmUser":{"name":"derrick63","email":"derrickmugisha169@gmail.com"},"repository":{"url":"git+https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda.git","type":"git"},"_npmVersion":"10.9.7","description":"Complete Rwanda administrative hierarchy dataset (Province > District > Sector > Cell > Village) with a zero-dependency lookup API and an optional Express server.","directories":{},"sideEffects":false,"_nodeVersion":"22.22.2","publishConfig":{"access":"public","provenance":false},"_hasShrinkwrap":false,"devDependencies":{"cors":"^2.8.5","dotenv":"^16.6.1","helmet":"^8.1.0","express":"^5.2.1","express-rate-limit":"^8.1.0"},"_npmOperationalInternal":{"tmp":"tmp/rwanda-admin-hierarchy_1.0.0_1783204910843_0.8008600180497141","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"1.1.0":{"name":"@derrick63/rwanda-admin-hierarchy","version":"1.1.0","keywords":["rwanda","administrative-data","administrative-divisions","province","district","sector","cell","village","geodata","dataset","kigali","nisr","umudugudu","imirenge","akagari","iso-3166","address-validation","address-form","location-picker","east-africa","africa"],"author":{"url":"https://github.com/Derrick-MUGISHA","name":"Derrick Mugisha"},"license":"ISC","_id":"@derrick63/rwanda-admin-hierarchy@1.1.0","maintainers":[{"name":"derrick63","email":"derrickmugisha169@gmail.com"}],"homepage":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda#readme","bugs":{"url":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda/issues"},"dist":{"shasum":"e937f9b2743e54f234deb1dbeb03e690378fa5ed","tarball":"https://registry.npmjs.org/@derrick63/rwanda-admin-hierarchy/-/rwanda-admin-hierarchy-1.1.0.tgz","fileCount":17,"integrity":"sha512-U1ZCvuRlZ2weSV+rLUbt5Gl2y0v/Baj49EtE7kdnV9DPk87Cpg0YJdRPrOikfAbFS1zHxzS2eh/x1M2ykldP4A==","signatures":[{"sig":"MEUCIQDmjW55tVDXAf4mbHSWJh5YDBe0f6kOx+whE/l9JzR2nAIgJw2pLQGR1+Zv7TmIvQYV1rUdYWAiwA8AEopZ7HDIlLw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@derrick63%2frwanda-admin-hierarchy@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":6195737},"main":"src/index.js","type":"commonjs","types":"src/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./data":"./data/rwanda-administrative.json","./changes":"./data/changes.json","./package.json":"./package.json","./data/provinces/*.json":"./data/provinces/*.json"},"gitHead":"7a7a7ab3ca61180267324d8cf480fd3bc82ff593","scripts":{"test":"node --test","start":"node src/server.js","prepack":"npm run validate:data && npm test","sync:data":"node scripts/sync-data.js","build:data":"node scripts/build-json-from-pdf.js && npm run sync:data && npm run split:data","split:data":"node scripts/split-data.js","export:data":"node scripts/export-flat.js","validate:data":"node scripts/validate-data.js && node scripts/sync-data.js --check"},"_npmUser":{"name":"derrick63","email":"derrickmugisha169@gmail.com"},"repository":{"url":"git+https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete Rwanda administrative hierarchy dataset (Province > District > Sector > Cell > Village) with a zero-dependency lookup API and an optional Express server.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"cors":"^2.8.5","dotenv":"^16.6.1","helmet":"^8.1.0","express":"^5.2.1","express-rate-limit":"^8.1.0"},"_npmOperationalInternal":{"tmp":"tmp/rwanda-admin-hierarchy_1.1.0_1783261117979_0.7768359364928199","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"1.2.0":{"name":"@derrick63/rwanda-admin-hierarchy","version":"1.2.0","keywords":["rwanda","administrative-data","administrative-divisions","province","district","sector","cell","village","geodata","dataset","kigali","nisr","umudugudu","imirenge","akagari","iso-3166","address-validation","address-form","location-picker","east-africa","africa"],"author":{"url":"https://github.com/Derrick-MUGISHA","name":"Derrick Mugisha"},"license":"ISC","_id":"@derrick63/rwanda-admin-hierarchy@1.2.0","maintainers":[{"name":"derrick63","email":"derrickmugisha169@gmail.com"}],"homepage":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda#readme","bugs":{"url":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda/issues"},"dist":{"shasum":"25c8b9997e5fe8d80a29fae2d89e1dcea3c55fb9","tarball":"https://registry.npmjs.org/@derrick63/rwanda-admin-hierarchy/-/rwanda-admin-hierarchy-1.2.0.tgz","fileCount":17,"integrity":"sha512-r1H0y9BIglQEs3HyXcxyCP5d2zU8k7hp5iasq7OE2xMyqLruDQGYSitvtnotVCJYafgn+hW5Lm9Ye0fS38yqiQ==","signatures":[{"sig":"MEQCIHsPE5Ss8FyxTXYUQ5P8c03PBoaxuE/YYeaLG5drRRBkAiBmCbFa/MqHB1wAYMpRcTZLy2LIulv9iw14SQN5c2hPsA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@derrick63%2frwanda-admin-hierarchy@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":6195737},"main":"src/index.js","type":"commonjs","types":"src/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./data":"./data/rwanda-administrative.json","./changes":"./data/changes.json","./package.json":"./package.json","./data/provinces/*.json":"./data/provinces/*.json"},"gitHead":"7a7a7ab3ca61180267324d8cf480fd3bc82ff593","scripts":{"test":"node --test","start":"node src/server.js","prepack":"npm run validate:data && npm test","sync:data":"node scripts/sync-data.js","build:data":"node scripts/build-json-from-pdf.js && npm run sync:data && npm run split:data","split:data":"node scripts/split-data.js","export:data":"node scripts/export-flat.js","validate:data":"node scripts/validate-data.js && node scripts/sync-data.js --check"},"_npmUser":{"name":"derrick63","email":"derrickmugisha169@gmail.com"},"repository":{"url":"git+https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete Rwanda administrative hierarchy dataset (Province > District > Sector > Cell > Village) with a zero-dependency lookup API and an optional Express server.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"cors":"^2.8.5","dotenv":"^16.6.1","helmet":"^8.1.0","express":"^5.2.1","express-rate-limit":"^8.1.0"},"_npmOperationalInternal":{"tmp":"tmp/rwanda-admin-hierarchy_1.2.0_1783261485803_0.23589496290410517","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"1.3.0":{"name":"@derrick63/rwanda-admin-hierarchy","version":"1.3.0","keywords":["rwanda","administrative-data","administrative-divisions","province","district","sector","cell","village","geodata","dataset","kigali","nisr","umudugudu","imirenge","akagari","iso-3166","address-validation","address-form","location-picker","east-africa","africa"],"author":{"url":"https://github.com/Derrick-MUGISHA","name":"Derrick Mugisha"},"license":"ISC","_id":"@derrick63/rwanda-admin-hierarchy@1.3.0","maintainers":[{"name":"derrick63","email":"derrickmugisha169@gmail.com"}],"homepage":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda#readme","bugs":{"url":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda/issues"},"dist":{"shasum":"fb4f838364832a5e05dfa484fb847775bc54a264","tarball":"https://registry.npmjs.org/@derrick63/rwanda-admin-hierarchy/-/rwanda-admin-hierarchy-1.3.0.tgz","fileCount":17,"integrity":"sha512-TAsuo2U/v7tae1ZkKdk32bq5re+JyohrmhPlHNQjav5ddjATyu1AJjhDR0E5yR3eXZPUL8FMJHsUKd66D9BQPQ==","signatures":[{"sig":"MEQCIDNdCpimkLyBawYBnHT9xRNvAL4fCW4eYm2B0vmtRHxrAiA6USLp6EezC6WGiP2IlZI9V5JfigfGmHP0C9VXH2/hmw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@derrick63%2frwanda-admin-hierarchy@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":6195737},"main":"src/index.js","type":"commonjs","types":"src/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./data":"./data/rwanda-administrative.json","./changes":"./data/changes.json","./package.json":"./package.json","./data/provinces/*.json":"./data/provinces/*.json"},"gitHead":"b50f31858c73dc8e4dfd379241818fd758ed610e","scripts":{"test":"node --test","start":"node src/server.js","prepack":"npm run validate:data && npm test","sync:data":"node scripts/sync-data.js","build:data":"node scripts/build-json-from-pdf.js && npm run sync:data && npm run split:data","split:data":"node scripts/split-data.js","export:data":"node scripts/export-flat.js","validate:data":"node scripts/validate-data.js && node scripts/sync-data.js --check"},"_npmUser":{"name":"derrick63","email":"derrickmugisha169@gmail.com"},"repository":{"url":"git+https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete Rwanda administrative hierarchy dataset (Province > District > Sector > Cell > Village) with a zero-dependency lookup API and an optional Express server.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"cors":"^2.8.5","dotenv":"^16.6.1","helmet":"^8.1.0","express":"^5.2.1","express-rate-limit":"^8.1.0"},"_npmOperationalInternal":{"tmp":"tmp/rwanda-admin-hierarchy_1.3.0_1783262083303_0.2613829673984369","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."}},"time":{"created":"2026-07-04T22:41:50.655Z","modified":"2026-07-08T14:04:50.428Z","1.0.0":"2026-07-04T22:41:50.974Z","1.1.0":"2026-07-05T14:18:38.141Z","1.2.0":"2026-07-05T14:24:45.956Z","1.3.0":"2026-07-05T14:34:43.514Z"},"bugs":{"url":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda/issues"},"author":{"url":"https://github.com/Derrick-MUGISHA","name":"Derrick Mugisha"},"license":"ISC","homepage":"https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda#readme","keywords":["rwanda","administrative-data","administrative-divisions","province","district","sector","cell","village","geodata","dataset","kigali","nisr","umudugudu","imirenge","akagari","iso-3166","address-validation","address-form","location-picker","east-africa","africa"],"repository":{"url":"git+https://github.com/Derrick-MUGISHA/Rwanda-Province-District-Sector-Cell-Village---in-Rwanda.git","type":"git"},"description":"Complete Rwanda administrative hierarchy dataset (Province > District > Sector > Cell > Village) with a zero-dependency lookup API and an optional Express server.","maintainers":[{"name":"derrick63","email":"derrickmugisha169@gmail.com"}],"readme":"# Rwanda Administrative Hierarchy API\n\n[![npm version](https://img.shields.io/npm/v/@derrick63/rwanda-admin-hierarchy)](https://www.npmjs.com/package/@derrick63/rwanda-admin-hierarchy)\n[![license](https://img.shields.io/badge/license-ISC-blue.svg)](./LICENSE)\n\nThis project provides a structured dataset and API for Rwanda administrative levels:\n\n`Country -> Province -> District -> Sector -> Cell -> Village`\n\n**5 provinces · 30 districts · 416 sectors · 2,142 cells · 14,816 villages** —\nsourced from the official NISR \"List of Villages\", with NISR codes at every\nlevel, ISO 3166-2 province codes, name search, and address validation.\nAvailable for [Node.js](https://www.npmjs.com/package/@derrick63/rwanda-admin-hierarchy),\n[Python](https://pypi.org/project/rwanda-admin-hierarchy/), Java (GitHub\nPackages), and Flutter (`dart/`), plus CSV/SQL/SQLite exports on every release.\n\nThe code is ISC-licensed; the dataset is licensed [CC BY 4.0](./LICENSE-DATA).\nWrong or missing place? Please\n[open a data-correction issue](../../issues/new/choose) — local knowledge keeps\nthis dataset trustworthy. See [CONTRIBUTING.md](./CONTRIBUTING.md).\n\n## Install\n\n```bash\nnpm install @derrick63/rwanda-admin-hierarchy\n```\n\nThe published package is a **zero-dependency** data library with bundled TypeScript\ntype definitions. The Express API server described below is a development/deployment\nextra and its dependencies are only installed when working inside this repository.\n\n## Information Source\n\nAll data structure, rules, and implementation behavior in this project are based on these two repository documents:\n\n- `Guidence.md` (implementation guidance and system rules)\n- `List_of_Villages_for_all_technology.pdf` (primary administrative data source used to build the JSON dataset)\n\nNo external assumptions are required to run or use this project.\n\n## What This Project Contains\n\n- `data/rwanda-administrative.json`  \n  Generated hierarchical dataset.\n- `src/server.js`  \n  Express API server with endpoints by hierarchy level.\n- `src/data-store.js`  \n  Loads and caches JSON once in memory.\n- `scripts/build-json-from-pdf.js`  \n  Rebuilds JSON dataset from the provided PDF.\n- `scripts/validate-data.js`  \n  Checks integrity rules (IDs, structure, duplicates within level).\n- `TECHNICAL_DOCUMENTATION.md`  \n  Full technical explanation of the system and constraints.\n\n## Requirements\n\n- Node.js (recommended: version 18+)\n- npm\n- `pdftotext` installed (used by the build script)\n- Java 17+ and Maven (only if you want the Java package)\n- Python 3.9+ (only if you want the Python package)\n\n## Environment Configuration\n\nThis project uses environment variables for secure runtime behavior.\n\n1) Copy the template:\n\n```bash\ncp .env.example .env\n```\n\n2) Edit `.env` for your environment.\n\nImportant variables:\n- `PORT`\n- `ENABLE_FULL_DATASET_ENDPOINT`\n- `RATE_LIMIT_MAX_REQUESTS`\n- `RATE_LIMIT_WINDOW_MS`\n- `ALLOWED_ORIGINS`\n- `TRUST_PROXY` (set when running behind a reverse proxy so rate limiting sees real client IPs)\n\nNever store publishing tokens (npm, PyPI, Maven) in `.env`. Use GitHub Actions\nsecrets for CI releases and `npm login` for local publishing.\n\n## How to Run (Step by Step)\n\n### 1) Install dependencies\n\n```bash\nnpm install\n```\n\n### 2) Build the JSON dataset from the PDF\n\n```bash\nnpm run build:data\n```\n\nThis reads `List_of_Villages_for_all_technology.pdf` and writes:\n\n`data/rwanda-administrative.json`\n\n### 3) Validate data integrity\n\n```bash\nnpm run validate:data\n```\n\nThis validates:\n- Required hierarchy structure\n- Unique IDs\n- Duplicate names within the same level\n- Nested object completeness\n\n### 4) Start the API server\n\n```bash\nnpm start\n```\n\nDefault server URL:\n\n`http://localhost:3000`\n\n## API Endpoints\n\n### Health check\n\n`GET /health`\n\n### Full dataset\n\n`GET /api/dataset`\n\n### All provinces\n\n`GET /api/provinces`\n\n### Districts by province ID\n\n`GET /api/provinces/:provinceId/districts`\n\n### Sectors by district ID\n\n`GET /api/districts/:districtId/sectors`\n\n### Cells by sector ID\n\n`GET /api/sectors/:sectorId/cells`\n\n### Villages by cell ID\n\n`GET /api/cells/:cellId/villages`\n\n### Search by name (any level)\n\n`GET /api/search?q=gitega&levels=sector,cell&limit=10`\n\nCase-, diacritic-insensitive and typo-tolerant. `levels` and `limit` are optional.\n\n### Reverse lookup (full ancestor chain)\n\n`GET /api/path/:id` — e.g. `/api/path/village-11010103`\n\n### Validate an address hierarchy\n\n`GET /api/validate?province=Kigali&district=Nyarugenge&sector=Gitega`\n\nEach level accepts an ID, an NISR/ISO code, or a name. Returns `{ valid, errors, match }`.\n\n## Use as a Package\n\nThis repository can also be used as a Node package (CommonJS).\n\nExample usage:\n\n```js\nconst {\n  getProvinces,\n  getDistrictsByProvinceId,\n  search,\n  getPath,\n  getByCode,\n  isValidHierarchy,\n} = require(\"@derrick63/rwanda-admin-hierarchy\");\n\n// Top-down traversal\nconst provinces = getProvinces();\nconst districts = getDistrictsByProvinceId(\"province-umujyi-wa-kigali\");\n\n// Name search — case-, diacritic-insensitive and typo-tolerant\nsearch(\"gítega\");                        // matches \"Gitega\" at any level\nsearch(\"Gitegga\", { levels: [\"sector\"] }); // misspellings still match\n\n// Reverse lookup: village -> cell -> sector -> district -> province\nconst path = getPath(\"village-11010103\");\n// path.province.name === \"Umujyi wa Kigali\", path.sector.name === \"Gitega\", ...\n\n// Standard codes: NISR administrative codes and ISO 3166-2\ngetByCode(\"RW-01\");    // City of Kigali (ISO 3166-2:RW)\ngetByCode(\"11\");       // Nyarugenge district (NISR code)\ngetByCode(\"11010103\"); // village by its 8-digit NISR code\n\n// Address/form validation — accepts names, ids, or codes at each level\nisValidHierarchy({\n  province: \"Kigali\",\n  district: \"Nyarugenge\",\n  sector: \"Gitega\",\n  cell: \"Akabahizi\",\n  village: \"Iterambere\",\n}); // true\n```\n\nExported package functions:\n\nHierarchy traversal:\n- `getDataset()`\n- `getProvinces()`\n- `getDistrictsByProvinceId(provinceId)`\n- `getSectorsByDistrictId(districtId)`\n- `getCellsBySectorId(sectorId)`\n- `getVillagesByCellId(cellId)`\n- `loadDataset()`\n\nFlat accessors (dropdowns, validation lists):\n- `getAllDistricts()`, `getAllSectors()`, `getAllCells()`, `getAllVillages()`\n\nSearch and lookup:\n- `search(query, { levels?, limit?, fuzzy? })` — fuzzy name search across all levels; every result includes its full ancestor `path`\n- `getById(id)` — resolve any ID at any level\n- `getByCode(code)` — resolve NISR codes (`\"11\"`, `\"1101\"`, `\"11010103\"`) and ISO 3166-2 province codes (`\"RW-01\"`)\n- `getPath(id)` — reverse lookup / ancestry for any ID\n\nValidation:\n- `isValidHierarchy(parts)` — boolean check that the given levels form one consistent chain\n- `validateHierarchy(parts)` — same, but returns `{ valid, errors, match }`\n\nProvenance and migrations:\n- `getDataMeta()` — dataset provenance (`dataVersion`, `source`, `license`) and per-level counts\n- `resolveId(oldId)` — resolves ids from previous dataset versions via the migration map\n- `getIdChanges()` — the raw migration history (`data/changes.json`)\n\n### Standard codes\n\nEvery node carries a `code` field with its official NISR administrative code,\nderived from the village codes in the source dataset:\n\n| Level | Code format | Example |\n| --- | --- | --- |\n| Province | 1 digit | `1` (Kigali City) |\n| District | 2 digits | `11` (Nyarugenge) |\n| Sector | 4 digits | `1101` (Gitega) |\n| Cell | 6 digits | `110101` (Akabahizi) |\n| Village | 8 digits | `11010103` (Iterambere) |\n\nProvinces additionally carry:\n- `isoCode` — the ISO 3166-2:RW subdivision code (`RW-01` … `RW-05`)\n- `nameVariants` — common English/French names (`\"City of Kigali\"`, `\"Southern Province\"`, …), which `search()` also matches\n\nNote: a few cells in the source PDF merge official NISR \"I\"/\"II\" cell pairs\n(e.g. Munanira I/II); those cells have `code: null` because no single official\ncode applies.\n\nTypeScript definitions are bundled (`src/index.d.ts`), so all functions and the\ndataset shape are fully typed out of the box.\n\nThe raw JSON dataset can also be imported directly:\n\n```js\nconst dataset = require(\"@derrick63/rwanda-admin-hierarchy/data\");\n```\n\nBrowser or serverless code that only needs one province can lazy-load a slice\n(~230–760 KB instead of the full dataset):\n\n```js\nconst kigali = require(\"@derrick63/rwanda-admin-hierarchy/data/provinces/umujyi-wa-kigali.json\");\n// data/provinces/index.json lists all five slices\n```\n\nBuild npm tarball locally:\n\n```bash\nnpm pack\n```\n\n### Dataset versioning and id migrations\n\nThe data snapshot is versioned independently of the package: `getDataMeta()`\nreturns `dataVersion` (currently `2019-07`, the NISR source publication date).\nWhen a rebuild removes or renames a node id, the migration is recorded in\n`data/changes.json` and old ids keep resolving:\n\n```js\nconst { resolveId } = require(\"@derrick63/rwanda-admin-hierarchy\");\nresolveId(\"province-umujyi-wa-kigali-district-nyarugenge-sector-mageragere\");\n// -> \"province-umujyi-wa-kigali-district-nyarugenge-sector-mageregere\"\n```\n\n### Electrification (NEP) categories\n\nEach village carries the National Electrification Plan category from the\nsource document as `nep`: `\"GE\"` (grid extension), `\"SAS\"` (standalone solar),\nor `\"Microgrid\"`.\n\n### Flat exports (CSV / SQL / SQLite)\n\nAnalysts and non-JS users can grab flat files from every GitHub release —\n`villages.csv` (one denormalized row per village), `rwanda.sql` (portable\nschema + inserts), and `rwanda.sqlite` — or generate them locally:\n\n```bash\nnpm run export:data   # writes exports/\n```\n\n## Use as a Maven Package (Java)\n\nThe Java package is in `java-mvn`.\n\n### Build the JAR\n\n```bash\nmvn -f java-mvn/pom.xml clean package\n```\n\nThe JAR will be created in:\n\n`java-mvn/target/rwanda-admin-hierarchy-1.0.0.jar`\n\n### Install to your local Maven repository\n\n```bash\nmvn -f java-mvn/pom.xml clean install\n```\n\n### Add dependency in your Java app\n\n```xml\n<dependency>\n  <groupId>io.github.derickmugisha</groupId>\n  <artifactId>rwanda-admin-hierarchy</artifactId>\n  <version>1.0.0</version>\n</dependency>\n```\n\n### Java usage example\n\n```java\nimport io.github.derickmugisha.rwanda.RwandaHierarchyService;\n\nRwandaHierarchyService service = RwandaHierarchyService.loadDefault();\nvar provinces = service.getProvinces();\nvar districts = service.getDistrictsByProvinceId(\"province-umujyi-wa-kigali\");\n```\n\n## Use as a Python Package\n\nPython package path:\n\n`python/`\n\n### Build Python distributions\n\n```bash\npython3 -m pip install --upgrade build\npython3 -m build python\n```\n\nBuild output:\n\n`python/dist/`\n\n### Install locally for testing\n\n```bash\npython3 -m pip install python/dist/*.whl\n```\n\n### Python usage example\n\n```python\nfrom rwanda_admin_hierarchy import get_provinces, get_districts_by_province_id\n\nprovinces = get_provinces()\ndistricts = get_districts_by_province_id(\"province-umujyi-wa-kigali\")\n```\n\n## CI/CD Pipelines\n\nGitHub Actions workflows are included:\n\n- `.github/workflows/ci-security.yml`\n  - Optimized checks with dependency caching for Node, Python, and Maven\n  - Builds all package targets\n  - Runs dependency audits (`npm audit`, `pip-audit`)\n- `.github/workflows/release-packages.yml`\n  - Manual release pipeline for npm, PyPI, and Maven\n  - Creates git tag and GitHub Release automatically after publish\n\n## Quick Usage Examples\n\nGet all provinces:\n\n```bash\ncurl http://localhost:3000/api/provinces\n```\n\nGet districts of a province:\n\n```bash\ncurl http://localhost:3000/api/provinces/province-umujyi-wa-kigali/districts\n```\n\nGet sectors of a district:\n\n```bash\ncurl http://localhost:3000/api/districts/province-umujyi-wa-kigali-district-nyarugenge/sectors\n```\n\nGet cells of a sector:\n\n```bash\ncurl http://localhost:3000/api/sectors/province-umujyi-wa-kigali-district-nyarugenge-sector-gitega/cells\n```\n\nGet villages of a cell:\n\n```bash\ncurl http://localhost:3000/api/cells/province-umujyi-wa-kigali-district-nyarugenge-sector-gitega-cell-akabahizi/villages\n```\n\n## Error Behavior\n\nIf an ID is not found, the API returns:\n\n- HTTP `404`\n- JSON error message like:\n\n```json\n{ \"error\": \"Province not found\" }\n```\n\n(Message varies by level: Province, District, Sector, or Cell.)\n\n## Use as a Flutter Package\n\nA Flutter package with the same dataset lives in `dart/`\n(`rwanda_admin_hierarchy`). It bundles the JSON as an asset and exposes typed\nmodels with the same traversal API:\n\n```dart\nimport 'package:rwanda_admin_hierarchy/rwanda_admin_hierarchy.dart';\n\nfinal rwanda = await RwandaAdminHierarchy.load();\nfinal districts = rwanda.districtsByProvinceId('province-umujyi-wa-kigali');\n```\n\nIt is not yet published to pub.dev; see `dart/README.md`.\n\n## Data and Logic Separation\n\nIn line with `Guidence.md`, data is kept in the `data` folder and separated from application logic.  \nThis allows:\n- Updating data without modifying backend code\n- Easy migration to a database later\n\n## End-to-End Flow\n\n1. Source data comes from `List_of_Villages_for_all_technology.pdf`\n2. Build script transforms it into hierarchical JSON\n3. Validation script checks integrity rules\n4. Server loads and caches JSON\n5. API serves structured hierarchy responses\n\n## Notes\n\n- If you update the PDF, run `npm run build:data` again.\n- Then always run `npm run validate:data` before starting the server.\n- Before publishing or releasing, run `npm run validate:data`.\n","readmeFilename":"README.md"}