@trap_stevo/geotide
Version:
Fuses IP intelligence, reverse geocoding, and radio/Wi-Fi triangulation into a single, real-time, precision-crafted API. Trace a single packet’s origin, map a million connections, or power real-time location-aware apps with elegance, accuracy, and streami
184 lines (136 loc) • 5.98 kB
Markdown
# 🌊 @trap_stevo/geotide
**The ultimate event-driven, precision-powered geolocation engine — from IP to doorstep, in real-time.**
Fuses IP intelligence, reverse geocoding, and radio/Wi-Fi triangulation into a single, real-time, precision-crafted API.
Trace a single packet’s origin, map a million connections, or power real-time location-aware apps with elegance, accuracy, and streaming insight.
## 🚀 Features
- 🌍 **Multi-Provider IP Intelligence** – Auto-races top geo APIs (`ipwhois`, `ipapi`, `ipinfo`, `ipgeolocation`) with scoring and failover
- 🛰 **Reverse Geocoding** – Converts coordinates to human-readable addresses
- ⚡ **Real-Time Event System** – Subscribe to lookups, cache hits, provider health, and reverse-geocoding events as they happen
- 🧩 **Custom Provider Injection** – Append your own IP lookup, reverse geocoding, or triangulation services
- 📦 **Batch Mode** – Resolve thousands of IPs at once with bounded concurrency and preserved order
- 🛡 **Resilient & Cached** – LRU caching and automatic provider failover for speed and reliability
- 🔍 **Confidence Scoring** – Each lookup is scored for trustworthiness
## 🧠 Use Cases
- Live geolocation dashboards
- Security and fraud prevention
- Multiplayer game region detection
- Content localization and targeting
- Network monitoring and analytics
- Emergency response systems
## ⚙️ System Requirements
| Requirement | Version |
|----------------|----------------------|
| **Node.js** | ≥ 19.x |
| **npm** | ≥ 9.x (recommended) |
| **OS** | Windows, macOS, Linux|
## 🔍 API Specifications
### 🔧 Methods
| Method | Signature | Returns | Description | Async? |
|---|---|---|---|---|
| `lookup(ip)` | `lookup(ip: string)` | `Promise<GeoResult \| null>` | Resolves a public IP into normalized location metadata. Uses provider race + scoring + TTL cache. | **Yes** |
| `lookupMany(ips, opts?)` | `lookupMany(ips: string[], opts?: { concurrency?: number })` | `Promise<(GeoResult \| null)[]>` | Batch IP lookup with bounded concurrency (default = `maxConcurrency`). | **Yes** |
| `reverse(lat, lon, opts?)` | `reverse(lat: number, lon: number, opts?: { deadlineMs?: number, cacheTtlMs?: number })` | `Promise<ReverseResult \| null>` | Reverse-geocodes coordinates to a human address by racing Mapbox/Google/Nominatim with caching. | **Yes** |
| `getClientIP(req)` | `getClientIP(req: IncomingMessage \| Express.Request)` | `string \| null` | Extracts the client's IP from HTTP request headers and connection info, supporting proxies and IPv6 normalization. | **No** |
| `on(event, handler)` | `on(event: GeoTideEvent, handler: (payload: any) => void)` | `this` | Subscribe to real-time events (telemetry, results, cache hits, health). | No |
| `off(event, handler)` | `off(event: GeoTideEvent, handler: Function)` | `this` | Unsubscribe a previously registered listener. | No |
### 📦 Return Types
```ts
type GeoResult = {
source: string; // provider name
ip: string;
city: string | null;
region: string | null;
country: string | null;
org: string | null;
isp: string | null;
loc: string | null; // "lat,lon"
timezone: string | null;
postal: string | null;
flag: string | null; // emoji when available
continent: string | null;
confidence: number; // 0..1
};
type ReverseResult = {
provider: string; // provider name
formatted: string;
components: any;
lat: number;
lon: number;
};
```
### 📡 Events
| Event | Payload | Description |
|---|---|---|
| `lookup:start` | `{ ip }` | A lookup has started. |
| `lookup:cache_hit` | `{ ip, result }` | Result served from cache. |
| `lookup:result` | `{ ip, result }` | Fresh lookup result returned. |
| `provider:success` | `{ provider, ip, durationMs, score }` | A provider returned data successfully. |
| `provider:fail` | `{ provider, ip, error }` | A provider failed. |
| `provider:unhealthy` | `{ provider, reason }` | Provider marked temporarily unhealthy. |
| `reverse:start` | `{ lat, lon }` | Reverse geocoding started. |
| `reverse:cache_hit` | `{ lat, lon, result }` | Reverse geocoding served from cache. |
| `reverse:result` | `{ lat, lon, result }` | Fresh reverse geocoding result returned. |
## 📦 Installation
```bash
npm install @trap_stevo/geotide
```
## 🛠️ Usage
### 🌐 IP Lookup
```js
const GeoTide = require("@trap_stevo/geotide");
const geo = new GeoTide({ enableGeoDebug : true });
const result = await geo.lookup("203.0.113.42");
console.log(result);
// {
// source: 'ipwhois',
// ip: '203.0.113.42',
// city: 'Sample City',
// region: 'Sample Region',
// country: 'Sample Country',
// org: 'Sample ISP Org',
// isp: 'Sample ISP',
// loc: '37.4221,-122.0841',
// timezone: 'America/Los_Angeles',
// postal: '94043',
// flag: '🌍',
// continent: 'North America',
// confidence: 1
// }
```
### 📦 Batch IP Lookup
```js
const results = await geo.lookupMany([
"203.0.113.42",
"8.8.8.8"
]);
console.log(results);
```
### 🗺 Reverse Geocoding
```js
const address = await geo.reverse(40.712776, -74.005974);
console.log(address.formatted);
// "Example Building, 123 Example Street, Sample City, NY, United States"
```
### ⚡ Real-Time Events
```js
geo.on("lookup:result", ({ ip, result }) => {
console.log(`[GeoTide] ${ip} → ${result.city}, ${result.country}`);
});
```
## 📜 License
See License in [LICENSE.md](./LICENSE.md)
> 🌊 **GeoTide — The Pulse of the Planet, in Real-Time.**
> From the ocean of IPs to the pinpoint of a doorstep, GeoTide flows with accuracy, speed, and live awareness.