@wayq/beekon-rn 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/BeekonRn.podspec +1 -1
  2. package/README.md +91 -39
  3. package/android/build.gradle +9 -4
  4. package/android/src/main/java/in/wayq/beekonrn/BeekonRnModule.kt +306 -60
  5. package/ios/BeekonRn.mm +90 -24
  6. package/ios/BeekonRn.swift +360 -60
  7. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/BeekonKit +0 -0
  8. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Info.plist +0 -0
  9. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.abi.json +7521 -1312
  10. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  11. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.swiftinterface +191 -40
  12. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/BeekonKit +0 -0
  13. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Info.plist +0 -0
  14. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.abi.json +7521 -1312
  15. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  16. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.swiftinterface +191 -40
  17. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.abi.json +7521 -1312
  18. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  19. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +191 -40
  20. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/_CodeSignature/CodeResources +2 -80
  21. package/lib/module/NativeBeekonRn.js +22 -7
  22. package/lib/module/NativeBeekonRn.js.map +1 -1
  23. package/lib/module/beekon.js +198 -46
  24. package/lib/module/beekon.js.map +1 -1
  25. package/lib/module/index.js.map +1 -1
  26. package/lib/module/internal/mappers.js +122 -28
  27. package/lib/module/internal/mappers.js.map +1 -1
  28. package/lib/module/types/config.js +2 -0
  29. package/lib/module/types/enums.js +2 -0
  30. package/lib/module/types/enums.js.map +1 -0
  31. package/lib/module/types/error.js +10 -4
  32. package/lib/module/types/error.js.map +1 -1
  33. package/lib/module/types/geofence.js +2 -0
  34. package/lib/module/types/geofence.js.map +1 -0
  35. package/lib/module/types/location.js +2 -0
  36. package/lib/module/types/sync.js +2 -0
  37. package/lib/module/types/sync.js.map +1 -0
  38. package/lib/typescript/src/NativeBeekonRn.d.ts +102 -20
  39. package/lib/typescript/src/NativeBeekonRn.d.ts.map +1 -1
  40. package/lib/typescript/src/beekon.d.ts +81 -33
  41. package/lib/typescript/src/beekon.d.ts.map +1 -1
  42. package/lib/typescript/src/index.d.ts +5 -2
  43. package/lib/typescript/src/index.d.ts.map +1 -1
  44. package/lib/typescript/src/internal/mappers.d.ts +12 -6
  45. package/lib/typescript/src/internal/mappers.d.ts.map +1 -1
  46. package/lib/typescript/src/types/config.d.ts +50 -20
  47. package/lib/typescript/src/types/config.d.ts.map +1 -1
  48. package/lib/typescript/src/types/enums.d.ts +48 -0
  49. package/lib/typescript/src/types/enums.d.ts.map +1 -0
  50. package/lib/typescript/src/types/error.d.ts +11 -5
  51. package/lib/typescript/src/types/error.d.ts.map +1 -1
  52. package/lib/typescript/src/types/geofence.d.ts +36 -0
  53. package/lib/typescript/src/types/geofence.d.ts.map +1 -0
  54. package/lib/typescript/src/types/location.d.ts +22 -8
  55. package/lib/typescript/src/types/location.d.ts.map +1 -1
  56. package/lib/typescript/src/types/state.d.ts +13 -4
  57. package/lib/typescript/src/types/state.d.ts.map +1 -1
  58. package/lib/typescript/src/types/sync.d.ts +27 -0
  59. package/lib/typescript/src/types/sync.d.ts.map +1 -0
  60. package/package.json +4 -5
  61. package/scripts/fetch-beekonkit.sh +5 -5
  62. package/src/NativeBeekonRn.ts +110 -20
  63. package/src/beekon.ts +219 -49
  64. package/src/index.tsx +21 -2
  65. package/src/internal/mappers.ts +187 -30
  66. package/src/types/config.ts +52 -20
  67. package/src/types/enums.ts +64 -0
  68. package/src/types/error.ts +11 -8
  69. package/src/types/geofence.ts +37 -0
  70. package/src/types/location.ts +28 -8
  71. package/src/types/state.ts +13 -3
  72. package/src/types/sync.ts +23 -0
  73. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeDirectory +0 -0
  74. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeRequirements +0 -0
  75. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeResources +0 -296
  76. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeSignature +0 -0
  77. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/_CodeSignature/CodeResources +0 -146
package/BeekonRn.podspec CHANGED
@@ -13,7 +13,7 @@ Pod::Spec.new do |s|
13
13
  # BeekonKit targets iOS 17.0 (uses CLLocationUpdate.liveUpdates). The
14
14
  # consuming app must also target iOS 17.0 or higher.
15
15
  s.platforms = { :ios => "17.0" }
