@wayq/beekon-rn 0.0.1 → 0.0.3

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 (78) hide show
  1. package/BeekonRn.podspec +3 -3
  2. package/README.md +24 -30
  3. package/android/build.gradle +3 -3
  4. package/android/src/main/java/in/wayq/beekonrn/BeekonRnModule.kt +182 -0
  5. package/android/src/main/java/{com → in}/wayq/beekonrn/BeekonRnPackage.kt +1 -1
  6. package/ios/BeekonRn.h +5 -1
  7. package/ios/BeekonRn.mm +15 -25
  8. package/ios/BeekonRn.swift +96 -116
  9. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeDirectory +0 -0
  10. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeResources +105 -42
  11. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeSignature +0 -0
  12. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/BeekonKit +0 -0
  13. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Info.plist +0 -0
  14. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.abi.json +2427 -0
  15. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  16. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.swiftinterface +85 -0
  17. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/PrivacyInfo.xcprivacy +1 -1
  18. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/_CodeSignature/CodeResources +36 -3
  19. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/BeekonKit +0 -0
  20. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Info.plist +0 -0
  21. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.abi.json +2427 -0
  22. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  23. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.swiftinterface +85 -0
  24. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.abi.json +2427 -0
  25. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  26. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +85 -0
  27. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/PrivacyInfo.xcprivacy +1 -1
  28. package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/_CodeSignature/CodeResources +69 -3
  29. package/lib/module/NativeBeekonRn.js +2 -2
  30. package/lib/module/NativeBeekonRn.js.map +1 -1
  31. package/lib/module/beekon.js +50 -53
  32. package/lib/module/beekon.js.map +1 -1
  33. package/lib/module/index.js +1 -0
  34. package/lib/module/index.js.map +1 -1
  35. package/lib/module/internal/mappers.js +49 -21
  36. package/lib/module/internal/mappers.js.map +1 -1
  37. package/lib/module/types/config.js +0 -2
  38. package/lib/module/types/error.js +19 -0
  39. package/lib/module/types/error.js.map +1 -0
  40. package/lib/module/types/location.js +2 -0
  41. package/lib/module/types/{position.js.map → location.js.map} +1 -1
  42. package/lib/typescript/src/NativeBeekonRn.d.ts +22 -26
  43. package/lib/typescript/src/NativeBeekonRn.d.ts.map +1 -1
  44. package/lib/typescript/src/beekon.d.ts +29 -42
  45. package/lib/typescript/src/beekon.d.ts.map +1 -1
  46. package/lib/typescript/src/index.d.ts +3 -3
  47. package/lib/typescript/src/index.d.ts.map +1 -1
  48. package/lib/typescript/src/internal/mappers.d.ts +10 -3
  49. package/lib/typescript/src/internal/mappers.d.ts.map +1 -1
  50. package/lib/typescript/src/types/config.d.ts +23 -31
  51. package/lib/typescript/src/types/config.d.ts.map +1 -1
  52. package/lib/typescript/src/types/error.d.ts +14 -0
  53. package/lib/typescript/src/types/error.d.ts.map +1 -0
  54. package/lib/typescript/src/types/location.d.ts +26 -0
  55. package/lib/typescript/src/types/location.d.ts.map +1 -0
  56. package/lib/typescript/src/types/state.d.ts +9 -9
  57. package/lib/typescript/src/types/state.d.ts.map +1 -1
  58. package/package.json +2 -2
  59. package/scripts/fetch-beekonkit.sh +5 -2
  60. package/src/NativeBeekonRn.ts +22 -26
  61. package/src/beekon.ts +58 -56
  62. package/src/index.tsx +3 -3
  63. package/src/internal/mappers.ts +52 -18
  64. package/src/types/config.ts +23 -32
  65. package/src/types/error.ts +22 -0
  66. package/src/types/location.ts +25 -0
  67. package/src/types/state.ts +13 -7
  68. package/android/src/main/java/com/wayq/beekonrn/BeekonRnModule.kt +0 -233
  69. package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
  70. package/lib/module/types/position.js +0 -2
  71. package/lib/module/types/preset.js +0 -2
  72. package/lib/module/types/preset.js.map +0 -1
  73. package/lib/typescript/src/types/position.d.ts +0 -24
  74. package/lib/typescript/src/types/position.d.ts.map +0 -1
  75. package/lib/typescript/src/types/preset.d.ts +0 -12
  76. package/lib/typescript/src/types/preset.d.ts.map +0 -1
  77. package/src/types/position.ts +0 -23
  78. package/src/types/preset.ts +0 -11
