@rejourneyco/react-native 1.0.1 → 1.0.3

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 (65) hide show
  1. package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +72 -391
  2. package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +11 -113
  3. package/android/src/main/java/com/rejourney/capture/SegmentUploader.kt +1 -15
  4. package/android/src/main/java/com/rejourney/capture/VideoEncoder.kt +1 -61
  5. package/android/src/main/java/com/rejourney/capture/ViewHierarchyScanner.kt +3 -1
  6. package/android/src/main/java/com/rejourney/lifecycle/SessionLifecycleService.kt +1 -22
  7. package/android/src/main/java/com/rejourney/network/DeviceAuthManager.kt +3 -26
  8. package/android/src/main/java/com/rejourney/network/NetworkMonitor.kt +0 -2
  9. package/android/src/main/java/com/rejourney/network/UploadManager.kt +7 -93
  10. package/android/src/main/java/com/rejourney/network/UploadWorker.kt +5 -41
  11. package/android/src/main/java/com/rejourney/privacy/PrivacyMask.kt +2 -58
  12. package/android/src/main/java/com/rejourney/touch/TouchInterceptor.kt +4 -4
  13. package/android/src/main/java/com/rejourney/utils/EventBuffer.kt +36 -7
  14. package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +7 -0
  15. package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +9 -0
  16. package/ios/Capture/RJCaptureEngine.m +3 -34
  17. package/ios/Capture/RJVideoEncoder.m +0 -26
  18. package/ios/Capture/RJViewHierarchyScanner.m +68 -51
  19. package/ios/Core/RJLifecycleManager.m +0 -14
  20. package/ios/Core/Rejourney.mm +53 -129
  21. package/ios/Network/RJDeviceAuthManager.m +0 -2
  22. package/ios/Network/RJUploadManager.h +8 -0
  23. package/ios/Network/RJUploadManager.m +45 -0
  24. package/ios/Privacy/RJPrivacyMask.m +5 -31
  25. package/ios/Rejourney.h +0 -14
  26. package/ios/Touch/RJTouchInterceptor.m +21 -15
  27. package/ios/Utils/RJEventBuffer.m +57 -69
  28. package/ios/Utils/RJPerfTiming.m +0 -5
  29. package/ios/Utils/RJWindowUtils.m +87 -87
  30. package/lib/commonjs/components/Mask.js +1 -6
  31. package/lib/commonjs/index.js +46 -117
  32. package/lib/commonjs/sdk/autoTracking.js +39 -313
  33. package/lib/commonjs/sdk/constants.js +2 -13
  34. package/lib/commonjs/sdk/errorTracking.js +1 -29
  35. package/lib/commonjs/sdk/metricsTracking.js +3 -24
  36. package/lib/commonjs/sdk/navigation.js +3 -42
  37. package/lib/commonjs/sdk/networkInterceptor.js +7 -60
  38. package/lib/commonjs/sdk/utils.js +73 -19
  39. package/lib/module/components/Mask.js +1 -6
  40. package/lib/module/index.js +45 -121
  41. package/lib/module/sdk/autoTracking.js +39 -314
  42. package/lib/module/sdk/constants.js +2 -13
  43. package/lib/module/sdk/errorTracking.js +1 -29
  44. package/lib/module/sdk/index.js +0 -2
  45. package/lib/module/sdk/metricsTracking.js +3 -24
  46. package/lib/module/sdk/navigation.js +3 -42
  47. package/lib/module/sdk/networkInterceptor.js +7 -60
  48. package/lib/module/sdk/utils.js +73 -19
  49. package/lib/typescript/NativeRejourney.d.ts +1 -0
  50. package/lib/typescript/sdk/autoTracking.d.ts +4 -4
  51. package/lib/typescript/sdk/utils.d.ts +31 -1
  52. package/lib/typescript/types/index.d.ts +0 -1
  53. package/package.json +17 -11
  54. package/src/NativeRejourney.ts +2 -0
  55. package/src/components/Mask.tsx +0 -3
  56. package/src/index.ts +43 -92
  57. package/src/sdk/autoTracking.ts +51 -284
  58. package/src/sdk/constants.ts +13 -13
  59. package/src/sdk/errorTracking.ts +1 -17
  60. package/src/sdk/index.ts +0 -2
  61. package/src/sdk/metricsTracking.ts +5 -33
  62. package/src/sdk/navigation.ts +8 -29
  63. package/src/sdk/networkInterceptor.ts +9 -42
  64. package/src/sdk/utils.ts +76 -19
  65. package/src/types/index.ts +0 -29
