@amplitude/session-replay-browser 1.5.2 → 1.6.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.
Files changed (42) hide show
  1. package/lib/cjs/config/joined-config.d.ts.map +1 -1
  2. package/lib/cjs/config/joined-config.js +104 -19
  3. package/lib/cjs/config/joined-config.js.map +1 -1
  4. package/lib/cjs/config/types.d.ts +5 -0
  5. package/lib/cjs/config/types.d.ts.map +1 -1
  6. package/lib/cjs/config/types.js +2 -0
  7. package/lib/cjs/config/types.js.map +1 -1
  8. package/lib/cjs/helpers.d.ts +2 -1
  9. package/lib/cjs/helpers.d.ts.map +1 -1
  10. package/lib/cjs/helpers.js +71 -7
  11. package/lib/cjs/helpers.js.map +1 -1
  12. package/lib/cjs/session-replay.d.ts +2 -0
  13. package/lib/cjs/session-replay.d.ts.map +1 -1
  14. package/lib/cjs/session-replay.js +51 -3
  15. package/lib/cjs/session-replay.js.map +1 -1
  16. package/lib/esm/config/joined-config.d.ts.map +1 -1
  17. package/lib/esm/config/joined-config.js +105 -20
  18. package/lib/esm/config/joined-config.js.map +1 -1
  19. package/lib/esm/config/types.d.ts +5 -0
  20. package/lib/esm/config/types.d.ts.map +1 -1
  21. package/lib/esm/config/types.js +1 -1
  22. package/lib/esm/config/types.js.map +1 -1
  23. package/lib/esm/helpers.d.ts +2 -1
  24. package/lib/esm/helpers.d.ts.map +1 -1
  25. package/lib/esm/helpers.js +70 -6
  26. package/lib/esm/helpers.js.map +1 -1
  27. package/lib/esm/session-replay.d.ts +2 -0
  28. package/lib/esm/session-replay.d.ts.map +1 -1
  29. package/lib/esm/session-replay.js +52 -4
  30. package/lib/esm/session-replay.js.map +1 -1
  31. package/lib/scripts/amplitude-min.js +1 -1
  32. package/lib/scripts/amplitude-min.js.gz +0 -0
  33. package/lib/scripts/amplitude-min.umd.js +1 -1
  34. package/lib/scripts/amplitude-min.umd.js.gz +0 -0
  35. package/lib/scripts/config/joined-config.d.ts.map +1 -1
  36. package/lib/scripts/config/types.d.ts +5 -0
  37. package/lib/scripts/config/types.d.ts.map +1 -1
  38. package/lib/scripts/helpers.d.ts +2 -1
  39. package/lib/scripts/helpers.d.ts.map +1 -1
  40. package/lib/scripts/session-replay.d.ts +2 -0
  41. package/lib/scripts/session-replay.d.ts.map +1 -1
  42. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,oCAAoC,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,yBAAyB,EAEzB,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB,qBAAa,kCAAkC;IAC7C,WAAW,EAAE,yBAAyB,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,CAAC,yBAAyB,CAAC,GAAG,SAAS,CAAC;gBAEhE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAInD,UAAU;IAOV,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;CA+EnF;AAED,eAAO,MAAM,wCAAwC,WAAkB,MAAM,WAAW,oBAAoB,gDAI3G,CAAC"}
1
+ {"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,oCAAoC,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EAErD,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB,qBAAa,kCAAkC;IAC7C,WAAW,EAAE,yBAAyB,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,CAAC,yBAAyB,CAAC,GAAG,SAAS,CAAC;gBAEhE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAInD,UAAU;IAOV,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;CA+HnF;AAED,eAAO,MAAM,wCAAwC,WAAkB,MAAM,WAAW,oBAAoB,gDAI3G,CAAC"}
@@ -27,10 +27,12 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
27
27
  });
28
28
  };
