@rejourneyco/react-native 1.0.0 → 1.0.2

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 (49) hide show
  1. package/README.md +29 -0
  2. package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +47 -30
  3. package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +25 -1
  4. package/android/src/main/java/com/rejourney/capture/CaptureHeuristics.kt +70 -32
  5. package/android/src/main/java/com/rejourney/core/Constants.kt +4 -4
  6. package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +14 -0
  7. package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +9 -0
  8. package/ios/Capture/RJCaptureEngine.m +72 -34
  9. package/ios/Capture/RJCaptureHeuristics.h +7 -5
  10. package/ios/Capture/RJCaptureHeuristics.m +138 -112
  11. package/ios/Capture/RJVideoEncoder.m +0 -26
  12. package/ios/Core/Rejourney.mm +64 -102
  13. package/ios/Utils/RJPerfTiming.m +0 -5
  14. package/ios/Utils/RJWindowUtils.m +0 -1
  15. package/lib/commonjs/components/Mask.js +1 -6
  16. package/lib/commonjs/index.js +12 -101
  17. package/lib/commonjs/sdk/autoTracking.js +55 -353
  18. package/lib/commonjs/sdk/constants.js +2 -13
  19. package/lib/commonjs/sdk/errorTracking.js +1 -29
  20. package/lib/commonjs/sdk/metricsTracking.js +3 -24
  21. package/lib/commonjs/sdk/navigation.js +3 -42
  22. package/lib/commonjs/sdk/networkInterceptor.js +7 -49
  23. package/lib/commonjs/sdk/utils.js +0 -5
  24. package/lib/module/components/Mask.js +1 -6
  25. package/lib/module/index.js +11 -105
  26. package/lib/module/sdk/autoTracking.js +55 -354
  27. package/lib/module/sdk/constants.js +2 -13
  28. package/lib/module/sdk/errorTracking.js +1 -29
  29. package/lib/module/sdk/index.js +0 -2
  30. package/lib/module/sdk/metricsTracking.js +3 -24
  31. package/lib/module/sdk/navigation.js +3 -42
  32. package/lib/module/sdk/networkInterceptor.js +7 -49
  33. package/lib/module/sdk/utils.js +0 -5
  34. package/lib/typescript/NativeRejourney.d.ts +2 -0
  35. package/lib/typescript/sdk/autoTracking.d.ts +5 -6
  36. package/lib/typescript/types/index.d.ts +0 -1
  37. package/package.json +11 -3
  38. package/src/NativeRejourney.ts +4 -0
  39. package/src/components/Mask.tsx +0 -3
  40. package/src/index.ts +11 -88
  41. package/src/sdk/autoTracking.ts +72 -331
  42. package/src/sdk/constants.ts +13 -13
  43. package/src/sdk/errorTracking.ts +1 -17
  44. package/src/sdk/index.ts +0 -2
  45. package/src/sdk/metricsTracking.ts +5 -33
  46. package/src/sdk/navigation.ts +8 -29
  47. package/src/sdk/networkInterceptor.ts +9 -33
  48. package/src/sdk/utils.ts +0 -5
  49. package/src/types/index.ts +0 -29
package/src/index.ts CHANGED
@@ -79,13 +79,11 @@ function getReactNative(): typeof import('react-native') | null {
79
79
  }
80
80
  }
81
81
 
82
- // Lazy-loaded logger
83
82
  let _logger: typeof import('./sdk/utils').logger | null = null;
84
83
 