@@ -222,7 +222,6 @@ export let LogLevel = /*#__PURE__*/function (LogLevel) {
222
222
  */
223
223
  class Logger {
224
224
  prefix = '[Rejourney]';
225
- debugMode = false;
226
225
 
227
226
  /**
228
227
  * Minimum log level to display.
@@ -243,7 +242,6 @@ class Logger {
243
242
  this.minimumLogLevel = level;
244
243
  }
245
244
  setDebugMode(enabled) {
246
- this.debugMode = enabled;
247
245
  this.minimumLogLevel = enabled ? LogLevel.DEBUG : typeof __DEV__ !== 'undefined' && __DEV__ ? LogLevel.ERROR : LogLevel.SILENT;
248
246
  }
249
247
 
@@ -264,14 +262,26 @@ class Logger {
264
262
  /** Log a warning message */
265
263
  warn(...args) {
266
264
  if (this.minimumLogLevel <= LogLevel.WARNING) {
267
- console.warn(this.prefix, ...args);
265
+ if (this.minimumLogLevel <= LogLevel.DEBUG) {
266
+ // Explicit Debug Mode: Show YellowBox
267
+ console.warn(this.prefix, ...args);
268
+ } else {
269
+ // Default Dev Mode: Log to console only, avoid YellowBox
270
+ console.log(this.prefix, '[WARN]', ...args);
271
+ }
268
272
  }
269
273
  }
270
274
 
271
275
  /** Log an error message */
272
276
  error(...args) {
273
277
  if (this.minimumLogLevel <= LogLevel.ERROR) {
274
- console.error(this.prefix, ...args);
278
+ if (this.minimumLogLevel <= LogLevel.DEBUG) {
279
+ // Explicit Debug Mode: Show RedBox
280
+ console.error(this.prefix, ...args);
281
+ } else {
282
+ // Default Dev Mode: Log to console only, avoid RedBox
283
+ console.log(this.prefix, '[ERROR]', ...args);
284
+ }
275
285
  }
276
286
  }
277
287
  notice(...args) {
@@ -280,19 +290,12 @@ class Logger {
280
290
  }
281
291
  }
282
292
 
283
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
284
- // Lifecycle Logs - Industry standard minimal logging
285
- // These are the only logs integrators will see in debug builds
286
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
287
-
288
293
  /**
289
294
  * Log SDK initialization success.
290
295
  * Only shown in development builds - this is the minimal "SDK started" log.
291
296
  */
292
297
  logInitSuccess(version) {
293
- if (this.debugMode) {
294
- this.info(`✓ SDK initialized (v${version})`);
295
- }
298
+ this.notice(`✓ SDK initialized (v${version})`);
296
299
  }
297
300
 
298
301
  /**
@@ -308,9 +311,7 @@ class Logger {
308
311
  * Only shown in development builds.
309
312
  */
310
313
  logSessionStart(sessionId) {
311
- if (this.debugMode) {
312
- this.info(`Session started: ${sessionId}`);
313
- }
314
+ this.notice(`Session started: ${sessionId}`);
314
315
  }
315
316
 
316
317
  /**
@@ -318,12 +319,10 @@ class Logger {
318
319
  * Only shown in development builds.
319
320
  */
320
321
  logSessionEnd(sessionId) {
321
- if (this.debugMode) {
322
- this.info(`Session ended: ${sessionId}`);
323
- }
322
+ this.notice(`Session ended: ${sessionId}`);
324
323
  }
325
324
  logObservabilityStart() {
326
- this.notice('Starting Rejourney observability');
325
+ this.notice('💧 Starting Rejourney observability');
327
326
  }
328
327
  logRecordingStart() {
329
328
  this.notice('Starting recording');
@@ -337,6 +336,61 @@ class Logger {
337
336
  logPackageMismatch() {
338
337
  this.notice('Bundle ID / package name mismatch');
339
338
  }
339
+
340
+ /**
341
+ * Log network request details
342
+ */
343
+ logNetworkRequest(request) {
344
+ const statusIcon = request.error || request.statusCode && request.statusCode >= 400 ? '🔴' : '🟢';
345
+ const method = request.method || 'GET';
346
+ // Shorten URL to just path if possible
347
+ let url = request.url || '';
348
+ try {
349
+ if (url.startsWith('http')) {
350
+ const urlObj = new URL(url);
351
+ url = urlObj.pathname;
352
+ }
353
+ } catch {
354
+ // Keep full URL if parsing fails
355
+ }
356
+ const duration = request.duration ? `(${Math.round(request.duration)}ms)` : '';
357
+ const status = request.statusCode ? `${request.statusCode}` : 'ERR';
358
+ this.notice(`${statusIcon} [NET] ${status} ${method} ${url} ${duration} ${request.error ? `Error: ${request.error}` : ''}`);
359
+ }
360
+
361
+ /**
362
+ * Log frustration event (rage taps, etc)
363
+ */
364
+ logFrustration(kind) {
365
+ this.notice(`🤬 Frustration detected: ${kind}`);
366
+ }
367
+
368
+ /**
369
+ * Log error captured by SDK
370
+ */
371
+ logError(message) {
372
+ this.notice(`X Error captured: ${message}`);
373
+ }
374
+
375
+ /**
376
+ * Log lifecycle event (Background/Foreground)
377
+ * Visible in development builds.
378
+ */
379
+ logLifecycleEvent(event) {
380
+ this.notice(`🔄 Lifecycle: ${event}`);
381
+ }
382
+
383
+ /**
384
+ * Log upload statistics
385
+ */
386
+ logUploadStats(metrics) {
387
+ const success = metrics.uploadSuccessCount;
388
+ const failed = metrics.uploadFailureCount;
389
+ const bytes = formatBytes(metrics.totalBytesUploaded);
390
+
391
+ // Always show in dev mode for reassurance, even if 0
392
+ this.notice(`📡 Upload Stats: ${success} success, ${failed} failed (${bytes} uploaded)`);
393
+ }
340
394
  }
341
395
  export const logger = new Logger();
342
396
  //# sourceMappingURL=utils.js.map
@@ -133,6 +133,7 @@ export interface Spec extends TurboModule {
133
133
  setDebugMode(enabled: boolean): Promise<{
134
134
  success: boolean;
135
135
  }>;
136
+ getDeviceInfo(): Promise<Object>;
136
137
  }
137
138
  /**
138
139
  * Default export for Codegen.
@@ -155,16 +155,16 @@ export declare function getSessionMetrics(): SessionMetrics & {
155
155
  * Reset metrics for new session
156
156
  */
157
157
  export declare function resetMetrics(): void;
158
- /** Clamp and set max session duration in minutes (1–10). Defaults to 10. */
159
158
  export declare function setMaxSessionDurationMinutes(minutes?: number): void;
160
- /** Returns true if the current session exceeded the configured max duration. */
161
159
  export declare function hasExceededMaxSessionDuration(): boolean;
162
- /** Returns remaining milliseconds until the session should stop. */
163
160
  export declare function getRemainingSessionDurationMs(): number;
164
161
  /**
165
162
  * Collect device information
166
163
  */
167
- export declare function collectDeviceInfo(): DeviceInfo;
164
+ /**
165
+ * Collect device information
166
+ */
167
+ export declare function collectDeviceInfo(): Promise<DeviceInfo>;
168
168
  /**
169
169
  * Get the anonymous ID (synchronous - returns generated ID immediately)
170
170
  */
@@ -91,7 +91,6 @@ export declare enum LogLevel {
91
91
  */
92
92
  declare class Logger {
93
93
  private prefix;
94
- private debugMode;
95
94
  /**
96
95
  * Minimum log level to display.
97
96
  *
@@ -142,6 +141,37 @@ declare class Logger {
142
141
  logRecordingRemoteDisabled(): void;
143
142
  logInvalidProjectKey(): void;
144
143
  logPackageMismatch(): void;
144
+ /**
145
+ * Log network request details
146
+ */
147
+ logNetworkRequest(request: {
148
+ method?: string;
149
+ url?: string;
150
+ statusCode?: number;
151
+ duration?: number;
152
+ error?: string;
153
+ }): void;
154
+ /**
155
+ * Log frustration event (rage taps, etc)
156
+ */
157
+ logFrustration(kind: string): void;
158
+ /**
159
+ * Log error captured by SDK
160
+ */
161
+ logError(message: string): void;
162
+ /**
163
+ * Log lifecycle event (Background/Foreground)
164
+ * Visible in development builds.
165
+ */
166
+ logLifecycleEvent(event: string): void;
167
+ /**
168
+ * Log upload statistics
169
+ */
170
+ logUploadStats(metrics: {
171
+ uploadSuccessCount: number;
172
+ uploadFailureCount: number;
173
+ totalBytesUploaded: number;
174
+ }): void;
145
175
  }
146
176
  export declare const logger: Logger;
147
177
  export {};
@@ -352,7 +352,6 @@ export interface SessionSummary {
352
352
  videoSegmentCount?: number;
353
353
  storageSize: number;
354
354
  isComplete: boolean;
355
- /** Path to session data file */
356
355
  filePath: string;
357
356
  }
358
357
  export interface ReplayState {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rejourneyco/react-native",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Rejourney Session Recording SDK for React Native",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -47,9 +47,21 @@
47
47
  },
48
48
  "keywords": [
49
49
  "react-native",
50
- "session-recording",
51
- "analytics",
52
- "replay"
50
+ "session-replay",
51
+ "observability",
52
+ "error-tracking",
53
+ "crash-reporting",
54
+ "anr-reporting",
55
+ "api-monitoring",
56
+ "alerting",
57
+ "mobile-analytics",
58
+ "mobile-observability",
59
+ "mobile-error-tracking",
60
+ "mobile-crash-reporting",
61
+ "mobile-anr-reporting",
62
+ "mobile-api-monitoring",
63
+ "mobile-performance-monitoring",
64
+ "mobile-user-behavior-analytics"
53
65
  ],
54
66
  "repository": {
55
67
  "type": "git",
@@ -67,9 +79,6 @@
67
79
  "dependency-cruiser": "^16.10.4",
68
80
  "@react-navigation/native": "*",
69
81
  "expo-router": "*",
70
- "expo-constants": "*",
71
- "expo-application": "*",
72
- "react-native-device-info": "*",
73
82
  "eslint": "^9.39.2",
74
83
  "react": "*",
75
84
  "react-native": "*",
@@ -81,10 +90,7 @@
81
90
  "react": "*",
82
91
  "react-native": "*",
83
92
  "@react-navigation/native": ">=6.0.0",
84
- "expo-router": ">=3.0.0",
85
- "expo-constants": ">=15.0.0",
86
- "expo-application": ">=5.0.0",
87
- "react-native-device-info": ">=10.0.0"
93
+ "expo-router": ">=3.0.0"
88
94
  },
89
95
  "codegenConfig": {
90
96
  "name": "RejourneySpec",
@@ -153,6 +153,8 @@ export interface Spec extends TurboModule {
153
153
  getUserIdentity(): Promise<string | null>;
154
154
 
155
155
  setDebugMode(enabled: boolean): Promise<{ success: boolean }>;
156
+
157
+ getDeviceInfo(): Promise<Object>;
156
158
  }
157
159
 
158
160
  /**
@@ -25,7 +25,6 @@
25
25
  import React from 'react';
26
26
  import type { ViewProps } from 'react-native';
27
27
 
28
- // Lazy-loaded React Native modules
29
28
  let _RN: typeof import('react-native') | null = null;
30
29
 
31
30
  function getRN(): typeof import('react-native') | null {
@@ -52,7 +51,6 @@ export interface MaskProps extends ViewProps {
52
51
  export const Mask: React.FC<MaskProps> = ({ children, style, ...props }) => {
53
52
  const RN = getRN();
54
53
 
55
- // If RN isn't loaded yet (shouldn't happen in practice), render children directly
56
54
  if (!RN) {
57
55
  return <>{children}</>;
58
56
  }
@@ -61,7 +59,6 @@ export const Mask: React.FC<MaskProps> = ({ children, style, ...props }) => {
61
59
 
62
60
  const styles = StyleSheet.create({
63
61
  container: {
64
- // Minimal container style - doesn't affect layout
65
62
  },
66
63
  });
67
64