@kafitra/react-native-live-tracking 0.1.0

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 (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +396 -0
  3. package/android/build.gradle +71 -0
  4. package/android/gradle.properties +7 -0
  5. package/android/src/main/AndroidManifest.xml +40 -0
  6. package/android/src/main/java/com/livetracking/LiveTrackingModuleImpl.kt +728 -0
  7. package/android/src/main/java/com/livetracking/LiveTrackingPackage.kt +16 -0
  8. package/android/src/main/java/com/livetracking/location/LocationEngine.kt +93 -0
  9. package/android/src/main/java/com/livetracking/network/NetworkListener.kt +127 -0
  10. package/android/src/main/java/com/livetracking/optimizer/ActivityRecognitionHandler.kt +248 -0
  11. package/android/src/main/java/com/livetracking/optimizer/MotionSleepManager.kt +130 -0
  12. package/android/src/main/java/com/livetracking/permissions/PermissionHandler.kt +145 -0
  13. package/android/src/main/java/com/livetracking/queue/QueueEngine.kt +167 -0
  14. package/android/src/main/java/com/livetracking/queue/QueuedLocation.kt +16 -0
  15. package/android/src/main/java/com/livetracking/queue/TrackingDatabase.kt +239 -0
  16. package/android/src/main/java/com/livetracking/receiver/BootReceiver.kt +53 -0
  17. package/android/src/main/java/com/livetracking/service/TrackingForegroundService.kt +145 -0
  18. package/android/src/main/java/com/livetracking/sync/FirebaseSyncEngine.kt +277 -0
  19. package/android/src/main/java/com/livetracking/sync/LocationDataPoint.kt +31 -0
  20. package/android/src/main/java/com/livetracking/sync/SyncEngineController.kt +220 -0
  21. package/android/src/main/java/com/livetracking/sync/SyncTargetConfig.kt +20 -0
  22. package/android/src/main/java/com/livetracking/sync/TargetHandler.kt +601 -0
  23. package/android/src/newarch/java/com/livetracking/LiveTrackingModule.kt +64 -0
  24. package/android/src/oldarch/java/com/livetracking/LiveTrackingModule.kt +70 -0
  25. package/android/src/test/java/com/livetracking/BackoffCalculationTest.kt +216 -0
  26. package/android/src/test/java/com/livetracking/BatchAccumulatorTest.kt +391 -0
  27. package/android/src/test/java/com/livetracking/BootReceiverTest.kt +247 -0
  28. package/android/src/test/java/com/livetracking/FirebaseSyncEngineTest.kt +337 -0
  29. package/android/src/test/java/com/livetracking/LocationEngineTest.kt +202 -0
  30. package/android/src/test/java/com/livetracking/MotionSleepManagerTest.kt +420 -0
  31. package/android/src/test/java/com/livetracking/OfflineQueueTest.kt +462 -0
  32. package/android/src/test/java/com/livetracking/PermissionHandlerTest.kt +200 -0
  33. package/android/src/test/java/com/livetracking/QueueEngineTest.kt +335 -0
  34. package/android/src/test/java/com/livetracking/SyncEngineControllerTest.kt +855 -0
  35. package/ios/ActivityRecognitionHandler.swift +196 -0
  36. package/ios/BackgroundModeHelper.swift +132 -0
  37. package/ios/FirebaseSyncEngine.swift +276 -0
  38. package/ios/LiveTracking-Bridging-Header.h +2 -0
  39. package/ios/LiveTracking.m +37 -0
  40. package/ios/LiveTracking.swift +773 -0
  41. package/ios/LocationDataPoint.swift +56 -0
  42. package/ios/LocationEngine.swift +160 -0
  43. package/ios/MotionSleepManager.swift +151 -0
  44. package/ios/NetworkListener.swift +105 -0
  45. package/ios/OfflineQueueManager.swift +503 -0
  46. package/ios/PermissionHandler.swift +148 -0
  47. package/ios/QueueEngine.swift +249 -0
  48. package/ios/SyncEngineController.swift +396 -0
  49. package/ios/SyncTargetConfig.swift +36 -0
  50. package/ios/TargetHandler.swift +715 -0
  51. package/ios/Tests/ActivityRecognitionHandlerTests.swift +259 -0
  52. package/ios/Tests/FirebaseSyncEngineTests.swift +303 -0
  53. package/ios/Tests/LocationEngineTests.swift +244 -0
  54. package/ios/Tests/MotionSleepManagerTests.swift +355 -0
  55. package/ios/Tests/NetworkListenerTests.swift +188 -0
  56. package/ios/Tests/OfflineQueueFlushTests.swift +375 -0
  57. package/ios/Tests/PermissionHandlerTests.swift +238 -0
  58. package/ios/Tests/QueueEngineTests.swift +346 -0
  59. package/ios/TrackingCleanup.swift +93 -0
  60. package/ios/TrackingNotificationManager.swift +187 -0
  61. package/lib/commonjs/EventEmitter.js +113 -0
  62. package/lib/commonjs/EventEmitter.js.map +1 -0
  63. package/lib/commonjs/LiveTracking.js +134 -0
  64. package/lib/commonjs/LiveTracking.js.map +1 -0
  65. package/lib/commonjs/NativeLiveTracking.js +21 -0
  66. package/lib/commonjs/NativeLiveTracking.js.map +1 -0
  67. package/lib/commonjs/filters/distanceTimeFilter.js +63 -0
  68. package/lib/commonjs/filters/distanceTimeFilter.js.map +1 -0
  69. package/lib/commonjs/index.js +103 -0
  70. package/lib/commonjs/index.js.map +1 -0
  71. package/lib/commonjs/serialization/locationSerializer.js +51 -0
  72. package/lib/commonjs/serialization/locationSerializer.js.map +1 -0
  73. package/lib/commonjs/types.js +77 -0
  74. package/lib/commonjs/types.js.map +1 -0
  75. package/lib/commonjs/utils/distance.js +63 -0
  76. package/lib/commonjs/utils/distance.js.map +1 -0
  77. package/lib/commonjs/utils/retry.js +80 -0
  78. package/lib/commonjs/utils/retry.js.map +1 -0
  79. package/lib/commonjs/validation.js +463 -0
  80. package/lib/commonjs/validation.js.map +1 -0
  81. package/lib/module/EventEmitter.js +105 -0
  82. package/lib/module/EventEmitter.js.map +1 -0
  83. package/lib/module/LiveTracking.js +127 -0
  84. package/lib/module/LiveTracking.js.map +1 -0
  85. package/lib/module/NativeLiveTracking.js +16 -0
  86. package/lib/module/NativeLiveTracking.js.map +1 -0
  87. package/lib/module/filters/distanceTimeFilter.js +58 -0
  88. package/lib/module/filters/distanceTimeFilter.js.map +1 -0
  89. package/lib/module/index.js +32 -0
  90. package/lib/module/index.js.map +1 -0
  91. package/lib/module/serialization/locationSerializer.js +45 -0
  92. package/lib/module/serialization/locationSerializer.js.map +1 -0
  93. package/lib/module/types.js +94 -0
  94. package/lib/module/types.js.map +1 -0
  95. package/lib/module/utils/distance.js +56 -0
  96. package/lib/module/utils/distance.js.map +1 -0
  97. package/lib/module/utils/retry.js +72 -0
  98. package/lib/module/utils/retry.js.map +1 -0
  99. package/lib/module/validation.js +456 -0
  100. package/lib/module/validation.js.map +1 -0
  101. package/lib/typescript/EventEmitter.d.ts +65 -0
  102. package/lib/typescript/EventEmitter.d.ts.map +1 -0
  103. package/lib/typescript/LiveTracking.d.ts +23 -0
  104. package/lib/typescript/LiveTracking.d.ts.map +1 -0
  105. package/lib/typescript/NativeLiveTracking.d.ts +25 -0
  106. package/lib/typescript/NativeLiveTracking.d.ts.map +1 -0
  107. package/lib/typescript/filters/distanceTimeFilter.d.ts +44 -0
  108. package/lib/typescript/filters/distanceTimeFilter.d.ts.map +1 -0
  109. package/lib/typescript/index.d.ts +21 -0
  110. package/lib/typescript/index.d.ts.map +1 -0
  111. package/lib/typescript/serialization/locationSerializer.d.ts +39 -0
  112. package/lib/typescript/serialization/locationSerializer.d.ts.map +1 -0
  113. package/lib/typescript/types.d.ts +217 -0
  114. package/lib/typescript/types.d.ts.map +1 -0
  115. package/lib/typescript/utils/distance.d.ts +38 -0
  116. package/lib/typescript/utils/distance.d.ts.map +1 -0
  117. package/lib/typescript/utils/retry.d.ts +60 -0
  118. package/lib/typescript/utils/retry.d.ts.map +1 -0
  119. package/lib/typescript/validation.d.ts +26 -0
  120. package/lib/typescript/validation.d.ts.map +1 -0
  121. package/package.json +126 -0
  122. package/react-native-live-tracking.podspec +47 -0
  123. package/src/EventEmitter.ts +118 -0
  124. package/src/LiveTracking.ts +159 -0
  125. package/src/NativeLiveTracking.ts +29 -0
  126. package/src/filters/distanceTimeFilter.ts +75 -0
  127. package/src/index.ts +51 -0
  128. package/src/serialization/locationSerializer.ts +57 -0
  129. package/src/types.ts +252 -0
  130. package/src/utils/distance.ts +68 -0
  131. package/src/utils/retry.ts +75 -0
  132. package/src/validation.ts +552 -0
@@ -0,0 +1,127 @@
1
+ /**
2
+ * JavaScript LiveTracking module that wraps NativeModule calls.
3
+ *
4
+ * Provides the public API for configuring, starting, and stopping
5
+ * location tracking, with validation and state management.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ import NativeLiveTracking from './NativeLiveTracking';
11
+ import { onLocationUpdate as emitterOnLocationUpdate, onError as emitterOnError } from './EventEmitter';
12
+ import { validateConfig, applyDefaults } from './validation';
13
+
14
+ /**
15
+ * Returns the native module or throws a descriptive error if not linked.
16
+ * Using a function accessor (rather than assertNative) keeps TypeScript
17
+ * happy since it can't narrow an imported binding via assertion functions.
18
+ */
19
+ function native() {
20
+ if (!NativeLiveTracking) {
21
+ throw new Error("[@kafitra/react-native-live-tracking] Native module 'LiveTracking' is not registered. " + 'Make sure you ran `pod install` and rebuilt the app from Xcode.');
22
+ }
23
+ return NativeLiveTracking;
24
+ }
25
+
26
+ /**
27
+ * Tracks whether configure() has been successfully called.
28
+ * Used to guard queue methods that require configuration.
29
+ */
30
+ let isConfigured = false;
31
+
32
+ /**
33
+ * Resets the configured state. Only for use in tests.
34
+ * @internal
35
+ */
36
+ export function _resetConfiguredStateForTesting() {
37
+ isConfigured = false;
38
+ }
39
+
40
+ /**
41
+ * LiveTracking module implementation.
42
+ *
43
+ * Wraps native module calls with validation, serialization,
44
+ * and state management on the JavaScript side.
45
+ */
46
+ const LiveTracking = {
47
+ /**
48
+ * Configure the tracking library with the given parameters.
49
+ * Validates the config, applies defaults, and passes to native layer.
50
+ */
51
+ async configure(config) {
52
+ const validationResult = validateConfig(config);
53
+ if (!validationResult.valid) {
54
+ const errorMessages = validationResult.errors.map(e => `[${e.field}]: ${e.message}`).join('; ');
55
+ throw new Error(`Invalid configuration: ${errorMessages}`);
56
+ }
57
+ const finalConfig = applyDefaults(config);
58
+ const jsonString = JSON.stringify(finalConfig);
59
+ const MAX_PAYLOAD_BYTES = 1024 * 1024; // 1 MB
60
+ if (jsonString.length > MAX_PAYLOAD_BYTES) {
61
+ throw new Error('Configuration payload is too large: serialized JSON exceeds 1 MB');
62
+ }
63
+ await native().configure(jsonString);
64
+ isConfigured = true;
65
+ },
66
+ /**
67
+ * Start location tracking.
68
+ * Requires `configure()` to have been called first.
69
+ */
70
+ async start() {
71
+ await native().start();
72
+ },
73
+ /**
74
+ * Stop location tracking and clean up resources.
75
+ */
76
+ async stop() {
77
+ await native().stop();
78
+ },
79
+ /**
80
+ * Register a callback for location updates.
81
+ */
82
+ onLocationUpdate(callback) {
83
+ return emitterOnLocationUpdate(callback);
84
+ },
85
+ /**
86
+ * Register a callback for tracking errors.
87
+ */
88
+ onError(callback) {
89
+ return emitterOnError(callback);
90
+ },
91
+ /**
92
+ * Get the current tracking status.
93
+ */
94
+ async getStatus() {
95
+ const jsonString = await native().getStatus();
96
+ return JSON.parse(jsonString);
97
+ },
98
+ /**
99
+ * Get the total number of locations currently queued for sync.
100
+ *
101
+ * @throws Error with code NOT_CONFIGURED if called before configure()
102
+ */
103
+ async getQueuedLocations() {
104
+ if (!isConfigured) {
105
+ const error = new Error('LiveTracking is not configured. Call configure() before getQueuedLocations().');
106
+ error.code = 'NOT_CONFIGURED';
107
+ throw error;
108
+ }
109
+ return native().getQueuedLocations();
110
+ },
111
+ /**
112
+ * Get the number of queued locations per target path.
113
+ *
114
+ * @throws Error with code NOT_CONFIGURED if called before configure()
115
+ */
116
+ async getQueuedLocationsByTarget() {
117
+ if (!isConfigured) {
118
+ const error = new Error('LiveTracking is not configured. Call configure() before getQueuedLocationsByTarget().');
119
+ error.code = 'NOT_CONFIGURED';
120
+ throw error;
121
+ }
122
+ const jsonString = await native().getQueuedLocationsByTarget();
123
+ return JSON.parse(jsonString);
124
+ }
125
+ };
126
+ export default LiveTracking;
127
+ //# sourceMappingURL=LiveTracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeLiveTracking","onLocationUpdate","emitterOnLocationUpdate","onError","emitterOnError","validateConfig","applyDefaults","native","Error","isConfigured","_resetConfiguredStateForTesting","LiveTracking","configure","config","validationResult","valid","errorMessages","errors","map","e","field","message","join","finalConfig","jsonString","JSON","stringify","MAX_PAYLOAD_BYTES","length","start","stop","callback","getStatus","parse","getQueuedLocations","error","code","getQueuedLocationsByTarget"],"sourceRoot":"../../src","sources":["LiveTracking.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAOA,kBAAkB,MAAM,sBAAsB;AACrD,SACEC,gBAAgB,IAAIC,uBAAuB,EAC3CC,OAAO,IAAIC,cAAc,QACpB,gBAAgB;AASvB,SAASC,cAAc,EAAEC,aAAa,QAAQ,cAAc;;AAE5D;AACA;AACA;AACA;AACA;AACA,SAASC,MAAMA,CAAA,EAA2C;EACxD,IAAI,CAACP,kBAAkB,EAAE;IACvB,MAAM,IAAIQ,KAAK,CACb,wFAAwF,GACtF,iEACJ,CAAC;EACH;EACA,OAAOR,kBAAkB;AAC3B;;AAEA;AACA;AACA;AACA;AACA,IAAIS,YAAY,GAAG,KAAK;;AAExB;AACA;AACA;AACA;AACA,OAAO,SAASC,+BAA+BA,CAAA,EAAS;EACtDD,YAAY,GAAG,KAAK;AACtB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAME,YAAgC,GAAG;EACvC;AACF;AACA;AACA;EACE,MAAMC,SAASA,CAACC,MAAsB,EAAiB;IACrD,MAAMC,gBAAgB,GAAGT,cAAc,CAACQ,MAAM,CAAC;IAC/C,IAAI,CAACC,gBAAgB,CAACC,KAAK,EAAE;MAC3B,MAAMC,aAAa,GAAGF,gBAAgB,CAACG,MAAM,CAC1CC,GAAG,CAAEC,CAAC,IAAK,IAAIA,CAAC,CAACC,KAAK,MAAMD,CAAC,CAACE,OAAO,EAAE,CAAC,CACxCC,IAAI,CAAC,IAAI,CAAC;MACb,MAAM,IAAId,KAAK,CAAC,0BAA0BQ,aAAa,EAAE,CAAC;IAC5D;IAEA,MAAMO,WAAW,GAAGjB,aAAa,CAACO,MAAM,CAAC;IACzC,MAAMW,UAAU,GAAGC,IAAI,CAACC,SAAS,CAACH,WAAW,CAAC;IAE9C,MAAMI,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACvC,IAAIH,UAAU,CAACI,MAAM,GAAGD,iBAAiB,EAAE;MACzC,MAAM,IAAInB,KAAK,CACb,kEACF,CAAC;IACH;IAEA,MAAMD,MAAM,CAAC,CAAC,CAACK,SAAS,CAACY,UAAU,CAAC;IACpCf,YAAY,GAAG,IAAI;EACrB,CAAC;EAED;AACF;AACA;AACA;EACE,MAAMoB,KAAKA,CAAA,EAAkB;IAC3B,MAAMtB,MAAM,CAAC,CAAC,CAACsB,KAAK,CAAC,CAAC;EACxB,CAAC;EAED;AACF;AACA;EACE,MAAMC,IAAIA,CAAA,EAAkB;IAC1B,MAAMvB,MAAM,CAAC,CAAC,CAACuB,IAAI,CAAC,CAAC;EACvB,CAAC;EAED;AACF;AACA;EACE7B,gBAAgBA,CAAC8B,QAA0C,EAAgB;IACzE,OAAO7B,uBAAuB,CAAC6B,QAAQ,CAAC;EAC1C,CAAC;EAED;AACF;AACA;EACE5B,OAAOA,CAAC4B,QAAwC,EAAgB;IAC9D,OAAO3B,cAAc,CAAC2B,QAAQ,CAAC;EACjC,CAAC;EAED;AACF;AACA;EACE,MAAMC,SAASA,CAAA,EAA4B;IACzC,MAAMR,UAAU,GAAG,MAAMjB,MAAM,CAAC,CAAC,CAACyB,SAAS,CAAC,CAAC;IAC7C,OAAOP,IAAI,CAACQ,KAAK,CAACT,UAAU,CAAC;EAC/B,CAAC;EAED;AACF;AACA;AACA;AACA;EACE,MAAMU,kBAAkBA,CAAA,EAAoB;IAC1C,IAAI,CAACzB,YAAY,EAAE;MACjB,MAAM0B,KAAK,GAAG,IAAI3B,KAAK,CACrB,+EACF,CAAC;MACA2B,KAAK,CAASC,IAAI,GAAG,gBAAgB;MACtC,MAAMD,KAAK;IACb;IACA,OAAO5B,MAAM,CAAC,CAAC,CAAC2B,kBAAkB,CAAC,CAAC;EACtC,CAAC;EAED;AACF;AACA;AACA;AACA;EACE,MAAMG,0BAA0BA,CAAA,EAAoC;IAClE,IAAI,CAAC5B,YAAY,EAAE;MACjB,MAAM0B,KAAK,GAAG,IAAI3B,KAAK,CACrB,uFACF,CAAC;MACA2B,KAAK,CAASC,IAAI,GAAG,gBAAgB;MACtC,MAAMD,KAAK;IACb;IACA,MAAMX,UAAU,GAAG,MAAMjB,MAAM,CAAC,CAAC,CAAC8B,0BAA0B,CAAC,CAAC;IAC9D,OAAOZ,IAAI,CAACQ,KAAK,CAACT,UAAU,CAAC;EAC/B;AACF,CAAC;AAED,eAAeb,YAAY","ignoreList":[]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Codegen spec for react-native-live-tracking.
3
+ *
4
+ * Uses TurboModuleRegistry.get (not getEnforcing) so that a missing or
5
+ * not-yet-registered module returns null instead of throwing synchronously.
6
+ * A top-level throw would corrupt the module graph and leave upstream
7
+ * importers (TrackingProvider, AppNavigator) with undefined module records.
8
+ *
9
+ * File must be named Native*.ts and live in the codegenConfig.jsSrcsDir
10
+ * for RN's codegen to pick it up.
11
+ */
12
+
13
+ import { TurboModuleRegistry, NativeModules } from 'react-native';
14
+ // Try TurboModule first (new arch with codegen), fall back to Bridge (old arch / interop)
15
+ export default TurboModuleRegistry.get('LiveTracking') ?? NativeModules.LiveTracking;
16
+ //# sourceMappingURL=NativeLiveTracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","NativeModules","get","LiveTracking"],"sourceRoot":"../../src","sources":["NativeLiveTracking.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,SAASA,mBAAmB,EAAEC,aAAa,QAAQ,cAAc;AAajE;AACA,eAAgBD,mBAAmB,CAACE,GAAG,CAAO,cAAc,CAAC,IAC3DD,aAAa,CAACE,YAAY","ignoreList":[]}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Distance/Time Matrix filter for location updates.
3
+ *
4
+ * This filter implements the battery optimization strategy that accepts a new
5
+ * location update based on the selected mode:
6
+ * - 'both' (default): BOTH time and distance conditions must be met
7
+ * - 'interval': only the time condition must be met
8
+ * - 'distance': only the distance condition must be met
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+
13
+ import { calculateDistance } from '../utils/distance';
14
+
15
+ /**
16
+ * Configuration subset required by the distance/time filter.
17
+ */
18
+
19
+ /**
20
+ * Determines whether a new location should be accepted based on the
21
+ * Distance/Time Matrix filter criteria.
22
+ *
23
+ * The filtering strategy depends on `config.mode`:
24
+ * - 'both': accepted only if both time and distance conditions are met
25
+ * - 'interval': accepted only if enough time has elapsed
26
+ * - 'distance': accepted only if enough distance has been covered
27
+ *
28
+ * @param lastLocation - The most recently accepted location
29
+ * @param newLocation - The candidate location to evaluate
30
+ * @param config - Filter configuration with intervalMs, distanceFilterMeters, and mode
31
+ * @returns `true` if the new location should be accepted, `false` otherwise
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const accepted = shouldAcceptLocation(
36
+ * { latitude: -6.2088, longitude: 106.8456, timestamp: 1700000000000, accuracy: 5, speed: null, altitude: null, bearing: null },
37
+ * { latitude: -6.2090, longitude: 106.8460, timestamp: 1700000015000, accuracy: 5, speed: 1.2, altitude: null, bearing: null },
38
+ * { intervalMs: 10000, distanceFilterMeters: 10, mode: 'both' }
39
+ * );
40
+ * ```
41
+ */
42
+ export function shouldAcceptLocation(lastLocation, newLocation, config) {
43
+ const mode = config.mode ?? 'both';
44
+ const timeDiff = newLocation.timestamp - lastLocation.timestamp;
45
+ const distance = calculateDistance(lastLocation.latitude, lastLocation.longitude, newLocation.latitude, newLocation.longitude);
46
+ const timeMet = timeDiff >= config.intervalMs;
47
+ const distanceMet = distance >= config.distanceFilterMeters;
48
+ switch (mode) {
49
+ case 'interval':
50
+ return timeMet;
51
+ case 'distance':
52
+ return distanceMet;
53
+ case 'both':
54
+ default:
55
+ return timeMet && distanceMet;
56
+ }
57
+ }
58
+ //# sourceMappingURL=distanceTimeFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["calculateDistance","shouldAcceptLocation","lastLocation","newLocation","config","mode","timeDiff","timestamp","distance","latitude","longitude","timeMet","intervalMs","distanceMet","distanceFilterMeters"],"sourceRoot":"../../../src","sources":["filters/distanceTimeFilter.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,iBAAiB,QAAQ,mBAAmB;;AAGrD;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAClCC,YAA0B,EAC1BC,WAAyB,EACzBC,MAAgC,EACvB;EACT,MAAMC,IAAI,GAAGD,MAAM,CAACC,IAAI,IAAI,MAAM;EAClC,MAAMC,QAAQ,GAAGH,WAAW,CAACI,SAAS,GAAGL,YAAY,CAACK,SAAS;EAC/D,MAAMC,QAAQ,GAAGR,iBAAiB,CAChCE,YAAY,CAACO,QAAQ,EACrBP,YAAY,CAACQ,SAAS,EACtBP,WAAW,CAACM,QAAQ,EACpBN,WAAW,CAACO,SACd,CAAC;EAED,MAAMC,OAAO,GAAGL,QAAQ,IAAIF,MAAM,CAACQ,UAAU;EAC7C,MAAMC,WAAW,GAAGL,QAAQ,IAAIJ,MAAM,CAACU,oBAAoB;EAE3D,QAAQT,IAAI;IACV,KAAK,UAAU;MACb,OAAOM,OAAO;IAChB,KAAK,UAAU;MACb,OAAOE,WAAW;IACpB,KAAK,MAAM;IACX;MACE,OAAOF,OAAO,IAAIE,WAAW;EACjC;AACF","ignoreList":[]}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * react-native-live-tracking
3
+ *
4
+ * Real-time location tracking library for React Native with Firebase synchronization.
5
+ * Supports both TurboModules (new architecture) and Bridge (old architecture).
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ import LiveTracking from './LiveTracking';
11
+ export default LiveTracking;
12
+ export { default as LiveTracking } from './LiveTracking';
13
+
14
+ // Re-export all types
15
+ export { TrackingState } from './types';
16
+ // Event listener functions
17
+ export { onLocationUpdate, onError, removeAllListeners } from './EventEmitter';
18
+
19
+ // Configuration validation utilities
20
+ export { validateConfig, applyDefaults } from './validation';
21
+
22
+ // Distance calculation utility
23
+ export { calculateDistance } from './utils/distance';
24
+
25
+ // Distance/Time Matrix filter
26
+ export { shouldAcceptLocation } from './filters/distanceTimeFilter';
27
+
28
+ // Location serialization for Firebase
29
+ export { serializeLocationForTarget } from './serialization/locationSerializer';
30
+ // Retry/backoff utilities
31
+ export { calculateBackoffDelay, shouldRetry } from './utils/retry';
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["LiveTracking","default","TrackingState","onLocationUpdate","onError","removeAllListeners","validateConfig","applyDefaults","calculateDistance","shouldAcceptLocation","serializeLocationForTarget","calculateBackoffDelay","shouldRetry"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAOA,YAAY,MAAM,gBAAgB;AAEzC,eAAeA,YAAY;AAC3B,SAASC,OAAO,IAAID,YAAY,QAAQ,gBAAgB;;AAExD;AACA,SAASE,aAAa,QAAQ,SAAS;AAkBvC;AACA,SAASC,gBAAgB,EAAEC,OAAO,EAAEC,kBAAkB,QAAQ,gBAAgB;;AAE9E;AACA,SAASC,cAAc,EAAEC,aAAa,QAAQ,cAAc;;AAE5D;AACA,SAASC,iBAAiB,QAAQ,kBAAkB;;AAEpD;AACA,SAASC,oBAAoB,QAAQ,8BAA8B;;AAEnE;AACA,SAASC,0BAA0B,QAAQ,oCAAoC;AAG/E;AACA,SAASC,qBAAqB,EAAEC,WAAW,QAAQ,eAAe","ignoreList":[]}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Location serialization for Firebase sync targets.
3
+ *
4
+ * Transforms LocationData into a generic payload suitable for any
5
+ * sync target, regardless of write method (set, push, update).
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ // ─── Payload Interface ───────────────────────────────────────────────────────
11
+
12
+ /**
13
+ * Serialized location payload for any sync target.
14
+ *
15
+ * Contains required fields (latitude, longitude, timestamp, accuracy)
16
+ * and optional sensor fields (speed, heading, altitude) which are
17
+ * included as `null` when unavailable from the device sensor.
18
+ * Placeholder values (0, -1) are never used for unavailable fields.
19
+ */
20
+
21
+ // ─── Serialization Function ──────────────────────────────────────────────────
22
+
23
+ /**
24
+ * Serialize a LocationData object for a generic Firebase sync target.
25
+ *
26
+ * Produces a payload containing all required location fields and optional
27
+ * sensor fields. When optional fields (speed, heading/bearing, altitude)
28
+ * are unavailable from the device sensor, they are included as `null`.
29
+ * Default placeholder values (0, -1) are never written for unavailable fields.
30
+ *
31
+ * @param location - The location data to serialize
32
+ * @returns Serialized payload for the sync target
33
+ */
34
+ export function serializeLocationForTarget(location) {
35
+ return {
36
+ latitude: location.latitude,
37
+ longitude: location.longitude,
38
+ timestamp: location.timestamp,
39
+ accuracy: location.accuracy,
40
+ speed: location.speed,
41
+ heading: location.bearing,
42
+ altitude: location.altitude
43
+ };
44
+ }
45
+ //# sourceMappingURL=locationSerializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["serializeLocationForTarget","location","latitude","longitude","timestamp","accuracy","speed","heading","bearing","altitude"],"sourceRoot":"../../../src","sources":["serialization/locationSerializer.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAWA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,0BAA0BA,CACxCC,QAAsB,EACC;EACvB,OAAO;IACLC,QAAQ,EAAED,QAAQ,CAACC,QAAQ;IAC3BC,SAAS,EAAEF,QAAQ,CAACE,SAAS;IAC7BC,SAAS,EAAEH,QAAQ,CAACG,SAAS;IAC7BC,QAAQ,EAAEJ,QAAQ,CAACI,QAAQ;IAC3BC,KAAK,EAAEL,QAAQ,CAACK,KAAK;IACrBC,OAAO,EAAEN,QAAQ,CAACO,OAAO;IACzBC,QAAQ,EAAER,QAAQ,CAACQ;EACrB,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * TypeScript type definitions for react-native-live-tracking.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+
7
+ // ─── Enums ───────────────────────────────────────────────────────────────────
8
+
9
+ /**
10
+ * Internal state machine for tracking lifecycle.
11
+ */
12
+ export let TrackingState = /*#__PURE__*/function (TrackingState) {
13
+ TrackingState["IDLE"] = "idle";
14
+ TrackingState["CONFIGURED"] = "configured";
15
+ TrackingState["TRACKING"] = "tracking";
16
+ TrackingState["MOTION_SLEEP"] = "motion_sleep";
17
+ TrackingState["PAUSED_GPS"] = "paused_gps";
18
+ return TrackingState;
19
+ }({});
20
+
21
+ // ─── Configuration Interfaces ────────────────────────────────────────────────
22
+
23
+ /**
24
+ * Strategy used by the distance/time filter.
25
+ * - 'interval': accept when enough time has elapsed
26
+ * - 'distance': accept when enough distance has been covered
27
+ * - 'both': accept only when both conditions are met (default)
28
+ */
29
+
30
+ /**
31
+ * Optimization parameters for location tracking.
32
+ */
33
+
34
+ /**
35
+ * Android foreground service notification configuration.
36
+ */
37
+
38
+ /**
39
+ * iOS persistent notification configuration.
40
+ * Shows a local notification while tracking is active (similar to Android's foreground service notification).
41
+ */
42
+
43
+ /**
44
+ * A user-defined sync target specifying a Firebase path, write method,
45
+ * and optional batching/offline queue settings.
46
+ */
47
+
48
+ /**
49
+ * Firebase connection and sync target configuration.
50
+ */
51
+
52
+ /**
53
+ * Main configuration object passed to `configure()`.
54
+ */
55
+
56
+ // ─── Data Interfaces ─────────────────────────────────────────────────────────
57
+
58
+ /**
59
+ * Location data emitted by the library on each valid location update.
60
+ */
61
+
62
+ // ─── Error & Status Interfaces ───────────────────────────────────────────────
63
+
64
+ /**
65
+ * Error object emitted by the library when tracking issues occur.
66
+ */
67
+
68
+ /**
69
+ * Current tracking status snapshot.
70
+ */
71
+
72
+ // ─── Validation Interfaces ───────────────────────────────────────────────────
73
+
74
+ /**
75
+ * Single configuration validation error.
76
+ */
77
+
78
+ /**
79
+ * Result of configuration validation.
80
+ */
81
+
82
+ // ─── Utility Types ───────────────────────────────────────────────────────────
83
+
84
+ /**
85
+ * Subscription handle returned by event listener registrations.
86
+ * Call `remove()` to unsubscribe from the event.
87
+ */
88
+
89
+ // ─── Module Interface ────────────────────────────────────────────────────────
90
+
91
+ /**
92
+ * Main public API interface for the react-native-live-tracking library.
93
+ */
94
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TrackingState"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,WAAYA,aAAa,0BAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAA,OAAbA,aAAa;AAAA;;AAQzB;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAYA;AACA;AACA;;AAgBA;AACA;AACA;AACA;;AAUA;AACA;AACA;AACA;;AAYA;AACA;AACA;;AAQA;AACA;AACA;;AAYA;;AAEA;AACA;AACA;;AAkBA;;AAEA;AACA;AACA;;AAYA;AACA;AACA;;AAcA;;AAEA;AACA;AACA;;AAUA;AACA;AACA;;AAQA;;AAEA;AACA;AACA;AACA;;AAMA;;AAEA;AACA;AACA","ignoreList":[]}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Distance calculation utility using the Haversine formula.
3
+ *
4
+ * The Haversine formula determines the great-circle distance between two points
5
+ * on a sphere given their longitudes and latitudes. This is used by the
6
+ * Distance/Time Matrix filter to determine if a new location update has moved
7
+ * far enough from the last known position.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+
12
+ /**
13
+ * Earth's mean radius in meters.
14
+ * Used as the sphere radius in the Haversine formula.
15
+ */
16
+ export const EARTH_RADIUS_METERS = 6371000;
17
+
18
+ /**
19
+ * Converts degrees to radians.
20
+ *
21
+ * @param degrees - Angle in degrees
22
+ * @returns Angle in radians
23
+ */
24
+ function toRadians(degrees) {
25
+ return degrees * (Math.PI / 180);
26
+ }
27
+
28
+ /**
29
+ * Calculates the distance in meters between two geographic coordinates
30
+ * using the Haversine formula.
31
+ *
32
+ * The Haversine formula accounts for the curvature of the Earth and provides
33
+ * accurate results for short and medium distances. It assumes a spherical Earth
34
+ * with a mean radius of 6,371,000 meters.
35
+ *
36
+ * @param lat1 - Latitude of the first point in degrees (-90 to 90)
37
+ * @param lng1 - Longitude of the first point in degrees (-180 to 180)
38
+ * @param lat2 - Latitude of the second point in degrees (-90 to 90)
39
+ * @param lng2 - Longitude of the second point in degrees (-180 to 180)
40
+ * @returns Distance between the two points in meters
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * // Distance between Jakarta and Bandung (approximately 120 km)
45
+ * const distance = calculateDistance(-6.2088, 106.8456, -6.9175, 107.6191);
46
+ * console.log(distance); // ~120,000 meters
47
+ * ```
48
+ */
49
+ export function calculateDistance(lat1, lng1, lat2, lng2) {
50
+ const dLat = toRadians(lat2 - lat1);
51
+ const dLng = toRadians(lng2 - lng1);
52
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
53
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
54
+ return EARTH_RADIUS_METERS * c;
55
+ }
56
+ //# sourceMappingURL=distance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["EARTH_RADIUS_METERS","toRadians","degrees","Math","PI","calculateDistance","lat1","lng1","lat2","lng2","dLat","dLng","a","sin","cos","c","atan2","sqrt"],"sourceRoot":"../../../src","sources":["utils/distance.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,OAAO,MAAMA,mBAAmB,GAAG,OAAO;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,SAASA,CAACC,OAAe,EAAU;EAC1C,OAAOA,OAAO,IAAIC,IAAI,CAACC,EAAE,GAAG,GAAG,CAAC;AAClC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAC/BC,IAAY,EACZC,IAAY,EACZC,IAAY,EACZC,IAAY,EACJ;EACR,MAAMC,IAAI,GAAGT,SAAS,CAACO,IAAI,GAAGF,IAAI,CAAC;EACnC,MAAMK,IAAI,GAAGV,SAAS,CAACQ,IAAI,GAAGF,IAAI,CAAC;EAEnC,MAAMK,CAAC,GACLT,IAAI,CAACU,GAAG,CAACH,IAAI,GAAG,CAAC,CAAC,GAAGP,IAAI,CAACU,GAAG,CAACH,IAAI,GAAG,CAAC,CAAC,GACvCP,IAAI,CAACW,GAAG,CAACb,SAAS,CAACK,IAAI,CAAC,CAAC,GACvBH,IAAI,CAACW,GAAG,CAACb,SAAS,CAACO,IAAI,CAAC,CAAC,GACzBL,IAAI,CAACU,GAAG,CAACF,IAAI,GAAG,CAAC,CAAC,GAClBR,IAAI,CAACU,GAAG,CAACF,IAAI,GAAG,CAAC,CAAC;EAEtB,MAAMI,CAAC,GAAG,CAAC,GAAGZ,IAAI,CAACa,KAAK,CAACb,IAAI,CAACc,IAAI,CAACL,CAAC,CAAC,EAAET,IAAI,CAACc,IAAI,CAAC,CAAC,GAAGL,CAAC,CAAC,CAAC;EAExD,OAAOZ,mBAAmB,GAAGe,CAAC;AAChC","ignoreList":[]}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Exponential backoff retry utilities for Firebase write operations.
3
+ *
4
+ * Used by the Firebase Sync Engine to determine delay between retry attempts
5
+ * when writes fail due to network issues or transient errors.
6
+ *
7
+ * @module utils/retry
8
+ */
9
+
10
+ /** Default base delay in milliseconds for exponential backoff */
11
+ export const DEFAULT_BASE_DELAY = 1000;
12
+
13
+ /** Default maximum jitter in milliseconds (±) to avoid thundering herd */
14
+ export const DEFAULT_MAX_JITTER = 200;
15
+
16
+ /** Maximum retry attempts for sync targets using 'set' or 'update' write methods */
17
+ export const MAX_RETRIES_SET_UPDATE = 3;
18
+
19
+ /** Maximum retry attempts for sync targets using 'push' write method */
20
+ export const MAX_RETRIES_PUSH = 5;
21
+
22
+ /**
23
+ * Calculates the delay before the next retry attempt using exponential backoff
24
+ * with random jitter.
25
+ *
26
+ * Formula: delay = baseDelay × 2^(attempt - 1) + random(-maxJitter, +maxJitter)
27
+ *
28
+ * The result is clamped to a minimum of 0 to prevent negative delays.
29
+ *
30
+ * @param attempt - The retry attempt number (1-indexed, first retry = 1)
31
+ * @param baseDelay - The base delay in milliseconds (default: 1000ms)
32
+ * @param maxJitter - The maximum jitter offset in milliseconds (default: 200ms).
33
+ * A random value between -maxJitter and +maxJitter is added to the delay.
34
+ * @returns The calculated delay in milliseconds (never negative)
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // First retry: ~1000ms ± 200ms
39
+ * const delay1 = calculateBackoffDelay(1);
40
+ *
41
+ * // Second retry: ~2000ms ± 200ms
42
+ * const delay2 = calculateBackoffDelay(2);
43
+ *
44
+ * // Third retry: ~4000ms ± 200ms
45
+ * const delay3 = calculateBackoffDelay(3);
46
+ * ```
47
+ */
48
+ export function calculateBackoffDelay(attempt, baseDelay = DEFAULT_BASE_DELAY, maxJitter = DEFAULT_MAX_JITTER) {
49
+ const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);
50
+ const jitter = (Math.random() * 2 - 1) * maxJitter;
51
+ return Math.max(0, exponentialDelay + jitter);
52
+ }
53
+
54
+ /**
55
+ * Determines whether a retry should be attempted based on the current attempt
56
+ * number and the maximum allowed retries.
57
+ *
58
+ * @param attempt - The current attempt number (1-indexed)
59
+ * @param maxRetries - The maximum number of retries allowed
60
+ * @returns `true` if the attempt is within the allowed retry limit, `false` otherwise
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * shouldRetry(1, 3); // true - first retry is allowed
65
+ * shouldRetry(3, 3); // true - third retry is allowed
66
+ * shouldRetry(4, 3); // false - exceeds max retries
67
+ * ```
68
+ */
69
+ export function shouldRetry(attempt, maxRetries) {
70
+ return attempt <= maxRetries;
71
+ }
72
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["DEFAULT_BASE_DELAY","DEFAULT_MAX_JITTER","MAX_RETRIES_SET_UPDATE","MAX_RETRIES_PUSH","calculateBackoffDelay","attempt","baseDelay","maxJitter","exponentialDelay","Math","pow","jitter","random","max","shouldRetry","maxRetries"],"sourceRoot":"../../../src","sources":["utils/retry.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,OAAO,MAAMA,kBAAkB,GAAG,IAAI;;AAEtC;AACA,OAAO,MAAMC,kBAAkB,GAAG,GAAG;;AAErC;AACA,OAAO,MAAMC,sBAAsB,GAAG,CAAC;;AAEvC;AACA,OAAO,MAAMC,gBAAgB,GAAG,CAAC;;AAEjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CACnCC,OAAe,EACfC,SAAiB,GAAGN,kBAAkB,EACtCO,SAAiB,GAAGN,kBAAkB,EAC9B;EACR,MAAMO,gBAAgB,GAAGF,SAAS,GAAGG,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEL,OAAO,GAAG,CAAC,CAAC;EAC7D,MAAMM,MAAM,GAAG,CAACF,IAAI,CAACG,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAIL,SAAS;EAClD,OAAOE,IAAI,CAACI,GAAG,CAAC,CAAC,EAAEL,gBAAgB,GAAGG,MAAM,CAAC;AAC/C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,WAAWA,CAACT,OAAe,EAAEU,UAAkB,EAAW;EACxE,OAAOV,OAAO,IAAIU,UAAU;AAC9B","ignoreList":[]}