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

@aialok/lakhua

v1.0.1

Published

Fast, offline reverse geocoding for India

Readme

@aialok/lakhua

Sub-millisecond reverse geocoding for India, fully offline.

No API calls. No network latency. No rate limits.

Built for backend services, cron jobs, and analytics workloads that need deterministic geocode lookups.

npm License: MIT

Features

  • 📍 converts lat, lon to city, state, optional district and pincode
  • 🔢 supports direct H3 index lookup via geocodeH3()
  • ↩️ parent-cell fallback (resolution 5 → 4) when exact cell has no data
  • ⚡ data loaded once per process — all subsequent lookups are in-memory map reads
  • 🐛 optional debug mode traces load time and per-lookup timing
  • 🔷 TypeScript-first — full type definitions included

Why Not Hosted APIs?

| Feature | @aialok/lakhua | Hosted API | |---|---|---| | Works offline | yes | no | | API key required | no | usually yes | | Network dependency | no | yes | | Per-request cost | no | usually yes | | Latency variability | low, in-process | network-dependent |

Installation

npm install @aialok/lakhua
# or
bun add @aialok/lakhua

Quick Start

import { geocode } from "@aialok/lakhua";

const result = geocode(28.6139, 77.2090);
if (result) {
  console.log(result.city, result.state);
}

API

Top-level functions (recommended)

geocode(lat: number, lon: number, options?: GeocodeOptions): GeocodeResult | null
geocodeH3(h3Index: string, options?: GeocodeOptions): GeocodeResult | null

These use the internal singleton geocoder — no class instantiation needed.

GeocodeOptions

interface GeocodeOptions {
  resolution?: number;  // H3 resolution for geocode(lat, lon). Default: 5
  fallback?: boolean;   // Walk up to parent resolution on miss. Default: true
  debug?: boolean;      // Print load and lookup timings. Default: false
}

GeocodeResult

interface GeocodeResult {
  city: string;
  state: string;
  district?: string;
  pincode?: string;
  matched_h3: string;         // H3 cell that matched (may be parent)
  matched_resolution: number; // Resolution of the matched cell
}

Returns null for invalid input or when no data exists for the given location.

Advanced class APIs

import { ReverseGeocoder, ReverseGeoDataLoader } from "@aialok/lakhua";

ReverseGeocoder.getInstance()
ReverseGeoDataLoader.getInstance()

Use these only when you need explicit control — e.g. testing or custom singleton lifecycle.

Examples

Coordinate lookup

import { geocode } from "@aialok/lakhua";

const result = geocode(12.9716, 77.5946); // Bengaluru
if (result) {
  console.log(result.city, result.state, result.pincode);
}

Direct H3 lookup

import { geocodeH3 } from "@aialok/lakhua";

const result = geocodeH3("8560145bfffffff");
if (result) {
  console.log(result.city);
}

Debug mode

import { geocode } from "@aialok/lakhua";

const result = geocode(19.076, 72.8777, { debug: true });
// prints load + lookup timings to console

Disable fallback

import { geocode } from "@aialok/lakhua";

const result = geocode(28.6139, 77.2090, { fallback: false });
// only checks resolution 5, no parent lookup

How It Works

  1. Convert lat, lon to H3 at resolution 5 (or configured resolution).
  2. Lookup the H3 key in in-memory store.
  3. If not found and fallback is enabled, check parent resolution 4.
  4. Return a result object, or null if no match exists.
lat, lon -> h3(res5) -> in-memory map -> optional parent(res4) -> result/null

Data Source and Indexing

Data Coverage

  • India-focused dataset
  • H3 resolutions: 4 and 5
  • Fields: city, state
  • Optional fields: district, pincode (when available)

Runtime Compatibility

  • Node.js
  • Bun

@aialok/lakhua reads packaged JSON files from local filesystem at runtime.

Performance

  • Data is loaded into memory once on first call.
  • Each lookup is a single map read — typically < 1ms.
  • With fallback enabled, up to 2 map reads (resolution 5, then 4).

Benchmarking

Use test/performance.test.ts to benchmark in your own environment. When publishing numbers, include machine type, runtime version, and warm/cold process context.

When Not To Use

  • You need rooftop-level precision
  • You need global coverage
  • You need live POI or continuously updated location feeds

Development

bun install
bun run lint
bun run format
bun run typecheck
bun test

License

MIT