← All @molecule/* packages · App templates

@molecule/app-geolocation

Native · native · App (browser) · v1.0.1 · Apache-2.0

Geolocation interface for molecule.dev

npm install @molecule/app-geolocation

npm · Source on GitHub

How it works

@molecule/app-geolocation bridges the native core to the native platform layer of the app.

import {
  checkPermission,
  clearWatch,
  getCurrentPosition,
  requestPermission,
  watchPosition,
} from '@molecule/app-geolocation'

async function showNearby(): Promise<void> {
  if ((await checkPermission()) !== 'granted') {
    const p = await requestPermission() // from a user gesture
    if (p !== 'granted') return // offer manual address entry instead
  }
  const { coords } = await getCurrentPosition({ enableHighAccuracy: false })
  console.log(coords.latitude, coords.longitude)
}

function trackRun(onPoint: (lat: number, lng: number) => void): () => void {
  const watchId = watchPosition((pos) => onPoint(pos.coords.latitude, pos.coords.longitude))
  return () => clearWatch(watchId) // ALWAYS clear on unmount
}

Works with: @molecule/app-bond

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Geolocation interface for molecule.dev.

Provides a unified API for GPS/location services that works across different platforms (web, native containers, etc.): one-off reads (getCurrentPosition), continuous watches (watchPosition / clearWatch), a permission flow (checkPermission / requestPermission), and a pure calculateDistance helper.

Quick Start

import {
  checkPermission,
  clearWatch,
  getCurrentPosition,
  requestPermission,
  watchPosition,
} from '@molecule/app-geolocation'

async function showNearby(): Promise<void> {
  if ((await checkPermission()) !== 'granted') {
    const p = await requestPermission() // from a user gesture
    if (p !== 'granted') return // offer manual address entry instead
  }
  const { coords } = await getCurrentPosition({ enableHighAccuracy: false })
  console.log(coords.latitude, coords.longitude)
}

function trackRun(onPoint: (lat: number, lng: number) => void): () => void {
  const watchId = watchPosition((pos) => onPoint(pos.coords.latitude, pos.coords.longitude))
  return () => clearWatch(watchId) // ALWAYS clear on unmount
}

Type

native

Installation

npm install @molecule/app-geolocation @molecule/app-bond

API

Interfaces

Coordinates

Geographic coordinates (latitude, longitude, accuracy, altitude, heading, speed).

interface Coordinates {
  /**
   * Latitude in decimal degrees.
   */
  latitude: number

  /**
   * Longitude in decimal degrees.
   */
  longitude: number

  /**
   * Accuracy in meters.
   */
  accuracy: number

  /**
   * Altitude in meters (if available).
   */
  altitude?: number

  /**
   * Altitude accuracy in meters (if available).
   */
  altitudeAccuracy?: number

  /**
   * Heading in degrees (0-360, if available).
   */
  heading?: number

  /**
   * Speed in m/s (if available).
   */
  speed?: number
}

CreateWebGeolocationProviderOptions

Options for creating a web geolocation provider.

interface CreateWebGeolocationProviderOptions {
  /**
   * Optional translation function for i18n support.
   * When provided, error messages will be passed through this function.
   */
  t?: TranslateFn
}

GeolocationError

Geolocation error with code (permission_denied, position_unavailable, timeout) and message.

interface GeolocationError {
  /**
   * Error code.
   */
  code: 'permission_denied' | 'position_unavailable' | 'timeout' | 'unknown'

  /**
   * Error message.
   */
  message: string
}

GeolocationProvider

Geolocation provider interface.

All geolocation providers must implement this interface.

interface GeolocationProvider {
  /**
   * Checks the current permission status.
   * @returns The current location permission state.
   */
  checkPermission(): Promise<LocationPermission>

  /**
   * Requests location permission.
   */
  requestPermission(): Promise<LocationPermission>

  /**
   * Gets the current position.
   */
  getCurrentPosition(options?: PositionOptions): Promise<Position>

  /**
   * Watches position changes.
   * Returns an ID that can be used to stop watching.
   */
  watchPosition(
    onSuccess: PositionCallback,
    onError?: ErrorCallback,
    options?: WatchOptions,
  ): string

  /**
   * Stops watching position changes.
   */
  clearWatch(watchId: string): void

  /**
   * Calculates distance between two coordinates in meters.
   * @returns The distance in meters between the two coordinates.
   */
  calculateDistance(
    from: { latitude: number; longitude: number },
    to: { latitude: number; longitude: number },
  ): number
}

Position

Geolocation position containing coordinates and a timestamp.

interface Position {
  /**
   * Geographic coordinates.
   */
  coords: Coordinates

  /**
   * Timestamp of the position.
   */
  timestamp: number
}

PositionOptions

Options for position queries (high accuracy mode, max cached age, timeout).

interface PositionOptions {
  /**
   * Enable high accuracy mode.
   */
  enableHighAccuracy?: boolean

  /**
   * Maximum age of cached position in ms.
   */
  maximumAge?: number

