npm package: @flightdev/geo
Description: Geolocation utilities for Flight Framework - read edge provider headers
Author: Flight Framework Team
Latest version: 0.1.2

# @flight-framework/geo

Geolocation utilities for Flight Framework. Read edge provider headers to extract user location data.

## Installation

```bash
npm install @flight-framework/geo
```

## Quick Start

```typescript
// Import the package and register an adapter
import { getGeo, registerGeoAdapter } from '@flight-framework/geo';
import { cloudflareAdapter } from '@flight-framework/geo/cloudflare';

// Register the adapter for your edge provider
registerGeoAdapter(cloudflareAdapter);

// In a server component or loader
export async function loader({ request }) {
    const geo = getGeo(request);

    return {
        country: geo.country,
        city: geo.city,
        currency: geo.country === 'AR' ? 'ARS' : 'USD',
    };
}
```

## Adapters

Install only the adapter for your edge provider:

| Provider | Import |
|----------|--------|
| Cloudflare | `@flight-framework/geo/cloudflare` |
| Vercel | `@flight-framework/geo/vercel` |
| Netlify | `@flight-framework/geo/netlify` |
| Fastly | `@flight-framework/geo/fastly` |

```typescript
// Cloudflare Workers
import { cloudflareAdapter } from '@flight-framework/geo/cloudflare';

// Vercel Edge
import { vercelAdapter } from '@flight-framework/geo/vercel';

// Netlify Edge Functions
import { netlifyAdapter } from '@flight-framework/geo/netlify';

// Fastly Compute
import { fastlyAdapter } from '@flight-framework/geo/fastly';
```

## API Reference

### getGeo(request)

Get geolocation data from a Request object.

```typescript
const geo = getGeo(request);

console.log(geo.country);    // "AR"
console.log(geo.city);       // "Buenos Aires"
console.log(geo.isEU);       // false
console.log(geo.latitude);   // -34.6037
console.log(geo.longitude);  // -58.3816
```

### GeoData Interface

```typescript
interface GeoData {
    country: string | null;       // ISO 3166-1 alpha-2 code
    countryName: string | null;   // Full country name
    region: string | null;        // Region/state code
    regionName: string | null;    // Region/state name
    city: string | null;
    postalCode: string | null;
    latitude: number | null;
    longitude: number | null;
    timezone: string | null;      // IANA timezone
    continent: string | null;     // Continent code
    isEU: boolean;                // EU country flag
    asn: number | null;           // Autonomous System Number
    organization: string | null;  // ISP name
}
```

### Client-Side Usage

Inject geo data during SSR for client access:

```typescript
// Server
import { getGeo, generateGeoScript } from '@flight-framework/geo';

const geo = getGeo(request);
const script = generateGeoScript(geo);
// Include in HTML: <script>window.__FLIGHT_GEO__={...}</script>

// Client
import { useGeo } from '@flight-framework/geo';

function LocationBanner() {
    const geo = useGeo();
    return <p>You are visiting from {geo.city}, {geo.country}</p>;
}
```

### Middleware

Add geo data to request context:

```typescript
import { createGeoMiddleware } from '@flight-framework/geo';

app.use(createGeoMiddleware());

// In handlers, access via ctx.locals.geo
app.get('/', (ctx) => {
    const geo = ctx.locals.geo;
    // ...
});
```

### Custom Adapters

Create adapters for other edge providers:

```typescript
import { registerGeoAdapter } from '@flight-framework/geo';
import type { GeoAdapter } from '@flight-framework/geo';

const myAdapter: GeoAdapter = {
    name: 'my-provider',
    priority: 50,
    detect: (headers) => headers.has('x-my-provider-country'),
    parse: (headers) => ({
        country: headers.get('x-my-provider-country'),
        // ... other fields
    }),
};

registerGeoAdapter(myAdapter);
```

## Utilities

```typescript
import {
    hasGeoData,
    formatGeoData,
    calculateDistance
} from '@flight-framework/geo';

// Check if geo data was successfully parsed
if (hasGeoData(geo)) {
    console.log('Location detected');
}

// Format for display
const location = formatGeoData(geo); // "Buenos Aires, BA, AR"

// Calculate distance between two points (km)
const distance = calculateDistance(lat1, lon1, lat2, lon2);
```

## License

MIT