@magmacomputing/tempo-plugin-geo
A dedicated Community plugin for the Tempo ecosystem providing universal geolocation lookup, forward and reverse geocoding gateway, pluggable provider architecture, cultural locale synchronization, and multi-tenant bounded coordinate caching.
For geometric GIS math, Great-Circle navigation, and impossible travel anomaly detection, see @magmacomputing/tempo-plugin-spatial.
Key Features
- Universal Geolocation Lookup: Hardware GPS (browser) or IP-based server lookup via
Tempo.geo.lookup(), cached for 24h. - Forward & Reverse Geocoding:
Tempo.geo.forward(query)converts place names to coordinates;Tempo.geo.reverse(coords)resolves locality metadata. - Pluggable Provider Architecture: Swap geocoding backends (
OpenStreetMapProvider,IpApiProvider,MockGeoProvider) or supply a custom provider viaTempo.geo.setProvider(). - Cultural Locale Synchronization:
t.geoLocate({ setLocale: 'native' })automatically infers BCP-47 locale from resolved country and territory. - Multi-Tenant Bounded Caching: Partitioned coordinate storage with 24h TTL and tenant-isolated keys via
Tempo.geo.set()/Tempo.geo.get(). - Immutable Namespace:
Tempo.geois recursively frozen—tamper-proof and zero-mutation.
Installation
bash
npm install @magmacomputing/tempo-plugin-geoQuickstart
Interactive Demo (@magmacomputing/tempo-plugin-geo)
Open in Full REPL↗// 🌍 Live Geolocation & Pluggable Providers (@magmacomputing/tempo-plugin-geo)
// Note: In browser sandbox, resolves browser GPS or IP-based coordinates
const lookup = await Tempo.geo.lookup({ reverse: true });
console.log('Detected City:', lookup.city ?? 'Local City', ',', lookup.country ?? 'Local Country');
console.log('Coordinates:', lookup.lat, lookup.lng);
// Attach coordinates to a Tempo instance:
const localTime = new Tempo('now', { geo: lookup });
console.log('Astronomical Season:', localTime.term.szn);
console.log('Moon Phase:', localTime.term.lunar.phase, localTime.term.lunar.emoji);
// Reverse Geocoding to place details:
const place = await Tempo.geo.reverse({ lat: -33.8688, lng: 151.2093 });
console.log('Reverse Geocoded Place:', place.city, place.country);
return `Located at ${lookup.city ?? 'Local City'} (${lookup.lat?.toFixed(2)}°, ${lookup.lng?.toFixed(2)}°)`;typescript
import { Tempo } from '@magmacomputing/tempo';
import { GeoPlugin } from '@magmacomputing/tempo-plugin-geo';
Tempo.use(GeoPlugin);
// Universal Geolocation Lookup (cached for 24h)
const lookup = await Tempo.geo.lookup();
console.log(lookup.lat, lookup.lng, lookup.city);
// Enrich a Tempo instance with physical reality and native cultural locale
const t = new Tempo('2026-06-21T12:00:00Z', {
geo: { lat: 30.0444, lng: 31.2357, country: 'EG' } // Cairo, Egypt
});
const localTime = await t.geoLocate({ setLocale: 'native' });
console.log(localTime.geo?.latitude, localTime.geo?.longitude);
console.log(localTime.locale); // 'ar-EG'
console.log(localTime.format({ dateStyle: 'full' })); // 'الأحد، ٢١ يونيو ٢٠٢٦' (Arabic Egyptian culture)Auto-Installation (Side-Effect Import)
typescript
import { Tempo } from '@magmacomputing/tempo';
import '@magmacomputing/tempo-plugin-geo/install';Reverse Geocoding and Instance Enrichment
typescript
import { Tempo } from '@magmacomputing/tempo';
import { GeoPlugin } from '@magmacomputing/tempo-plugin-geo';
Tempo.use(GeoPlugin);
// Reverse geocode coordinates to place details (using built-in lookup or custom GeoProvider)
const place = await Tempo.geo.reverse({ lat: -33.8688, lng: 151.2093 });
console.log(place?.city, place?.country); // Sydney, AU
// Or enrich an existing instance via t.geoLocate({ reverse: true })
const t = new Tempo({ geo: { lat: -33.8688, lng: 151.2093 } });
const enriched = await t.geoLocate({ reverse: true });
console.log(enriched.geo?.city, enriched.geo?.country); // Sydney, AUAPI Reference
Which Method Should I Choose?
| Goal | Method to Use | Input | Output |
|---|---|---|---|
| "Where is this machine / user right now?" | await Tempo.geo.lookup({ refresh: true }) | None / { refresh: true } | Fresh { latitude, longitude, city, ... } |
| "Convert place name / address to coordinates" | await Tempo.geo.forward("Paris") | Address query string | { latitude, longitude, ... } |
| "Convert GPS coordinates to street / city / country" | await Tempo.geo.reverse({ lat, lng }) | Coordinate object | { city, country, ... } |
| "Extract or safely normalize coordinates from any input" | await Tempo.geo.resolve(input) | Instance, config, or object | Canonical { latitude, longitude, ... } |
| "Localize a Tempo instance with timezone & cultural calendar" | await t.geoLocate() | Existing Tempo instance | New enriched Tempo instance |
Comprehensive Tempo.geo API Surface
| Method / Property | Category | Description |
|---|---|---|
Tempo.geo.lookup(opts?) | Lookup | Universal geolocation lookup (browser hardware GPS or server IP lookup) cached for 24h. Supports { refresh: true }. |
Tempo.geo.forward(query, opts?) | Geocoding | Forward geocodes place query string to coordinates using active provider. |
Tempo.geo.reverse(coords, opts?) | Geocoding | Reverse geocodes coordinates to locality/address metadata (city, country, displayName, etc.) using active provider. |
Tempo.geo.setProvider(provider) | Provider Gateway | Sets custom geolocation/geocoding provider gateway (e.g. OpenStreetMap, Mapbox, internal IP proxy). |
Tempo.geo.getProvider() | Provider Gateway | Retrieves the active custom geolocation provider. |
Tempo.geo.resolve(input, opts?) | Utility | Asynchronously resolves coordinates from an instance, configuration, or ambient storage cache. |
Tempo.geo.coerce(input) | Geometry | Pure function normalizing various coordinate formats (lat/lng, latitude/longitude, tuples, etc.) into a canonical GeoConfig. |
resolveCulturalLocale(locale?, country?, mode?) | Cultural Sync | Standalone function resolving synchronized BCP 47 locale from current locale and ISO country code/name. |
Tempo.geo.get(keyOrOpts?) | Storage | Reads stored coordinates for the specified tenant/IP or ambient default. |
Tempo.geo.set(coords, ttl?, keyOrOpts?) | Storage | Sets coordinates in storage with an optional custom TTL (default: 24h) and multi-tenant partitioning. |
Tempo.geo.clear(keyOrOpts?) | Storage | Purges stored coordinates from storage. |
Tempo.geo.current | Storage | Read-only getter returning the active global/ambient coordinates snapshot (getStashedGeo() ?? Tempo.config.geo). |
Tempo.geo.server(opts?) | Low-Level | Low-level server-side IP geolocation handler. |
Tempo.geo.browser(opts?) | Low-Level | Low-level browser Geolocation API handler. |
Fluent Instance Methods
| Instance Method | Description |
|---|---|
t.geoLocate(opts?) | Asynchronously resolves physical location (with optional reverse geocoding { reverse: true } and cultural locale synchronization { setLocale: true }) and returns a new enriched Tempo instance. |
t.geoLookup(opts?) | Resolves coordinates for this instance via explicit coordinates or automatic IP/hardware lookup. |
Security & Immutability
In keeping with Tempo's strict immutability principles, the Tempo.geo namespace is fully locked down:
- Deeply Frozen: The entire
Tempo.geonamespace and attached utilities are recursively frozen viadeepFreeze. - Tamper-Proof: Protected against reassignment or monkey-patching.
- Pure Instance Operations: Instance methods like
t.geoLocate()return new, enrichedTempoinstances, preserving the immutability of the original instance.
Topic Guides
Explore detailed guides on specific capabilities:
- Provider Gateway & Geocoding: Forward geocoding, reverse geocoding, custom geocoding providers (
OpenStreetMapProvider,IpApiProvider,MockGeoProvider), and call-site overrides. - Cultural Synchronization: Automatic cultural locale inference (
setLocale: true/'native'), territorial language resolution, and internationalization synergy. - Storage & Multi-Tenant Caching: Ambient coordinate caching, 24h TTL
BoundedCache, tenant isolation, and server vs. client operational warnings. - Production Use Cases & Architectural Patterns: Multi-tenant SaaS localization, pluggable geocoding gateways, isolated tenant storage caching, and server edge middleware.
License
This is a Community plugin. It is completely free and open-source for personal and commercial use under the MIT license.