@multiplayer-app/session-recorder-react-native 1.0.1-beta.10 → 1.0.1-beta.12

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 CHANGED
@@ -55,6 +55,65 @@ npx expo install @react-native-async-storage/async-storage @react-native-communi
55
55
 
56
56
  If you use Expo Router or a managed workflow, no extra autolinking steps are required beyond installing the packages.
57
57
 
58
+ ### Expo Autolinking Support
59
+
60
+ This package includes full Expo autolinking support with the following configuration files:
61
+
62
+ - ✅ `expo-module.config.json` - Defines supported platforms and module names
63
+ - ✅ `react-native.config.js` - Configures React Native CLI autolinking
64
+ - ✅ Proper TurboModule registration for both iOS and Android
65
+
66
+ The module will be automatically detected and linked when you install it in your Expo project.
67
+
68
+ #### Expo Go vs Development Builds
69
+
70
+ **Important**: This package uses native modules that require custom native code. While autolinking is configured, you may encounter issues with **Expo Go** due to its limitations with custom native modules.
71
+
72
+ **If autolinking doesn't work with Expo Go**, try using development builds instead:
73
+
74
+ ```bash
75
+ # For iOS
76
+ npx expo run:ios
77
+
78
+ # For Android
79
+ npx expo run:android
80
+ ```
81
+
82
+ Development builds include your custom native modules and provide the full native functionality needed for session recording.
83
+
84
+ #### Troubleshooting Expo Autolinking
85
+
86
+ If you encounter issues with module autolinking in Expo:
87
+
88
+ 1. **Check Expo SDK compatibility**: Ensure you're using a compatible Expo SDK version
89
+ 2. **Clear cache**: Run `npx expo start -c` to clear the Expo cache
90
+ 3. **Use development builds**: Switch from Expo Go to development builds as shown above
91
+ 4. **Verify configuration**: Ensure the autolinking configuration files are present in your `node_modules/@multiplayer-app/session-recorder-react-native/` directory
92
+
93
+ #### Expo Configuration
94
+
95
+ For Expo applications, the package automatically detects the Expo environment:
96
+
97
+ ```javascript
98
+ import SessionRecorder from '@multiplayer-app/session-recorder-react-native';
99
+
100
+ SessionRecorder.init({
101
+ application: 'my-expo-app',
102
+ version: '1.0.0',
103
+ environment: 'production',
104
+ apiKey: 'YOUR_MULTIPLAYER_API_KEY',
105
+ recordGestures: true,
106
+ recordNavigation: true,
107
+ recordScreen: true,
108
+ });
109
+ ```
110
+
111
+ The package will automatically:
112
+
113
+ - Detect Expo environment using `expo-constants`
114
+ - Add Expo-specific attributes to traces
115
+ - Optimize performance for Expo runtime
116
+
58
117
  #### Why direct install is required
59
118
 
60
119
  - Autolinking scans only the app's `package.json`
@@ -809,7 +868,27 @@ SessionRecorder.init(config);
809
868
  - Ensure `expo-constants` is installed: `npx expo install expo-constants`
810
869
  - Check that you're using the correct Expo SDK version
811
870
 
812
- #### 6. Build Issues
871
+ #### 6. TurboModule Not Found (Expo Go)
872
+
873
+ If you see this error in Expo Go:
874
+
875
+ ```
876
+ TurboModuleRegistry.getEnforcing(...): 'SessionRecorderNative' could not be found
877
+ ```
878
+
879
+ **Solution**: Switch to development builds instead of Expo Go:
880
+
881
+ ```bash
882
+ # For iOS
883
+ npx expo run:ios
884
+
885
+ # For Android
886
+ npx expo run:android
887
+ ```
888
+
889
+ Expo Go has limitations with custom native modules. Development builds include your custom native code and will resolve this issue.
890
+
891
+ #### 7. Build Issues
813
892
 
814
893
  - **iOS**: Run `cd ios && pod install` after installing dependencies
815
894
  - **Android**: Run `cd android && ./gradlew clean`
@@ -25,7 +25,7 @@ import com.facebook.react.module.annotations.ReactModule
25
25
 
26
26
  @ReactModule(name = SessionRecorderNativeModule.NAME)
27
27
  class SessionRecorderNativeModule(reactContext: ReactApplicationContext) :