29
29
  SessionReplayJoinedConfigGenerator.prototype.generateJoinedConfig = function (sessionId) {
30
+ var _a, _b, _c;
30
31
  return tslib_1.__awaiter(this, void 0, void 0, function () {
31
- var config, remoteConfig, samplingConfig_1, privacyConfig_1, err_1, knownError, samplingConfig, privacyConfig, key, k;
32
- return tslib_1.__generator(this, function (_a) {
33
- switch (_a.label) {
32
+ var config, remoteConfig, samplingConfig_1, privacyConfig, err_1, knownError, samplingConfig, remotePrivacyConfig, localPrivacyConfig, joinedPrivacyConfig, privacyConfigSelectorMap, selectorMap, _d, _e, _f, selector, selectorType;
33
+ var e_1, _g;
34
+ return tslib_1.__generator(this, function (_h) {
35
+ switch (_h.label) {
34
36
  case 0:
35
37
  config = tslib_1.__assign({}, this.localConfig);
36
38
  // Special case here as optOut is implemented via getter/setter
@@ -38,30 +40,30 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
38
40
  // We always want captureEnabled to be true, unless there's an override
39
41
  // in the remote config.
40
42
  config.captureEnabled = true;
41
- _a.label = 1;
43
+ _h.label = 1;
42
44
  case 1:
43
- _a.trys.push([1, 4, , 5]);
45
+ _h.trys.push([1, 4, , 5]);
44
46
  if (!this.remoteConfigFetch) {
45
47
  return [2 /*return*/, config];
46
48
  }
47
49
  return [4 /*yield*/, this.remoteConfigFetch.getRemoteConfig('sessionReplay', 'sr_sampling_config', sessionId)];
48
50
  case 2:
49
- samplingConfig_1 = _a.sent();
51
+ samplingConfig_1 = _h.sent();
50
52
  return [4 /*yield*/, this.remoteConfigFetch.getRemoteConfig('sessionReplay', 'sr_privacy_config', sessionId)];
51
53
  case 3:
52
- privacyConfig_1 = _a.sent();
53
- if (samplingConfig_1 || privacyConfig_1) {
54
+ privacyConfig = _h.sent();
55
+ if (samplingConfig_1 || privacyConfig) {
54
56
  remoteConfig = {};
55
57
  if (samplingConfig_1) {
56
58
  remoteConfig.sr_sampling_config = samplingConfig_1;
57
59
  }
58
- if (privacyConfig_1) {
59
- remoteConfig.sr_privacy_config = privacyConfig_1;
60
+ if (privacyConfig) {
61
+ remoteConfig.sr_privacy_config = privacyConfig;
60
62
  }
61
63
  }
62
64
  return [3 /*break*/, 5];
63
65
  case 4:
64
- err_1 = _a.sent();
66
+ err_1 = _h.sent();
65
67
  knownError = err_1;
66
68
  this.localConfig.loggerProvider.warn(knownError.message);
67
69
  config.captureEnabled = true;
@@ -70,7 +72,7 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
70
72
  if (!remoteConfig) {
71
73
  return [2 /*return*/, config];
72
74
  }
73
- samplingConfig = remoteConfig.sr_sampling_config, privacyConfig = remoteConfig.sr_privacy_config;
75
+ samplingConfig = remoteConfig.sr_sampling_config, remotePrivacyConfig = remoteConfig.sr_privacy_config;
74
76
  if (samplingConfig && Object.keys(samplingConfig).length > 0) {
75
77
  if (Object.prototype.hasOwnProperty.call(samplingConfig, 'capture_enabled')) {
76
78
  config.captureEnabled = samplingConfig.capture_enabled;
@@ -89,15 +91,98 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
89
91
  config.captureEnabled = true;
90
92
  this.localConfig.loggerProvider.debug('Remote config successfully fetched, but no values set for project, Session Replay capture enabled.');
91
93
  }
92
- // Override all keys in the local config with the remote privacy config.
93
- if (privacyConfig && Object.keys(privacyConfig).length > 0) {
94
- if (!config.privacyConfig) {
95
- config.privacyConfig = {};
94
+ // Remote config join acts somewhat like a left join between the remote and the local
95
+ // config. That is, remote config has precedence over local values as with sampling.
96
+ // However, non conflicting values will be added to the lists.
97
+ // Here's an example to illustrate:
98
+ //
99
+ // Remote config: {'.selector1': 'MASK', '.selector2': 'UNMASK'}
100
+ // Local config: {'.selector1': 'UNMASK', '.selector3': 'MASK'}
101
+ //
102
+ // Resolved config: {'.selector1': 'MASK', '.selector2': 'UNMASK', '.selector3': 'MASK'}
103
+ // config.privacyConfig = {
104
+ // ...(config.privacyConfig ?? {}),
105
+ // ...remotePrivacyConfig,
106
+ // };
107
+ if (remotePrivacyConfig) {
108
+ localPrivacyConfig = (_a = config.privacyConfig) !== null && _a !== void 0 ? _a : {};
109
+ joinedPrivacyConfig = {
110
+ defaultMaskLevel: (_c = (_b = remotePrivacyConfig.defaultMaskLevel) !== null && _b !== void 0 ? _b : localPrivacyConfig.defaultMaskLevel) !== null && _c !== void 0 ? _c : 'medium',
111
+ blockSelector: [],
112
+ maskSelector: [],
113
+ unmaskSelector: [],
114
+ };
115
+ privacyConfigSelectorMap = function (privacyConfig) {
116
+ var e_2, _a, e_3, _b, e_4, _c;
117
+ var _d, _e, _f;
118
+ var selectorMap = {};
119
+ if (typeof privacyConfig.blockSelector === 'string') {
120
+ privacyConfig.blockSelector = [privacyConfig.blockSelector];
121
+ }
122
+ try {
123
+ for (var _g = tslib_1.__values((_d = privacyConfig.blockSelector) !== null && _d !== void 0 ? _d : []), _h = _g.next(); !_h.done; _h = _g.next()) {
124
+ var selector = _h.value;
125
+ selectorMap[selector] = 'block';
126
+ }
127
+ }
128
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
129
+ finally {
130
+ try {
131
+ if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
132
+ }
133
+ finally { if (e_2) throw e_2.error; }
134
+ }
135
+ try {
136
+ for (var _j = tslib_1.__values((_e = privacyConfig.maskSelector) !== null && _e !== void 0 ? _e : []), _k = _j.next(); !_k.done; _k = _j.next()) {
137
+ var selector = _k.value;
138
+ selectorMap[selector] = 'mask';
139
+ }
140
+ }
141
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
142
+ finally {
143
+ try {
144
+ if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
145
+ }
146
+ finally { if (e_3) throw e_3.error; }
147
+ }
148
+ try {
149
+ for (var _l = tslib_1.__values((_f = privacyConfig.unmaskSelector) !== null && _f !== void 0 ? _f : []), _m = _l.next(); !_m.done; _m = _l.next()) {
150
+ var selector = _m.value;
151
+ selectorMap[selector] = 'unmask';
152
+ }
153
+ }
154
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
155
+ finally {
156
+ try {
157
+ if (_m && !_m.done && (_c = _l.return)) _c.call(_l);
158
+ }
159
+ finally { if (e_4) throw e_4.error; }
160
+ }
161
+ return selectorMap;
162
+ };
163
+ selectorMap = tslib_1.__assign(tslib_1.__assign({}, privacyConfigSelectorMap(localPrivacyConfig)), privacyConfigSelectorMap(remotePrivacyConfig));
164
+ try {
165
+ for (_d = tslib_1.__values(Object.entries(selectorMap)), _e = _d.next(); !_e.done; _e = _d.next()) {
166
+ _f = tslib_1.__read(_e.value, 2), selector = _f[0], selectorType = _f[1];
167
+ if (selectorType === 'mask') {
168
+ joinedPrivacyConfig.maskSelector.push(selector);
169
+ }
170
+ else if (selectorType === 'block') {
171
+ joinedPrivacyConfig.blockSelector.push(selector);
172
+ }
173
+ else if (selectorType === 'unmask') {
174
+ joinedPrivacyConfig.unmaskSelector.push(selector);
175
+ }
176
+ }
96
177
  }
97
- for (key in privacyConfig) {
98
- k = key;
99
- config.privacyConfig[k] = privacyConfig[k];
178
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
179
+ finally {
180
+ try {
181
+ if (_e && !_e.done && (_g = _d.return)) _g.call(_d);
182
+ }
183
+ finally { if (e_1) throw e_1.error; }
100
184
  }
185
+ config.privacyConfig = joinedPrivacyConfig;
101
186
  }
102
187
  return [2 /*return*/, config];
103
188
  }
@@ -1 +1 @@
1
- {"version":3,"file":"joined-config.js","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { RemoteConfigFetch, createRemoteConfigFetch } from '@amplitude/analytics-remote-config';\nimport { SessionReplayOptions } from '../typings/session-replay';\nimport { SessionReplayLocalConfig } from './local-config';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n SessionReplayJoinedConfig,\n PrivacyConfig,\n SessionReplayRemoteConfig,\n} from './types';\n\nexport class SessionReplayJoinedConfigGenerator {\n localConfig: ISessionReplayLocalConfig;\n remoteConfigFetch: RemoteConfigFetch<SessionReplayRemoteConfig> | undefined;\n\n constructor(apiKey: string, options: SessionReplayOptions) {\n this.localConfig = new SessionReplayLocalConfig(apiKey, options);\n }\n\n async initialize() {\n this.remoteConfigFetch = await createRemoteConfigFetch<SessionReplayRemoteConfig>({\n localConfig: this.localConfig,\n configKeys: ['sessionReplay'],\n });\n }\n\n async generateJoinedConfig(sessionId?: number): Promise<SessionReplayJoinedConfig> {\n const config: SessionReplayJoinedConfig = { ...this.localConfig };\n // Special case here as optOut is implemented via getter/setter\n config.optOut = this.localConfig.optOut;\n // We always want captureEnabled to be true, unless there's an override\n // in the remote config.\n config.captureEnabled = true;\n let remoteConfig: SessionReplayRemoteConfig | undefined;\n try {\n if (!this.remoteConfigFetch) {\n return config;\n }\n\n const samplingConfig = await this.remoteConfigFetch.getRemoteConfig(\n 'sessionReplay',\n 'sr_sampling_config',\n sessionId,\n );\n\n const privacyConfig = await this.remoteConfigFetch.getRemoteConfig(\n 'sessionReplay',\n 'sr_privacy_config',\n sessionId,\n );\n\n if (samplingConfig || privacyConfig) {\n remoteConfig = {};\n if (samplingConfig) {\n remoteConfig.sr_sampling_config = samplingConfig;\n }\n if (privacyConfig) {\n remoteConfig.sr_privacy_config = privacyConfig;\n }\n }\n } catch (err: unknown) {\n const knownError = err as Error;\n this.localConfig.loggerProvider.warn(knownError.message);\n config.captureEnabled = true;\n }\n\n if (!remoteConfig) {\n return config;\n }\n\n const { sr_sampling_config: samplingConfig, sr_privacy_config: privacyConfig } = remoteConfig;\n if (samplingConfig && Object.keys(samplingConfig).length > 0) {\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'capture_enabled')) {\n config.captureEnabled = samplingConfig.capture_enabled;\n } else {\n config.captureEnabled = false;\n }\n\n if (samplingConfig.sample_rate) {\n config.sampleRate = samplingConfig.sample_rate;\n }\n } else {\n // If config API response was valid (ie 200), but no config returned, assume that\n // customer has not yet set up config, and use sample rate from SDK options,\n // allowing for immediate replay capture\n config.captureEnabled = true;\n this.localConfig.loggerProvider.debug(\n 'Remote config successfully fetched, but no values set for project, Session Replay capture enabled.',\n );\n }\n\n // Override all keys in the local config with the remote privacy config.\n if (privacyConfig && Object.keys(privacyConfig).length > 0) {\n if (!config.privacyConfig) {\n config.privacyConfig = {};\n }\n\n for (const key in privacyConfig) {\n const k = key as keyof PrivacyConfig;\n config.privacyConfig[k] = privacyConfig[k];\n }\n }\n\n return config;\n }\n}\n\nexport const createSessionReplayJoinedConfigGenerator = async (apiKey: string, options: SessionReplayOptions) => {\n const joinedConfigGenerator = new SessionReplayJoinedConfigGenerator(apiKey, options);\n await joinedConfigGenerator.initialize();\n return joinedConfigGenerator;\n};\n"]}
1
+ {"version":3,"file":"joined-config.js","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { RemoteConfigFetch, createRemoteConfigFetch } from '@amplitude/analytics-remote-config';\nimport { SessionReplayOptions } from '../typings/session-replay';\nimport { SessionReplayLocalConfig } from './local-config';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n PrivacyConfig,\n SessionReplayJoinedConfig,\n SessionReplayRemoteConfig,\n} from './types';\n\nexport class SessionReplayJoinedConfigGenerator {\n localConfig: ISessionReplayLocalConfig;\n remoteConfigFetch: RemoteConfigFetch<SessionReplayRemoteConfig> | undefined;\n\n constructor(apiKey: string, options: SessionReplayOptions) {\n this.localConfig = new SessionReplayLocalConfig(apiKey, options);\n }\n\n async initialize() {\n this.remoteConfigFetch = await createRemoteConfigFetch<SessionReplayRemoteConfig>({\n localConfig: this.localConfig,\n configKeys: ['sessionReplay'],\n });\n }\n\n async generateJoinedConfig(sessionId?: number): Promise<SessionReplayJoinedConfig> {\n const config: SessionReplayJoinedConfig = { ...this.localConfig };\n // Special case here as optOut is implemented via getter/setter\n config.optOut = this.localConfig.optOut;\n // We always want captureEnabled to be true, unless there's an override\n // in the remote config.\n config.captureEnabled = true;\n let remoteConfig: SessionReplayRemoteConfig | undefined;\n try {\n if (!this.remoteConfigFetch) {\n return config;\n }\n\n const samplingConfig = await this.remoteConfigFetch.getRemoteConfig(\n 'sessionReplay',\n 'sr_sampling_config',\n sessionId,\n );\n\n const privacyConfig = await this.remoteConfigFetch.getRemoteConfig(\n 'sessionReplay',\n 'sr_privacy_config',\n sessionId,\n );\n\n if (samplingConfig || privacyConfig) {\n remoteConfig = {};\n if (samplingConfig) {\n remoteConfig.sr_sampling_config = samplingConfig;\n }\n if (privacyConfig) {\n remoteConfig.sr_privacy_config = privacyConfig;\n }\n }\n } catch (err: unknown) {\n const knownError = err as Error;\n this.localConfig.loggerProvider.warn(knownError.message);\n config.captureEnabled = true;\n }\n\n if (!remoteConfig) {\n return config;\n }\n\n const { sr_sampling_config: samplingConfig, sr_privacy_config: remotePrivacyConfig } = remoteConfig;\n if (samplingConfig && Object.keys(samplingConfig).length > 0) {\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'capture_enabled')) {\n config.captureEnabled = samplingConfig.capture_enabled;\n } else {\n config.captureEnabled = false;\n }\n\n if (samplingConfig.sample_rate) {\n config.sampleRate = samplingConfig.sample_rate;\n }\n } else {\n // If config API response was valid (ie 200), but no config returned, assume that\n // customer has not yet set up config, and use sample rate from SDK options,\n // allowing for immediate replay capture\n config.captureEnabled = true;\n this.localConfig.loggerProvider.debug(\n 'Remote config successfully fetched, but no values set for project, Session Replay capture enabled.',\n );\n }\n\n // Remote config join acts somewhat like a left join between the remote and the local\n // config. That is, remote config has precedence over local values as with sampling.\n // However, non conflicting values will be added to the lists.\n // Here's an example to illustrate:\n //\n // Remote config: {'.selector1': 'MASK', '.selector2': 'UNMASK'}\n // Local config: {'.selector1': 'UNMASK', '.selector3': 'MASK'}\n //\n // Resolved config: {'.selector1': 'MASK', '.selector2': 'UNMASK', '.selector3': 'MASK'}\n // config.privacyConfig = {\n // ...(config.privacyConfig ?? {}),\n // ...remotePrivacyConfig,\n // };\n\n if (remotePrivacyConfig) {\n const localPrivacyConfig: PrivacyConfig = config.privacyConfig ?? {};\n\n const joinedPrivacyConfig: Required<PrivacyConfig> & { blockSelector: string[] } = {\n defaultMaskLevel: remotePrivacyConfig.defaultMaskLevel ?? localPrivacyConfig.defaultMaskLevel ?? 'medium',\n blockSelector: [],\n maskSelector: [],\n unmaskSelector: [],\n };\n\n const privacyConfigSelectorMap = (privacyConfig: PrivacyConfig): Record<string, 'mask' | 'unmask' | 'block'> => {\n const selectorMap: Record<string, 'mask' | 'unmask' | 'block'> = {};\n if (typeof privacyConfig.blockSelector === 'string') {\n privacyConfig.blockSelector = [privacyConfig.blockSelector];\n }\n\n for (const selector of privacyConfig.blockSelector ?? []) {\n selectorMap[selector] = 'block';\n }\n for (const selector of privacyConfig.maskSelector ?? []) {\n selectorMap[selector] = 'mask';\n }\n for (const selector of privacyConfig.unmaskSelector ?? []) {\n selectorMap[selector] = 'unmask';\n }\n return selectorMap;\n };\n\n const selectorMap: Record<string, 'mask' | 'unmask' | 'block'> = {\n ...privacyConfigSelectorMap(localPrivacyConfig),\n ...privacyConfigSelectorMap(remotePrivacyConfig),\n };\n\n for (const [selector, selectorType] of Object.entries(selectorMap)) {\n if (selectorType === 'mask') {\n joinedPrivacyConfig.maskSelector.push(selector);\n } else if (selectorType === 'block') {\n joinedPrivacyConfig.blockSelector.push(selector);\n } else if (selectorType === 'unmask') {\n joinedPrivacyConfig.unmaskSelector.push(selector);\n }\n }\n\n config.privacyConfig = joinedPrivacyConfig;\n }\n\n return config;\n }\n}\n\nexport const createSessionReplayJoinedConfigGenerator = async (apiKey: string, options: SessionReplayOptions) => {\n const joinedConfigGenerator = new SessionReplayJoinedConfigGenerator(apiKey, options);\n await joinedConfigGenerator.initialize();\n return joinedConfigGenerator;\n};\n"]}
@@ -12,8 +12,13 @@ export interface SessionReplayRemoteConfigAPIResponse {
12
12
  sessionReplay: SessionReplayRemoteConfig;
13
13
  };
14
14
  }
15
+ export type MaskLevel = 'light' | 'medium' | 'conservative';
16
+ export declare const DEFAULT_MASK_LEVEL = "medium";
15
17
  export type PrivacyConfig = {
16
18
  blockSelector?: string | string[];
19
+ defaultMaskLevel?: MaskLevel;
20
+ maskSelector?: string[];
21
+ unmaskSelector?: string[];
17
22
  };
18
23
  export interface SessionReplayLocalConfig extends Config {
19
24
  apiKey: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,kBAAkB,CAAC,EAAE,cAAc,CAAC;IACpC,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACnC,CAAC;AAEF,MAAM,WAAW,oCAAoC;IACnD,OAAO,EAAE;QACP,aAAa,EAAE,yBAAyB,CAAC;KAC1C,CAAC;CACH;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,MAAM,WAAW,wBAAyB,SAAQ,MAAM;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3G,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;IACrF,eAAe,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,kCAAkC;IACjD,oBAAoB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;CAClF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,kBAAkB,CAAC,EAAE,cAAc,CAAC;IACpC,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACnC,CAAC;AAEF,MAAM,WAAW,oCAAoC;IACnD,OAAO,EAAE;QACP,aAAa,EAAE,yBAAyB,CAAC;KAC1C,CAAC;CACH;AAED,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,QAAQ,GACR,cAAc,CAAC;AAEnB,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAG3C,MAAM,MAAM,aAAa,GAAG;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,WAAW,wBAAyB,SAAQ,MAAM;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3G,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;IACrF,eAAe,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,kCAAkC;IACjD,oBAAoB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;CAClF"}
@@ -1,2 +1,4 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
+ exports.DEFAULT_MASK_LEVEL = void 0;
3
+ exports.DEFAULT_MASK_LEVEL = 'medium';
2
4
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"","sourcesContent":["import { Config, LogLevel, Logger } from '@amplitude/analytics-types';\n\nexport interface SamplingConfig {\n sample_rate: number;\n capture_enabled: boolean;\n}\n\nexport type SessionReplayRemoteConfig = {\n sr_sampling_config?: SamplingConfig;\n sr_privacy_config?: PrivacyConfig;\n};\n\nexport interface SessionReplayRemoteConfigAPIResponse {\n configs: {\n sessionReplay: SessionReplayRemoteConfig;\n };\n}\n\nexport type PrivacyConfig = {\n blockSelector?: string | string[];\n};\n\nexport interface SessionReplayLocalConfig extends Config {\n apiKey: string;\n loggerProvider: Logger;\n logLevel: LogLevel;\n flushMaxRetries: number;\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n debugMode?: boolean;\n configEndpointUrl?: string;\n}\n\nexport interface SessionReplayJoinedConfig extends SessionReplayLocalConfig {\n captureEnabled?: boolean;\n}\n\nexport interface SessionReplayRemoteConfigFetch {\n getServerUrl: () => void;\n getSamplingConfig: (sessionId?: number) => Promise<SessionReplayRemoteConfig['sr_sampling_config'] | void>;\n fetchRemoteConfig: (sessionId?: number) => Promise<SessionReplayRemoteConfig | void>;\n getRemoteConfig: (sessionId?: number) => Promise<SessionReplayRemoteConfig | void>;\n}\n\nexport interface SessionReplayJoinedConfigGenerator {\n generateJoinedConfig: (sessionId?: number) => Promise<SessionReplayJoinedConfig>;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":";;AAuBa,QAAA,kBAAkB,GAAG,QAAQ,CAAC","sourcesContent":["import { Config, LogLevel, Logger } from '@amplitude/analytics-types';\n\nexport interface SamplingConfig {\n sample_rate: number;\n capture_enabled: boolean;\n}\n\nexport type SessionReplayRemoteConfig = {\n sr_sampling_config?: SamplingConfig;\n sr_privacy_config?: PrivacyConfig;\n};\n\nexport interface SessionReplayRemoteConfigAPIResponse {\n configs: {\n sessionReplay: SessionReplayRemoteConfig;\n };\n}\n\nexport type MaskLevel =\n | 'light' // only mask a subset of inputs that’s deemed sensitive - password, credit card, telephone #, email. These are information we never want to capture.\n | 'medium' // mask all inputs\n | 'conservative'; // mask all inputs and all texts\n\nexport const DEFAULT_MASK_LEVEL = 'medium';\n\n// err on the side of excluding more\nexport type PrivacyConfig = {\n blockSelector?: string | string[]; // exclude in the UI\n defaultMaskLevel?: MaskLevel;\n maskSelector?: string[];\n unmaskSelector?: string[];\n};\n\nexport interface SessionReplayLocalConfig extends Config {\n apiKey: string;\n loggerProvider: Logger;\n logLevel: LogLevel;\n flushMaxRetries: number;\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n debugMode?: boolean;\n configEndpointUrl?: string;\n}\n\nexport interface SessionReplayJoinedConfig extends SessionReplayLocalConfig {\n captureEnabled?: boolean;\n}\n\nexport interface SessionReplayRemoteConfigFetch {\n getServerUrl: () => void;\n getSamplingConfig: (sessionId?: number) => Promise<SessionReplayRemoteConfig['sr_sampling_config'] | void>;\n fetchRemoteConfig: (sessionId?: number) => Promise<SessionReplayRemoteConfig | void>;\n getRemoteConfig: (sessionId?: number) => Promise<SessionReplayRemoteConfig | void>;\n}\n\nexport interface SessionReplayJoinedConfigGenerator {\n generateJoinedConfig: (sessionId?: number) => Promise<SessionReplayJoinedConfig>;\n}\n"]}
@@ -1,4 +1,5 @@
1
- export declare const maskInputFn: (text: string, element: HTMLElement) => string;
1
+ import { PrivacyConfig } from './config/types';
2
+ export declare const maskFn: (elementType: 'text' | 'input', config?: PrivacyConfig) => (text: string, element: HTMLElement | null) => string;
2
3
  export declare const generateHashCode: (str: string) => number;
3
4
  export declare const isSessionInSample: (sessionId: number, sampleRate: number) => boolean;
4
5
  export declare const getCurrentUrl: () => string;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,SAAU,MAAM,WAAW,WAAW,WAK7D,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAkB,MAAM,WASpD,CAAC;AAEF,eAAO,MAAM,iBAAiB,cAAwB,MAAM,cAAc,MAAM,YAM/E,CAAC;AAEF,eAAO,MAAM,aAAa,cAGzB,CAAC;AAEF,eAAO,MAAM,uBAAuB,cAAe,MAAM,YAAY,MAAM,KAAG,MAE7E,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiC,aAAa,EAAE,MAAM,gBAAgB,CAAC;AA+E9E,eAAO,MAAM,MAAM,gBACH,MAAM,GAAG,OAAO,WAAW,aAAa,YAC/C,MAAM,WAAW,WAAW,GAAG,IAAI,KAAG,MAE5C,CAAC;AAEJ,eAAO,MAAM,gBAAgB,QAAkB,MAAM,WASpD,CAAC;AAEF,eAAO,MAAM,iBAAiB,cAAwB,MAAM,cAAc,MAAM,YAM/E,CAAC;AAEF,eAAO,MAAM,aAAa,cAGzB,CAAC;AAEF,eAAO,MAAM,uBAAuB,cAAe,MAAM,YAAY,MAAM,KAAG,MAE7E,CAAC"}
@@ -1,15 +1,79 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.generateSessionReplayId = exports.getCurrentUrl = exports.isSessionInSample = exports.generateHashCode = exports.maskInputFn = void 0;
2
+ exports.generateSessionReplayId = exports.getCurrentUrl = exports.isSessionInSample = exports.generateHashCode = exports.maskFn = void 0;
3
3
  var analytics_client_common_1 = require("@amplitude/analytics-client-common");
4
4
  var constants_1 = require("./constants");
5
- var maskInputFn = function (text, element) {
6
- var _a;
7
- if ((_a = element.classList) === null || _a === void 0 ? void 0 : _a.contains(constants_1.UNMASK_TEXT_CLASS)) {
8
- return text;
5
+ var types_1 = require("./config/types");
6
+ var rrweb_snapshot_1 = require("@amplitude/rrweb-snapshot");
7
+ /**
8
+ * Light: Subset of inputs
9
+ * Medium: All inputs
10
+ * Conservative: All inputs and all texts
11
+ */
12
+ var isMaskedForLevel = function (elementType, level, element) {
13
+ switch (level) {
14
+ case 'light': {
15
+ if (elementType !== 'input') {
16
+ return true;
17
+ }
18
+ var inputType = element ? (0, rrweb_snapshot_1.getInputType)(element) : '';
19
+ /* istanbul ignore if */ // TODO(lew): For some reason it's impossible to test this.
20
+ if (!inputType) {
21
+ return false;
22
+ }
23
+ if (['password', 'hidden', 'email', 'tel'].includes(inputType)) {
24
+ return true;
25
+ }
26
+ if (element.autocomplete.startsWith('cc-')) {
27
+ return true;
28
+ }
29
+ return false;
30
+ }
31
+ case 'medium':
32
+ case 'conservative':
33
+ return true;
34
+ default:
35
+ return isMaskedForLevel(elementType, types_1.DEFAULT_MASK_LEVEL, element);
9
36
  }
10
- return '*'.repeat(text.length);
11
37
  };
12
- exports.maskInputFn = maskInputFn;
38
+ /**
39
+ * Checks if the given element set to be masked by rrweb
40
+ *
41
+ * Priority is:
42
+ * 1. [In code] Element/class based masking/unmasking <> [Config based] Selector based masking/unmasking
43
+ * 2. Use app defaults
44
+ */
45
+ var isMasked = function (elementType, config, element) {
46
+ var _a, _b, _c;
47
+ if (config === void 0) { config = { defaultMaskLevel: types_1.DEFAULT_MASK_LEVEL }; }
48
+ if (element) {
49
+ // Element or parent is explicitly instrumented in code to mask
50
+ if (element.closest('.' + constants_1.MASK_TEXT_CLASS)) {
51
+ return true;
52
+ }
53
+ // Config has override for mask
54
+ var shouldMask = ((_a = config.maskSelector) !== null && _a !== void 0 ? _a : []).some(function (selector) { return element.closest(selector); });
55
+ if (shouldMask) {
56
+ return true;
57
+ }
58
+ // Code or config has override to unmask
59
+ if (element.closest('.' + constants_1.UNMASK_TEXT_CLASS)) {
60
+ return false;
61
+ }
62
+ // Here we are probably sent an element, but we want to match if they have a
63
+ // parent with an unmask selector.
64
+ var shouldUnmask = ((_b = config.unmaskSelector) !== null && _b !== void 0 ? _b : []).some(function (selector) { return element.closest(selector); });
65
+ if (shouldUnmask) {
66
+ return false;
67
+ }
68
+ }
69
+ return isMaskedForLevel(elementType, (_c = config.defaultMaskLevel) !== null && _c !== void 0 ? _c : types_1.DEFAULT_MASK_LEVEL, element);
70
+ };
71
+ var maskFn = function (elementType, config) {
72
+ return function (text, element) {
73
+ return isMasked(elementType, config, element) ? text.replace(/[^\s]/g, '*') : text;
74
+ };
75
+ };
76
+ exports.maskFn = maskFn;
13
77
  var generateHashCode = function (str) {
14
78
  var hash = 0;
15
79
  if (str.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":";;AAAA,8EAAoE;AACpE,yCAAgD;AAEzC,IAAM,WAAW,GAAG,UAAC,IAAY,EAAE,OAAoB;;IAC5D,IAAI,MAAA,OAAO,CAAC,SAAS,0CAAE,QAAQ,CAAC,6BAAiB,CAAC,EAAE;QAClD,OAAO,IAAI,CAAC;KACb;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC,CAAC;AALW,QAAA,WAAW,eAKtB;AAEK,IAAM,gBAAgB,GAAG,UAAU,GAAW;IACnD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACnC,IAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC;QAChC,IAAI,IAAI,CAAC,CAAC;KACX;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AATW,QAAA,gBAAgB,oBAS3B;AAEK,IAAM,iBAAiB,GAAG,UAAU,SAAiB,EAAE,UAAkB;IAC9E,IAAM,UAAU,GAAG,IAAA,wBAAgB,EAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1D,IAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,IAAM,eAAe,GAAG,OAAO,GAAG,EAAE,CAAC;IACrC,IAAM,GAAG,GAAG,eAAe,GAAG,GAAG,CAAC;IAClC,OAAO,GAAG,GAAG,GAAG,GAAG,UAAU,CAAC;AAChC,CAAC,CAAC;AANW,QAAA,iBAAiB,qBAM5B;AAEK,IAAM,aAAa,GAAG;IAC3B,IAAM,WAAW,GAAG,IAAA,wCAAc,GAAE,CAAC;IACrC,OAAO,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,QAAQ,EAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AAChE,CAAC,CAAC;AAHW,QAAA,aAAa,iBAGxB;AAEK,IAAM,uBAAuB,GAAG,UAAC,SAAiB,EAAE,QAAgB;IACzE,OAAO,UAAG,QAAQ,cAAI,SAAS,CAAE,CAAC;AACpC,CAAC,CAAC;AAFW,QAAA,uBAAuB,2BAElC","sourcesContent":["import { getGlobalScope } from '@amplitude/analytics-client-common';\nimport { UNMASK_TEXT_CLASS } from './constants';\n\nexport const maskInputFn = (text: string, element: HTMLElement) => {\n if (element.classList?.contains(UNMASK_TEXT_CLASS)) {\n return text;\n }\n return '*'.repeat(text.length);\n};\n\nexport const generateHashCode = function (str: string) {\n let hash = 0;\n if (str.length === 0) return hash;\n for (let i = 0; i < str.length; i++) {\n const chr = str.charCodeAt(i);\n hash = (hash << 5) - hash + chr;\n hash |= 0;\n }\n return hash;\n};\n\nexport const isSessionInSample = function (sessionId: number, sampleRate: number) {\n const hashNumber = generateHashCode(sessionId.toString());\n const absHash = Math.abs(hashNumber);\n const absHashMultiply = absHash * 31;\n const mod = absHashMultiply % 100;\n return mod / 100 < sampleRate;\n};\n\nexport const getCurrentUrl = () => {\n const globalScope = getGlobalScope();\n return globalScope?.location ? globalScope.location.href : '';\n};\n\nexport const generateSessionReplayId = (sessionId: number, deviceId: string): string => {\n return `${deviceId}/${sessionId}`;\n};\n"]}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { getGlobalScope } from '@amplitude/analytics-client-common';\nimport { MASK_TEXT_CLASS, UNMASK_TEXT_CLASS } from './constants';\nimport { DEFAULT_MASK_LEVEL, MaskLevel, PrivacyConfig } from './config/types';\nimport { getInputType } from '@amplitude/rrweb-snapshot';\n\n/**\n * Light: Subset of inputs\n * Medium: All inputs\n * Conservative: All inputs and all texts\n */\nconst isMaskedForLevel = (elementType: 'input' | 'text', level: MaskLevel, element: HTMLElement | null): boolean => {\n switch (level) {\n case 'light': {\n if (elementType !== 'input') {\n return true;\n }\n\n const inputType = element ? getInputType(element) : '';\n /* istanbul ignore if */ // TODO(lew): For some reason it's impossible to test this.\n if (!inputType) {\n return false;\n }\n\n if (['password', 'hidden', 'email', 'tel'].includes(inputType)) {\n return true;\n }\n\n if ((element as HTMLInputElement).autocomplete.startsWith('cc-')) {\n return true;\n }\n\n return false;\n }\n case 'medium':\n case 'conservative':\n return true;\n default:\n return isMaskedForLevel(elementType, DEFAULT_MASK_LEVEL, element);\n }\n};\n\n/**\n * Checks if the given element set to be masked by rrweb\n *\n * Priority is:\n * 1. [In code] Element/class based masking/unmasking <> [Config based] Selector based masking/unmasking\n * 2. Use app defaults\n */\nconst isMasked = (\n elementType: 'input' | 'text',\n config: PrivacyConfig = { defaultMaskLevel: DEFAULT_MASK_LEVEL },\n element: HTMLElement | null,\n): boolean => {\n if (element) {\n // Element or parent is explicitly instrumented in code to mask\n if (element.closest('.' + MASK_TEXT_CLASS)) {\n return true;\n }\n\n // Config has override for mask\n const shouldMask = (config.maskSelector ?? []).some((selector) => element.closest(selector));\n if (shouldMask) {\n return true;\n }\n\n // Code or config has override to unmask\n if (element.closest('.' + UNMASK_TEXT_CLASS)) {\n return false;\n }\n\n // Here we are probably sent an element, but we want to match if they have a\n // parent with an unmask selector.\n const shouldUnmask = (config.unmaskSelector ?? []).some((selector) => element.closest(selector));\n if (shouldUnmask) {\n return false;\n }\n }\n\n return isMaskedForLevel(elementType, config.defaultMaskLevel ?? DEFAULT_MASK_LEVEL, element);\n};\n\nexport const maskFn =\n (elementType: 'text' | 'input', config?: PrivacyConfig) =>\n (text: string, element: HTMLElement | null): string => {\n return isMasked(elementType, config, element) ? text.replace(/[^\\s]/g, '*') : text;\n };\n\nexport const generateHashCode = function (str: string) {\n let hash = 0;\n if (str.length === 0) return hash;\n for (let i = 0; i < str.length; i++) {\n const chr = str.charCodeAt(i);\n hash = (hash << 5) - hash + chr;\n hash |= 0;\n }\n return hash;\n};\n\nexport const isSessionInSample = function (sessionId: number, sampleRate: number) {\n const hashNumber = generateHashCode(sessionId.toString());\n const absHash = Math.abs(hashNumber);\n const absHashMultiply = absHash * 31;\n const mod = absHashMultiply % 100;\n return mod / 100 < sampleRate;\n};\n\nexport const getCurrentUrl = () => {\n const globalScope = getGlobalScope();\n return globalScope?.location ? globalScope.location.href : '';\n};\n\nexport const generateSessionReplayId = (sessionId: number, deviceId: string): string => {\n return `${deviceId}/${sessionId}`;\n};\n"]}
@@ -12,6 +12,7 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
12
12
  recordCancelCallback: ReturnType<typeof record> | null;
13
13
  constructor();
14
14
  init(apiKey: string, options: SessionReplayOptions): import("@amplitude/analytics-types").AmplitudeReturn<void>;
15
+ removeInvalidSelectors(): void;
15
16
  protected _init(apiKey: string, options: SessionReplayOptions): Promise<void>;
16
17
  setSessionId(sessionId: number, deviceId?: string): import("@amplitude/analytics-types").AmplitudeReturn<void>;
17
18
  asyncSetSessionId(sessionId: number, deviceId?: string): Promise<void>;
@@ -26,6 +27,7 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
26
27
  shouldOptOut(): boolean | undefined;
27
28
  getShouldRecord(ignoreFocus?: boolean): boolean;
28
29
  getBlockSelectors(): string | string[] | undefined;
30
+ getMaskTextSelectors(): string | undefined;
29
31
  recordEvents(): void;
30
32
  stopRecordingEvents: () => void;
31
33
  getDeviceId(): string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAQ,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,yBAAyB,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;AAU/F,OAAO,EACL,sBAAsB,EACtB,0BAA0B,IAAI,mCAAmC,EACjE,kBAAkB,IAAI,mBAAmB,EACzC,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,qBAAa,aAAc,YAAW,sBAAsB;IAC1D,IAAI,SAAuC;IAC3C,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC;IAC9C,qBAAqB,EAAE,kCAAkC,GAAG,SAAS,CAAC;IACtE,WAAW,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,mCAAmC,GAAG,SAAS,CAAC;IAC/D,cAAc,EAAE,OAAO,CAAC;IACxB,oBAAoB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAQ;;IAM9D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;cAIlC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IA0BnE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAI3C,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAoB5D,kCAAkC;IAUlC,0BAA0B;;;IAwB1B,YAAY,aAEV;IAEF,aAAa,aAEX;IAEF,0BAA0B,CAAC,SAAS,CAAC,EAAE,MAAM;IAW7C,UAAU,CAAC,sBAAsB,UAAQ;IAqBzC,YAAY;IAUZ,eAAe,CAAC,WAAW,UAAQ;IAgCnC,iBAAiB,IAAI,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAIlD,YAAY;IAwCZ,mBAAmB,aAQjB;IAEF,WAAW;IAUX,YAAY;IAIN,KAAK,CAAC,QAAQ,UAAQ;IAM5B,QAAQ;CAST"}
1
+ {"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAQ,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,yBAAyB,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;AAU/F,OAAO,EACL,sBAAsB,EACtB,0BAA0B,IAAI,mCAAmC,EACjE,kBAAkB,IAAI,mBAAmB,EACzC,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,qBAAa,aAAc,YAAW,sBAAsB;IAC1D,IAAI,SAAuC;IAC3C,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC;IAC9C,qBAAqB,EAAE,kCAAkC,GAAG,SAAS,CAAC;IACtE,WAAW,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,mCAAmC,GAAG,SAAS,CAAC;IAC/D,cAAc,EAAE,OAAO,CAAC;IACxB,oBAAoB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAQ;;IAM9D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAIlD,sBAAsB;cA+BN,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAgCnE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAI3C,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAoB5D,kCAAkC;IAUlC,0BAA0B;;;IAwB1B,YAAY,aAEV;IAEF,aAAa,aAEX;IAEF,0BAA0B,CAAC,SAAS,CAAC,EAAE,MAAM;IAW7C,UAAU,CAAC,sBAAsB,UAAQ;IAqBzC,YAAY;IAUZ,eAAe,CAAC,WAAW,UAAQ;IAgCnC,iBAAiB,IAAI,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAIlD,oBAAoB,IAAI,MAAM,GAAG,SAAS;IAa1C,YAAY;IA4CZ,mBAAmB,aAQjB;IAEF,WAAW;IAUX,YAAY;IAIN,KAAK,CAAC,QAAQ,UAAQ;IAM5B,QAAQ;CAST"}
@@ -35,6 +35,37 @@ var SessionReplay = /** @class */ (function () {
35
35
  SessionReplay.prototype.init = function (apiKey, options) {
36
36
  return (0, analytics_core_1.returnWrapper)(this._init(apiKey, options));
37
37
  };
38
+ SessionReplay.prototype.removeInvalidSelectors = function () {
39
+ var _a;
40
+ if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.privacyConfig)) {
41
+ return;
42
+ }
43
+ // This allows us to not search the DOM.
44
+ var fragment = document.createDocumentFragment();
45
+ var dropInvalidSelectors = function (selectors) {
46
+ if (selectors === void 0) { selectors = []; }
47
+ if (typeof selectors === 'string') {
48
+ selectors = [selectors];
49
+ }
50
+ selectors = selectors.filter(function (selector) {
51
+ try {
52
+ fragment.querySelector(selector);
53
+ }
54
+ catch (_a) {
55
+ console.warn("[session-replay-browser] omitting selector \"".concat(selector, "\" because it is invalid"));
56
+ return false;
57
+ }
58
+ return true;
59
+ });
60
+ if (selectors.length === 0) {
61
+ return undefined;
62
+ }
63
+ return selectors;
64
+ };
65
+ this.config.privacyConfig.blockSelector = dropInvalidSelectors(this.config.privacyConfig.blockSelector);
66
+ this.config.privacyConfig.maskSelector = dropInvalidSelectors(this.config.privacyConfig.maskSelector);
67
+ this.config.privacyConfig.unmaskSelector = dropInvalidSelectors(this.config.privacyConfig.unmaskSelector);
68
+ };
38
69
  SessionReplay.prototype._init = function (apiKey, options) {
39
70
  return tslib_1.__awaiter(this, void 0, void 0, function () {
40
71
  var _a, _b, _c, globalScope;
@@ -51,6 +82,8 @@ var SessionReplay = /** @class */ (function () {
51
82
  return [4 /*yield*/, this.joinedConfigGenerator.generateJoinedConfig(this.identifiers.sessionId)];
52
83
  case 2:
53
84
  _b.config = _d.sent();
85
+ this.loggerProvider.debug(JSON.stringify({ name: 'joined privacy config', privacyConfig: this.config.privacyConfig }, null, 2));
86
+ this.removeInvalidSelectors();
54
87
  _c = this;
55
88
  return [4 /*yield*/, (0, events_manager_1.createEventsManager)({
56
89
  config: this.config,
@@ -202,15 +235,27 @@ var SessionReplay = /** @class */ (function () {
202
235
  var _a, _b;
203
236
  return (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.privacyConfig) === null || _b === void 0 ? void 0 : _b.blockSelector;
204
237
  };
238
+ SessionReplay.prototype.getMaskTextSelectors = function () {
239
+ var _a, _b, _c, _d;
240
+ if (((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.privacyConfig) === null || _b === void 0 ? void 0 : _b.defaultMaskLevel) === 'conservative') {
241
+ return '*';
242
+ }
243
+ var maskSelector = (_d = (_c = this.config) === null || _c === void 0 ? void 0 : _c.privacyConfig) === null || _d === void 0 ? void 0 : _d.maskSelector;
244
+ if (!maskSelector) {
245
+ return;
246
+ }
247
+ return maskSelector;
248
+ };
205
249
  SessionReplay.prototype.recordEvents = function () {
206
250
  var _this = this;
207
251
  var _a;
208
252
  var shouldRecord = this.getShouldRecord();
209
253
  var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
210
- if (!shouldRecord || !sessionId) {
254
+ if (!shouldRecord || !sessionId || !this.config) {
211
255
  return;
212
256
  }
213
257
  this.stopRecordingEvents();
258
+ var privacyConfig = this.config.privacyConfig;
214
259
  this.recordCancelCallback = (0, rrweb_1.record)({
215
260
  emit: function (event) {
216
261
  var globalScope = (0, analytics_client_common_1.getGlobalScope)();
@@ -226,9 +271,12 @@ var SessionReplay = /** @class */ (function () {
226
271
  maskAllInputs: true,
227
272
  maskTextClass: constants_1.MASK_TEXT_CLASS,
228
273
  blockClass: constants_1.BLOCK_CLASS,
229
- // rrweb only exposes array type through its types, but arrays are also be supported. #class, ['#class', 'id']
274
+ // rrweb only exposes string type through its types, but arrays are also be supported. #class, ['#class', 'id']
230
275
  blockSelector: this.getBlockSelectors(),
231
- maskInputFn: helpers_1.maskInputFn,
276
+ maskInputFn: (0, helpers_1.maskFn)('input', privacyConfig),
277
+ maskTextFn: (0, helpers_1.maskFn)('text', privacyConfig),
278
+ // rrweb only exposes string type through its types, but arrays are also be supported. since rrweb uses .matches() which supports arrays.
279
+ maskTextSelector: this.getMaskTextSelectors(),
232
280
  recordCanvas: false,
233
281
  errorHandler: function (error) {
234
282
  var typedError = error;
@@ -1 +1 @@
1
- {"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAnalyticsConnector, getGlobalScope } from '@amplitude/analytics-client-common';\nimport { Logger, returnWrapper } from '@amplitude/analytics-core';\nimport { Logger as ILogger } from '@amplitude/analytics-types';\nimport { pack, record } from '@amplitude/rrweb';\nimport { createSessionReplayJoinedConfigGenerator } from './config/joined-config';\nimport { SessionReplayJoinedConfig, SessionReplayJoinedConfigGenerator } from './config/types';\nimport {\n BLOCK_CLASS,\n DEFAULT_SESSION_REPLAY_PROPERTY,\n MASK_TEXT_CLASS,\n SESSION_REPLAY_DEBUG_PROPERTY,\n} from './constants';\nimport { createEventsManager } from './events/events-manager';\nimport { generateHashCode, isSessionInSample, maskInputFn } from './helpers';\nimport { SessionIdentifiers } from './identifiers';\nimport {\n AmplitudeSessionReplay,\n SessionReplayEventsManager as AmplitudeSessionReplayEventsManager,\n SessionIdentifiers as ISessionIdentifiers,\n SessionReplayOptions,\n} from './typings/session-replay';\n\nexport class SessionReplay implements AmplitudeSessionReplay {\n name = '@amplitude/session-replay-browser';\n config: SessionReplayJoinedConfig | undefined;\n joinedConfigGenerator: SessionReplayJoinedConfigGenerator | undefined;\n identifiers: ISessionIdentifiers | undefined;\n eventsManager: AmplitudeSessionReplayEventsManager | undefined;\n loggerProvider: ILogger;\n recordCancelCallback: ReturnType<typeof record> | null = null;\n\n constructor() {\n this.loggerProvider = new Logger();\n }\n\n init(apiKey: string, options: SessionReplayOptions) {\n return returnWrapper(this._init(apiKey, options));\n }\n\n protected async _init(apiKey: string, options: SessionReplayOptions) {\n this.loggerProvider = options.loggerProvider || new Logger();\n this.identifiers = new SessionIdentifiers({ sessionId: options.sessionId, deviceId: options.deviceId });\n this.joinedConfigGenerator = await createSessionReplayJoinedConfigGenerator(apiKey, options);\n this.config = await this.joinedConfigGenerator.generateJoinedConfig(this.identifiers.sessionId);\n\n this.eventsManager = await createEventsManager({\n config: this.config,\n sessionId: this.identifiers.sessionId,\n });\n\n this.loggerProvider.log('Installing @amplitude/session-replay-browser.');\n\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.removeEventListener('blur', this.blurListener);\n globalScope.removeEventListener('focus', this.focusListener);\n globalScope.addEventListener('blur', this.blurListener);\n globalScope.addEventListener('focus', this.focusListener);\n }\n\n if (globalScope && globalScope.document && globalScope.document.hasFocus()) {\n this.initialize(true);\n }\n }\n\n setSessionId(sessionId: number, deviceId?: string) {\n return returnWrapper(this.asyncSetSessionId(sessionId, deviceId));\n }\n\n async asyncSetSessionId(sessionId: number, deviceId?: string) {\n const previousSessionId = this.identifiers && this.identifiers.sessionId;\n if (previousSessionId) {\n this.stopRecordingAndSendEvents(previousSessionId);\n }\n\n const deviceIdForReplayId = deviceId || this.getDeviceId();\n this.identifiers = new SessionIdentifiers({\n sessionId: sessionId,\n deviceId: deviceIdForReplayId,\n });\n\n // If there is no previous session id, SDK is being initialized for the first time,\n // and config was just fetched in initialization, so no need to fetch it a second time\n if (this.joinedConfigGenerator && previousSessionId) {\n this.config = await this.joinedConfigGenerator.generateJoinedConfig(this.identifiers.sessionId);\n }\n this.recordEvents();\n }\n\n getSessionReplayDebugPropertyValue() {\n let apiKeyHash = '';\n if (this.config) {\n apiKeyHash = generateHashCode(this.config.apiKey).toString();\n }\n return JSON.stringify({\n appHash: apiKeyHash,\n });\n }\n\n getSessionReplayProperties() {\n if (!this.config || !this.identifiers) {\n this.loggerProvider.error('Session replay init has not been called, cannot get session recording properties.');\n return {};\n }\n\n // If the user is in debug mode, ignore the focus handler when tagging events.\n // this is a common mishap when someone is developing locally and not seeing events getting tagged.\n const ignoreFocus = !!this.config.debugMode;\n const shouldRecord = this.getShouldRecord(ignoreFocus);\n\n if (shouldRecord) {\n const eventProperties: { [key: string]: string | null } = {\n [DEFAULT_SESSION_REPLAY_PROPERTY]: this.identifiers.sessionReplayId ? this.identifiers.sessionReplayId : null,\n };\n if (this.config.debugMode) {\n eventProperties[SESSION_REPLAY_DEBUG_PROPERTY] = this.getSessionReplayDebugPropertyValue();\n }\n return eventProperties;\n }\n\n return {};\n }\n\n blurListener = () => {\n this.stopRecordingAndSendEvents();\n };\n\n focusListener = () => {\n this.initialize();\n };\n\n stopRecordingAndSendEvents(sessionId?: number) {\n this.stopRecordingEvents();\n\n const sessionIdToSend = sessionId || this.identifiers?.sessionId;\n const deviceId = this.getDeviceId();\n this.eventsManager &&\n sessionIdToSend &&\n deviceId &&\n this.eventsManager.sendCurrentSequenceEvents({ sessionId: sessionIdToSend, deviceId });\n }\n\n initialize(shouldSendStoredEvents = false) {\n if (!this.identifiers?.sessionId) {\n this.loggerProvider.log(`Session is not being recorded due to lack of session id.`);\n return;\n }\n\n const deviceId = this.getDeviceId();\n if (!deviceId) {\n this.loggerProvider.log(`Session is not being recorded due to lack of device id.`);\n return;\n }\n\n this.eventsManager &&\n shouldSendStoredEvents &&\n this.eventsManager.sendStoredEvents({\n deviceId,\n });\n\n this.recordEvents();\n }\n\n shouldOptOut() {\n let identityStoreOptOut: boolean | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreOptOut = identityStore.getIdentity().optOut;\n }\n\n return identityStoreOptOut !== undefined ? identityStoreOptOut : this.config?.optOut;\n }\n\n getShouldRecord(ignoreFocus = false) {\n if (!this.identifiers || !this.config || !this.identifiers.sessionId) {\n this.loggerProvider.error(`Session is not being recorded due to lack of config, please call sessionReplay.init.`);\n return false;\n }\n if (!this.config.captureEnabled) {\n this.loggerProvider.log(\n `Session ${this.identifiers.sessionId} not being captured due to capture being disabled for project.`,\n );\n return false;\n }\n\n const globalScope = getGlobalScope();\n if (!ignoreFocus && globalScope && globalScope.document && !globalScope.document.hasFocus()) {\n this.loggerProvider.log(\n `Session ${this.identifiers.sessionId} temporarily not recording due to lack of browser focus.`,\n );\n return false;\n }\n\n if (this.shouldOptOut()) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to optOut config.`);\n return false;\n }\n\n const isInSample = isSessionInSample(this.identifiers.sessionId, this.config.sampleRate);\n if (!isInSample) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to sample rate.`);\n }\n return isInSample;\n }\n\n getBlockSelectors(): string | string[] | undefined {\n return this.config?.privacyConfig?.blockSelector;\n }\n\n recordEvents() {\n const shouldRecord = this.getShouldRecord();\n const sessionId = this.identifiers?.sessionId;\n if (!shouldRecord || !sessionId) {\n return;\n }\n this.stopRecordingEvents();\n this.recordCancelCallback = record({\n emit: (event) => {\n const globalScope = getGlobalScope();\n if ((globalScope && globalScope.document && !globalScope.document.hasFocus()) || !this.getShouldRecord()) {\n this.stopRecordingAndSendEvents();\n return;\n }\n const eventString = JSON.stringify(event);\n const deviceId = this.getDeviceId();\n deviceId && this.eventsManager && this.eventsManager.addEvent({ event: eventString, sessionId, deviceId });\n },\n packFn: pack,\n maskAllInputs: true,\n maskTextClass: MASK_TEXT_CLASS,\n blockClass: BLOCK_CLASS,\n // rrweb only exposes array type through its types, but arrays are also be supported. #class, ['#class', 'id']\n blockSelector: this.getBlockSelectors() as string,\n maskInputFn,\n recordCanvas: false,\n errorHandler: (error) => {\n const typedError = error as Error;\n\n // styled-components relies on this error being thrown and bubbled up, rrweb is otherwise suppressing it\n if (typedError.message.includes('insertRule') && typedError.message.includes('CSSStyleSheet')) {\n throw typedError;\n }\n this.loggerProvider.warn('Error while recording: ', typedError.toString());\n // Return true so that we don't clutter user's consoles with internal rrweb errors\n return true;\n },\n });\n }\n\n stopRecordingEvents = () => {\n try {\n this.recordCancelCallback && this.recordCancelCallback();\n this.recordCancelCallback = null;\n } catch (error) {\n const typedError = error as Error;\n this.loggerProvider.warn(`Error occurred while stopping recording: ${typedError.toString()}`);\n }\n };\n\n getDeviceId() {\n let identityStoreDeviceId: string | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreDeviceId = identityStore.getIdentity().deviceId;\n }\n\n return identityStoreDeviceId || this.identifiers?.deviceId;\n }\n\n getSessionId() {\n return this.identifiers?.sessionId;\n }\n\n async flush(useRetry = false) {\n if (this.eventsManager) {\n return this.eventsManager.flush(useRetry);\n }\n }\n\n shutdown() {\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.removeEventListener('blur', this.blurListener);\n globalScope.removeEventListener('focus', this.focusListener);\n }\n\n this.stopRecordingAndSendEvents();\n }\n}\n"]}
1
+ {"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAnalyticsConnector, getGlobalScope } from '@amplitude/analytics-client-common';\nimport { Logger, returnWrapper } from '@amplitude/analytics-core';\nimport { Logger as ILogger } from '@amplitude/analytics-types';\nimport { pack, record } from '@amplitude/rrweb';\nimport { createSessionReplayJoinedConfigGenerator } from './config/joined-config';\nimport { SessionReplayJoinedConfig, SessionReplayJoinedConfigGenerator } from './config/types';\nimport {\n BLOCK_CLASS,\n DEFAULT_SESSION_REPLAY_PROPERTY,\n MASK_TEXT_CLASS,\n SESSION_REPLAY_DEBUG_PROPERTY,\n} from './constants';\nimport { createEventsManager } from './events/events-manager';\nimport { generateHashCode, isSessionInSample, maskFn } from './helpers';\nimport { SessionIdentifiers } from './identifiers';\nimport {\n AmplitudeSessionReplay,\n SessionReplayEventsManager as AmplitudeSessionReplayEventsManager,\n SessionIdentifiers as ISessionIdentifiers,\n SessionReplayOptions,\n} from './typings/session-replay';\n\nexport class SessionReplay implements AmplitudeSessionReplay {\n name = '@amplitude/session-replay-browser';\n config: SessionReplayJoinedConfig | undefined;\n joinedConfigGenerator: SessionReplayJoinedConfigGenerator | undefined;\n identifiers: ISessionIdentifiers | undefined;\n eventsManager: AmplitudeSessionReplayEventsManager | undefined;\n loggerProvider: ILogger;\n recordCancelCallback: ReturnType<typeof record> | null = null;\n\n constructor() {\n this.loggerProvider = new Logger();\n }\n\n init(apiKey: string, options: SessionReplayOptions) {\n return returnWrapper(this._init(apiKey, options));\n }\n\n removeInvalidSelectors() {\n if (!this.config?.privacyConfig) {\n return;\n }\n\n // This allows us to not search the DOM.\n const fragment = document.createDocumentFragment();\n\n const dropInvalidSelectors = (selectors: string[] | string = []): string[] | undefined => {\n if (typeof selectors === 'string') {\n selectors = [selectors];\n }\n selectors = selectors.filter((selector: string) => {\n try {\n fragment.querySelector(selector);\n } catch {\n console.warn(`[session-replay-browser] omitting selector \"${selector}\" because it is invalid`);\n return false;\n }\n return true;\n });\n if (selectors.length === 0) {\n return undefined;\n }\n return selectors;\n };\n this.config.privacyConfig.blockSelector = dropInvalidSelectors(this.config.privacyConfig.blockSelector);\n this.config.privacyConfig.maskSelector = dropInvalidSelectors(this.config.privacyConfig.maskSelector);\n this.config.privacyConfig.unmaskSelector = dropInvalidSelectors(this.config.privacyConfig.unmaskSelector);\n }\n\n protected async _init(apiKey: string, options: SessionReplayOptions) {\n this.loggerProvider = options.loggerProvider || new Logger();\n this.identifiers = new SessionIdentifiers({ sessionId: options.sessionId, deviceId: options.deviceId });\n this.joinedConfigGenerator = await createSessionReplayJoinedConfigGenerator(apiKey, options);\n this.config = await this.joinedConfigGenerator.generateJoinedConfig(this.identifiers.sessionId);\n\n this.loggerProvider.debug(\n JSON.stringify({ name: 'joined privacy config', privacyConfig: this.config.privacyConfig }, null, 2),\n );\n\n this.removeInvalidSelectors();\n\n this.eventsManager = await createEventsManager({\n config: this.config,\n sessionId: this.identifiers.sessionId,\n });\n\n this.loggerProvider.log('Installing @amplitude/session-replay-browser.');\n\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.removeEventListener('blur', this.blurListener);\n globalScope.removeEventListener('focus', this.focusListener);\n globalScope.addEventListener('blur', this.blurListener);\n globalScope.addEventListener('focus', this.focusListener);\n }\n\n if (globalScope && globalScope.document && globalScope.document.hasFocus()) {\n this.initialize(true);\n }\n }\n\n setSessionId(sessionId: number, deviceId?: string) {\n return returnWrapper(this.asyncSetSessionId(sessionId, deviceId));\n }\n\n async asyncSetSessionId(sessionId: number, deviceId?: string) {\n const previousSessionId = this.identifiers && this.identifiers.sessionId;\n if (previousSessionId) {\n this.stopRecordingAndSendEvents(previousSessionId);\n }\n\n const deviceIdForReplayId = deviceId || this.getDeviceId();\n this.identifiers = new SessionIdentifiers({\n sessionId: sessionId,\n deviceId: deviceIdForReplayId,\n });\n\n // If there is no previous session id, SDK is being initialized for the first time,\n // and config was just fetched in initialization, so no need to fetch it a second time\n if (this.joinedConfigGenerator && previousSessionId) {\n this.config = await this.joinedConfigGenerator.generateJoinedConfig(this.identifiers.sessionId);\n }\n this.recordEvents();\n }\n\n getSessionReplayDebugPropertyValue() {\n let apiKeyHash = '';\n if (this.config) {\n apiKeyHash = generateHashCode(this.config.apiKey).toString();\n }\n return JSON.stringify({\n appHash: apiKeyHash,\n });\n }\n\n getSessionReplayProperties() {\n if (!this.config || !this.identifiers) {\n this.loggerProvider.error('Session replay init has not been called, cannot get session recording properties.');\n return {};\n }\n\n // If the user is in debug mode, ignore the focus handler when tagging events.\n // this is a common mishap when someone is developing locally and not seeing events getting tagged.\n const ignoreFocus = !!this.config.debugMode;\n const shouldRecord = this.getShouldRecord(ignoreFocus);\n\n if (shouldRecord) {\n const eventProperties: { [key: string]: string | null } = {\n [DEFAULT_SESSION_REPLAY_PROPERTY]: this.identifiers.sessionReplayId ? this.identifiers.sessionReplayId : null,\n };\n if (this.config.debugMode) {\n eventProperties[SESSION_REPLAY_DEBUG_PROPERTY] = this.getSessionReplayDebugPropertyValue();\n }\n return eventProperties;\n }\n\n return {};\n }\n\n blurListener = () => {\n this.stopRecordingAndSendEvents();\n };\n\n focusListener = () => {\n this.initialize();\n };\n\n stopRecordingAndSendEvents(sessionId?: number) {\n this.stopRecordingEvents();\n\n const sessionIdToSend = sessionId || this.identifiers?.sessionId;\n const deviceId = this.getDeviceId();\n this.eventsManager &&\n sessionIdToSend &&\n deviceId &&\n this.eventsManager.sendCurrentSequenceEvents({ sessionId: sessionIdToSend, deviceId });\n }\n\n initialize(shouldSendStoredEvents = false) {\n if (!this.identifiers?.sessionId) {\n this.loggerProvider.log(`Session is not being recorded due to lack of session id.`);\n return;\n }\n\n const deviceId = this.getDeviceId();\n if (!deviceId) {\n this.loggerProvider.log(`Session is not being recorded due to lack of device id.`);\n return;\n }\n\n this.eventsManager &&\n shouldSendStoredEvents &&\n this.eventsManager.sendStoredEvents({\n deviceId,\n });\n\n this.recordEvents();\n }\n\n shouldOptOut() {\n let identityStoreOptOut: boolean | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreOptOut = identityStore.getIdentity().optOut;\n }\n\n return identityStoreOptOut !== undefined ? identityStoreOptOut : this.config?.optOut;\n }\n\n getShouldRecord(ignoreFocus = false) {\n if (!this.identifiers || !this.config || !this.identifiers.sessionId) {\n this.loggerProvider.error(`Session is not being recorded due to lack of config, please call sessionReplay.init.`);\n return false;\n }\n if (!this.config.captureEnabled) {\n this.loggerProvider.log(\n `Session ${this.identifiers.sessionId} not being captured due to capture being disabled for project.`,\n );\n return false;\n }\n\n const globalScope = getGlobalScope();\n if (!ignoreFocus && globalScope && globalScope.document && !globalScope.document.hasFocus()) {\n this.loggerProvider.log(\n `Session ${this.identifiers.sessionId} temporarily not recording due to lack of browser focus.`,\n );\n return false;\n }\n\n if (this.shouldOptOut()) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to optOut config.`);\n return false;\n }\n\n const isInSample = isSessionInSample(this.identifiers.sessionId, this.config.sampleRate);\n if (!isInSample) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to sample rate.`);\n }\n return isInSample;\n }\n\n getBlockSelectors(): string | string[] | undefined {\n return this.config?.privacyConfig?.blockSelector;\n }\n\n getMaskTextSelectors(): string | undefined {\n if (this.config?.privacyConfig?.defaultMaskLevel === 'conservative') {\n return '*';\n }\n\n const maskSelector = this.config?.privacyConfig?.maskSelector;\n if (!maskSelector) {\n return;\n }\n\n return maskSelector as unknown as string;\n }\n\n recordEvents() {\n const shouldRecord = this.getShouldRecord();\n const sessionId = this.identifiers?.sessionId;\n if (!shouldRecord || !sessionId || !this.config) {\n return;\n }\n this.stopRecordingEvents();\n const privacyConfig = this.config.privacyConfig;\n this.recordCancelCallback = record({\n emit: (event) => {\n const globalScope = getGlobalScope();\n if ((globalScope && globalScope.document && !globalScope.document.hasFocus()) || !this.getShouldRecord()) {\n this.stopRecordingAndSendEvents();\n return;\n }\n const eventString = JSON.stringify(event);\n const deviceId = this.getDeviceId();\n deviceId && this.eventsManager && this.eventsManager.addEvent({ event: eventString, sessionId, deviceId });\n },\n packFn: pack,\n maskAllInputs: true,\n maskTextClass: MASK_TEXT_CLASS,\n blockClass: BLOCK_CLASS,\n // rrweb only exposes string type through its types, but arrays are also be supported. #class, ['#class', 'id']\n blockSelector: this.getBlockSelectors() as string,\n maskInputFn: maskFn('input', privacyConfig),\n maskTextFn: maskFn('text', privacyConfig),\n // rrweb only exposes string type through its types, but arrays are also be supported. since rrweb uses .matches() which supports arrays.\n maskTextSelector: this.getMaskTextSelectors(),\n recordCanvas: false,\n errorHandler: (error) => {\n const typedError = error as Error;\n\n // styled-components relies on this error being thrown and bubbled up, rrweb is otherwise suppressing it\n if (typedError.message.includes('insertRule') && typedError.message.includes('CSSStyleSheet')) {\n throw typedError;\n }\n this.loggerProvider.warn('Error while recording: ', typedError.toString());\n // Return true so that we don't clutter user's consoles with internal rrweb errors\n return true;\n },\n });\n }\n\n stopRecordingEvents = () => {\n try {\n this.recordCancelCallback && this.recordCancelCallback();\n this.recordCancelCallback = null;\n } catch (error) {\n const typedError = error as Error;\n this.loggerProvider.warn(`Error occurred while stopping recording: ${typedError.toString()}`);\n }\n };\n\n getDeviceId() {\n let identityStoreDeviceId: string | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreDeviceId = identityStore.getIdentity().deviceId;\n }\n\n return identityStoreDeviceId || this.identifiers?.deviceId;\n }\n\n getSessionId() {\n return this.identifiers?.sessionId;\n }\n\n async flush(useRetry = false) {\n if (this.eventsManager) {\n return this.eventsManager.flush(useRetry);\n }\n }\n\n shutdown() {\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.removeEventListener('blur', this.blurListener);\n globalScope.removeEventListener('focus', this.focusListener);\n }\n\n this.stopRecordingAndSendEvents();\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,oCAAoC,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,yBAAyB,EAEzB,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB,qBAAa,kCAAkC;IAC7C,WAAW,EAAE,yBAAyB,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,CAAC,yBAAyB,CAAC,GAAG,SAAS,CAAC;gBAEhE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAInD,UAAU;IAOV,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;CA+EnF;AAED,eAAO,MAAM,wCAAwC,WAAkB,MAAM,WAAW,oBAAoB,gDAI3G,CAAC"}
1
+ {"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,oCAAoC,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EAErD,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB,qBAAa,kCAAkC;IAC7C,WAAW,EAAE,yBAAyB,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,CAAC,yBAAyB,CAAC,GAAG,SAAS,CAAC;gBAEhE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAInD,UAAU;IAOV,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;CA+HnF;AAED,eAAO,MAAM,wCAAwC,WAAkB,MAAM,WAAW,oBAAoB,gDAI3G,CAAC"}