85
84
  function getLogger() {
86
85
  if (_logger) return _logger;
87
86
  if (_sdkDisabled) {
88
- // Return a no-op logger if SDK is disabled
89
87
  return {
90
88
  debug: () => { },
91
89
  info: console.log.bind(console, '[Rejourney]'),
@@ -175,7 +173,7 @@ const noopAutoTracking = {
175
173
  notifyStateChange: () => { },
176
174
  getSessionMetrics: () => ({}),
177
175
  resetMetrics: () => { },
178
- collectDeviceInfo: () => ({}),
176
+ collectDeviceInfo: async () => ({} as any),
179
177
  ensurePersistentAnonymousId: async () => 'anonymous',
180
178
  };
181
179
 
@@ -193,8 +191,6 @@ function getAutoTracking() {
193
191
  }
194
192
 
195
193
  // State
196
- const USER_IDENTITY_KEY = '@rejourney_user_identity';
197
-
198
194
  let _isInitialized = false;
199
195
  let _isRecording = false;
200
196
  let _initializationFailed = false;
@@ -209,24 +205,19 @@ let _lastScrollOffset: number = 0;
209
205
  const SCROLL_THROTTLE_MS = 100;
210
206
 
211
207
  // Helper to save/load user identity
212
- async function persistUserIdentity(identity: string | null): Promise<void> {
213
- try {
214
- const AsyncStorage = require('@react-native-async-storage/async-storage').default;
215
- if (identity) {
216
- await AsyncStorage.setItem(USER_IDENTITY_KEY, identity);
217
- } else {
218
- await AsyncStorage.removeItem(USER_IDENTITY_KEY);
219
- }
220
- } catch (e) {
221
- // Ignore storage errors
222
- }
208
+ // NOW HANDLED NATIVELY - No-op on JS side to avoid unnecessary bridge calls
209
+ async function persistUserIdentity(_identity: string | null): Promise<void> {
210
+ // Native module handles persistence automatically in setUserIdentity
223
211
  }
224
212
 
225
213
  async function loadPersistedUserIdentity(): Promise<string | null> {
226
214
  try {
227
- const AsyncStorage = require('@react-native-async-storage/async-storage').default;
228
- return await AsyncStorage.getItem(USER_IDENTITY_KEY);
229
- } catch (e) {
215
+ const nativeModule = getRejourneyNative();
216
+ if (!nativeModule) return null;
217
+
218
+ // NATIVE STORAGE: Read directly from SharedPreferences/NSUserDefaults
219
+ return await nativeModule.getUserIdentity();
220
+ } catch {
230
221
  return null;
231
222
  }
232
223
  }
@@ -248,9 +239,7 @@ function isRuntimeReady(): boolean {
248
239
  if (_runtimeReady) return true;
249
240
 
250
241
  try {
251
- // Try to access a core module to verify runtime is ready
252
242
  const RN = require('react-native');
253
- // If we can access NativeModules without error, runtime is ready
254
243
  if (RN.NativeModules) {
255
244
  _runtimeReady = true;
256
245
  return true;
@@ -332,12 +321,10 @@ function getRejourneyNative(): Spec | null {
332
321
  }
333
322
  }
334
323
  } catch (error) {
335
- // If any access fails, log and return null
336
324
  getLogger().warn('Rejourney: Failed to access native modules:', error);
337
325
  _rejourneyNative = null;
338
326
  }
339
327
 
340
- // Ensure we never return undefined - convert to null
341
328
  if (_rejourneyNative === undefined) {
342
329
  _rejourneyNative = null;
343
330
  }
@@ -500,7 +487,7 @@ const Rejourney: RejourneyAPI = {
500
487
  // Collect and log device info
501
488
  if (_storedConfig?.collectDeviceInfo !== false) {
502
489
  try {
503
- const deviceInfo = getAutoTracking().collectDeviceInfo();
490
+ const deviceInfo = await getAutoTracking().collectDeviceInfo();
504
491
  this.logEvent('device_info', deviceInfo as unknown as Record<string, unknown>);
505
492
  } catch (deviceError) {
506
493
  getLogger().warn('Failed to collect device info:', deviceError);
@@ -534,13 +521,11 @@ const Rejourney: RejourneyAPI = {
534
521
  }
535
522
  );
536
523
 
537
- // logger.debug('Network interception enabled');
538
524
  } catch (networkError) {
539
525
  getLogger().warn('Failed to setup network interception:', networkError);
540
526
  }
541
527
  }
542
528
 
543
- // logger.debug('Auto tracking enabled');
544
529
 
545
530
  return true;
546
531
  } catch (error) {
@@ -560,11 +545,9 @@ const Rejourney: RejourneyAPI = {
560
545
  }
561
546
 
562
547
  try {
563
- // Get session metrics before stopping
564
548
  const metrics = getAutoTracking().getSessionMetrics();
565
549
  this.logEvent('session_metrics', metrics as unknown as Record<string, unknown>);
566
550
 
567
- // Cleanup
568
551
  getNetworkInterceptor().disableNetworkInterceptor();
569
552
  getAutoTracking().cleanupAutoTracking();
570
553
  getAutoTracking().resetMetrics();
@@ -572,7 +555,6 @@ const Rejourney: RejourneyAPI = {
572
555
  await safeNativeCall('stopSession', () => getRejourneyNative()!.stopSession(), undefined);
573
556
 
574
557
  _isRecording = false;
575
- // Use lifecycle log for session end - only shown in dev builds
576
558
  getLogger().logSessionEnd('current');
577
559
  } catch (error) {
578
560
  getLogger().error('Failed to stop recording:', error);
@@ -610,9 +592,7 @@ const Rejourney: RejourneyAPI = {
610
592
  setUserIdentity(userId: string): void {
611
593
  _userIdentity = userId;
612
594
  persistUserIdentity(userId).catch(() => { });
613
- // logger.debug(`User identity set: ${userId}`);
614
595
 
615
- // If recording is active, update the native module immediately
616
596
  if (_isRecording && getRejourneyNative()) {
617
597
  safeNativeCallSync(
618
598
  'setUserIdentity',
@@ -631,9 +611,7 @@ const Rejourney: RejourneyAPI = {
631
611
  clearUserIdentity(): void {
632
612
  _userIdentity = null;
633
613
  persistUserIdentity(null).catch(() => { });
634
- // logger.debug('User identity cleared');
635
614
 
636
- // If recording is active, update the native module immediately
637
615
  if (_isRecording && getRejourneyNative()) {
638
616
  safeNativeCallSync(
639
617
  'setUserIdentity',
@@ -652,10 +630,7 @@ const Rejourney: RejourneyAPI = {
652
630
  * @param params - Optional screen parameters
653
631
  */
654
632
  tagScreen(screenName: string, _params?: Record<string, unknown>): void {
655
- // Track screen for metrics and funnel tracking
656
633
  getAutoTracking().trackScreen(screenName);
657
-
658
- // Notify state change (kept for API compatibility)
659
634
  getAutoTracking().notifyStateChange();
660
635
 
661
636
  safeNativeCallSync(
@@ -852,10 +827,6 @@ const Rejourney: RejourneyAPI = {
852
827
  );
853
828
  },
854
829
 
855
- // ========================================================================
856
- // OAuth / External URL Tracking
857
- // ========================================================================
858
-
859
830
  /**
860
831
  * Notify the SDK that an OAuth flow is starting
861
832
  *
@@ -1011,10 +982,6 @@ const Rejourney: RejourneyAPI = {
1011
982
  );
1012
983
  },
1013
984
 
1014
- // ========================================================================
1015
- // SDK Telemetry / Observability
1016
- // ========================================================================
1017
-
1018
985
  /**
1019
986
  * Get SDK telemetry metrics for observability
1020
987
  *
@@ -1072,10 +1039,6 @@ const Rejourney: RejourneyAPI = {
1072
1039
  }
1073
1040
  },
1074
1041
 
1075
- // ========================================================================
1076
- // Privacy / View Masking
1077
- // ========================================================================
1078
-
1079
1042
  /**
1080
1043
  * Mask a view by its nativeID prop (will be occluded in recordings)
1081
1044
  *
@@ -1120,10 +1083,6 @@ const Rejourney: RejourneyAPI = {
1120
1083
  },
1121
1084
  };
1122
1085
 
1123
- // =============================================================================
1124
- // Automatic Lifecycle Management
1125
- // =============================================================================
1126
-
1127
1086
  /**
1128
1087
  * Handle app state changes for automatic session management
1129
1088
  * - Pauses recording when app goes to background
@@ -1157,20 +1116,14 @@ function setupLifecycleManagement(): void {
1157
1116
  const RN = getReactNative();
1158
1117
  if (!RN) return;
1159
1118
 
1160
- // Remove any existing subscription
1161
1119
  if (_appStateSubscription) {
1162
1120
  _appStateSubscription.remove();
1163
1121
  _appStateSubscription = null;
1164
1122
  }
1165
1123
 
1166
1124
  try {
1167
- // Get current app state
1168
1125
  _currentAppState = RN.AppState.currentState || 'active';
1169
-
1170
- // Subscribe to app state changes
1171
1126
  _appStateSubscription = RN.AppState.addEventListener('change', handleAppStateChange);
1172
-
1173
- // Setup auth error listener from native module
1174
1127
  setupAuthErrorListener();
1175
1128
 
1176
1129
  getLogger().debug('Lifecycle management enabled');
@@ -1197,9 +1150,6 @@ function setupAuthErrorListener(): void {
1197
1150
  try {
1198
1151
  const nativeModule = getRejourneyNative();
1199
1152
  if (nativeModule) {
1200
- // RN warns if a non-null module is passed without addListener/removeListeners.
1201
- // Our native module may not implement these no-op methods yet, so only pass
1202
- // the module when those hooks exist; otherwise use the global emitter.
1203
1153
  const maybeAny = nativeModule as any;
1204
1154
  const hasEventEmitterHooks =
1205
1155
  typeof maybeAny?.addListener === 'function' && typeof maybeAny?.removeListeners === 'function';
@@ -1219,10 +1169,8 @@ function setupAuthErrorListener(): void {
1219
1169
  getLogger().logInvalidProjectKey();
1220
1170
  }
1221
1171
 
1222
- // Update SDK state - recording has been stopped by native
1223
1172
  _isRecording = false;
1224
1173
 
1225
- // Call user's error handler if provided
1226
1174
  if (_storedConfig?.onAuthError) {
1227
1175
  try {
1228
1176
  _storedConfig.onAuthError(error);
@@ -1234,7 +1182,6 @@ function setupAuthErrorListener(): void {
1234
1182
  );
1235
1183
  }
1236
1184
  } catch (error) {
1237
- // Event emitter not available on this platform - that's OK
1238
1185
  getLogger().debug('Auth error listener not available:', error);
1239
1186
  }
1240
1187
  }
@@ -1253,10 +1200,6 @@ function cleanupLifecycleManagement(): void {
1253
1200
  }
1254
1201
  }
1255
1202
 
1256
- // =============================================================================
1257
- // Simple Initialization API
1258
- // =============================================================================
1259
-
1260
1203
  /**
1261
1204
  * Initialize Rejourney SDK - STEP 1 of 3
1262
1205
  *
@@ -1289,14 +1232,12 @@ export function initRejourney(
1289
1232
  publicRouteKey: string,
1290
1233
  options?: Omit<RejourneyConfig, 'publicRouteKey'>
1291
1234
  ): void {
1292
- // Validate public route key
1293
1235
  if (!publicRouteKey || typeof publicRouteKey !== 'string') {
1294
1236
  getLogger().warn('Rejourney: Invalid public route key provided. SDK will be disabled.');
1295
1237
  _initializationFailed = true;
1296
1238
  return;
1297
1239
  }
1298
1240
 
1299
- // Store config for later use
1300
1241
  _storedConfig = {
1301
1242
  ...options,
1302
1243
  publicRouteKey,
@@ -1357,7 +1298,6 @@ export function startRejourney(): void {
1357
1298
  getLogger().logRecordingStart();
1358
1299
  getLogger().debug('Starting session...');
1359
1300
 
1360
- // Fire and forget - don't block the caller
1361
1301
  (async () => {
1362
1302
  try {
1363
1303
  const started = await Rejourney._startSession();
@@ -1391,11 +1331,8 @@ export function stopRejourney(): void {
1391
1331
 
1392
1332
  export default Rejourney;
1393
1333
 
1394
- // Export types
1395
1334
  export * from './types';
1396
1335
 
1397
- // Export auto tracking utilities for advanced usage
1398
- // These are used internally but can be called manually if needed
1399
1336
  export {
1400
1337
  trackTap,
1401
1338
  trackScroll,
@@ -1406,11 +1343,8 @@ export {
1406
1343
  getSessionMetrics,
1407
1344
  } from './sdk/autoTracking';
1408
1345
 
1409
- // Navigation
1410
1346
  export { trackNavigationState, useNavigationTracking } from './sdk/autoTracking';
1411
1347
 
1412
- // Re-export LogLevel enum from utils
1413
- // Note: This is safe because the enum itself doesn't trigger react-native imports
1414
1348
  export { LogLevel } from './sdk/utils';
1415
1349
 
1416
1350
  /**
@@ -1445,15 +1379,4 @@ export function setLogLevel(level: number): void {
1445
1379
  getLogger().setLogLevel(level);
1446
1380
  }
1447
1381
 
1448
- // Note: Components and hooks removed in new engine
1449
- // Session replay now handled by dashboard web UI
1450
- // export { RejourneyReplay } from './components/replay/RejourneyReplay';
1451
- // export { GestureTracker } from './components/GestureTracker';
1452
- // export { SessionList } from './components/SessionList';
1453
- // export { useRejourney } from './hooks/useRejourney';
1454
- // export { useReplay } from './hooks/useReplay';
1455
-
1456
- // Note: SDK managers removed in new engine - all functionality handled by native module
1457
-
1458
- // Export Mask component
1459
1382
  export { Mask } from './components/Mask';