@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
@@ -67,13 +67,10 @@ function getReactNative() {
67
67
  return null;
68
68
  }
69
69
  }
70
-
71
- // Lazy-loaded logger
72
70
  let _logger = null;
73
71
  function getLogger() {
74
72
  if (_logger) return _logger;
75
73
  if (_sdkDisabled) {
76
- // Return a no-op logger if SDK is disabled
77
74
  return {
78
75
  debug: () => {},
79
76
  info: console.log.bind(console, '[Rejourney]'),
@@ -152,7 +149,7 @@ const noopAutoTracking = {
152
149
  notifyStateChange: () => {},
153
150
  getSessionMetrics: () => ({}),
154
151
  resetMetrics: () => {},
155
- collectDeviceInfo: () => ({}),
152
+ collectDeviceInfo: async () => ({}),
156
153
  ensurePersistentAnonymousId: async () => 'anonymous'
157
154
  };
158
155
  function getAutoTracking() {
@@ -168,7 +165,6 @@ function getAutoTracking() {
168
165
  }
169
166
 
170
167
  // State
171
- const USER_IDENTITY_KEY = '@rejourney_user_identity';
172
168
  let _isInitialized = false;
173
169
  let _isRecording = false;
174
170
  let _initializationFailed = false;
@@ -183,23 +179,18 @@ let _lastScrollOffset = 0;
183
179
  const SCROLL_THROTTLE_MS = 100;
184
180
 
185
181
  // Helper to save/load user identity
186
- async function persistUserIdentity(identity) {
187
- try {
188
- const AsyncStorage = require('@react-native-async-storage/async-storage').default;
189
- if (identity) {
190
- await AsyncStorage.setItem(USER_IDENTITY_KEY, identity);
191
- } else {
192
- await AsyncStorage.removeItem(USER_IDENTITY_KEY);
193
- }
194
- } catch (e) {
195
- // Ignore storage errors
196
- }
182
+ // NOW HANDLED NATIVELY - No-op on JS side to avoid unnecessary bridge calls
183
+ async function persistUserIdentity(_identity) {
184
+ // Native module handles persistence automatically in setUserIdentity
197
185
  }
198
186
  async function loadPersistedUserIdentity() {
199
187
  try {
200
- const AsyncStorage = require('@react-native-async-storage/async-storage').default;
201
- return await AsyncStorage.getItem(USER_IDENTITY_KEY);
202
- } catch (e) {
188
+ const nativeModule = getRejourneyNative();
189
+ if (!nativeModule) return null;
190
+
191
+ // NATIVE STORAGE: Read directly from SharedPreferences/NSUserDefaults
192
+ return await nativeModule.getUserIdentity();
193
+ } catch {
203
194
  return null;
204
195
  }
205
196
  }
@@ -219,9 +210,7 @@ let _runtimeReady = false;
219
210
  function isRuntimeReady() {
220
211
  if (_runtimeReady) return true;
221
212
  try {
222
- // Try to access a core module to verify runtime is ready
223
213
  const RN = require('react-native');
224
- // If we can access NativeModules without error, runtime is ready
225
214
  if (RN.NativeModules) {
226
215
  _runtimeReady = true;
227
216
  return true;
@@ -304,12 +293,9 @@ function getRejourneyNative() {
304
293
  }
305
294
  }
306
295
  } catch (error) {
307
- // If any access fails, log and return null
308
296
  getLogger().warn('Rejourney: Failed to access native modules:', error);
309
297
  _rejourneyNative = null;
310
298
  }
311
-
312
- // Ensure we never return undefined - convert to null
313
299
  if (_rejourneyNative === undefined) {
314
300
  _rejourneyNative = null;
315
301
  }
@@ -451,7 +437,7 @@ const Rejourney = {
451
437
  // Collect and log device info
452
438
  if (_storedConfig?.collectDeviceInfo !== false) {
453
439
  try {
454
- const deviceInfo = getAutoTracking().collectDeviceInfo();
440
+ const deviceInfo = await getAutoTracking().collectDeviceInfo();
455
441
  this.logEvent('device_info', deviceInfo);
456
442
  } catch (deviceError) {
457
443
  getLogger().warn('Failed to collect device info:', deviceError);
@@ -469,15 +455,10 @@ const Rejourney = {
469
455
  ignoreUrls,
470
456
  captureSizes: _storedConfig?.networkCaptureSizes !== false
471
457
  });
472
-
473
- // logger.debug('Network interception enabled');
474
458
  } catch (networkError) {
475
459
  getLogger().warn('Failed to setup network interception:', networkError);
476
460
  }
477
461
  }
478
-
479
- // logger.debug('Auto tracking enabled');
480
-
481
462
  return true;
482
463
  } catch (error) {
483
464
  getLogger().error('Failed to start recording:', error);
@@ -494,17 +475,13 @@ const Rejourney = {
494
475
  return;
495
476
  }
496
477
  try {
497
- // Get session metrics before stopping
498
478
  const metrics = getAutoTracking().getSessionMetrics();
499
479
  this.logEvent('session_metrics', metrics);
500
-
501
- // Cleanup
502
480
  getNetworkInterceptor().disableNetworkInterceptor();
503
481
  getAutoTracking().cleanupAutoTracking();
504
482
  getAutoTracking().resetMetrics();
505
483
  await safeNativeCall('stopSession', () => getRejourneyNative().stopSession(), undefined);
506
484
  _isRecording = false;
507
- // Use lifecycle log for session end - only shown in dev builds
508
485
  getLogger().logSessionEnd('current');
509
486
  } catch (error) {
510
487
  getLogger().error('Failed to stop recording:', error);
@@ -536,9 +513,6 @@ const Rejourney = {
536
513
  setUserIdentity(userId) {
537
514
  _userIdentity = userId;
538
515
  persistUserIdentity(userId).catch(() => {});
539
- // logger.debug(`User identity set: ${userId}`);
540
-
541
- // If recording is active, update the native module immediately
542
516
  if (_isRecording && getRejourneyNative()) {
543
517
  safeNativeCallSync('setUserIdentity', () => {
544
518
  getRejourneyNative().setUserIdentity(userId).catch(() => {});
@@ -552,9 +526,6 @@ const Rejourney = {
552
526
  clearUserIdentity() {
553
527
  _userIdentity = null;
554
528
  persistUserIdentity(null).catch(() => {});
555
- // logger.debug('User identity cleared');
556
-
557
- // If recording is active, update the native module immediately
558
529
  if (_isRecording && getRejourneyNative()) {
559
530
  safeNativeCallSync('setUserIdentity', () => {
560
531
  getRejourneyNative().setUserIdentity('anonymous').catch(() => {});
@@ -568,10 +539,7 @@ const Rejourney = {
568
539
  * @param params - Optional screen parameters
569
540
  */
570
541
  tagScreen(screenName, _params) {
571
- // Track screen for metrics and funnel tracking
572
542
  getAutoTracking().trackScreen(screenName);
573
-
574
- // Notify state change (kept for API compatibility)
575
543
  getAutoTracking().notifyStateChange();
576
544
  safeNativeCallSync('tagScreen', () => {
577
545
  getRejourneyNative().screenChanged(screenName).catch(() => {});
@@ -749,10 +717,6 @@ const Rejourney = {
749
717
  getAutoTracking().trackScroll();
750
718
  await safeNativeCall('onScroll', () => getRejourneyNative().onScroll(scrollOffset), undefined);
751
719
  },
752
- // ========================================================================
753
- // OAuth / External URL Tracking
754
- // ========================================================================
755
-
756
720
  /**
757
721
  * Notify the SDK that an OAuth flow is starting
758
722
  *
@@ -888,10 +852,6 @@ const Rejourney = {
888
852
  getRejourneyNative().logEvent('network_request', networkEvent).catch(() => {});
889
853
  }, undefined);
890
854
  },
891
- // ========================================================================
892
- // SDK Telemetry / Observability
893
- // ========================================================================
894
-
895
855
  /**
896
856
  * Get SDK telemetry metrics for observability
897
857
  *
@@ -939,10 +899,6 @@ const Rejourney = {
939
899
  getLogger().warn('debugTriggerANR is only available in development mode');
940
900
  }
941
901
  },
942
- // ========================================================================
943
- // Privacy / View Masking
944
- // ========================================================================
945
-
946
902
  /**
947
903
  * Mask a view by its nativeID prop (will be occluded in recordings)
948
904
  *
@@ -978,10 +934,6 @@ const Rejourney = {
978
934
  }
979
935
  };
980
936
 
981
- // =============================================================================
982
- // Automatic Lifecycle Management
983
- // =============================================================================
984
-
985
937
  /**
986
938
  * Handle app state changes for automatic session management
987
939
  * - Pauses recording when app goes to background
@@ -1012,20 +964,13 @@ function setupLifecycleManagement() {
1012
964
  if (_sdkDisabled) return;
1013
965
  const RN = getReactNative();
1014
966
  if (!RN) return;
1015
-
1016
- // Remove any existing subscription
1017
967
  if (_appStateSubscription) {
1018
968
  _appStateSubscription.remove();
1019
969
  _appStateSubscription = null;
1020
970
  }
1021
971
  try {
1022
- // Get current app state
1023
972
  _currentAppState = RN.AppState.currentState || 'active';
1024
-
1025
- // Subscribe to app state changes
1026
973
  _appStateSubscription = RN.AppState.addEventListener('change', handleAppStateChange);
1027
-
1028
- // Setup auth error listener from native module
1029
974
  setupAuthErrorListener();
1030
975
  getLogger().debug('Lifecycle management enabled');
1031
976
  } catch (error) {
@@ -1048,9 +993,6 @@ function setupAuthErrorListener() {
1048
993
  try {
1049
994
  const nativeModule = getRejourneyNative();
1050
995
  if (nativeModule) {
1051
- // RN warns if a non-null module is passed without addListener/removeListeners.
1052
- // Our native module may not implement these no-op methods yet, so only pass
1053
- // the module when those hooks exist; otherwise use the global emitter.
1054
996
  const maybeAny = nativeModule;
1055
997
  const hasEventEmitterHooks = typeof maybeAny?.addListener === 'function' && typeof maybeAny?.removeListeners === 'function';
1056
998
  const eventEmitter = hasEventEmitterHooks ? new RN.NativeEventEmitter(maybeAny) : new RN.NativeEventEmitter();
@@ -1061,11 +1003,7 @@ function setupAuthErrorListener() {
1061
1003
  } else if (error?.code === 404) {
1062
1004
  getLogger().logInvalidProjectKey();
1063
1005
  }
1064
-
1065
- // Update SDK state - recording has been stopped by native
1066
1006
  _isRecording = false;
1067
-
1068
- // Call user's error handler if provided
1069
1007
  if (_storedConfig?.onAuthError) {
1070
1008
  try {
1071
1009
  _storedConfig.onAuthError(error);
@@ -1076,7 +1014,6 @@ function setupAuthErrorListener() {
1076
1014
  });
1077
1015
  }
1078
1016
  } catch (error) {
1079
- // Event emitter not available on this platform - that's OK
1080
1017
  getLogger().debug('Auth error listener not available:', error);
1081
1018
  }
1082
1019
  }
@@ -1095,10 +1032,6 @@ function cleanupLifecycleManagement() {
1095
1032
  }
1096
1033
  }
1097
1034
 
1098
- // =============================================================================
1099
- // Simple Initialization API
1100
- // =============================================================================
1101
-
1102
1035
  /**
1103
1036
  * Initialize Rejourney SDK - STEP 1 of 3
1104
1037
  *
@@ -1128,14 +1061,11 @@ function cleanupLifecycleManagement() {
1128
1061
  * ```
1129
1062
  */
1130
1063
  export function initRejourney(publicRouteKey, options) {
1131
- // Validate public route key
1132
1064
  if (!publicRouteKey || typeof publicRouteKey !== 'string') {
1133
1065
  getLogger().warn('Rejourney: Invalid public route key provided. SDK will be disabled.');
1134
1066
  _initializationFailed = true;
1135
1067
  return;
1136
1068
  }
1137
-
1138
- // Store config for later use
1139
1069
  _storedConfig = {
1140
1070
  ...options,
1141
1071
  publicRouteKey
@@ -1189,8 +1119,6 @@ export function startRejourney() {
1189
1119
  }
1190
1120
  getLogger().logRecordingStart();
1191
1121
  getLogger().debug('Starting session...');
1192
-
1193
- // Fire and forget - don't block the caller
1194
1122
  (async () => {
1195
1123
  try {
1196
1124
  const started = await Rejourney._startSession();
@@ -1222,19 +1150,9 @@ export function stopRejourney() {
1222
1150
  }
1223
1151
  }
1224
1152
  export default Rejourney;
1225
-
1226
- // Export types
1227
1153
  export * from './types';
1228
-
1229
- // Export auto tracking utilities for advanced usage
1230
- // These are used internally but can be called manually if needed
1231
1154
  export { trackTap, trackScroll, trackGesture, trackInput, trackScreen, captureError, getSessionMetrics } from './sdk/autoTracking';
1232
-
1233
- // Navigation
1234
1155
  export { trackNavigationState, useNavigationTracking } from './sdk/autoTracking';
1235
-
1236
- // Re-export LogLevel enum from utils
1237
- // Note: This is safe because the enum itself doesn't trigger react-native imports
1238
1156
  export { LogLevel } from './sdk/utils';
1239
1157
 
1240
1158
  /**
@@ -1268,17 +1186,5 @@ export { LogLevel } from './sdk/utils';
1268
1186
  export function setLogLevel(level) {
1269
1187
  getLogger().setLogLevel(level);
1270
1188
  }
1271
-
1272
- // Note: Components and hooks removed in new engine
1273
- // Session replay now handled by dashboard web UI
1274
- // export { RejourneyReplay } from './components/replay/RejourneyReplay';
1275
- // export { GestureTracker } from './components/GestureTracker';
1276
- // export { SessionList } from './components/SessionList';
1277
- // export { useRejourney } from './hooks/useRejourney';
1278
- // export { useReplay } from './hooks/useReplay';
1279
-
1280
- // Note: SDK managers removed in new engine - all functionality handled by native module
1281
-
1282
- // Export Mask component
1283
1189
  export { Mask } from './components/Mask';
1284
1190
  //# sourceMappingURL=index.js.map