@@ -1,19 +1,21 @@
1
1
  import type { BeekonConfig } from '../types/config';
2
- import type { BeekonState, PauseReason } from '../types/state';
3
- import type { Position } from '../types/position';
4
- import type { WireConfig, WirePosition, WireState } from '../NativeBeekonRn';
2
+ import type { BeekonState, StopReason } from '../types/state';
3
+ import type { Location } from '../types/location';
4
+ import { BeekonError, type BeekonErrorKind } from '../types/error';
5
+ import type { WireConfig, WireLocation, WireState } from '../NativeBeekonRn';
6
+
7
+ const DEFAULT_INTERVAL_SECONDS = 30;
8
+ const DEFAULT_DISTANCE_METERS = 100;
5
9
 
6
10
  export function configToWire(config: BeekonConfig): WireConfig {
7
11
  return {
8
- preset: config.preset ?? 'balanced',
9
- distanceFilterMeters: config.distanceFilterMeters,
10
- intervalMillis: config.intervalMillis,
12
+ intervalSeconds: config.intervalSeconds ?? DEFAULT_INTERVAL_SECONDS,
13
+ distanceMeters: config.distanceMeters ?? DEFAULT_DISTANCE_METERS,
11
14
  androidNotification: config.androidNotification,
12
- licenseKey: config.licenseKey,
13
15
  };
14
16
  }
15
17
 
