@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
@@ -175,13 +175,10 @@ function getReactNative() {
175
175
  return null;
176
176
  }
177
177
  }
178
-
179
- // Lazy-loaded logger
180
178
  let _logger = null;
181
179
  function getLogger() {
182
180
  if (_logger) return _logger;
183
181
  if (_sdkDisabled) {
184
- // Return a no-op logger if SDK is disabled
185
182
  return {
186
183
  debug: () => {},
187
184
  info: console.log.bind(console, '[Rejourney]'),
@@ -260,7 +257,7 @@ const noopAutoTracking = {
260
257
  notifyStateChange: () => {},
261
258
  getSessionMetrics: () => ({}),
262
259
  resetMetrics: () => {},
263
- collectDeviceInfo: () => ({}),
260
+ collectDeviceInfo: async () => ({}),
264
261
  ensurePersistentAnonymousId: async () => 'anonymous'
265
262
  };
266
263
  function getAutoTracking() {
@@ -276,7 +273,6 @@ function getAutoTracking() {
276
273
  }
277
274
 
278
275
  // State
279
- const USER_IDENTITY_KEY = '@rejourney_user_identity';
280
276
  let _isInitialized = false;
281
277
  let _isRecording = false;
282
278
  let _initializationFailed = false;
@@ -291,23 +287,18 @@ let _lastScrollOffset = 0;
291
287
  const SCROLL_THROTTLE_MS = 100;
292
288
 
293
289
  // Helper to save/load user identity
294
- async function persistUserIdentity(identity) {
295
- try {
296
- const AsyncStorage = require('@react-native-async-storage/async-storage').default;
297
- if (identity) {
298
- await AsyncStorage.setItem(USER_IDENTITY_KEY, identity);
299
- } else {
300
- await AsyncStorage.removeItem(USER_IDENTITY_KEY);
301
- }
302
- } catch (e) {
303
- // Ignore storage errors
304
- }
290
+ // NOW HANDLED NATIVELY - No-op on JS side to avoid unnecessary bridge calls
291
+ async function persistUserIdentity(_identity) {
292
+ // Native module handles persistence automatically in setUserIdentity
305
293
  }
306
294
  async function loadPersistedUserIdentity() {
307
295
  try {
308
- const AsyncStorage = require('@react-native-async-storage/async-storage').default;
309
- return await AsyncStorage.getItem(USER_IDENTITY_KEY);
310
- } catch (e) {
296
+ const nativeModule = getRejourneyNative();
297
+ if (!nativeModule) return null;
298
+
299
+ // NATIVE STORAGE: Read directly from SharedPreferences/NSUserDefaults
300
+ return await nativeModule.getUserIdentity();
301
+ } catch {
311
302
  return null;
312
303
  }
313
304
  }
@@ -327,9 +318,7 @@ let _runtimeReady = false;
327
318
  function isRuntimeReady() {
328
319
  if (_runtimeReady) return true;
329
320
  try {
330
- // Try to access a core module to verify runtime is ready
331
321
  const RN = require('react-native');
332
- // If we can access NativeModules without error, runtime is ready
333
322
  if (RN.NativeModules) {
334
323
  _runtimeReady = true;
335
324
  return true;
@@ -412,12 +401,9 @@ function getRejourneyNative() {
412
401
  }
413
402
  }
414
403
  } catch (error) {
415
- // If any access fails, log and return null
416
404
  getLogger().warn('Rejourney: Failed to access native modules:', error);
417
405
  _rejourneyNative = null;
418
406
  }
419
-
420
- // Ensure we never return undefined - convert to null
421
407
  if (_rejourneyNative === undefined) {
422
408
  _rejourneyNative = null;
423
409
  }
@@ -559,7 +545,7 @@ const Rejourney = {
559
545
  // Collect and log device info
560
546
  if (_storedConfig?.collectDeviceInfo !== false) {
561
547
  try {
562
- const deviceInfo = getAutoTracking().collectDeviceInfo();
548
+ const deviceInfo = await getAutoTracking().collectDeviceInfo();
563
549
  this.logEvent('device_info', deviceInfo);
564
550
  } catch (deviceError) {
565
551
  getLogger().warn('Failed to collect device info:', deviceError);
@@ -577,15 +563,10 @@ const Rejourney = {
577
563
  ignoreUrls,
578
564
  captureSizes: _storedConfig?.networkCaptureSizes !== false
579
565
  });
580
-
581
- // logger.debug('Network interception enabled');
582
566
  } catch (networkError) {
583
567
  getLogger().warn('Failed to setup network interception:', networkError);
584
568
  }
585
569
  }
586
-
587
- // logger.debug('Auto tracking enabled');
588
-
589
570
  return true;
590
571
  } catch (error) {
591
572
  getLogger().error('Failed to start recording:', error);
@@ -602,17 +583,13 @@ const Rejourney = {
602
583
  return;
603
584
  }
604
585
  try {
605
- // Get session metrics before stopping
606
586
  const metrics = getAutoTracking().getSessionMetrics();
607
587
  this.logEvent('session_metrics', metrics);
608
-
609
- // Cleanup
610
588
  getNetworkInterceptor().disableNetworkInterceptor();
611
589
  getAutoTracking().cleanupAutoTracking();
612
590
  getAutoTracking().resetMetrics();
613
591
  await safeNativeCall('stopSession', () => getRejourneyNative().stopSession(), undefined);
614
592
  _isRecording = false;
615
- // Use lifecycle log for session end - only shown in dev builds
616
593
  getLogger().logSessionEnd('current');
617
594
  } catch (error) {
618
595
  getLogger().error('Failed to stop recording:', error);
@@ -644,9 +621,6 @@ const Rejourney = {
644
621
  setUserIdentity(userId) {
645
622
  _userIdentity = userId;
646
623
  persistUserIdentity(userId).catch(() => {});
647
- // logger.debug(`User identity set: ${userId}`);
648
-
649
- // If recording is active, update the native module immediately
650
624
  if (_isRecording && getRejourneyNative()) {
651
625
  safeNativeCallSync('setUserIdentity', () => {
652
626
  getRejourneyNative().setUserIdentity(userId).catch(() => {});
@@ -660,9 +634,6 @@ const Rejourney = {
660
634
  clearUserIdentity() {
661
635
  _userIdentity = null;
662
636
  persistUserIdentity(null).catch(() => {});
663
- // logger.debug('User identity cleared');
664
-
665
- // If recording is active, update the native module immediately
666
637
  if (_isRecording && getRejourneyNative()) {
667
638
  safeNativeCallSync('setUserIdentity', () => {
668
639
  getRejourneyNative().setUserIdentity('anonymous').catch(() => {});
@@ -676,10 +647,7 @@ const Rejourney = {
676
647
  * @param params - Optional screen parameters
677
648
  */
678
649
  tagScreen(screenName, _params) {
679
- // Track screen for metrics and funnel tracking
680
650
  getAutoTracking().trackScreen(screenName);
681
-
682
- // Notify state change (kept for API compatibility)
683
651
  getAutoTracking().notifyStateChange();
684
652
  safeNativeCallSync('tagScreen', () => {
685
653
  getRejourneyNative().screenChanged(screenName).catch(() => {});
@@ -857,10 +825,6 @@ const Rejourney = {
857
825
  getAutoTracking().trackScroll();
858
826
  await safeNativeCall('onScroll', () => getRejourneyNative().onScroll(scrollOffset), undefined);
859
827
  },
860
- // ========================================================================
861
- // OAuth / External URL Tracking
862
- // ========================================================================
863
-
864
828
  /**
865
829
  * Notify the SDK that an OAuth flow is starting
866
830
  *
@@ -996,10 +960,6 @@ const Rejourney = {
996
960
  getRejourneyNative().logEvent('network_request', networkEvent).catch(() => {});
997
961
  }, undefined);
998
962
  },
999
- // ========================================================================
1000
- // SDK Telemetry / Observability
1001
- // ========================================================================
1002
-
1003
963
  /**
1004
964
  * Get SDK telemetry metrics for observability
1005
965
  *
@@ -1047,10 +1007,6 @@ const Rejourney = {
1047
1007
  getLogger().warn('debugTriggerANR is only available in development mode');
1048
1008
  }
1049
1009
  },
1050
- // ========================================================================
1051
- // Privacy / View Masking
1052
- // ========================================================================
1053
-
1054
1010
  /**
1055
1011
  * Mask a view by its nativeID prop (will be occluded in recordings)
1056
1012
  *
@@ -1086,10 +1042,6 @@ const Rejourney = {
1086
1042
  }
1087
1043
  };
1088
1044
 
1089
- // =============================================================================
1090
- // Automatic Lifecycle Management
1091
- // =============================================================================
1092
-
1093
1045
  /**
1094
1046
  * Handle app state changes for automatic session management
1095
1047
  * - Pauses recording when app goes to background
@@ -1120,20 +1072,13 @@ function setupLifecycleManagement() {
1120
1072
  if (_sdkDisabled) return;
1121
1073
  const RN = getReactNative();
1122
1074
  if (!RN) return;
1123
-
1124
- // Remove any existing subscription
1125
1075
  if (_appStateSubscription) {
1126
1076
  _appStateSubscription.remove();
1127
1077
  _appStateSubscription = null;
1128
1078
  }
1129
1079
  try {
1130
- // Get current app state
1131
1080
  _currentAppState = RN.AppState.currentState || 'active';
1132
-
1133
- // Subscribe to app state changes
1134
1081
  _appStateSubscription = RN.AppState.addEventListener('change', handleAppStateChange);
1135
-
1136
- // Setup auth error listener from native module
1137
1082
  setupAuthErrorListener();
1138
1083
  getLogger().debug('Lifecycle management enabled');
1139
1084
  } catch (error) {
@@ -1156,9 +1101,6 @@ function setupAuthErrorListener() {
1156
1101
  try {
1157
1102
  const nativeModule = getRejourneyNative();
1158
1103
  if (nativeModule) {
1159
- // RN warns if a non-null module is passed without addListener/removeListeners.
1160
- // Our native module may not implement these no-op methods yet, so only pass
1161
- // the module when those hooks exist; otherwise use the global emitter.
1162
1104
  const maybeAny = nativeModule;
1163
1105
  const hasEventEmitterHooks = typeof maybeAny?.addListener === 'function' && typeof maybeAny?.removeListeners === 'function';
1164
1106
  const eventEmitter = hasEventEmitterHooks ? new RN.NativeEventEmitter(maybeAny) : new RN.NativeEventEmitter();
@@ -1169,11 +1111,7 @@ function setupAuthErrorListener() {
1169
1111
  } else if (error?.code === 404) {
1170
1112
  getLogger().logInvalidProjectKey();
1171
1113
  }
1172
-
1173
- // Update SDK state - recording has been stopped by native
1174
1114
  _isRecording = false;
1175
-
1176
- // Call user's error handler if provided
1177
1115
  if (_storedConfig?.onAuthError) {
1178
1116
  try {
1179
1117
  _storedConfig.onAuthError(error);
@@ -1184,7 +1122,6 @@ function setupAuthErrorListener() {
1184
1122
  });
1185
1123
  }
1186
1124
  } catch (error) {
1187
- // Event emitter not available on this platform - that's OK
1188
1125
  getLogger().debug('Auth error listener not available:', error);
1189
1126
  }
1190
1127
  }
@@ -1203,10 +1140,6 @@ function cleanupLifecycleManagement() {
1203
1140
  }
1204
1141
  }
1205
1142
 
1206
- // =============================================================================
1207
- // Simple Initialization API
1208
- // =============================================================================
1209
-
1210
1143
  /**
1211
1144
  * Initialize Rejourney SDK - STEP 1 of 3
1212
1145
  *
@@ -1236,14 +1169,11 @@ function cleanupLifecycleManagement() {
1236
1169
  * ```
1237
1170
  */
1238
1171
  function initRejourney(publicRouteKey, options) {
1239
- // Validate public route key
1240
1172
  if (!publicRouteKey || typeof publicRouteKey !== 'string') {
1241
1173
  getLogger().warn('Rejourney: Invalid public route key provided. SDK will be disabled.');
1242
1174
  _initializationFailed = true;
1243
1175
  return;
1244
1176
  }
1245
-
1246
- // Store config for later use
1247
1177
  _storedConfig = {
1248
1178
  ...options,
1249
1179
  publicRouteKey
@@ -1297,8 +1227,6 @@ function startRejourney() {
1297
1227
  }
1298
1228
  getLogger().logRecordingStart();
1299
1229
  getLogger().debug('Starting session...');
1300
-
1301
- // Fire and forget - don't block the caller
1302
1230
  (async () => {
1303
1231
  try {
1304
1232
  const started = await Rejourney._startSession();
@@ -1329,12 +1257,7 @@ function stopRejourney() {
1329
1257
  getLogger().warn('Error stopping Rejourney:', error);
1330
1258
  }
1331
1259
  }
1332
- var _default = exports.default = Rejourney; // Export types
1333
- // Export auto tracking utilities for advanced usage
1334
- // These are used internally but can be called manually if needed
1335
- // Navigation
1336
- // Re-export LogLevel enum from utils
1337
- // Note: This is safe because the enum itself doesn't trigger react-native imports
1260
+ var _default = exports.default = Rejourney;
1338
1261
  /**
1339
1262
  * Configure SDK log verbosity.
1340
1263
  *
@@ -1366,16 +1289,4 @@ var _default = exports.default = Rejourney; // Export types
1366
1289
  function setLogLevel(level) {
1367
1290
  getLogger().setLogLevel(level);
1368
1291
  }
1369
-
1370
- // Note: Components and hooks removed in new engine
1371
- // Session replay now handled by dashboard web UI
1372
- // export { RejourneyReplay } from './components/replay/RejourneyReplay';
1373
- // export { GestureTracker } from './components/GestureTracker';
1374
- // export { SessionList } from './components/SessionList';
1375
- // export { useRejourney } from './hooks/useRejourney';
1376
- // export { useReplay } from './hooks/useReplay';
1377
-
1378
- // Note: SDK managers removed in new engine - all functionality handled by native module
1379
-
1380
- // Export Mask component
1381
1292
  //# sourceMappingURL=index.js.map