npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@microsoft/power-apps-native-bglocation

v0.2.0

Published

React Native geolocation library with native tracking and app-scoped durable storage for pending LocationData.

Readme

@microsoft/power-apps-native-bglocation

React Native geolocation library for Power Apps wrap apps. Captures GPS in a native tracking service, stores rows durably, and uploads them to Dataverse via native sync adapters using a single OData $batch POST.

Architecture

JS (thin)                          Native (owns everything)
─────────                          ────────────────────────
geoService(dataSource, app_id)  →  configure + permissions + start tracking
                                   GPS provider → durable insert
                                   AuthServiceFactory → MsalAuthService / OneAuthService
                                   DataverseLocationSyncAdapter → $batch POST
                                   inline upload after every fix

| | Foreground | Background | App killed | |---|---|---|---| | GPS capture | ✅ every fix | ✅ if trackInBackground + permission | ✅ if persistAcrossRestarts | | Upload | ✅ inline after each fix | ✅ inline after each fix | ✅ resumes on next fix after restart |

Install

npm install @microsoft/power-apps-native-bglocation

Autolinking handles Android and iOS.

Quick start

import { geoService, ConnectionType, AuthMethod } from '@microsoft/power-apps-native-bglocation';

const geo = geoService(
  {
    authMethod: AuthMethod.MSAL,
    connectionType: ConnectionType.Dataverse,
    connectionUrl: 'https://org2c30b92b.crm8.dynamics.com',
    trackInBackground: true,
    persistAcrossRestarts: false,
  },
  'my-wrap-app',
);

await geo.startTracking();
await geo.isTracking();
await geo.stopTracking();

// One-shot current location (no tracking, no storage, no upload)
const location = await geo.getCurrentLocation();
console.log(location.latitude, location.longitude);

startTracking() handles everything: sends config to native, requests permissions, then starts native tracking.

getCurrentLocation() requests permissions if needed and returns a single GPS fix — independent of tracking, no Dataverse config required.

API

| Method | Returns | Description | |---|---|---| | geoService(dataSource, app_id) | BgLocationClient | Create a configured client | | startTracking() | string | Configure + permissions + GPS start | | stopTracking() | string | Stop GPS + clear active flag | | isTracking() | boolean | Persisted flag | | getPermissionStatus() | PermissionStatus | { foreground: boolean, background: boolean } | | getCurrentLocation() | LocationData | One-shot GPS fix (requests permissions automatically) |

Configuration

All fields on DataverseDataSource:

| Field | Required | Default | Description | |---|---|---|---| | authMethod | ✅ | — | AuthMethod.MSAL or AuthMethod.OneAuth | | connectionType | ✅ | — | ConnectionType.Dataverse | | connectionUrl | ✅ | — | Dataverse environment URL | | trackInBackground | ✅ | — | Keep GPS alive when the app is backgrounded | | persistAcrossRestarts | ✅ | — | Resume after reboot / app relaunch | | tableName | | msdyn_locationrecords | Dataverse entity set name | | fieldMap | | see below | Location field → Dataverse column mapping | | intervalMs | | 30000 | GPS update interval in ms | | distanceFilterMeters | | 10 | Minimum movement before a new fix | | notification | | auto | Android foreground notification { title, body } |

Default Dataverse table

If you don't pass tableName or fieldMap, the library uses these defaults (defined in src/constants/dataverse.ts):

DATAVERSE_DEFAULT_TABLE = 'msdyn_locationrecords'

DATAVERSE_DEFAULT_FIELD_MAP = {
  id:        'msdyn_locationrecordid',
  appId:     'msdyn_appid',
  latitude:  'msdyn_latitude',
  longitude: 'msdyn_longitude',
  altitude:  'msdyn_altitude',
  accuracy:  'msdyn_accuracy',
  heading:   'msdyn_heading',
  speed:     'msdyn_speed',
  timestamp: 'msdyn_timestamp',
}

Using your own table

const geo = geoService(
  {
    authMethod: AuthMethod.MSAL,
    connectionType: ConnectionType.Dataverse,
    connectionUrl: 'https://myorg.crm.dynamics.com',
    trackInBackground: true,
    persistAcrossRestarts: false,
    tableName: 'myprefix_gpstracking',
    fieldMap: {
      id:        'myprefix_trackingid',
      appId:     'myprefix_appid',
      latitude:  'myprefix_lat',
      longitude: 'myprefix_lng',
      timestamp: 'myprefix_capturedat',
    },
  },
  'my-app',
);

Dataverse system-managed user columns such as created by, modified by, owner, and owning user are set by Dataverse from the authenticated caller.

Available internal field names: id, appId, latitude, longitude, altitude, accuracy, heading, speed, timestamp.

Auth

Native resolves tokens via AuthServiceFactoryMsalAuthService or OneAuthService. Both implement LocationAuthService (acquireToken(resourceUrl)). Token acquisition is reflection based, so the package does not take a compile-time dependency on the host auth SDK.

Native sync architecture

ios/
  auth/
    LocationAuthService.h
    OneAuthService.h/.m
    MsalAuthService.h/.m
    AuthServiceFactory.h/.m
  sync/providers/
    BaseLocationSyncAdapter.h/.m
    DataverseLocationSyncAdapter.h/.m
    LocationSyncAdapterFactory.h/.m

Upload is inline: every GPS fix triggers durable insert → token acquire → $batch POST → delete uploaded rows.

Extension SDK

This package also exports GeolocationExtension — an INativeExtension implementation for the PAM HostingSDK. Canvas apps can trigger geolocation commands via the CordovaV2 bridge without importing the package directly.

import { GeolocationExtension } from '@microsoft/power-apps-native-bglocation';

// Register with the HostingSDK's MessageReceiverOrchestrator
const extension = new GeolocationExtension(context);
orchestrator.register(extension);

The PCF sends JSON messages through the bridge:

{ "command": "startTracking", "app_id": "my-app", "dataSource": { ... } }
{ "command": "stopTracking" }
{ "command": "isTracking" }
{ "command": "getCurrentLocation" }
{ "command": "getPermissionStatus" }

The extension uses the same BgLocationClient and geoService() internally — no separate code path.

Status

  • Android — functional.
  • iOS — Objective-C implementation mirrors the Android architecture. It still needs device-side Xcode validation on macOS.

Validation

npm run build  --prefix packages/powerapps-geolocation-control
npm run test   --prefix packages/powerapps-geolocation-control
npm run lint   --prefix packages/powerapps-geolocation-control