  /**
   * Timeout in ms.
   */
  timeout?: number
}

WatchOptions

Watch options (extends position options).

interface WatchOptions extends PositionOptions {
  /**
   * Minimum distance change in meters before triggering update.
   */
  distanceFilter?: number
}

Types

ErrorCallback

Callback invoked when a geolocation error occurs.

type ErrorCallback = (error: GeolocationError) => void

LocationPermission

Location permission state: granted, denied, or prompt (not yet requested).

type LocationPermission = 'granted' | 'denied' | 'prompt'

PositionCallback

Callback invoked with a resolved geographic position.

type PositionCallback = (position: Position) => void

Functions

calculateDistance(from, to)

Calculates the distance between two geographic coordinates.

function calculateDistance(
  from: { latitude: number; longitude: number },
  to: { latitude: number; longitude: number },
): number
  • from — The starting coordinate.
  • from.latitude — The starting latitude in decimal degrees.
  • from.longitude — The starting longitude in decimal degrees.
  • to — The destination coordinate.
  • to.latitude — The destination latitude in decimal degrees.
  • to.longitude — The destination longitude in decimal degrees.

Returns: The distance in meters between the two coordinates.

checkPermission()

Checks the current location permission status.

function checkPermission(): Promise<LocationPermission>

Returns: The current location permission state.

clearWatch(watchId)

Stops watching position changes for the given watch.

function clearWatch(watchId: string): void
  • watchId — The identifier returned by {@link watchPosition}.

Returns: void

createWebGeolocationProvider(options)

Creates a web-based geolocation provider using the browser Geolocation API.

function createWebGeolocationProvider(
  options?: CreateWebGeolocationProviderOptions,
): GeolocationProvider
  • options — Provider configuration including optional i18n translation function.

Returns: A {@link GeolocationProvider} backed by the browser Geolocation API.

getCurrentPosition(options)

Gets the device's current geographic position.

function getCurrentPosition(options?: PositionOptions): Promise<Position>
  • options — Configuration for accuracy, timeout, and caching behavior.

Returns: The current position with coordinates and timestamp.

getProvider()

Gets the current geolocation provider, falling back to the web implementation.

function getProvider(): GeolocationProvider

Returns: The active geolocation provider instance.

hasProvider()

Checks if a geolocation provider has been bonded.

function hasProvider(): boolean

Returns: Whether a geolocation provider is currently registered.

haversineDistance(from, to)

Calculates the distance between two coordinates using the Haversine formula.

function haversineDistance(
  from: { latitude: number; longitude: number },
  to: { latitude: number; longitude: number },
): number
  • from — The starting coordinate.
  • from.latitude — The starting latitude in decimal degrees.
  • from.longitude — The starting longitude in decimal degrees.
  • to — The destination coordinate.
  • to.latitude — The destination latitude in decimal degrees.
  • to.longitude — The destination longitude in decimal degrees.

Returns: The distance in meters between the two coordinates.

requestPermission()

Requests location permission from the user.

function requestPermission(): Promise<LocationPermission>

Returns: The resulting permission state after the request.

setProvider(provider)

Sets the geolocation provider implementation.

function setProvider(provider: GeolocationProvider): void
  • provider — The provider implementation.

toRadians(degrees)

Converts degrees to radians.

function toRadians(degrees: number): number
  • degrees — The angle in degrees to convert.

Returns: The angle in radians.

watchPosition(onSuccess, onError, options)

Watches for continuous position changes.

function watchPosition(
  onSuccess: PositionCallback,
  onError?: ErrorCallback,
  options?: WatchOptions,
): string
  • onSuccess — Callback invoked with each new position update.
  • onError — Callback invoked when a geolocation error occurs.
  • options — Configuration for accuracy, distance filter, and timing.

Returns: A watch identifier that can be passed to {@link clearWatch} to stop watching.

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-bond ^1.0.1

Runtime Dependencies

  • @molecule/app-bond

Location is sensitive, permissioned data — treat it carefully:

  • No wiring is needed on web: the first accessor call silently bonds the built-in browser provider (createWebGeolocationProvider). No native bond package ships with molecule — in a native container wire your own GeolocationProvider via setProvider() BEFORE the first geolocation call, or the web fallback gets bonded instead.
  • HTTPS (secure context) is required on web — on plain http the browser reports permission denied without ever prompting. localhost is exempt.
  • Request permission at the point of use, from a user gesture (requestPermission), NOT on load. An unexpected prompt gets denied, and a denied permission is REMEMBERED (no re-prompt — only settings).
  • Check checkPermission first and handle denial — offer a manual fallback (type an address) rather than blocking; never assume granted.
  • Always clearWatch a watchPosition when the screen unmounts — a live GPS watch drains the battery fast. Use getCurrentPosition for a one-off read.
  • Capture only when needed and don't retain/transmit more precision than the feature requires — it's personal data.

Translations

Translation strings are provided by @molecule/app-locales-geolocation.