@nextuneapps/geofencing
v0.1.8
Published
Express middleware and routes for NextUne location and exchange-rate data, with TypeScript types.
Readme
@nextuneapps/geofencing
Express (Node.js) library paired with the Django package nextune-geofencing: optional middleware that attaches location-related fields to each request, optional mounted routes, and TypeScript types for the payload shapes your app works with. Published on npm under the nextuneapps org.
Install
npm install @nextuneapps/geofencingexpress is a peer dependency (v4 or v5). Node 18+ (uses fetch). Published dist/ is CommonJS so it loads with require() and works with typical Express setups; TypeScript and bundlers can still import it.
Types (IDE-friendly payloads)
Import types from the package root so handlers, serializers, and tests stay aligned with the JSON you handle:
import type {
NextuneLocationPayload,
NextuneGeo,
NextuneGeofencing,
ExchangeRatesResponse,
ExchangeRatesBlock,
GeofencingRouterErrorBody,
} from "@nextuneapps/geofencing";Location (NextuneLocationPayload) — returned by the GET …/whoami route (caller IP), POST …/ip, and the same shape from your own proxies or clients. Narrow unknown bodies like this:
import type {
NextuneLocationPayload,
NextuneGeo,
NextuneGeofencing,
} from "@nextuneapps/geofencing";
function summarizeLocation(body: unknown) {
const data = body as NextuneLocationPayload;
const geo: NextuneGeo | undefined = data.geo;
const gf: NextuneGeofencing | null | undefined = data.geofencing;
return {
currency: gf?.currency ?? geo?.currency,
country: gf?.country_code ?? geo?.country,
payment_methods: data.payment_methods,
};
}Exchange rates — same idea for FX payloads:
import type { ExchangeRatesResponse, ExchangeRatesBlock } from "@nextuneapps/geofencing";
function ratesTable(body: unknown, baseCode: string) {
const payload = body as ExchangeRatesResponse;
const block: ExchangeRatesBlock | undefined = payload[baseCode.toUpperCase()];
return block?.rates;
}Middleware req — after geofencingMiddleware(), req.geofencing is typed (see the package’s Express module augmentation).
import express from "express";
import { geofencingMiddleware } from "@nextuneapps/geofencing";
const app = express();
app.use(geofencingMiddleware());
app.get("/checkout", (req, res) => {
const gf = req.geofencing;
res.json({
country: req.country_code,
country_name: req.country_name,
currency: gf?.currency,
payment_hint: gf?.currency_symbol,
});
});Router errors — treat error JSON from the package router consistently:
import type { GeofencingRouterErrorBody } from "@nextuneapps/geofencing";
function isRouterError(x: unknown): x is GeofencingRouterErrorBody {
return typeof x === "object" && x !== null && "error" in x;
}Middleware
Attaches req.geofencing, req.country_code, and req.country_name (same field names as the Django package).
import express from "express";
import { geofencingMiddleware } from "@nextuneapps/geofencing";
const app = express();
app.use(geofencingMiddleware());
app.get("/example", (req, res) => {
res.json({
country: req.country_code,
name: req.country_name,
geofencing: req.geofencing,
});
});Routes
Mount the router and JSON parsing for POST /ip:
import express from "express";
import { createGeofencingRouter } from "@nextuneapps/geofencing";
const app = express();
app.use(express.json());
app.use("/v1/geo", createGeofencingRouter());GET /v1/geo/whoami— resolves the caller’s IP, then returns location JSON asNextuneLocationPayload. Commonly used for “current visitor” country, currency, andgeofencing.POST /v1/geo/ip— body{ "ip": "203.0.113.1" }→ same location JSON shape (NextuneLocationPayload).GET /v1/geo/exchange-rates/:currency— three-letter ISO code (e.g.KES) → exchange-rate JSON (ExchangeRatesResponse).