28
- ReactContextBaseJavaModule(reactContext) {
28
+ NativeSessionRecorderNativeSpec(reactContext) {
29
29
 
30
30
  override fun getName(): String {
31
31
  return NAME
@@ -10,7 +10,7 @@ import java.util.HashMap
10
10
  class SessionRecorderNativePackage : BaseReactPackage() {
11
11
  override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
12
  return if (name == SessionRecorderNativeModule.NAME) {
13
- SessionRecorderNativeModule(reactContext) as NativeModule
13
+ SessionRecorderNativeModule(reactContext)
14
14
  } else {
15
15
  null
16
16
  }
@@ -25,7 +25,7 @@ class SessionRecorderNativePackage : BaseReactPackage() {
25
25
  false, // canOverrideExistingModule
26
26
  false, // needsEagerInit
27
27
  false, // isCxxModule
28
- false // isTurboModule
28
+ true // isTurboModule
29
29
  )
30
30
  moduleInfos
31
31
  }
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
 
3
- import { NativeModules } from 'react-native';
4
- export default NativeModules.SessionRecorderNative;
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('SessionRecorderNative');
5
5
  //# sourceMappingURL=SessionRecorderNativeSpec.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeModules","SessionRecorderNative"],"sourceRoot":"../../src","sources":["SessionRecorderNativeSpec.ts"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,cAAc;AAmD5C,eAAeA,aAAa,CAACC,qBAAqB","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["SessionRecorderNativeSpec.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AA+BlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
@@ -1,14 +1,6 @@
1
- export interface Spec {
2
- /**
3
- * Capture the current screen and apply masking to sensitive elements
4
- * @returns Promise that resolves to base64 encoded image
5
- */
1
+ import type { TurboModule } from 'react-native';
2
+ export interface Spec extends TurboModule {
6
3
  captureAndMask(): Promise<string>;
7
- /**
8
- * Capture the current screen and apply masking with custom options
9
- * @param options Custom masking options
10
- * @returns Promise that resolves to base64 encoded image
11
- */
12
4
  captureAndMaskWithOptions(options: MaskingOptions): Promise<string>;
13
5
  startGestureRecording(): Promise<void>;
14
6
  stopGestureRecording(): Promise<void>;
@@ -19,22 +11,14 @@ export interface Spec {
19
11
  removeListeners(count: number): void;
20
12
  }
21
13
  export interface MaskingOptions {
22
- /** Quality of the captured image (0.1 to 1.0, default: 0.3 for smaller file size) */
23
- quality?: number;
24
- /** Scale of the captured image (0.1 to 1.0, default: 1.0) */
25
- scale?: number;
26
- /** Whether to mask text inputs (UITextField, UITextView, React Native text components) */
27
14
  maskTextInputs?: boolean;
28
- /** Whether to mask images (UIImageView, React Native Image components) */
29
15
  maskImages?: boolean;
30
- /** Whether to mask buttons (UIButton) */
31
16
  maskButtons?: boolean;
32
- /** Whether to mask labels (UILabel) */
33
17
  maskLabels?: boolean;
34
- /** Whether to mask web views (WKWebView) */
35
18
  maskWebViews?: boolean;
36
- /** Whether to mask sandboxed views (system views that don't belong to current process) */
37
19
  maskSandboxedViews?: boolean;
20
+ quality?: number;
21
+ scale?: number;
38
22
  }
39
23
  declare const _default: Spec;
40
24
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"SessionRecorderNativeSpec.d.ts","sourceRoot":"","sources":["../../../src/SessionRecorderNativeSpec.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,IAAI;IACnB;;;OAGG;IACH,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAElC;;;;OAIG;IACH,yBAAyB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAGpE,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,kBAAkB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACzD,aAAa,CACX,WAAW,EAAE,MAAM,EACnB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,GAAG,GACb,IAAI,CAAC;IACR,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0FAA0F;IAC1F,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;wBAEqD,IAAI;AAA1D,wBAA2D"}
1
+ {"version":3,"file":"SessionRecorderNativeSpec.d.ts","sourceRoot":"","sources":["../../../src/SessionRecorderNativeSpec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,yBAAyB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,kBAAkB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACzD,aAAa,CACX,WAAW,EAAE,MAAM,EACnB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,GAAG,GACb,IAAI,CAAC;IACR,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;AAED,wBAA+E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplayer-app/session-recorder-react-native",
3
- "version": "1.0.1-beta.10",
3
+ "version": "1.0.1-beta.12",
4
4
  "description": "Multiplayer Fullstack Session Recorder for React Native",
5
5
  "author": {
6
6
  "name": "Multiplayer Software, Inc.",
@@ -1,20 +1,9 @@
1
- import { NativeModules } from 'react-native';
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
2
3
 
3
- export interface Spec {
4
- /**
5
- * Capture the current screen and apply masking to sensitive elements
6
- * @returns Promise that resolves to base64 encoded image
7
- */
4
+ export interface Spec extends TurboModule {
8
5
  captureAndMask(): Promise<string>;
9
-
10
- /**
11
- * Capture the current screen and apply masking with custom options
12
- * @param options Custom masking options
13
- * @returns Promise that resolves to base64 encoded image
14
- */
15
6
  captureAndMaskWithOptions(options: MaskingOptions): Promise<string>;
16
-
17
- // Gesture recording APIs
18
7
  startGestureRecording(): Promise<void>;
19
8
  stopGestureRecording(): Promise<void>;
20
9
  isGestureRecordingActive(): Promise<boolean>;
@@ -24,29 +13,21 @@ export interface Spec {
24
13
  x: number,
25
14
  y: number,
26
15
  target?: string,
27
- metadata?: any
16
+ metadata?: any,
28
17
  ): void;
29
18
  addListener(eventName: string): void;
30
19
  removeListeners(count: number): void;
31
20
  }
32
21
 
33
22
  export interface MaskingOptions {
34
- /** Quality of the captured image (0.1 to 1.0, default: 0.3 for smaller file size) */
35
- quality?: number;
36
- /** Scale of the captured image (0.1 to 1.0, default: 1.0) */
37
- scale?: number;
38
- /** Whether to mask text inputs (UITextField, UITextView, React Native text components) */
39
23
  maskTextInputs?: boolean;
40
- /** Whether to mask images (UIImageView, React Native Image components) */
41
24
  maskImages?: boolean;
42
- /** Whether to mask buttons (UIButton) */
43
25
  maskButtons?: boolean;
44
- /** Whether to mask labels (UILabel) */
45
26
  maskLabels?: boolean;
46
- /** Whether to mask web views (WKWebView) */
47
27
  maskWebViews?: boolean;
48
- /** Whether to mask sandboxed views (system views that don't belong to current process) */
49
28
  maskSandboxedViews?: boolean;
29
+ quality?: number;
30
+ scale?: number;
50
31
  }
51
32
 
52
- export default NativeModules.SessionRecorderNative as Spec;
33
+ export default TurboModuleRegistry.getEnforcing<Spec>('SessionRecorderNative');
@@ -1,79 +0,0 @@
1
- package com.multiplayer.sessionrecordernative
2
-
3
- import com.facebook.react.bridge.ReactApplicationContext
4
- import com.facebook.react.bridge.ReactContextBaseJavaModule
5
- import com.facebook.react.bridge.ReactMethod
6
- import com.facebook.react.bridge.Promise
7
- import com.facebook.react.bridge.Callback
8
- import com.facebook.react.bridge.ReadableMap
9
- import com.facebook.react.bridge.Arguments
10
- import com.facebook.react.bridge.WritableMap
11
-
12
- /**
13
- * Spec class for SessionRecorderNative TurboModule
14
- * This class defines the interface that React Native expects for TurboModules
15
- */
16
- class SessionRecorderNativeSpec(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
17
-
18
- override fun getName(): String {
19
- return NAME
20
- }
21
-
22
- companion object {
23
- const val NAME = "SessionRecorderNative"
24
- }
25
-
26
- // Delegate to the actual implementation
27
- private val implementation = SessionRecorderNativeModule(reactContext)
28
-
29
- @ReactMethod
30
- fun captureAndMask(promise: Promise) {
31
- implementation.captureAndMask(promise)
32
- }
33
-
34
- @ReactMethod
35
- fun captureAndMaskWithOptions(options: ReadableMap, promise: Promise) {
36
- implementation.captureAndMaskWithOptions(options, promise)
37
- }
38
-
39
- @ReactMethod
40
- fun startGestureRecording(promise: Promise) {
41
- implementation.startGestureRecording(promise)
42
- }
43
-
44
- @ReactMethod
45
- fun stopGestureRecording(promise: Promise) {
46
- implementation.stopGestureRecording(promise)
47
- }
48
-
49
- @ReactMethod
50
- fun isGestureRecordingActive(promise: Promise) {
51
- implementation.isGestureRecordingActive(promise)
52
- }
53
-
54
- @ReactMethod
55
- fun setGestureCallback(callback: Callback) {
56
- implementation.setGestureCallback(callback)
57
- }
58
-
59
- @ReactMethod
60
- fun recordGesture(
61
- gestureType: String,
62
- x: Double,
63
- y: Double,
64
- target: String?,
65
- metadata: ReadableMap?
66
- ) {
67
- implementation.recordGesture(gestureType, x, y, target, metadata)
68
- }
69
-
70
- @ReactMethod
71
- fun addListener(eventName: String) {
72
- implementation.addListener(eventName)
73
- }
74
-
75
- @ReactMethod
76
- fun removeListeners(count: Int) {
77
- implementation.removeListeners(count)
78
- }
79
- }