@amplitude/plugin-session-replay-react-native 0.4.10 → 0.5.0-sr-4646-rc.0
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 +21 -1
- package/android/src/main/java/com/amplitude/pluginsessionreplayreactnative/PluginSessionReplayReactNativeModule.kt +14 -3
- package/ios/PluginSessionReplayReactNative.mm +1 -1
- package/ios/PluginSessionReplayReactNative.swift +19 -1
- package/lib/commonjs/index.js +0 -7
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/session-replay-config.js +40 -2
- package/lib/commonjs/session-replay-config.js.map +1 -1
- package/lib/commonjs/session-replay.js +11 -2
- package/lib/commonjs/session-replay.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/index.js +0 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/session-replay-config.js +36 -2
- package/lib/module/session-replay-config.js.map +1 -1
- package/lib/module/session-replay.js +11 -2
- package/lib/module/session-replay.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/session-replay-config.d.ts +56 -3
- package/lib/typescript/session-replay-config.d.ts.map +1 -1
- package/lib/typescript/session-replay.d.ts +3 -1
- package/lib/typescript/session-replay.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/lib/typescript/version.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +1 -2
- package/src/session-replay-config.ts +69 -5
- package/src/session-replay.ts +17 -6
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -20,15 +20,35 @@ const config: SessionReplayConfig = {
|
|
|
20
20
|
enableRemoteConfig: true, // default true
|
|
21
21
|
sampleRate: 1, // default 0
|
|
22
22
|
logLevel: LogLevel.Warn, // default LogLevel.Warn
|
|
23
|
+
privacyConfig: { maskLevel: 'medium' }, // 'medium' is the default
|
|
23
24
|
};
|
|
24
25
|
await init('YOUR_API_KEY').promise;
|
|
25
26
|
await add(new SessionReplayPlugin(config)).promise;
|
|
26
27
|
|
|
27
28
|
```
|
|
28
29
|
|
|
30
|
+
## Mask levels
|
|
31
|
+
|
|
32
|
+
Control how aggressively Session Replay masks sensitive content via the `privacyConfig.maskLevel` config option:
|
|
33
|
+
|
|
34
|
+
| Value | What gets masked |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `'light'` | Password and phone-number `<TextInput>` fields only |
|
|
37
|
+
| `'medium'` (default) | All `<TextInput>` fields |
|
|
38
|
+
| `'conservative'` | All `<TextInput>` fields **and** all `<Text>` elements |
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
import { SessionReplayPlugin } from '@amplitude/plugin-session-replay-react-native';
|
|
42
|
+
|
|
43
|
+
const config: SessionReplayConfig = {
|
|
44
|
+
privacyConfig: { maskLevel: 'conservative' }, // mask all text and inputs
|
|
45
|
+
};
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
> **Note:** Third-party text renderers that bypass UIKit/Android's standard text views (for example `react-native-svg`, `@shopify/react-native-skia`) are not detected by automatic masking. Wrap such content in `<AmpMaskView mask="amp-mask">` to mask it manually.
|
|
29
49
|
|
|
30
50
|
## Masking views
|
|
31
|
-
To
|
|
51
|
+
To mask certain views, add the `AmpMaskView` tag with the mask property `amp-mask` around the section to be masked
|
|
32
52
|
|
|
33
53
|
```js
|
|
34
54
|
import { AmpMaskView } from '@amplitude/plugin-session-replay-react-native';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.amplitude.pluginsessionreplayreactnative
|
|
2
2
|
|
|
3
3
|
import com.amplitude.android.sessionreplay.SessionReplay
|
|
4
|
+
import com.amplitude.android.sessionreplay.config.MaskLevel
|
|
5
|
+
import com.amplitude.android.sessionreplay.config.PrivacyConfig
|
|
4
6
|
import com.amplitude.common.Logger
|
|
5
7
|
import com.amplitude.common.android.LogcatLogger
|
|
6
8
|
import com.amplitude.core.ServerZone
|
|
@@ -20,7 +22,7 @@ class PluginSessionReplayReactNativeModule(private val reactContext: ReactApplic
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
@ReactMethod
|
|
23
|
-
fun setup(apiKey: String, deviceId: String?, sessionId: Double, serverZone: String?, sampleRate: Double, enableRemoteConfig: Boolean, logLevel: Int, autoStart: Boolean) {
|
|
25
|
+
fun setup(apiKey: String, deviceId: String?, sessionId: Double, serverZone: String?, sampleRate: Double, enableRemoteConfig: Boolean, logLevel: Int, autoStart: Boolean, maskLevel: String) {
|
|
24
26
|
LogcatLogger.logger.logMode = when (logLevel) {
|
|
25
27
|
0 -> Logger.LogMode.OFF
|
|
26
28
|
1 -> Logger.LogMode.ERROR
|
|
@@ -30,6 +32,13 @@ class PluginSessionReplayReactNativeModule(private val reactContext: ReactApplic
|
|
|
30
32
|
else -> Logger.LogMode.WARN
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
val mappedMaskLevel = when (maskLevel.lowercase()) {
|
|
36
|
+
"light" -> MaskLevel.LIGHT
|
|
37
|
+
"medium" -> MaskLevel.MEDIUM
|
|
38
|
+
"conservative" -> MaskLevel.CONSERVATIVE
|
|
39
|
+
else -> MaskLevel.MEDIUM
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
LogcatLogger.logger.debug("""
|
|
34
43
|
setup:
|
|
35
44
|
API Key: $apiKey
|
|
@@ -40,6 +49,7 @@ class PluginSessionReplayReactNativeModule(private val reactContext: ReactApplic
|
|
|
40
49
|
Enable Remote Config: $enableRemoteConfig
|
|
41
50
|
Log Level: $logLevel
|
|
42
51
|
Auto Start: $autoStart
|
|
52
|
+
Mask Level: $maskLevel
|
|
43
53
|
""".trimIndent())
|
|
44
54
|
|
|
45
55
|
sessionReplay = SessionReplay(
|
|
@@ -54,7 +64,8 @@ class PluginSessionReplayReactNativeModule(private val reactContext: ReactApplic
|
|
|
54
64
|
"EU" -> ServerZone.EU
|
|
55
65
|
else -> ServerZone.US
|
|
56
66
|
},
|
|
57
|
-
autoStart = autoStart
|
|
67
|
+
autoStart = autoStart,
|
|
68
|
+
privacyConfig = PrivacyConfig(maskLevel = mappedMaskLevel)
|
|
58
69
|
)
|
|
59
70
|
}
|
|
60
71
|
|
|
@@ -87,7 +98,7 @@ class PluginSessionReplayReactNativeModule(private val reactContext: ReactApplic
|
|
|
87
98
|
}
|
|
88
99
|
promise.resolve(map)
|
|
89
100
|
}
|
|
90
|
-
|
|
101
|
+
|
|
91
102
|
@ReactMethod
|
|
92
103
|
fun start() {
|
|
93
104
|
sessionReplay.start()
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
@interface RCT_EXTERN_MODULE(PluginSessionReplayReactNative, NSObject)
|
|
4
4
|
|
|
5
|
-
RCT_EXTERN_METHOD(setup:(NSString)apiKey deviceId:(NSString)deviceId sessionId:(nonnull NSNumber)sessionId serverZone:(NSString)serverZone sampleRate:(float)sampleRate enableRemoteConfig:(BOOL)enableRemoteConfig logLevel:(int)logLevel autoStart:(BOOL)autoStart resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
5
|
+
RCT_EXTERN_METHOD(setup:(NSString)apiKey deviceId:(NSString)deviceId sessionId:(nonnull NSNumber)sessionId serverZone:(NSString)serverZone sampleRate:(float)sampleRate enableRemoteConfig:(BOOL)enableRemoteConfig logLevel:(int)logLevel autoStart:(BOOL)autoStart maskLevel:(NSString)maskLevel resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
6
6
|
|
|
7
7
|
RCT_EXTERN_METHOD(setSessionId:(nonnull NSNumber)sessionId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
8
8
|
|
|
@@ -6,7 +6,7 @@ class PluginSessionReplayReactNative: NSObject {
|
|
|
6
6
|
|
|
7
7
|
var sessionReplay: SessionReplay!
|
|
8
8
|
|
|
9
|
-
@objc(setup:deviceId:sessionId:serverZone:sampleRate:enableRemoteConfig:logLevel:autoStart:resolve:reject:)
|
|
9
|
+
@objc(setup:deviceId:sessionId:serverZone:sampleRate:enableRemoteConfig:logLevel:autoStart:maskLevel:resolve:reject:)
|
|
10
10
|
func setup(_ apiKey: String,
|
|
11
11
|
deviceId: String,
|
|
12
12
|
sessionId: NSNumber,
|
|
@@ -15,6 +15,7 @@ class PluginSessionReplayReactNative: NSObject {
|
|
|
15
15
|
enableRemoteConfig: Bool,
|
|
16
16
|
logLevel: Int,
|
|
17
17
|
autoStart: Bool,
|
|
18
|
+
maskLevel: String,
|
|
18
19
|
resolve: RCTPromiseResolveBlock,
|
|
19
20
|
reject: RCTPromiseRejectBlock) -> Void {
|
|
20
21
|
print(
|
|
@@ -28,6 +29,7 @@ class PluginSessionReplayReactNative: NSObject {
|
|
|
28
29
|
Enable Remote Config: \(enableRemoteConfig)
|
|
29
30
|
Log Level: \(logLevel)
|
|
30
31
|
Auto Start: \(autoStart)
|
|
32
|
+
Mask Level: \(maskLevel)
|
|
31
33
|
"""
|
|
32
34
|
)
|
|
33
35
|
sessionReplay = SessionReplay(apiKey:apiKey,
|
|
@@ -36,6 +38,7 @@ class PluginSessionReplayReactNative: NSObject {
|
|
|
36
38
|
sampleRate: sampleRate,
|
|
37
39
|
logger:ConsoleLogger(logLevel: logLevel),
|
|
38
40
|
serverZone: serverZone == "EU" ? .EU : .US,
|
|
41
|
+
maskLevel: .fromString(maskLevel),
|
|
39
42
|
enableRemoteConfig: enableRemoteConfig)
|
|
40
43
|
if (autoStart) {
|
|
41
44
|
sessionReplay.start()
|
|
@@ -90,3 +93,18 @@ class PluginSessionReplayReactNative: NSObject {
|
|
|
90
93
|
resolve(nil)
|
|
91
94
|
}
|
|
92
95
|
}
|
|
96
|
+
|
|
97
|
+
extension MaskLevel {
|
|
98
|
+
static func fromString(_ input: String) -> MaskLevel {
|
|
99
|
+
switch input.lowercased() {
|
|
100
|
+
case "light":
|
|
101
|
+
return .light
|
|
102
|
+
case "medium":
|
|
103
|
+
return .medium
|
|
104
|
+
case "conservative":
|
|
105
|
+
return .conservative
|
|
106
|
+
default:
|
|
107
|
+
return .medium
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -9,12 +9,6 @@ Object.defineProperty(exports, "AmpMaskView", {
|
|
|
9
9
|
return _appMaskView.AmpMaskView;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
-
Object.defineProperty(exports, "SessionReplayConfig", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () {
|
|
15
|
-
return _sessionReplayConfig.SessionReplayConfig;
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
12
|
Object.defineProperty(exports, "SessionReplayPlugin", {
|
|
19
13
|
enumerable: true,
|
|
20
14
|
get: function () {
|
|
@@ -23,5 +17,4 @@ Object.defineProperty(exports, "SessionReplayPlugin", {
|
|
|
23
17
|
});
|
|
24
18
|
var _sessionReplay = require("./session-replay");
|
|
25
19
|
var _appMaskView = require("./app-mask-view");
|
|
26
|
-
var _sessionReplayConfig = require("./session-replay-config");
|
|
27
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_sessionReplay","require","_appMaskView"
|
|
1
|
+
{"version":3,"names":["_sessionReplay","require","_appMaskView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAGA,IAAAC,YAAA,GAAAD,OAAA","ignoreList":[]}
|
|
@@ -3,14 +3,52 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "LogLevel", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _analyticsTypes.LogLevel;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
exports.getDefaultConfig = void 0;
|
|
7
13
|
var _analyticsTypes = require("@amplitude/analytics-types");
|
|
14
|
+
/**
|
|
15
|
+
* Masking levels for sensitive content in session replay.
|
|
16
|
+
*
|
|
17
|
+
* Declared as a string-literal union (rather than an `enum`) to match the
|
|
18
|
+
* Session Replay browser SDK and avoid the const-enum inlining pitfalls of
|
|
19
|
+
* string enums under aggressive compilers. Kept structurally identical to the
|
|
20
|
+
* standalone `@amplitude/session-replay-react-native` SDK's `MaskLevel` so the
|
|
21
|
+
* two packages stay in lockstep without coupling the plugin's runtime to the
|
|
22
|
+
* standalone native module.
|
|
23
|
+
*
|
|
24
|
+
* - `light`: mask only inputs that are always sensitive (password, etc.).
|
|
25
|
+
* - `medium`: mask all `<TextInput>` fields.
|
|
26
|
+
* - `conservative`: mask all `<TextInput>` fields and all `<Text>` content.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Configuration for the Session Replay React Native plugin.
|
|
31
|
+
*
|
|
32
|
+
* Unlike the standalone `@amplitude/session-replay-react-native` SDK, the
|
|
33
|
+
* plugin auto-sources `apiKey`, `deviceId`, `sessionId`, and `serverZone`
|
|
34
|
+
* from the analytics client's `ReactNativeConfig` at `setup()` time, so
|
|
35
|
+
* those fields are intentionally absent from the public plugin config.
|
|
36
|
+
* The plugin also never shipped a deprecated top-level `maskLevel`, so no
|
|
37
|
+
* input-boundary normalization (and no `SessionReplayConfigInternal` alias)
|
|
38
|
+
* is needed here.
|
|
39
|
+
*/
|
|
40
|
+
|
|
8
41
|
const getDefaultConfig = () => {
|
|
9
42
|
return {
|
|
10
|
-
|
|
43
|
+
autoStart: true,
|
|
11
44
|
enableRemoteConfig: true,
|
|
12
45
|
logLevel: _analyticsTypes.LogLevel.Warn,
|
|
13
|
-
|
|
46
|
+
// Intentionally left without a `maskLevel`: the effective default
|
|
47
|
+
// (`'medium'`) is resolved once at the native boundary in `setup()`.
|
|
48
|
+
// Baking it in here would make a partial user `privacyConfig` (e.g. `{}`)
|
|
49
|
+
// unable to fall through to the `?? 'medium'` resolution.
|
|
50
|
+
privacyConfig: {},
|
|
51
|
+
sampleRate: 0
|
|
14
52
|
};
|
|
15
53
|
};
|
|
16
54
|
exports.getDefaultConfig = getDefaultConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_analyticsTypes","require","getDefaultConfig","
|
|
1
|
+
{"version":3,"names":["_analyticsTypes","require","getDefaultConfig","autoStart","enableRemoteConfig","logLevel","LogLevel","Warn","privacyConfig","sampleRate","exports"],"sourceRoot":"../../src","sources":["session-replay-config.ts"],"mappings":";;;;;;;;;;;;AAAA,IAAAA,eAAA,GAAAC,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAmCO,MAAMC,gBAAqD,GAAGA,CAAA,KAAM;EACzE,OAAO;IACLC,SAAS,EAAE,IAAI;IACfC,kBAAkB,EAAE,IAAI;IACxBC,QAAQ,EAAEC,wBAAQ,CAACC,IAAI;IACvB;IACA;IACA;IACA;IACAC,aAAa,EAAE,CAAC,CAAC;IACjBC,UAAU,EAAE;EACd,CAAC;AACH,CAAC;AAACC,OAAA,CAAAR,gBAAA,GAAAA,gBAAA","ignoreList":[]}
|
|
@@ -7,7 +7,6 @@ exports.SessionReplayPlugin = void 0;
|
|
|
7
7
|
var _nativeModule = require("./native-module");
|
|
8
8
|
var _version = require("./version");
|
|
9
9
|
var _sessionReplayConfig = require("./session-replay-config");
|
|
10
|
-
var _analyticsTypes = require("@amplitude/analytics-types");
|
|
11
10
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
12
11
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
13
12
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
@@ -32,7 +31,17 @@ class SessionReplayPlugin {
|
|
|
32
31
|
async setup(config, _) {
|
|
33
32
|
this.config = config;
|
|
34
33
|
console.log(`Installing @amplitude/plugin-session-replay-react-native, version ${_version.VERSION}.`);
|
|
35
|
-
|
|
34
|
+
// `apiKey`, `deviceId`, `sessionId`, and `serverZone` are sourced from the
|
|
35
|
+
// analytics client's `ReactNativeConfig` because the plugin runs inside an
|
|
36
|
+
// initialized Amplitude SDK and inherits identity from it.
|
|
37
|
+
// Resolve the effective mask level here — the single source of truth for
|
|
38
|
+
// the default. `privacyConfig.maskLevel` can be `undefined` when a partial
|
|
39
|
+
// `privacyConfig` (e.g. `{}`) is supplied, so fall back to `'medium'` rather
|
|
40
|
+
// than forwarding `undefined` across the native bridge.
|
|
41
|
+
const resolvedMaskLevel = this.sessionReplayConfig.privacyConfig.maskLevel ?? 'medium';
|
|
42
|
+
await _nativeModule.PluginSessionReplayReactNative.setup(config.apiKey, config.deviceId, config.sessionId, config.serverZone, this.sessionReplayConfig.sampleRate, this.sessionReplayConfig.enableRemoteConfig, this.sessionReplayConfig.logLevel, this.sessionReplayConfig.autoStart,
|
|
43
|
+
// TODO(SDKRN-15): Migrate native bridge to accept the full privacyConfig object instead of a flat maskLevel string.
|
|
44
|
+
resolvedMaskLevel);
|
|
36
45
|
this.isInitialized = true;
|
|
37
46
|
}
|
|
38
47
|
async execute(event) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_nativeModule","require","_version","_sessionReplayConfig","
|
|
1
|
+
{"version":3,"names":["_nativeModule","require","_version","_sessionReplayConfig","SessionReplayPlugin","name","type","isInitialized","constructor","config","sessionReplayConfig","getDefaultConfig","console","log","setup","_","VERSION","resolvedMaskLevel","privacyConfig","maskLevel","PluginSessionReplayReactNative","apiKey","deviceId","sessionId","serverZone","sampleRate","enableRemoteConfig","logLevel","autoStart","execute","event","Promise","resolve","getSessionId","setSessionId","session_id","sessionRecordingProperties","getSessionReplayProperties","event_properties","start","stop","teardown","exports"],"sourceRoot":"../../src","sources":["session-replay.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["VERSION","exports"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":";;;;;;AAAO,MAAMA,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAG,
|
|
1
|
+
{"version":3,"names":["VERSION","exports"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":";;;;;;AAAO,MAAMA,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAG,oBAAoB","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["SessionReplayPlugin","AmpMaskView"
|
|
1
|
+
{"version":3,"names":["SessionReplayPlugin","AmpMaskView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,kBAAkB;AAGtD,SAASC,WAAW,QAAQ,iBAAiB","ignoreList":[]}
|
|
@@ -1,10 +1,44 @@
|
|
|
1
1
|
import { LogLevel } from '@amplitude/analytics-types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Masking levels for sensitive content in session replay.
|
|
5
|
+
*
|
|
6
|
+
* Declared as a string-literal union (rather than an `enum`) to match the
|
|
7
|
+
* Session Replay browser SDK and avoid the const-enum inlining pitfalls of
|
|
8
|
+
* string enums under aggressive compilers. Kept structurally identical to the
|
|
9
|
+
* standalone `@amplitude/session-replay-react-native` SDK's `MaskLevel` so the
|
|
10
|
+
* two packages stay in lockstep without coupling the plugin's runtime to the
|
|
11
|
+
* standalone native module.
|
|
12
|
+
*
|
|
13
|
+
* - `light`: mask only inputs that are always sensitive (password, etc.).
|
|
14
|
+
* - `medium`: mask all `<TextInput>` fields.
|
|
15
|
+
* - `conservative`: mask all `<TextInput>` fields and all `<Text>` content.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for the Session Replay React Native plugin.
|
|
20
|
+
*
|
|
21
|
+
* Unlike the standalone `@amplitude/session-replay-react-native` SDK, the
|
|
22
|
+
* plugin auto-sources `apiKey`, `deviceId`, `sessionId`, and `serverZone`
|
|
23
|
+
* from the analytics client's `ReactNativeConfig` at `setup()` time, so
|
|
24
|
+
* those fields are intentionally absent from the public plugin config.
|
|
25
|
+
* The plugin also never shipped a deprecated top-level `maskLevel`, so no
|
|
26
|
+
* input-boundary normalization (and no `SessionReplayConfigInternal` alias)
|
|
27
|
+
* is needed here.
|
|
28
|
+
*/
|
|
29
|
+
|
|
2
30
|
export const getDefaultConfig = () => {
|
|
3
31
|
return {
|
|
4
|
-
|
|
32
|
+
autoStart: true,
|
|
5
33
|
enableRemoteConfig: true,
|
|
6
34
|
logLevel: LogLevel.Warn,
|
|
7
|
-
|
|
35
|
+
// Intentionally left without a `maskLevel`: the effective default
|
|
36
|
+
// (`'medium'`) is resolved once at the native boundary in `setup()`.
|
|
37
|
+
// Baking it in here would make a partial user `privacyConfig` (e.g. `{}`)
|
|
38
|
+
// unable to fall through to the `?? 'medium'` resolution.
|
|
39
|
+
privacyConfig: {},
|
|
40
|
+
sampleRate: 0
|
|
8
41
|
};
|
|
9
42
|
};
|
|
43
|
+
export { LogLevel };
|
|
10
44
|
//# sourceMappingURL=session-replay-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["LogLevel","getDefaultConfig","
|
|
1
|
+
{"version":3,"names":["LogLevel","getDefaultConfig","autoStart","enableRemoteConfig","logLevel","Warn","privacyConfig","sampleRate"],"sourceRoot":"../../src","sources":["session-replay-config.ts"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,4BAA4B;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAmCA,OAAO,MAAMC,gBAAqD,GAAGA,CAAA,KAAM;EACzE,OAAO;IACLC,SAAS,EAAE,IAAI;IACfC,kBAAkB,EAAE,IAAI;IACxBC,QAAQ,EAAEJ,QAAQ,CAACK,IAAI;IACvB;IACA;IACA;IACA;IACAC,aAAa,EAAE,CAAC,CAAC;IACjBC,UAAU,EAAE;EACd,CAAC;AACH,CAAC;AACD,SAASP,QAAQ","ignoreList":[]}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import { PluginSessionReplayReactNative } from './native-module';
|
|
8
8
|
import { VERSION } from './version';
|
|
9
9
|
import { getDefaultConfig } from './session-replay-config';
|
|
10
|
-
import { LogLevel } from '@amplitude/analytics-types';
|
|
11
10
|
export class SessionReplayPlugin {
|
|
12
11
|
name = '@amplitude/plugin-session-replay-react-native';
|
|
13
12
|
type = 'enrichment';
|
|
@@ -26,7 +25,17 @@ export class SessionReplayPlugin {
|
|
|
26
25
|
async setup(config, _) {
|
|
27
26
|
this.config = config;
|
|
28
27
|
console.log(`Installing @amplitude/plugin-session-replay-react-native, version ${VERSION}.`);
|
|
29
|
-
|
|
28
|
+
// `apiKey`, `deviceId`, `sessionId`, and `serverZone` are sourced from the
|
|
29
|
+
// analytics client's `ReactNativeConfig` because the plugin runs inside an
|
|
30
|
+
// initialized Amplitude SDK and inherits identity from it.
|
|
31
|
+
// Resolve the effective mask level here — the single source of truth for
|
|
32
|
+
// the default. `privacyConfig.maskLevel` can be `undefined` when a partial
|
|
33
|
+
// `privacyConfig` (e.g. `{}`) is supplied, so fall back to `'medium'` rather
|
|
34
|
+
// than forwarding `undefined` across the native bridge.
|
|
35
|
+
const resolvedMaskLevel = this.sessionReplayConfig.privacyConfig.maskLevel ?? 'medium';
|
|
36
|
+
await PluginSessionReplayReactNative.setup(config.apiKey, config.deviceId, config.sessionId, config.serverZone, this.sessionReplayConfig.sampleRate, this.sessionReplayConfig.enableRemoteConfig, this.sessionReplayConfig.logLevel, this.sessionReplayConfig.autoStart,
|
|
37
|
+
// TODO(SDKRN-15): Migrate native bridge to accept the full privacyConfig object instead of a flat maskLevel string.
|
|
38
|
+
resolvedMaskLevel);
|
|
30
39
|
this.isInitialized = true;
|
|
31
40
|
}
|
|
32
41
|
async execute(event) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["PluginSessionReplayReactNative","VERSION","getDefaultConfig","
|
|
1
|
+
{"version":3,"names":["PluginSessionReplayReactNative","VERSION","getDefaultConfig","SessionReplayPlugin","name","type","isInitialized","constructor","config","sessionReplayConfig","console","log","setup","_","resolvedMaskLevel","privacyConfig","maskLevel","apiKey","deviceId","sessionId","serverZone","sampleRate","enableRemoteConfig","logLevel","autoStart","execute","event","Promise","resolve","getSessionId","setSessionId","session_id","sessionRecordingProperties","getSessionReplayProperties","event_properties","start","stop","teardown"],"sourceRoot":"../../src","sources":["session-replay.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/module/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.5.0-sr-4646-rc.0';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["VERSION"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":"AAAA,OAAO,MAAMA,OAAO,GAAG,
|
|
1
|
+
{"version":3,"names":["VERSION"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":"AAAA,OAAO,MAAMA,OAAO,GAAG,oBAAoB","ignoreList":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { SessionReplayPlugin } from './session-replay';
|
|
2
|
+
export { type SessionReplayConfig, type MaskLevel, type PrivacyConfig } from './session-replay-config';
|
|
2
3
|
export { AmpMaskView } from './app-mask-view';
|
|
3
|
-
export { SessionReplayConfig } from './session-replay-config';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAEvG,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1,9 +1,62 @@
|
|
|
1
1
|
import { LogLevel } from '@amplitude/analytics-types';
|
|
2
|
+
/**
|
|
3
|
+
* Masking levels for sensitive content in session replay.
|
|
4
|
+
*
|
|
5
|
+
* Declared as a string-literal union (rather than an `enum`) to match the
|
|
6
|
+
* Session Replay browser SDK and avoid the const-enum inlining pitfalls of
|
|
7
|
+
* string enums under aggressive compilers. Kept structurally identical to the
|
|
8
|
+
* standalone `@amplitude/session-replay-react-native` SDK's `MaskLevel` so the
|
|
9
|
+
* two packages stay in lockstep without coupling the plugin's runtime to the
|
|
10
|
+
* standalone native module.
|
|
11
|
+
*
|
|
12
|
+
* - `light`: mask only inputs that are always sensitive (password, etc.).
|
|
13
|
+
* - `medium`: mask all `<TextInput>` fields.
|
|
14
|
+
* - `conservative`: mask all `<TextInput>` fields and all `<Text>` content.
|
|
15
|
+
*/
|
|
16
|
+
export type MaskLevel = 'light' | 'medium' | 'conservative';
|
|
17
|
+
export interface PrivacyConfig {
|
|
18
|
+
maskLevel?: MaskLevel;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for the Session Replay React Native plugin.
|
|
22
|
+
*
|
|
23
|
+
* Unlike the standalone `@amplitude/session-replay-react-native` SDK, the
|
|
24
|
+
* plugin auto-sources `apiKey`, `deviceId`, `sessionId`, and `serverZone`
|
|
25
|
+
* from the analytics client's `ReactNativeConfig` at `setup()` time, so
|
|
26
|
+
* those fields are intentionally absent from the public plugin config.
|
|
27
|
+
* The plugin also never shipped a deprecated top-level `maskLevel`, so no
|
|
28
|
+
* input-boundary normalization (and no `SessionReplayConfigInternal` alias)
|
|
29
|
+
* is needed here.
|
|
30
|
+
*/
|
|
2
31
|
export interface SessionReplayConfig {
|
|
3
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Whether to automatically start recording when the plugin is added
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
autoStart?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether to enable remote configuration
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
4
41
|
enableRemoteConfig?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Log level for the SDK
|
|
44
|
+
* @default LogLevel.Warn
|
|
45
|
+
*/
|
|
5
46
|
logLevel?: LogLevel;
|
|
6
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Privacy configuration for session replay.
|
|
49
|
+
* When `maskLevel` is omitted it resolves to `'medium'` at the native boundary.
|
|
50
|
+
* @default {}
|
|
51
|
+
*/
|
|
52
|
+
privacyConfig?: PrivacyConfig;
|
|
53
|
+
/**
|
|
54
|
+
* Sample rate for session replay (0.0 to 1.0)
|
|
55
|
+
* Determines what percentage of sessions will be recorded
|
|
56
|
+
* @default 0
|
|
57
|
+
*/
|
|
58
|
+
sampleRate?: number;
|
|
7
59
|
}
|
|
8
|
-
export declare const getDefaultConfig: () => SessionReplayConfig
|
|
60
|
+
export declare const getDefaultConfig: () => Required<SessionReplayConfig>;
|
|
61
|
+
export { LogLevel };
|
|
9
62
|
//# sourceMappingURL=session-replay-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay-config.d.ts","sourceRoot":"","sources":["../../src/session-replay-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,
|
|
1
|
+
{"version":3,"file":"session-replay-config.d.ts","sourceRoot":"","sources":["../../src/session-replay-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,cAAc,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,QAAQ,CAAC,mBAAmB,CAYhE,CAAC;AACF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { EnrichmentPlugin, Event, ReactNativeClient, ReactNativeConfig } from '@amplitude/analytics-types';
|
|
2
2
|
import { SessionReplayConfig } from './session-replay-config';
|
|
3
|
+
type ResolvedSessionReplayConfig = Required<SessionReplayConfig>;
|
|
3
4
|
export declare class SessionReplayPlugin implements EnrichmentPlugin<ReactNativeClient, ReactNativeConfig> {
|
|
4
5
|
name: string;
|
|
5
6
|
type: "enrichment";
|
|
6
7
|
config: ReactNativeConfig;
|
|
7
8
|
isInitialized: boolean;
|
|
8
|
-
sessionReplayConfig:
|
|
9
|
+
sessionReplayConfig: ResolvedSessionReplayConfig;
|
|
9
10
|
constructor(config?: SessionReplayConfig);
|
|
10
11
|
setup(config: ReactNativeConfig, _: ReactNativeClient): Promise<void>;
|
|
11
12
|
execute(event: Event): Promise<Event | null>;
|
|
@@ -14,4 +15,5 @@ export declare class SessionReplayPlugin implements EnrichmentPlugin<ReactNative
|
|
|
14
15
|
teardown(): Promise<void>;
|
|
15
16
|
getSessionReplayProperties(): Promise<any>;
|
|
16
17
|
}
|
|
18
|
+
export {};
|
|
17
19
|
//# sourceMappingURL=session-replay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIhH,OAAO,EAAE,mBAAmB,EAAoB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIhH,OAAO,EAAE,mBAAmB,EAAoB,MAAM,yBAAyB,CAAC;AAEhF,KAAK,2BAA2B,GAAG,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AAEjE,qBAAa,mBAAoB,YAAW,gBAAgB,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAChG,IAAI,SAAmD;IACvD,IAAI,eAAyB;IAI7B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,aAAa,UAAS;IAEtB,mBAAmB,EAAE,2BAA2B,CAAC;gBAErC,MAAM,GAAE,mBAAwB;IAQtC,KAAK,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BrE,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAuB5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAYzB,0BAA0B;CAMjC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.5.0-sr-4646-rc.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,uBAAuB,CAAC"}
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { SessionReplayPlugin } from './session-replay';
|
|
2
|
+
export { type SessionReplayConfig, type MaskLevel, type PrivacyConfig } from './session-replay-config';
|
|
2
3
|
|
|
3
4
|
export { AmpMaskView } from './app-mask-view';
|
|
4
|
-
|
|
5
|
-
export { SessionReplayConfig } from './session-replay-config';
|
|
@@ -1,17 +1,81 @@
|
|
|
1
1
|
import { LogLevel } from '@amplitude/analytics-types';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Masking levels for sensitive content in session replay.
|
|
5
|
+
*
|
|
6
|
+
* Declared as a string-literal union (rather than an `enum`) to match the
|
|
7
|
+
* Session Replay browser SDK and avoid the const-enum inlining pitfalls of
|
|
8
|
+
* string enums under aggressive compilers. Kept structurally identical to the
|
|
9
|
+
* standalone `@amplitude/session-replay-react-native` SDK's `MaskLevel` so the
|
|
10
|
+
* two packages stay in lockstep without coupling the plugin's runtime to the
|
|
11
|
+
* standalone native module.
|
|
12
|
+
*
|
|
13
|
+
* - `light`: mask only inputs that are always sensitive (password, etc.).
|
|
14
|
+
* - `medium`: mask all `<TextInput>` fields.
|
|
15
|
+
* - `conservative`: mask all `<TextInput>` fields and all `<Text>` content.
|
|
16
|
+
*/
|
|
17
|
+
export type MaskLevel = 'light' | 'medium' | 'conservative';
|
|
18
|
+
|
|
19
|
+
export interface PrivacyConfig {
|
|
20
|
+
maskLevel?: MaskLevel;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for the Session Replay React Native plugin.
|
|
25
|
+
*
|
|
26
|
+
* Unlike the standalone `@amplitude/session-replay-react-native` SDK, the
|
|
27
|
+
* plugin auto-sources `apiKey`, `deviceId`, `sessionId`, and `serverZone`
|
|
28
|
+
* from the analytics client's `ReactNativeConfig` at `setup()` time, so
|
|
29
|
+
* those fields are intentionally absent from the public plugin config.
|
|
30
|
+
* The plugin also never shipped a deprecated top-level `maskLevel`, so no
|
|
31
|
+
* input-boundary normalization (and no `SessionReplayConfigInternal` alias)
|
|
32
|
+
* is needed here.
|
|
33
|
+
*/
|
|
3
34
|
export interface SessionReplayConfig {
|
|
4
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Whether to automatically start recording when the plugin is added
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
39
|
+
autoStart?: boolean;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether to enable remote configuration
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
5
45
|
enableRemoteConfig?: boolean;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Log level for the SDK
|
|
49
|
+
* @default LogLevel.Warn
|
|
50
|
+
*/
|
|
6
51
|
logLevel?: LogLevel;
|
|
7
|
-
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Privacy configuration for session replay.
|
|
55
|
+
* When `maskLevel` is omitted it resolves to `'medium'` at the native boundary.
|
|
56
|
+
* @default {}
|
|
57
|
+
*/
|
|
58
|
+
privacyConfig?: PrivacyConfig;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Sample rate for session replay (0.0 to 1.0)
|
|
62
|
+
* Determines what percentage of sessions will be recorded
|
|
63
|
+
* @default 0
|
|
64
|
+
*/
|
|
65
|
+
sampleRate?: number;
|
|
8
66
|
}
|
|
9
67
|
|
|
10
|
-
export const getDefaultConfig: () => SessionReplayConfig = () => {
|
|
68
|
+
export const getDefaultConfig: () => Required<SessionReplayConfig> = () => {
|
|
11
69
|
return {
|
|
12
|
-
|
|
70
|
+
autoStart: true,
|
|
13
71
|
enableRemoteConfig: true,
|
|
14
72
|
logLevel: LogLevel.Warn,
|
|
15
|
-
|
|
73
|
+
// Intentionally left without a `maskLevel`: the effective default
|
|
74
|
+
// (`'medium'`) is resolved once at the native boundary in `setup()`.
|
|
75
|
+
// Baking it in here would make a partial user `privacyConfig` (e.g. `{}`)
|
|
76
|
+
// unable to fall through to the `?? 'medium'` resolution.
|
|
77
|
+
privacyConfig: {},
|
|
78
|
+
sampleRate: 0,
|
|
16
79
|
};
|
|
17
80
|
};
|
|
81
|
+
export { LogLevel };
|
package/src/session-replay.ts
CHANGED
|
@@ -8,7 +8,8 @@ import type { EnrichmentPlugin, Event, ReactNativeClient, ReactNativeConfig } fr
|
|
|
8
8
|
import { PluginSessionReplayReactNative } from './native-module';
|
|
9
9
|
import { VERSION } from './version';
|
|
10
10
|
import { SessionReplayConfig, getDefaultConfig } from './session-replay-config';
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
type ResolvedSessionReplayConfig = Required<SessionReplayConfig>;
|
|
12
13
|
|
|
13
14
|
export class SessionReplayPlugin implements EnrichmentPlugin<ReactNativeClient, ReactNativeConfig> {
|
|
14
15
|
name = '@amplitude/plugin-session-replay-react-native';
|
|
@@ -19,7 +20,7 @@ export class SessionReplayPlugin implements EnrichmentPlugin<ReactNativeClient,
|
|
|
19
20
|
config: ReactNativeConfig;
|
|
20
21
|
isInitialized = false;
|
|
21
22
|
|
|
22
|
-
sessionReplayConfig:
|
|
23
|
+
sessionReplayConfig: ResolvedSessionReplayConfig;
|
|
23
24
|
|
|
24
25
|
constructor(config: SessionReplayConfig = {}) {
|
|
25
26
|
this.sessionReplayConfig = {
|
|
@@ -32,15 +33,25 @@ export class SessionReplayPlugin implements EnrichmentPlugin<ReactNativeClient,
|
|
|
32
33
|
async setup(config: ReactNativeConfig, _: ReactNativeClient): Promise<void> {
|
|
33
34
|
this.config = config;
|
|
34
35
|
console.log(`Installing @amplitude/plugin-session-replay-react-native, version ${VERSION}.`);
|
|
36
|
+
// `apiKey`, `deviceId`, `sessionId`, and `serverZone` are sourced from the
|
|
37
|
+
// analytics client's `ReactNativeConfig` because the plugin runs inside an
|
|
38
|
+
// initialized Amplitude SDK and inherits identity from it.
|
|
39
|
+
// Resolve the effective mask level here — the single source of truth for
|
|
40
|
+
// the default. `privacyConfig.maskLevel` can be `undefined` when a partial
|
|
41
|
+
// `privacyConfig` (e.g. `{}`) is supplied, so fall back to `'medium'` rather
|
|
42
|
+
// than forwarding `undefined` across the native bridge.
|
|
43
|
+
const resolvedMaskLevel = this.sessionReplayConfig.privacyConfig.maskLevel ?? 'medium';
|
|
35
44
|
await PluginSessionReplayReactNative.setup(
|
|
36
45
|
config.apiKey,
|
|
37
46
|
config.deviceId,
|
|
38
47
|
config.sessionId,
|
|
39
48
|
config.serverZone,
|
|
40
|
-
this.sessionReplayConfig.sampleRate
|
|
41
|
-
this.sessionReplayConfig.enableRemoteConfig
|
|
42
|
-
this.sessionReplayConfig.logLevel
|
|
43
|
-
this.sessionReplayConfig.autoStart
|
|
49
|
+
this.sessionReplayConfig.sampleRate,
|
|
50
|
+
this.sessionReplayConfig.enableRemoteConfig,
|
|
51
|
+
this.sessionReplayConfig.logLevel,
|
|
52
|
+
this.sessionReplayConfig.autoStart,
|
|
53
|
+
// TODO(SDKRN-15): Migrate native bridge to accept the full privacyConfig object instead of a flat maskLevel string.
|
|
54
|
+
resolvedMaskLevel,
|
|
44
55
|
);
|
|
45
56
|
this.isInitialized = true;
|
|
46
57
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.5.0-sr-4646-rc.0';
|