16
- export function wireToPosition(w: WirePosition): Position {
18
+ export function wireToLocation(w: WireLocation): Location {
17
19
  return {
18
20
  lat: w.lat,
19
21
  lng: w.lng,
@@ -25,26 +27,58 @@ export function wireToPosition(w: WirePosition): Position {
25
27
  };
26
28
  }
27
29
 
28
- function toPauseReason(s: string | undefined): PauseReason {
29
- if (s === 'permissionRevoked' || s === 'locationDisabled') return s;
30
- return 'unknown';
30
+ function toStopReason(s: string | undefined): StopReason {
31
+ switch (s) {
32
+ case 'user':
33
+ case 'permissionDenied':
34
+ case 'locationServicesDisabled':
35
+ case 'system':
36
+ return s;
37
+ default:
38
+ // Defensive — native should never emit an unknown reason.
39
+ return 'user';
40
+ }
31
41
  }
32
42
 
33
43
  export function wireToState(w: WireState): BeekonState {
34
44
  switch (w.type) {
35
45
  case 'idle':
36
46
  return { kind: 'idle' };
37
- case 'starting':
38
- return { kind: 'starting' };
39
47
  case 'tracking':
40
48
  return { kind: 'tracking' };
41
- case 'paused':
42
- return { kind: 'paused', reason: toPauseReason(w.pauseReason) };
43
49
  case 'stopped':
44
- return { kind: 'stopped' };
50
+ return { kind: 'stopped', reason: toStopReason(w.stopReason) };
45
51
  default:
46
- // Defensive fallback. Native should never emit an unknown state, but
47
- // forward-compat: treat as idle rather than throwing.
52
+ // Forward-compat: treat unknown as idle rather than throwing.
48
53
  return { kind: 'idle' };
49
54
  }
50
55
  }
56
+
57
+ /**
58
+ * Re-throw a native promise rejection as a typed `BeekonError`. Native modules
59
+ * encode the kind in the error code string (`PERMISSION_DENIED`,
60
+ * `LOCATION_SERVICES_DISABLED`, `STORAGE_FAILURE`); anything else falls
61
+ * through as the original error.
62
+ */
63
+ export function rethrowAsBeekonError(e: unknown): never {
64
+ const code = (e as { code?: string } | undefined)?.code;
65
+ const message = (e as { message?: string } | undefined)?.message ?? String(e);
66
+ const kind = codeToKind(code);
67
+ if (kind) {
68
+ throw new BeekonError(kind, message);
69
+ }
70
+ throw e;
71
+ }
72
+
73
+ function codeToKind(code: string | undefined): BeekonErrorKind | undefined {
74
+ switch (code) {
75
+ case 'PERMISSION_DENIED':
76
+ return 'permissionDenied';
77
+ case 'LOCATION_SERVICES_DISABLED':
78
+ return 'locationServicesDisabled';
79
+ case 'STORAGE_FAILURE':
80
+ return 'storageFailure';
81
+ default:
82
+ return undefined;
83
+ }
84
+ }
@@ -1,42 +1,33 @@
1
- import type { Preset } from './preset';
2
-
3
1
  /**
4
- * Foreground service notification config — required when running on Android
5
- * because Android 8+ requires a persistent notification while a foreground
6
- * service is active. Ignored on iOS.
2
+ * Foreground-service notification overrides. Android-only — required by the
3
+ * platform because every location foreground service must show a persistent
4
+ * notification. All fields are optional; missing values resolve at runtime
5
+ * against the host app's label and icon. Ignored on iOS.
7
6
  */
8
7
  export type AndroidNotificationConfig = {
9
- /** NotificationChannel id (Android 8+). */
10
- channelId: string;
11
- /** User-visible channel display name. */
12
- channelName: string;
13
- /** Foreground notification id. Must be > 0. */
14
- notificationId: number;
15
- /** Notification title shown in the status bar. */
16
- title: string;
17
- /** Notification body text. */
18
- text: string;
8
+ /** Notification title. Defaults to "Location active". */
9
+ title?: string;
10
+ /** Notification body text. Defaults to the host app's label. */
11
+ text?: string;
19
12
  /**
20
- * Drawable resource name for the notification icon (e.g. `ic_notification`).
21
- * Resolved at runtime via `Resources.getIdentifier()` against the host app's
22
- * `res/drawable*` folders. Pass the resource name without extension or
23
- * `R.drawable.` prefix.
13
+ * Drawable resource name (e.g. `ic_notification`) — resolved at runtime via
14
+ * `Resources.getIdentifier()` against the host app's `res/drawable*` folders.
15
+ * Pass the resource name without extension or `R.drawable.` prefix. Defaults
16
+ * to the host app's `applicationInfo.icon`.
24
17
  */
25
- smallIconResName: string;
18
+ smallIconResName?: string;
26
19
  };
27
20
 
21
+ /**
22
+ * Tracking configuration. Two knobs: a minimum time interval and a minimum
23
+ * distance between emitted fixes. A fix is admitted only when **both** gates
24
+ * are satisfied. Pass `0` to disable a gate.
25
+ */
28
26
  export type BeekonConfig = {
29
- /** Sampling preset. Default: `'balanced'`. */
30
- preset?: Preset;
31
- /** Override the preset's distance gate (meters). */
32
- distanceFilterMeters?: number;
33
- /** Override the preset's interval (milliseconds). */
34
- intervalMillis?: number;
35
- /**
36
- * Required when running on Android. Ignored on iOS. The plugin throws
37
- * `NOT_CONFIGURED` if missing on Android.
38
- */
27
+ /** Minimum seconds between admitted fixes. Default: `30`. `0` disables the time gate. */
28
+ intervalSeconds?: number;
29
+ /** Minimum metres between admitted fixes. Default: `100`. `0` disables the distance gate. */
30
+ distanceMeters?: number;
31
+ /** Android-only notification overrides. Ignored on iOS. */
39
32
  androidNotification?: AndroidNotificationConfig;
40
- /** Optional license key. Reserved for future use. */
41
- licenseKey?: string;
42
33
  };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Error kinds thrown from `Beekon.start()` / `Beekon.history()`. Match the
3
+ * native `BeekonError` cases byte-for-byte.
4
+ */
5
+ export type BeekonErrorKind =
6
+ | 'permissionDenied'
7
+ | 'locationServicesDisabled'
8
+ | 'storageFailure';
9
+
10
+ /**
11
+ * Typed error surfaced from the bridge. The native module rejects promises
12
+ * with the kind encoded as the error code; the facade re-wraps into this.
13
+ */
14
+ export class BeekonError extends Error {
15
+ public readonly kind: BeekonErrorKind;
16
+
17
+ constructor(kind: BeekonErrorKind, message: string) {
18
+ super(message);
19
+ this.name = 'BeekonError';
20
+ this.kind = kind;
21
+ }
22
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A single location fix as emitted by the native SDK after gating. Fields map
3
+ * 1:1 to `in.wayq.beekon.Location` on Android and `BeekonKit.Location` on iOS.
4
+ *
5
+ * `lat`, `lng`, and `timestamp` are always present. The four optional fields
6
+ * are `null` when the OS did not report a value — the SDK never invents a
7
+ * value to mask absence (e.g. a stationary device returns `bearing === null`,
8
+ * not `0`).
9
+ */
10
+ export type Location = {
11
+ /** Latitude in degrees, WGS-84. */
12
+ lat: number;
13
+ /** Longitude in degrees, WGS-84. */
14
+ lng: number;
15
+ /** Horizontal accuracy in meters (1-sigma); `null` if unreported. */
16
+ accuracy: number | null;
17
+ /** Speed in m/s; `null` if unreported. */
18
+ speed: number | null;
19
+ /** Bearing in degrees `[0, 360)` clockwise from true north; `null` if unreported. */
20
+ bearing: number | null;
21
+ /** Altitude in meters above the WGS-84 ellipsoid; `null` if unreported. */
22
+ altitude: number | null;
23
+ /** Time the OS provider reported this fix (not when JS received it). */
24
+ timestamp: Date;
25
+ };
@@ -1,16 +1,22 @@
1
1
  /**
2
- * Why tracking is paused. Names match the native `PauseReason` enum on both
3
- * platforms byte-for-byte.
2
+ * Reason a tracking session ended. Mirrors `StopReason` on both platforms.
3
+ *
4
+ * `'system'` is Android-only — surfaces when the OS terminates the foreground
5
+ * service (memory pressure, force-stop). iOS will never emit `'system'`.
4
6
  */
5
- export type PauseReason = 'permissionRevoked' | 'locationDisabled' | 'unknown';
7
+ export type StopReason =
8
+ | 'user'
9
+ | 'permissionDenied'
10
+ | 'locationServicesDisabled'
11
+ | 'system';
6
12
 
7
13
  /**
8
- * Tracking state. Mirrors the native `BeekonState` sealed hierarchy on both
14
+ * Tracking state. Mirrors the native `BeekonState` sealed type on both
9
15
  * platforms. Use the `kind` field as a discriminator.
16
+ *
17
+ * Lifecycle: `idle → tracking → stopped(reason)`.
10
18
  */
11
19
  export type BeekonState =
12
20
  | { kind: 'idle' }
13
- | { kind: 'starting' }
14
21
  | { kind: 'tracking' }
15
- | { kind: 'paused'; reason: PauseReason }
16
- | { kind: 'stopped' };
22
+ | { kind: 'stopped'; reason: StopReason };
@@ -1,233 +0,0 @@
1
- package com.wayq.beekonrn
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.Promise
5
- import com.facebook.react.bridge.ReactApplicationContext
6
- import com.facebook.react.bridge.ReadableMap
7
- import com.facebook.react.bridge.WritableArray
8
- import com.facebook.react.bridge.WritableMap
9
- import com.wayq.beekon.Beekon
10
- import com.wayq.beekon.BeekonConfig
11
- import com.wayq.beekon.BeekonError
12
- import com.wayq.beekon.BeekonState
13
- import com.wayq.beekon.NotificationConfig
14
- import com.wayq.beekon.PauseReason
15
- import com.wayq.beekon.Position
16
- import com.wayq.beekon.Preset
17
- import java.time.Instant
18
- import kotlinx.coroutines.CoroutineScope
19
- import kotlinx.coroutines.Dispatchers
20
- import kotlinx.coroutines.Job
21
- import kotlinx.coroutines.SupervisorJob
22
- import kotlinx.coroutines.cancel
23
- import kotlinx.coroutines.flow.collect
24
- import kotlinx.coroutines.launch
25
-
26
- class BeekonRnModule(private val reactContext: ReactApplicationContext) :
27
- NativeBeekonRnSpec(reactContext) {
28
-
29
- // Default dispatcher (not Main.immediate) — Codegen's emitOnX is thread-safe
30
- // and marshals to JS internally, so collecting on Main buys nothing and
31
- // risks jank if any mapper does work. SupervisorJob so a single failure
32
- // doesn't tear down siblings.
33
- private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
34
- private var stateJob: Job? = null
35
- private var positionsJob: Job? = null
36
-
37
- override fun initialize(promise: Promise) {
38
- scope.launch {
39
- try {
40
- Beekon.initialize(reactContext.applicationContext)
41
-
42
- // Idempotent: re-init replaces collectors. Native flows are hot
43
- // (StateFlow / SharedFlow) so resubscription replays the latest value.
44
- stateJob?.cancel()
45
- positionsJob?.cancel()
46
- stateJob = scope.launch {
47
- Beekon.state.collect { s -> emitOnState(stateToWire(s)) }
48
- }
49
- positionsJob = scope.launch {
50
- Beekon.positions.collect { p -> emitOnPosition(positionToWire(p)) }
51
- }
52
- promise.resolve(null)
53
- } catch (t: Throwable) {
54
- promise.reject(errorCode(t), t.message ?: "init failed", t)
55
- }
56
- }
57
- }
58
-
59
- override fun configure(config: ReadableMap, promise: Promise) {
60
- scope.launch {
61
- try {
62
- Beekon.configure(wireToConfig(config))
63
- promise.resolve(null)
64
- } catch (t: Throwable) {
65
- promise.reject(errorCode(t), t.message ?: "configure failed", t)
66
- }
67
- }
68
- }
69
-
70
- override fun start(promise: Promise) {
71
- scope.launch {
72
- try {
73
- Beekon.start()
74
- promise.resolve(null)
75
- } catch (t: Throwable) {
76
- promise.reject(errorCode(t), t.message ?: "start failed", t)
77
- }
78
- }
79
- }
80
-
81
- override fun stop(promise: Promise) {
82
- scope.launch {
83
- try {
84
- Beekon.stop()
85
- promise.resolve(null)
86
- } catch (t: Throwable) {
87
- promise.reject(errorCode(t), t.message ?: "stop failed", t)
88
- }
89
- }
90
- }
91
-
92
- override fun shutdown(promise: Promise) {
93
- scope.launch {
94
- try {
95
- stateJob?.cancel()
96
- positionsJob?.cancel()
97
- Beekon.shutdown()
98
- promise.resolve(null)
99
- } catch (t: Throwable) {
100
- promise.reject(errorCode(t), t.message ?: "shutdown failed", t)
101
- }
102
- }
103
- }
104
-
105
- override fun history(fromMs: Double, toMs: Double, promise: Promise) {
106
- scope.launch {
107
- try {
108
- val from = Instant.ofEpochMilli(fromMs.toLong())
109
- val to = Instant.ofEpochMilli(toMs.toLong())
110
- val positions = Beekon.history(from, to)
111
- val arr: WritableArray = Arguments.createArray()
112
- for (p in positions) arr.pushMap(positionToWire(p))
113
- promise.resolve(arr)
114
- } catch (t: Throwable) {
115
- promise.reject(errorCode(t), t.message ?: "history failed", t)
116
- }
117
- }
118
- }
119
-
120
- override fun invalidate() {
121
- super.invalidate()
122
- scope.cancel()
123
- }
124
-
125
- // ---------------------------------------------------------------------------
126
- // Mappers (Wire ↔ Kotlin types)
127
- // ---------------------------------------------------------------------------
128
-
129
- private fun wireToConfig(map: ReadableMap): BeekonConfig {
130
- val preset = when (map.getString("preset")) {
131
- "saver" -> Preset.Saver
132
- "precision" -> Preset.Precision
133
- else -> Preset.Balanced
134
- }
135
- val distanceFilterMeters =
136
- if (map.hasKey("distanceFilterMeters") && !map.isNull("distanceFilterMeters"))
137
- map.getDouble("distanceFilterMeters").toFloat()
138
- else null
139
- val intervalMillis =
140
- if (map.hasKey("intervalMillis") && !map.isNull("intervalMillis"))
141
- map.getDouble("intervalMillis").toLong()
142
- else null
143
- val notifMap = map.getMap("androidNotification")
144
- ?: throw IllegalArgumentException(
145
- "androidNotification is required when running on Android"
146
- )
147
- val licenseKey =
148
- if (map.hasKey("licenseKey") && !map.isNull("licenseKey"))
149
- map.getString("licenseKey")
150
- else null
151
-
152
- return BeekonConfig(
153
- preset = preset,
154
- distanceFilterMeters = distanceFilterMeters,
155
- intervalMillis = intervalMillis,
156
- notification = wireToNotificationConfig(notifMap),
157
- licenseKey = licenseKey,
158
- )
159
- }
160
-
161
- private fun wireToNotificationConfig(map: ReadableMap): NotificationConfig {
162
- val resName = map.getString("smallIconResName")
163
- ?: throw IllegalArgumentException("smallIconResName is required")
164
- val pkg = reactContext.packageName
165
- val iconId = reactContext.resources.getIdentifier(resName, "drawable", pkg)
166
- if (iconId == 0) {
167
- throw IllegalArgumentException(
168
- "drawable resource '$resName' not found in package '$pkg'"
169
- )
170
- }
171
- return NotificationConfig(
172
- channelId = map.getString("channelId")
173
- ?: throw IllegalArgumentException("channelId is required"),
174
- channelName = map.getString("channelName")
175
- ?: throw IllegalArgumentException("channelName is required"),
176
- notificationId = map.getInt("notificationId"),
177
- title = map.getString("title")
178
- ?: throw IllegalArgumentException("title is required"),
179
- text = map.getString("text")
180
- ?: throw IllegalArgumentException("text is required"),
181
- smallIcon = iconId,
182
- )
183
- }
184
-
185
- private fun positionToWire(p: Position): WritableMap {
186
- val m = Arguments.createMap()
187
- m.putDouble("lat", p.lat)
188
- m.putDouble("lng", p.lng)
189
- m.putDouble("accuracy", p.accuracy.toDouble())
190
- m.putDouble("speed", p.speed.toDouble())
191
- m.putDouble("bearing", p.bearing.toDouble())
192
- m.putDouble("altitude", p.altitude)
193
- m.putDouble("timestampMs", p.timestamp.toEpochMilli().toDouble())
194
- return m
195
- }
196
-
197
- private fun stateToWire(s: BeekonState): WritableMap {
198
- val m = Arguments.createMap()
199
- when (s) {
200
- BeekonState.Idle -> m.putString("type", "idle")
201
- BeekonState.Starting -> m.putString("type", "starting")
202
- BeekonState.Tracking -> m.putString("type", "tracking")
203
- is BeekonState.Paused -> {
204
- m.putString("type", "paused")
205
- m.putString("pauseReason", pauseReasonToWire(s.reason))
206
- }
207
- BeekonState.Stopped -> m.putString("type", "stopped")
208
- }
209
- return m
210
- }
211
-
212
- private fun pauseReasonToWire(r: PauseReason): String = when (r) {
213
- PauseReason.PermissionRevoked -> "permissionRevoked"
214
- PauseReason.LocationDisabled -> "locationDisabled"
215
- PauseReason.Unknown -> "unknown"
216
- }
217
-
218
- // Maps native error sealed types to stable JS-side codes. Same code strings
219
- // on iOS so JS can switch on them platform-agnostically.
220
- private fun errorCode(t: Throwable): String = when (t) {
221
- is BeekonError.NotInitialised -> "NOT_INITIALISED"
222
- is BeekonError.NotConfigured -> "NOT_CONFIGURED"
223
- is BeekonError.PermissionDenied -> "PERMISSION_DENIED"
224
- is BeekonError.NoGmsAvailable -> "NO_GMS_AVAILABLE"
225
- is BeekonError.ServiceFailed -> "SERVICE_FAILED"
226
- is BeekonError.InternalError -> "INTERNAL_ERROR"
227
- else -> "INTERNAL_ERROR"
228
- }
229
-
230
- companion object {
231
- const val NAME = NativeBeekonRnSpec.NAME
232
- }
233
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- //# sourceMappingURL=position.js.map
@@ -1,2 +0,0 @@
1
- "use strict";
2
- //# sourceMappingURL=preset.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../src","sources":["types/preset.ts"],"mappings":"","ignoreList":[]}
@@ -1,24 +0,0 @@
1
- /**
2
- * A single location fix as emitted by the native SDK after gating. Fields map
3
- * 1:1 to `com.wayq.beekon.Position` on Android and `Beekon.Position` on iOS.
4
- *
5
- * The SDK does NOT smooth or filter positions beyond the gate — values are
6
- * forwarded as the OS provider reported them (raw passthrough).
7
- */
8
- export type Position = {
9
- /** Latitude in degrees, WGS-84. */
10
- lat: number;
11
- /** Longitude in degrees, WGS-84. */
12
- lng: number;
13
- /** Horizontal accuracy in meters (1-sigma). */
14
- accuracy: number;
15
- /** Speed in m/s. May be 0 if the OS provider doesn't supply it. */
16
- speed: number;
17
- /** Bearing in degrees clockwise from true north. */
18
- bearing: number;
19
- /** Altitude in meters above the WGS-84 ellipsoid. */
20
- altitude: number;
21
- /** Time the OS provider reported this fix (not when JS received it). */
22
- timestamp: Date;
23
- };
24
- //# sourceMappingURL=position.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../../../src/types/position.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,SAAS,EAAE,IAAI,CAAC;CACjB,CAAC"}
@@ -1,12 +0,0 @@
1
- /**
2
- * Sampling preset. Determines the gating interval and distance threshold the
3
- * native SDK uses before emitting a position. Per `docs/REQUIREMENTS.md`:
4
- *
5
- * | Preset | Interval | Distance | Battery (typical) |
6
- * |-----------|----------|----------|-------------------|
7
- * | saver | 60_000ms | 150 m | 3–8% |
8
- * | balanced | 30_000ms | 100 m | 5–10% |
9
- * | precision | 10_000ms | 30 m | 15–25% |
10
- */
11
- export type Preset = 'saver' | 'balanced' | 'precision';
12
- //# sourceMappingURL=preset.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../../../src/types/preset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC"}
@@ -1,23 +0,0 @@
1
- /**
2
- * A single location fix as emitted by the native SDK after gating. Fields map
3
- * 1:1 to `com.wayq.beekon.Position` on Android and `Beekon.Position` on iOS.
4
- *
5
- * The SDK does NOT smooth or filter positions beyond the gate — values are
6
- * forwarded as the OS provider reported them (raw passthrough).
7
- */
8
- export type Position = {
9
- /** Latitude in degrees, WGS-84. */
10
- lat: number;
11
- /** Longitude in degrees, WGS-84. */
12
- lng: number;
13
- /** Horizontal accuracy in meters (1-sigma). */
14
- accuracy: number;
15
- /** Speed in m/s. May be 0 if the OS provider doesn't supply it. */
16
- speed: number;
17
- /** Bearing in degrees clockwise from true north. */
18
- bearing: number;
19
- /** Altitude in meters above the WGS-84 ellipsoid. */
20
- altitude: number;
21
- /** Time the OS provider reported this fix (not when JS received it). */
22
- timestamp: Date;
23
- };
@@ -1,11 +0,0 @@
1
- /**
2
- * Sampling preset. Determines the gating interval and distance threshold the
3
- * native SDK uses before emitting a position. Per `docs/REQUIREMENTS.md`:
4
- *
5
- * | Preset | Interval | Distance | Battery (typical) |
6
- * |-----------|----------|----------|-------------------|
7
- * | saver | 60_000ms | 150 m | 3–8% |
8
- * | balanced | 30_000ms | 100 m | 5–10% |
9
- * | precision | 10_000ms | 30 m | 15–25% |
10
- */
11
- export type Preset = 'saver' | 'balanced' | 'precision';