@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.
- package/README.md +29 -0
- package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +47 -30
- package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +25 -1
- package/android/src/main/java/com/rejourney/capture/CaptureHeuristics.kt +70 -32
- package/android/src/main/java/com/rejourney/core/Constants.kt +4 -4
- package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +14 -0
- package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +9 -0
- package/ios/Capture/RJCaptureEngine.m +72 -34
- package/ios/Capture/RJCaptureHeuristics.h +7 -5
- package/ios/Capture/RJCaptureHeuristics.m +138 -112
- package/ios/Capture/RJVideoEncoder.m +0 -26
- package/ios/Core/Rejourney.mm +64 -102
- package/ios/Utils/RJPerfTiming.m +0 -5
- package/ios/Utils/RJWindowUtils.m +0 -1
- package/lib/commonjs/components/Mask.js +1 -6
- package/lib/commonjs/index.js +12 -101
- package/lib/commonjs/sdk/autoTracking.js +55 -353
- package/lib/commonjs/sdk/constants.js +2 -13
- package/lib/commonjs/sdk/errorTracking.js +1 -29
- package/lib/commonjs/sdk/metricsTracking.js +3 -24
- package/lib/commonjs/sdk/navigation.js +3 -42
- package/lib/commonjs/sdk/networkInterceptor.js +7 -49
- package/lib/commonjs/sdk/utils.js +0 -5
- package/lib/module/components/Mask.js +1 -6
- package/lib/module/index.js +11 -105
- package/lib/module/sdk/autoTracking.js +55 -354
- package/lib/module/sdk/constants.js +2 -13
- package/lib/module/sdk/errorTracking.js +1 -29
- package/lib/module/sdk/index.js +0 -2
- package/lib/module/sdk/metricsTracking.js +3 -24
- package/lib/module/sdk/navigation.js +3 -42
- package/lib/module/sdk/networkInterceptor.js +7 -49
- package/lib/module/sdk/utils.js +0 -5
- package/lib/typescript/NativeRejourney.d.ts +2 -0
- package/lib/typescript/sdk/autoTracking.d.ts +5 -6
- package/lib/typescript/types/index.d.ts +0 -1
- package/package.json +11 -3
- package/src/NativeRejourney.ts +4 -0
- package/src/components/Mask.tsx +0 -3
- package/src/index.ts +11 -88
- package/src/sdk/autoTracking.ts +72 -331
- package/src/sdk/constants.ts +13 -13
- package/src/sdk/errorTracking.ts +1 -17
- package/src/sdk/index.ts +0 -2
- package/src/sdk/metricsTracking.ts +5 -33
- package/src/sdk/navigation.ts +8 -29
- package/src/sdk/networkInterceptor.ts +9 -33
- package/src/sdk/utils.ts +0 -5
- 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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
|
228
|
-
|
|
229
|
-
|
|
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';
|