{"_id":"@aialok/lakhua","_rev":"3-7df526acdf1cc7aa8abfd1e705fd9848","name":"@aialok/lakhua","dist-tags":{"latest":"1.0.1"},"versions":{"0.1.1":{"name":"@aialok/lakhua","version":"0.1.1","_id":"@aialok/lakhua@0.1.1","maintainers":[{"name":"aialok","email":"alokgupta1560@gmail.com"}],"homepage":"https://github.com/aialok/lakhua#readme","bugs":{"url":"https://github.com/aialok/lakhua/issues"},"dist":{"shasum":"beb62bc2131ae9b09ea56167635370ce344be0d6","tarball":"https://registry.npmjs.org/@aialok/lakhua/-/lakhua-0.1.1.tgz","fileCount":20,"integrity":"sha512-1LpxFilm9loYgbBsbZIFYTNEV5oV8D5YIxrr3qiaRNu7kmhPWV1X1b39tgEnK6OAcAHOVwtOWTTjZuBCviTyow==","signatures":[{"sig":"MEQCIFXSPd5YygNJzMiCO6LMdVbarFD97dyP8m388GzUu7hpAiBlbPiRFQ8JwF0VoudwBcYWzCMWfizCe2bhpR3rwCjUdg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aialok%2flakhua@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1384959},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"7195d37a4ae820f38636f53d7eeed19d2b9adda1","scripts":{"lint":"bunx @biomejs/biome check .","test":"bun test","build":"bun run clean && bunx tsc -p tsconfig.json","check":"bun run format:check && bun run typecheck && bun test","clean":"rm -rf dist","format":"bunx @biomejs/biome format .","prepack":"bun run build","lint:fix":"bunx @biomejs/biome check . --write","precommit":"bun run lint-staged && bun run typecheck","typecheck":"bunx tsc -p tsconfig.json --noEmit","format:fix":"bunx @biomejs/biome format . --write","lint-format":"bun run lint:fix && bun run format:fix","lint-staged":"lint-staged","format:check":"bunx @biomejs/biome check .","pack:dry-run":"npm pack --dry-run --json","example:basic":"bun run examples/basic.ts","example:batch":"bun run examples/batch.ts"},"_npmUser":{"name":"aialok","email":"alokgupta1560@gmail.com"},"repository":{"url":"git+https://github.com/aialok/lakhua.git","type":"git"},"_npmVersion":"10.8.2","description":"Fast, offline reverse geocoding for India","directories":{},"lint-staged":{"*.{ts,js,mjs,cjs,json,md}":["bunx @biomejs/biome check --write"]},"_nodeVersion":"20.20.0","dependencies":{"h3-js":"^4.3.0"},"_hasShrinkwrap":false,"packageManager":"bun@1.2.20","devDependencies":{"husky":"^9.1.7","@types/bun":"^1.2.20","typescript":"^5.7.3","@types/node":"^22.10.7","lint-staged":"^15.2.10","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/lakhua_0.1.1_1771673815537_0.7163587892820902","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@aialok/lakhua","version":"1.0.0","_id":"@aialok/lakhua@1.0.0","maintainers":[{"name":"aialok","email":"alokgupta1560@gmail.com"}],"homepage":"https://github.com/aialok/lakhua#readme","bugs":{"url":"https://github.com/aialok/lakhua/issues"},"dist":{"shasum":"3fd6bff5555597cf8e7ded3d6ac5f15c89240bc0","tarball":"https://registry.npmjs.org/@aialok/lakhua/-/lakhua-1.0.0.tgz","fileCount":20,"integrity":"sha512-VVzV5GFE04x5gpKF+FZfQPV665ZXsUG66f7+9ThZztt2IXuyCysYYfSxT0cL/meRkpYlgnxKMcBJX5cvTgshNw==","signatures":[{"sig":"MEQCIAQlFA2u7LC2/5wsbrS2U6WfffTr6kmS9iz+fYiGYkesAiBONT1CKwDDhfKsBSJiTO8LCsK1OnpAzR1xMXafmytvWw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aialok%2flakhua@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1387327},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"94cc41452b44bac1d2bac02905bae21af57f21fd","scripts":{"lint":"bunx @biomejs/biome check .","test":"bun test","build":"bun run clean && bunx tsc -p tsconfig.json","check":"bun run format:check && bun run typecheck && bun test","clean":"rm -rf dist","format":"bunx @biomejs/biome format .","prepack":"bun run build","lint:fix":"bunx @biomejs/biome check . --write","precommit":"bun run lint-staged && bun run typecheck","typecheck":"bunx tsc -p tsconfig.json --noEmit","format:fix":"bunx @biomejs/biome format . --write","lint-format":"bun run lint:fix && bun run format:fix","lint-staged":"lint-staged","format:check":"bunx @biomejs/biome check .","pack:dry-run":"npm pack --dry-run --json","example:basic":"bun run examples/basic.ts","example:batch":"bun run examples/batch.ts"},"_npmUser":{"name":"aialok","email":"alokgupta1560@gmail.com"},"repository":{"url":"git+https://github.com/aialok/lakhua.git","type":"git"},"_npmVersion":"10.8.2","description":"Fast, offline reverse geocoding for India","directories":{},"lint-staged":{"*.{ts,js,mjs,cjs,json,md}":["bunx @biomejs/biome check --write"]},"_nodeVersion":"20.20.0","dependencies":{"h3-js":"^4.3.0"},"_hasShrinkwrap":false,"packageManager":"bun@1.2.20","devDependencies":{"husky":"^9.1.7","@types/bun":"^1.2.20","typescript":"^5.7.3","@types/node":"^22.10.7","lint-staged":"^15.2.10","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/lakhua_1.0.0_1771693759196_0.475934755699966","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@aialok/lakhua","version":"1.0.1","description":"Fast, offline reverse geocoding for India","keywords":["reverse geocoding","offline geocoding","india geocoding","geocoding","geospatial","gis","h3","h3-js","h3 index","openstreetmap","osm","point in polygon","bounding box","admin boundaries","geospatial indexing","coordinates","latitude","longitude","city","state","district","tehsil","postal code","pincode","batch geocoding","location lookup","no api key","free geocoding","india maps"],"type":"module","repository":{"type":"git","url":"git+https://github.com/aialok/lakhua.git"},"packageManager":"bun@1.2.20","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"clean":"rm -rf dist","build":"bun run clean && bunx tsc -p tsconfig.json","test":"bun test","typecheck":"bunx tsc -p tsconfig.json --noEmit","lint":"bunx @biomejs/biome check .","lint:fix":"bunx @biomejs/biome check . --write","format":"bunx @biomejs/biome format .","format:check":"bunx @biomejs/biome check .","format:fix":"bunx @biomejs/biome format . --write","lint-format":"bun run lint:fix && bun run format:fix","check":"bun run format:check && bun run typecheck && bun test","lint-staged":"lint-staged","precommit":"bun run lint-staged && bun run typecheck","example:basic":"bun run examples/basic.ts","example:batch":"bun run examples/batch.ts","pack:dry-run":"npm pack --dry-run --json","prepack":"bun run build"},"dependencies":{"h3-js":"^4.3.0"},"devDependencies":{"@biomejs/biome":"^1.9.4","@types/bun":"^1.2.20","@types/node":"^22.10.7","husky":"^9.1.7","lint-staged":"^15.2.10","typescript":"^5.7.3"},"lint-staged":{"*.{ts,js,mjs,cjs,json,md}":["bunx @biomejs/biome check --write"]},"_id":"@aialok/lakhua@1.0.1","gitHead":"d71d28afd1b1d85f5c1c014ef8fddd3382903af1","bugs":{"url":"https://github.com/aialok/lakhua/issues"},"homepage":"https://github.com/aialok/lakhua#readme","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-g5qZz1Ov3b/XU0m6w/jpDB3sBLC0bDfj00SU5hrdAXsIBUDT8O9ryb0A6DuGqkX4H4BqqPVYsAddbFHAXdXJ4A==","shasum":"850b7583df3b48553094b9a9338926d9c85eb929","tarball":"https://registry.npmjs.org/@aialok/lakhua/-/lakhua-1.0.1.tgz","fileCount":20,"unpackedSize":1387877,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aialok%2flakhua@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHhKN729ADSPUlhm4ilx/Nipqo5D6yzvQ/B3xWuRm0SjAiEArVLHtXEH1upaDrvtINjTx6TUzSEYc0Vs+UOglgAbxbA="}]},"_npmUser":{"name":"aialok","email":"alokgupta1560@gmail.com"},"directories":{},"maintainers":[{"name":"aialok","email":"alokgupta1560@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/lakhua_1.0.1_1772131008892_0.05234681499954652"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-21T11:36:55.446Z","modified":"2026-02-26T18:36:49.410Z","0.1.1":"2026-02-21T11:36:55.731Z","1.0.0":"2026-02-21T17:09:19.443Z","1.0.1":"2026-02-26T18:36:49.110Z"},"bugs":{"url":"https://github.com/aialok/lakhua/issues"},"homepage":"https://github.com/aialok/lakhua#readme","repository":{"type":"git","url":"git+https://github.com/aialok/lakhua.git"},"description":"Fast, offline reverse geocoding for India","maintainers":[{"name":"aialok","email":"alokgupta1560@gmail.com"}],"readme":"# @aialok/lakhua\n\nSub-millisecond reverse geocoding for India, fully offline.\n\nNo API calls. No network latency. No rate limits.\n\nBuilt for backend services, cron jobs, and analytics workloads that need deterministic geocode lookups.\n\n[![npm](https://img.shields.io/npm/v/@aialok/lakhua)](https://www.npmjs.com/package/@aialok/lakhua)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green)](../../LICENSE)\n\n## Features\n\n- 📍 converts `lat, lon` to `city`, `state`, optional `district` and `pincode`\n- 🔢 supports direct H3 index lookup via `geocodeH3()`\n- ↩️ parent-cell fallback (`resolution 5 → 4`) when exact cell has no data\n- ⚡ data loaded once per process — all subsequent lookups are in-memory map reads\n- 🐛 optional debug mode traces load time and per-lookup timing\n- 🔷 TypeScript-first — full type definitions included\n\n## Why Not Hosted APIs?\n\n| Feature | `@aialok/lakhua` | Hosted API |\n|---|---|---|\n| Works offline | yes | no |\n| API key required | no | usually yes |\n| Network dependency | no | yes |\n| Per-request cost | no | usually yes |\n| Latency variability | low, in-process | network-dependent |\n\n## Installation\n\n```bash\nnpm install @aialok/lakhua\n# or\nbun add @aialok/lakhua\n```\n\n## Quick Start\n\n```ts\nimport { geocode } from \"@aialok/lakhua\";\n\nconst result = geocode(28.6139, 77.2090);\nif (result) {\n  console.log(result.city, result.state);\n}\n```\n\n## API\n\n### Top-level functions (recommended)\n\n```ts\ngeocode(lat: number, lon: number, options?: GeocodeOptions): GeocodeResult | null\ngeocodeH3(h3Index: string, options?: GeocodeOptions): GeocodeResult | null\n```\n\nThese use the internal singleton geocoder — no class instantiation needed.\n\n### `GeocodeOptions`\n\n```ts\ninterface GeocodeOptions {\n  resolution?: number;  // H3 resolution for geocode(lat, lon). Default: 5\n  fallback?: boolean;   // Walk up to parent resolution on miss. Default: true\n  debug?: boolean;      // Print load and lookup timings. Default: false\n}\n```\n\n### `GeocodeResult`\n\n```ts\ninterface GeocodeResult {\n  city: string;\n  state: string;\n  district?: string;\n  pincode?: string;\n  matched_h3: string;         // H3 cell that matched (may be parent)\n  matched_resolution: number; // Resolution of the matched cell\n}\n```\n\nReturns `null` for invalid input or when no data exists for the given location.\n\n### Advanced class APIs\n\n```ts\nimport { ReverseGeocoder, ReverseGeoDataLoader } from \"@aialok/lakhua\";\n\nReverseGeocoder.getInstance()\nReverseGeoDataLoader.getInstance()\n```\n\nUse these only when you need explicit control — e.g. testing or custom singleton lifecycle.\n\n## Examples\n\n### Coordinate lookup\n\n```ts\nimport { geocode } from \"@aialok/lakhua\";\n\nconst result = geocode(12.9716, 77.5946); // Bengaluru\nif (result) {\n  console.log(result.city, result.state, result.pincode);\n}\n```\n\n### Direct H3 lookup\n\n```ts\nimport { geocodeH3 } from \"@aialok/lakhua\";\n\nconst result = geocodeH3(\"8560145bfffffff\");\nif (result) {\n  console.log(result.city);\n}\n```\n\n### Debug mode\n\n```ts\nimport { geocode } from \"@aialok/lakhua\";\n\nconst result = geocode(19.076, 72.8777, { debug: true });\n// prints load + lookup timings to console\n```\n\n### Disable fallback\n\n```ts\nimport { geocode } from \"@aialok/lakhua\";\n\nconst result = geocode(28.6139, 77.2090, { fallback: false });\n// only checks resolution 5, no parent lookup\n```\n\n## How It Works\n\n1. Convert `lat, lon` to H3 at resolution 5 (or configured resolution).\n2. Lookup the H3 key in in-memory store.\n3. If not found and fallback is enabled, check parent resolution 4.\n4. Return a result object, or `null` if no match exists.\n\n```text\nlat, lon -> h3(res5) -> in-memory map -> optional parent(res4) -> result/null\n```\n\n## Data Source and Indexing\n\n- Indexing system: [Uber H3](https://h3geo.org/)\n- Geographic source data: OpenStreetMap data by [OpenStreetMap contributors](https://www.openstreetmap.org/copyright)\n- Distribution model: precomputed JSON stores bundled with the package\n\n## Data Coverage\n\n- India-focused dataset\n- H3 resolutions: 4 and 5\n- Fields: `city`, `state`\n- Optional fields: `district`, `pincode` (when available)\n\n## Runtime Compatibility\n\n- Node.js\n- Bun\n\n`@aialok/lakhua` reads packaged JSON files from local filesystem at runtime.\n\n## Performance\n\n- Data is loaded into memory once on first call.\n- Each lookup is a single map read — typically < 1ms.\n- With fallback enabled, up to 2 map reads (resolution 5, then 4).\n\n## Benchmarking\n\nUse `test/performance.test.ts` to benchmark in your own environment.\nWhen publishing numbers, include machine type, runtime version, and warm/cold process context.\n\n## When Not To Use\n\n- You need rooftop-level precision\n- You need global coverage\n- You need live POI or continuously updated location feeds\n\n## Development\n\n```bash\nbun install\nbun run lint\nbun run format\nbun run typecheck\nbun test\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","keywords":["reverse geocoding","offline geocoding","india geocoding","geocoding","geospatial","gis","h3","h3-js","h3 index","openstreetmap","osm","point in polygon","bounding box","admin boundaries","geospatial indexing","coordinates","latitude","longitude","city","state","district","tehsil","postal code","pincode","batch geocoding","location lookup","no api key","free geocoding","india maps"]}