16
- s.source = { :git => "https://github.com/wayqteam/beekon.git", :tag => "v#{s.version}" }
16
+ s.source = { :git => "https://github.com/wayqteam/beekon-rn.git", :tag => "v#{s.version}" }
17
17
 
18
18
  s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
19
19
  # Headers are only for the auto-generated `BeekonRn-Swift.h` interop — keep
package/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  React Native binding for the [Beekon](https://github.com/wayqteam/beekon) location SDK.
4
4
 
5
- A thin pass-through over the native Android (`io.github.wayqteam:beekon`) and iOS (`BeekonKit`) libraries. The public TypeScript surface mirrors the Kotlin / Swift APIs in shape: `configure / start / stop`, callback-backed `state` and `locations` streams, and a `history(from, to)` query.
5
+ A thin pass-through over the native Android (`io.github.wayqteam:beekon`) and iOS (`BeekonKit`) libraries at version **0.0.5**. The public TypeScript surface mirrors the Kotlin / Swift APIs in shape: a 12-method `Beekon` singleton, four callback streams (`state`, `locations`, `geofenceEvents`, `syncStatus`), geofencing, and optional server sync.
6
6
 
7
- Built on the React Native New Architecture (TurboModules + Codegen). The binding is a thin delegation layer — all logic, persistence, and OS integration lives natively. **Writes never cross into JavaScript**: in background the JS engine isn't guaranteed to be alive, so the native libraries own the persistence path end-to-end.
7
+ Built on the React Native New Architecture (TurboModules + Codegen). The binding contains no location logic — all tracking, persistence, geofencing, and OS integration live natively. **Writes never cross into JavaScript**: in the background the JS engine isn't guaranteed to be alive, so the native libraries own the persistence path end-to-end.
8
+
9
+ There is **no `initialize()`** — the native SDKs auto-initialize. `start()` / `stop()` **never throw**: subscribe to `onState` to learn whether tracking is active and why it stopped.
8
10
 
9
11
  ## Requirements
10
12
 
@@ -12,7 +14,7 @@ Built on the React Native New Architecture (TurboModules + Codegen). The binding
12
14
  |---|---|
13
15
  | React Native | 0.76+ (target 0.85) |
14
16
  | iOS | 17.0 |
15
- | Android | API 26 |
17
+ | Android | **API 26** (required by the native AAR) |
16
18
  | New Architecture | required (Old Arch is unsupported) |
17
19
 
18
20
  ## Install
@@ -23,19 +25,17 @@ npm install @wayq/beekon-rn
23
25
  yarn add @wayq/beekon-rn
24
26
  ```
25
27
 
26
- iOS:
28
+ iOS — the package fetches and bundles `BeekonKit.xcframework` (SHA256-verified) during `prepare`, so just install pods:
27
29
 
28
30
  ```sh
29
31
  cd ios && pod install
30
32
  ```
31
33
 
32
- The package bundles `BeekonKit.xcframework` directly no manual SwiftPM setup needed.
33
-
34
- Android: Maven Central is auto-included by the autolinker. The native AAR (`io.github.wayqteam:beekon`) is pulled transitively.
34
+ Android Maven Central is auto-included by the autolinker; the native AAR (`io.github.wayqteam:beekon`) is pulled transitively.
35
35
 
36
36
  ## Permissions
37
37
 
38
- The library does NOT request permissions itself — your app must. Use a library like [`react-native-permissions`](https://github.com/zoontek/react-native-permissions) or platform APIs.
38
+ The library does NOT request permissions — your app must (e.g. via [`react-native-permissions`](https://github.com/zoontek/react-native-permissions) or `PermissionsAndroid`). Foreground location works without background location.
39
39
 
40
40
  **Android** (`AndroidManifest.xml`):
41
41
 
@@ -45,46 +45,85 @@ The library does NOT request permissions itself — your app must. Use a library
45
45
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
46
46
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
47
47
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
48
+ <!-- Only when BeekonConfig.detectActivity is enabled -->
49
+ <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
48
50
  ```
49
51
 
50
52
  **iOS** (`Info.plist`):
51
53
 
52
54
  ```xml
53
55
  <key>NSLocationWhenInUseUsageDescription</key>
54
- <string>...</string>
56
+ <string>…</string>
55
57
  <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
56
- <string>...</string>
58
+ <string>…</string>
59
+ <!-- Only when BeekonConfig.detectActivity is enabled -->
60
+ <key>NSMotionUsageDescription</key>
61
+ <string>…</string>
57
62
  <key>UIBackgroundModes</key>
58
- <array><string>location</string></array>
63
+ <array>
64
+ <string>location</string>
65
+ <string>fetch</string>
66
+ </array>
67
+ <key>BGTaskSchedulerPermittedIdentifiers</key>
68
+ <array>
69
+ <string>in.wayq.beekon.sync</string>
70
+ </array>
71
+ ```
72
+
73
+ ## Background-task registration (iOS)
74
+
75
+ For background sync scheduling and cold-launch resume, register Beekon's background task **synchronously during app launch** (it must run before `didFinishLaunchingWithOptions` returns). In your `AppDelegate.swift`:
76
+
77
+ ```swift
78
+ import BeekonRn
79
+
80
+ func application(_ application: UIApplication,
81
+ didFinishLaunchingWithOptions launchOptions: …) -> Bool {
82
+ BeekonRnImpl.registerBackgroundTasks()
83
+ // … React Native setup …
84
+ return true
85
+ }
59
86
  ```
60
87
 
88
+ Foreground tracking and the JS streams work without this; only background sync / relaunch need it.
89
+
90
+ ## Cold-launch resume (Android)
91
+
92
+ To resume tracking after the OS killed the process, call `in.wayq.beekon.Beekon.start()` from your `Application.onCreate` (native — the JS engine may not be running on a background relaunch). From JS, `Beekon.resumeIfNeeded()` covers the foreground case.
93
+
61
94
  ## Usage
62
95
 
63
96
  ```ts
64
97
  import { Beekon, type BeekonState, type Location } from '@wayq/beekon-rn';
65
98
 
66
- // Subscribe — returns an unsubscribe function. State replays the latest value
67
- // to new subscribers; locations is broadcast (no replay).
99
+ // Subscribe — each returns an unsubscribe function. `onState` / `onSyncStatus`
100
+ // replay the latest value to new subscribers; `onLocation` / `onGeofenceEvent`
101
+ // are broadcast (no replay).
68
102
  const offState = Beekon.onState((s: BeekonState) => console.log('state', s));
69
103
  const offLoc = Beekon.onLocation((l: Location) => console.log('location', l));
70
104
 
71
- // Configure. Defaults: 30 s / 100 m. Pass 0 to disable a gate.
105
+ // Configure (optional; defaults below). Pass 0 to disable a gate.
72
106
  await Beekon.configure({
73
- intervalSeconds: 10,
74
- distanceMeters: 30,
75
- androidNotification: {
76
- title: 'Tracking',
77
- text: 'Recording your route',
78
- smallIconResName: 'ic_notification', // drawable in your app
107
+ minTimeBetweenLocationsSeconds: 30, // default 30
108
+ minDistanceBetweenLocationsMeters: 100, // default 100
109
+ accuracyMode: 'balanced', // 'high' | 'balanced' | 'low'
110
+ whenStationary: 'pause', // 'keepTracking' | 'pause' | 'pauseWithCheckIns'
111
+ detectActivity: false,
112
+ // Optional server upload:
113
+ sync: {
114
+ url: 'https://example.com/ingest',
115
+ headers: { Authorization: 'Bearer …' },
79
116
  },
117
+ // Android-only foreground-service notification:
118
+ notification: { title: 'Tracking', text: 'Recording your route' },
80
119
  });
81
120
 
82
- await Beekon.start();
83
- // ... later
121
+ await Beekon.start(); // never throws — observe onState
122
+ // later
84
123
  await Beekon.stop();
85
124
 
86
- // Read past fixes.
87
- const fixes = await Beekon.history(new Date(Date.now() - 3600_000), new Date());
125
+ // History (local store; source of truth even when JS was asleep).
126
+ const fixes = await Beekon.getLocations(new Date(Date.now() - 3600_000), new Date());
88
127
 
89
128
  // Cleanup.
90
129
  offState();
@@ -95,21 +134,34 @@ offLoc();
95
134
 
96
135
  | Method | Description |
97
136
  |---|---|
98
- | `Beekon.configure(config)` | Set sampling thresholds. Optional. |
99
- | `Beekon.start()` | Begin tracking. State `tracking`. |
100
- | `Beekon.stop()` | Stop tracking. Idempotent. State → `stopped` (`reason: 'user'`). |
101
- | `Beekon.history(from, to)` | Read persisted fixes in range. |
102
- | `Beekon.onState(cb)` | Subscribe to state. Returns unsubscribe fn. |
103
- | `Beekon.onLocation(cb)` | Subscribe to gated fixes. Returns unsubscribe fn. |
104
-
105
- State is a discriminated union on `kind`: `'idle' | 'tracking' | 'stopped'`. The `'stopped'` variant carries a `reason: 'user' | 'permissionDenied' | 'locationServicesDisabled' | 'system'` (`'system'` is Android-only).
106
-
107
- Errors are thrown as `BeekonError` instances with `kind`:
108
- `'permissionDenied'`, `'locationServicesDisabled'`, `'storageFailure'`.
109
-
110
- ## Storage and retention
111
-
112
- The native SDKs persist every gated fix locally (Room on Android, GRDB on iOS) JS is a passive reader. Retention: **TTL 7 days OR most recent 100 K rows**, whichever is smaller; auto-pruned on each write batch.
137
+ | `configure(config)` | Set config. Optional, idempotent. Does not throw. |
138
+ | `start()` | Begin tracking. Never throws — observe `onState`. |
139
+ | `stop()` | Stop tracking. Idempotent. Never throws. |
140
+ | `resumeIfNeeded()` | Resume a session active before the app was terminated. |
141
+ | `getLocations(from, to)` | Read persisted fixes in `[from, to]`. Throws `'storage'`. |
142
+ | `deleteLocations(before?)` | Delete fixes at/before `before` (all when omitted). Throws `'storage'`. |
143
+ | `pendingUploadCount()` | Count of fixes not yet uploaded. Throws `'storage'`. |
144
+ | `sync()` | Request an immediate upload (no-op if sync unconfigured). |
145
+ | `setExtras(extras)` | Custom key/value fields sent with every upload. |
146
+ | `addGeofences(geofences)` | Register geofences. Throws `'invalidGeofence'`. |
147
+ | `removeGeofences(ids)` | Unregister geofences by id. |
148
+ | `listGeofences()` | The currently registered geofences. |
149
+ | `onState(cb)` | Subscribe to state. Replay-1. Returns unsubscribe fn. |
150
+ | `onLocation(cb)` | Subscribe to gated fixes. No replay. |
151
+ | `onGeofenceEvent(cb)` | Subscribe to geofence enter/exit. No replay. |
152
+ | `onSyncStatus(cb)` | Subscribe to upload health. Replay-1. |
153
+
154
+ `BeekonState` is a discriminated union on `kind`: `'idle' | 'tracking' | 'stopped'`. The `'stopped'` variant carries `reason: 'user' | 'permissionDenied' | 'locationServicesDisabled' | 'locationUnavailable' | 'system'`.
155
+
156
+ `SyncStatus` is a union on `kind`: `'idle' | 'pending' | 'failed'`; `'failed'` carries `reason: 'auth' | 'rejected'`.
157
+
158
+ `Location` carries `id`, `latitude`, `longitude`, `timestamp`, the nullable `accuracy` / `speed` / `bearing` / `altitude`, plus `quality`, `trigger`, `motion`, `activity` (`null` unless `detectActivity`), and `isMock`. Optional numeric fields are `null` when the OS did not report a value — never `0`.
159
+
160
+ The **only** thrown errors are `BeekonError` instances with `kind: 'storage' | 'invalidGeofence'`. Permission / services / lifecycle problems are not thrown — they surface on `onState` as `stopped(reason)`.
161
+
162
+ ## Storage, retention, and sync
163
+
164
+ The native SDKs persist every gated fix locally (Room on Android, GRDB on iOS) — JS is a passive reader. Retention: **TTL 7 days OR the most recent 100 K rows**, whichever is smaller; auto-pruned on each write batch. With `sync` configured, accepted rows are deleted locally after upload, so `getLocations` / `pendingUploadCount` return only un-uploaded fixes.
113
165
 
114
166
  ## License
115
167
 
@@ -1,7 +1,8 @@
1
1
  buildscript {
2
2
  ext.BeekonRn = [
3
3
  kotlinVersion: "2.1.20",
4
- minSdkVersion: 24,
4
+ // minSdk 26 is required by the native Beekon AAR (io.github.wayqteam:beekon).
5
+ minSdkVersion: 26,
5
6
  compileSdkVersion: 36,
6
7
  targetSdkVersion: 36
7
8
  ]
@@ -57,8 +58,12 @@ android {
57
58
  }
58
59
 
59
60
  compileOptions {
60
- sourceCompatibility JavaVersion.VERSION_1_8
61
- targetCompatibility JavaVersion.VERSION_1_8
61
+ sourceCompatibility JavaVersion.VERSION_17
62
+ targetCompatibility JavaVersion.VERSION_17
63
+ }
64
+
65
+ kotlinOptions {
66
+ jvmTarget = "17"
62
67
  }
63
68
  }
64
69
 
@@ -72,7 +77,7 @@ dependencies {
72
77
  // Native Beekon SDK — published from beekon-android/ via Maven Central.
73
78
  // Pinned exact in v0.x to avoid surprise breakage; loosen to a range when
74
79
  // the SDK reaches v1 stability.
75
- implementation "io.github.wayqteam:beekon:0.0.3"
80
+ implementation "io.github.wayqteam:beekon:0.0.5"
76
81
  // Kotlin coroutines — required for collecting Beekon's StateFlow/SharedFlow.
77
82
  // Beekon already depends on coroutines transitively, but declaring it here
78
83
  // makes the dependency intent explicit.