@amplitude/session-replay-browser 1.24.1 → 1.25.1
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 +12 -0
- package/lib/cjs/hooks/click.d.ts +3 -1
- package/lib/cjs/hooks/click.d.ts.map +1 -1
- package/lib/cjs/hooks/click.js +4 -4
- package/lib/cjs/hooks/click.js.map +1 -1
- package/lib/cjs/hooks/scroll.d.ts +1 -1
- package/lib/cjs/hooks/scroll.d.ts.map +1 -1
- package/lib/cjs/hooks/scroll.js +7 -8
- package/lib/cjs/hooks/scroll.js.map +1 -1
- package/lib/cjs/observers/index.d.ts +2 -0
- package/lib/cjs/observers/index.d.ts.map +1 -0
- package/lib/cjs/observers/index.js +6 -0
- package/lib/cjs/observers/index.js.map +1 -0
- package/lib/cjs/session-replay.d.ts +5 -2
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +98 -38
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/utils/rrweb.d.ts +34 -0
- package/lib/cjs/utils/rrweb.d.ts.map +1 -0
- package/lib/cjs/utils/rrweb.js +49 -0
- package/lib/cjs/utils/rrweb.js.map +1 -0
- package/lib/cjs/version.d.ts +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/cjs/version.js.map +1 -1
- package/lib/esm/hooks/click.d.ts +3 -1
- package/lib/esm/hooks/click.d.ts.map +1 -1
- package/lib/esm/hooks/click.js +4 -4
- package/lib/esm/hooks/click.js.map +1 -1
- package/lib/esm/hooks/scroll.d.ts +1 -1
- package/lib/esm/hooks/scroll.d.ts.map +1 -1
- package/lib/esm/hooks/scroll.js +1 -2
- package/lib/esm/hooks/scroll.js.map +1 -1
- package/lib/esm/observers/index.d.ts +2 -0
- package/lib/esm/observers/index.d.ts.map +1 -0
- package/lib/esm/observers/index.js +3 -0
- package/lib/esm/observers/index.js.map +1 -0
- package/lib/esm/session-replay.d.ts +5 -2
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +98 -38
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/utils/rrweb.d.ts +34 -0
- package/lib/esm/utils/rrweb.d.ts.map +1 -0
- package/lib/esm/utils/rrweb.js +42 -0
- package/lib/esm/utils/rrweb.js.map +1 -0
- package/lib/esm/version.d.ts +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/esm/version.js.map +1 -1
- package/lib/scripts/observers-min.js +2 -0
- package/lib/scripts/observers-min.js.gz +0 -0
- package/lib/scripts/observers-min.js.map +1 -0
- package/lib/scripts/rrweb-record-min.js +2 -0
- package/lib/scripts/rrweb-record-min.js.gz +0 -0
- package/lib/scripts/rrweb-record-min.js.map +1 -0
- package/lib/scripts/session-replay-browser-esm.js +1 -1
- package/lib/scripts/session-replay-browser-esm.js.gz +0 -0
- package/lib/scripts/session-replay-browser-esm.js.map +1 -1
- package/lib/scripts/session-replay-browser-min.js +1 -1
- package/lib/scripts/session-replay-browser-min.js.gz +0 -0
- package/lib/scripts/session-replay-browser-min.js.map +1 -1
- package/lib/scripts/session-replay-min.js +2 -0
- package/lib/scripts/session-replay-min.js.gz +0 -0
- package/lib/scripts/session-replay-min.js.map +1 -0
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -95,6 +95,17 @@ sessionReplay.shutdown()
|
|
|
95
95
|
|`performanceConfig.timeout`|`number`|No|`undefined`|Optional timeout in milliseconds for the `requestIdleCallback` API. If specified, this value will be used to set a maximum time for the browser to wait before executing the deferred compression task, even if the browser is not idle.|
|
|
96
96
|
|`experimental.useWebWorker`|`boolean`|No|`false`|If the SDK should compress the replay events using a webworker.|
|
|
97
97
|
|
|
98
|
+
## Bundle Size Optimization
|
|
99
|
+
The Session Replay SDK uses dynamic imports to optimize bundle size and improve initial page load performance. Key modules are loaded on-demand rather than being included in the initial bundle:
|
|
100
|
+
|
|
101
|
+
- **`@amplitude/rrweb-record`**: The core recording functionality is dynamically imported when `sessionReplay.init()` is called and capture should begin. In cases where users are not sampled or have opted out, then the Session Replay SDK will not import these dependencies.
|
|
102
|
+
|
|
103
|
+
This approach ensures that:
|
|
104
|
+
- Your application's initial JavaScript bundle remains as small as possible.
|
|
105
|
+
- Only the necessary Session Replay dependencies are loaded.
|
|
106
|
+
|
|
107
|
+
The dynamic imports happen asynchronously and won't block your application's initialization. If the imports fail for any reason, the SDK will not initiate capture.
|
|
108
|
+
|
|
98
109
|
## Privacy
|
|
99
110
|
By default, the session replay will mask all inputs, meaning the text in inputs will appear in a session replay as asterisks: `***`. You may require more specific masking controls based on your use case, so we offer the following controls:
|
|
100
111
|
|
|
@@ -117,3 +128,4 @@ sessionReplay.init(AMPLITUDE_API_KEY, {
|
|
|
117
128
|
}
|
|
118
129
|
})
|
|
119
130
|
```
|
|
131
|
+
|
package/lib/cjs/hooks/click.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { mouseInteractionCallBack } from '@amplitude/rrweb-types';
|
|
1
|
+
import type { mouseInteractionCallBack } from '@amplitude/rrweb-types';
|
|
2
|
+
import { Mirror } from '../utils/rrweb';
|
|
2
3
|
import { SessionReplayEventsManager as AmplitudeSessionReplayEventsManager } from '../typings/session-replay';
|
|
3
4
|
import { PayloadBatcher } from 'src/track-destination';
|
|
4
5
|
import { ILogger } from '@amplitude/analytics-core';
|
|
@@ -20,6 +21,7 @@ type Options = {
|
|
|
20
21
|
sessionId: string | number;
|
|
21
22
|
deviceIdFn: () => string | undefined;
|
|
22
23
|
eventsManager: AmplitudeSessionReplayEventsManager<'interaction', string>;
|
|
24
|
+
mirror: Mirror;
|
|
23
25
|
ugcFilterRules: UGCFilterRule[];
|
|
24
26
|
};
|
|
25
27
|
export declare const clickNonBatcher: PayloadBatcher;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"click.d.ts","sourceRoot":"","sources":["../../../src/hooks/click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"click.d.ts","sourceRoot":"","sources":["../../../src/hooks/click.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,EAAmB,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,0BAA0B,IAAI,mCAAmC,EAAE,MAAM,2BAA2B,CAAC;AAC9G,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAkB,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAIjD,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAGF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,KAAK,OAAO,GAAG;IACb,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACrC,aAAa,EAAE,mCAAmC,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC,CAAC;AAIF,eAAO,MAAM,eAAe,EAAE,cAU7B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAyB1B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,wBAoD5D,CAAC"}
|
package/lib/cjs/hooks/click.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.clickHook = exports.clickBatcher = exports.clickNonBatcher = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
var rrweb_types_1 = require("@amplitude/rrweb-types");
|
|
6
|
-
var rrweb_1 = require("
|
|
6
|
+
var rrweb_1 = require("../utils/rrweb");
|
|
7
7
|
var finder_1 = require("../libs/finder");
|
|
8
8
|
var analytics_core_1 = require("@amplitude/analytics-core");
|
|
9
9
|
var helpers_1 = require("../helpers");
|
|
@@ -47,7 +47,7 @@ var clickBatcher = function (_a) {
|
|
|
47
47
|
};
|
|
48
48
|
exports.clickBatcher = clickBatcher;
|
|
49
49
|
var clickHook = function (logger, _a) {
|
|
50
|
-
var eventsManager = _a.eventsManager, sessionId = _a.sessionId, deviceIdFn = _a.deviceIdFn, ugcFilterRules = _a.ugcFilterRules;
|
|
50
|
+
var eventsManager = _a.eventsManager, sessionId = _a.sessionId, deviceIdFn = _a.deviceIdFn, mirror = _a.mirror, ugcFilterRules = _a.ugcFilterRules;
|
|
51
51
|
return function (e) {
|
|
52
52
|
if (e.type !== rrweb_types_1.MouseInteractions.Click) {
|
|
53
53
|
return;
|
|
@@ -65,7 +65,7 @@ var clickHook = function (logger, _a) {
|
|
|
65
65
|
if (x === undefined || y === undefined) {
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
|
-
var node =
|
|
68
|
+
var node = mirror.getNode(e.id);
|
|
69
69
|
var selector;
|
|
70
70
|
if (node) {
|
|
71
71
|
try {
|
|
@@ -75,7 +75,7 @@ var clickHook = function (logger, _a) {
|
|
|
75
75
|
logger.debug('error resolving selector from finder');
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
var _a = rrweb_1.
|
|
78
|
+
var _a = (0, rrweb_1.getWindowScroll)(globalScope), scrollX = _a.left, scrollY = _a.top;
|
|
79
79
|
var pageUrl = (0, helpers_1.getPageUrl)(location.href, ugcFilterRules);
|
|
80
80
|
var event = {
|
|
81
81
|
x: x + scrollX,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"click.js","sourceRoot":"","sources":["../../../src/hooks/click.ts"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"click.js","sourceRoot":"","sources":["../../../src/hooks/click.ts"],"names":[],"mappings":"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","sourcesContent":["import type { mouseInteractionCallBack } from '@amplitude/rrweb-types';\nimport { MouseInteractions } from '@amplitude/rrweb-types';\nimport { getWindowScroll, Mirror } from '../utils/rrweb';\nimport { SessionReplayEventsManager as AmplitudeSessionReplayEventsManager } from '../typings/session-replay';\nimport { PayloadBatcher } from 'src/track-destination';\nimport { finder } from '../libs/finder';\nimport { getGlobalScope, ILogger } from '@amplitude/analytics-core';\nimport { UGCFilterRule } from 'src/config/types';\nimport { getPageUrl } from '../helpers';\n\n// exported for testing\nexport type ClickEvent = {\n timestamp: number;\n x: number;\n y: number;\n viewportWidth: number;\n viewportHeight: number;\n pageUrl: string;\n selector?: string;\n type: 'click';\n};\n\n// exported for testing\nexport type ClickEventWithCount = ClickEvent & { count: number };\n\ntype Options = {\n sessionId: string | number;\n deviceIdFn: () => string | undefined;\n eventsManager: AmplitudeSessionReplayEventsManager<'interaction', string>;\n mirror: Mirror;\n ugcFilterRules: UGCFilterRule[];\n};\n\nconst HOUR_IN_MILLISECONDS = 3_600_000;\n\nexport const clickNonBatcher: PayloadBatcher = ({ version, events }) => {\n const clickEvents: ClickEvent[] = [];\n events.forEach((evt: string) => {\n const record = JSON.parse(evt) as Record<string, unknown>;\n record.count = 1;\n if (record.type === 'click') {\n clickEvents.push(record as ClickEvent);\n }\n });\n return { version, events: clickEvents };\n};\n\nexport const clickBatcher: PayloadBatcher = ({ version, events }) => {\n const clickEvents: ClickEvent[] = [];\n events.forEach((evt: string) => {\n const record = JSON.parse(evt) as Record<string, unknown>;\n if (record.type === 'click') {\n clickEvents.push(record as ClickEvent);\n }\n });\n\n const reduced = clickEvents.reduce<Record<string, ClickEventWithCount>>((prev, curr) => {\n const { x, y, selector, timestamp } = curr;\n\n // round down to nearest hour.\n const hour = timestamp - (timestamp % HOUR_IN_MILLISECONDS);\n\n const k = `${x}:${y}:${selector ?? ''}:${hour}`;\n if (!prev[k]) {\n prev[k] = { ...curr, timestamp: hour, count: 1 };\n } else {\n prev[k].count += 1;\n }\n return prev;\n }, {});\n\n return { version, events: Object.values(reduced) };\n};\n\nexport const clickHook: (logger: ILogger, options: Options) => mouseInteractionCallBack =\n (logger, { eventsManager, sessionId, deviceIdFn, mirror, ugcFilterRules }) =>\n (e) => {\n if (e.type !== MouseInteractions.Click) {\n return;\n }\n\n const globalScope = getGlobalScope();\n if (!globalScope) {\n return;\n }\n\n const { location, innerHeight, innerWidth } = globalScope;\n // it only makes sense to send events if a pageUrl exists\n if (!location) {\n return;\n }\n\n const { x, y } = e;\n if (x === undefined || y === undefined) {\n return;\n }\n\n const node = mirror.getNode(e.id);\n let selector;\n if (node) {\n try {\n selector = finder(node as Element);\n } catch (err) {\n logger.debug('error resolving selector from finder');\n }\n }\n\n const { left: scrollX, top: scrollY } = getWindowScroll(globalScope as unknown as Window);\n\n const pageUrl = getPageUrl(location.href, ugcFilterRules);\n\n const event: ClickEvent = {\n x: x + scrollX,\n y: y + scrollY,\n selector,\n\n viewportHeight: innerHeight,\n viewportWidth: innerWidth,\n pageUrl,\n timestamp: Date.now(),\n type: 'click',\n };\n const deviceId = deviceIdFn();\n if (deviceId) {\n eventsManager.addEvent({ sessionId, event: { type: 'interaction', data: JSON.stringify(event) }, deviceId });\n }\n };\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { scrollCallback, scrollPosition } from '@amplitude/rrweb-types';
|
|
1
|
+
import type { scrollCallback, scrollPosition } from '@amplitude/rrweb-types';
|
|
2
2
|
import { BeaconTransport } from '../beacon-transport';
|
|
3
3
|
import { SessionReplayJoinedConfig } from '../config/types';
|
|
4
4
|
import { SessionReplayDestinationSessionMetadata } from '../typings/session-replay';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../../src/hooks/scroll.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../../src/hooks/scroll.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,uCAAuC,EAAE,MAAM,2BAA2B,CAAC;AAGpF,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC;AAE5E;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAChE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0E;IAEjG,MAAM,CAAC,OAAO,CACZ,OAAO,EAAE,IAAI,CAAC,uCAAuC,EAAE,UAAU,CAAC,EAClE,MAAM,EAAE,yBAAyB,GAChC,aAAa;gBAKd,SAAS,EAAE,eAAe,CAAC,kBAAkB,CAAC,EAC9C,MAAM,EAAE,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;IAWjF,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,IAAW,cAAc,IAAI,MAAM,CAElC;IAED,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED,MAAM,CAAC,CAAC,EAAE,cAAc;IAuBxB,IAAI,EAAE,cAAc,CAElB;IAEF,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,MAAM,GAAG,SAAS,KAAK,CAAC,CAAC,EAAE,mBAAmB,GAAG,KAAK,KAAK,IAAI,CAsBtF;CACH"}
|
package/lib/cjs/hooks/scroll.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ScrollWatcher = void 0;
|
|
4
|
-
var rrweb_1 = require("
|
|
4
|
+
var rrweb_1 = require("../utils/rrweb");
|
|
5
5
|
var beacon_transport_1 = require("../beacon-transport");
|
|
6
6
|
var analytics_core_1 = require("@amplitude/analytics-core");
|
|
7
7
|
var helpers_1 = require("../helpers");
|
|
8
|
-
var getWindowHeight = rrweb_1.utils.getWindowHeight, getWindowWidth = rrweb_1.utils.getWindowWidth;
|
|
9
8
|
/**
|
|
10
9
|
* This is intended to watch and update max scroll activity when loaded for a particular page.
|
|
11
10
|
* A new instance should be created if the page URL changes, since by default it does not reset
|
|
@@ -33,8 +32,8 @@ var ScrollWatcher = /** @class */ (function () {
|
|
|
33
32
|
maxScrollY: _this._maxScrollY,
|
|
34
33
|
maxScrollWidth: _this._maxScrollWidth,
|
|
35
34
|
maxScrollHeight: _this._maxScrollHeight,
|
|
36
|
-
viewportHeight: getWindowHeight(),
|
|
37
|
-
viewportWidth: getWindowWidth(),
|
|
35
|
+
viewportHeight: (0, rrweb_1.getWindowHeight)(),
|
|
36
|
+
viewportWidth: (0, rrweb_1.getWindowWidth)(),
|
|
38
37
|
pageUrl: (0, helpers_1.getPageUrl)(globalScope.location.href, (_b = (_a = _this.config.interactionConfig) === null || _a === void 0 ? void 0 : _a.ugcFilterRules) !== null && _b !== void 0 ? _b : []),
|
|
39
38
|
timestamp: _this.timestamp,
|
|
40
39
|
type: 'scroll',
|
|
@@ -45,8 +44,8 @@ var ScrollWatcher = /** @class */ (function () {
|
|
|
45
44
|
}; };
|
|
46
45
|
this._maxScrollX = 0;
|
|
47
46
|
this._maxScrollY = 0;
|
|
48
|
-
this._maxScrollWidth = getWindowWidth();
|
|
49
|
-
this._maxScrollHeight = getWindowHeight();
|
|
47
|
+
this._maxScrollWidth = (0, rrweb_1.getWindowWidth)();
|
|
48
|
+
this._maxScrollHeight = (0, rrweb_1.getWindowHeight)();
|
|
50
49
|
this.config = config;
|
|
51
50
|
this.transport = transport;
|
|
52
51
|
}
|
|
@@ -84,7 +83,7 @@ var ScrollWatcher = /** @class */ (function () {
|
|
|
84
83
|
ScrollWatcher.prototype.update = function (e) {
|
|
85
84
|
var now = Date.now();
|
|
86
85
|
if (e.x > this._maxScrollX) {
|
|
87
|
-
var width = getWindowWidth();
|
|
86
|
+
var width = (0, rrweb_1.getWindowWidth)();
|
|
88
87
|
this._maxScrollX = e.x;
|
|
89
88
|
var maxScrollWidth = e.x + width;
|
|
90
89
|
if (maxScrollWidth > this._maxScrollWidth) {
|
|
@@ -93,7 +92,7 @@ var ScrollWatcher = /** @class */ (function () {
|
|
|
93
92
|
this.timestamp = now;
|
|
94
93
|
}
|
|
95
94
|
if (e.y > this._maxScrollY) {
|
|
96
|
-
var height = getWindowHeight();
|
|
95
|
+
var height = (0, rrweb_1.getWindowHeight)();
|
|
97
96
|
this._maxScrollY = e.y;
|
|
98
97
|
var maxScrollHeight = e.y + height;
|
|
99
98
|
if (maxScrollHeight > this._maxScrollHeight) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll.js","sourceRoot":"","sources":["../../../src/hooks/scroll.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"scroll.js","sourceRoot":"","sources":["../../../src/hooks/scroll.ts"],"names":[],"mappings":"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","sourcesContent":["import { getWindowHeight, getWindowWidth } from '../utils/rrweb';\nimport type { scrollCallback, scrollPosition } from '@amplitude/rrweb-types';\nimport { BeaconTransport } from '../beacon-transport';\nimport { getGlobalScope } from '@amplitude/analytics-core';\nimport { SessionReplayJoinedConfig } from '../config/types';\nimport { SessionReplayDestinationSessionMetadata } from '../typings/session-replay';\nimport { getPageUrl } from '../helpers';\n\nexport type ScrollEvent = {\n timestamp: number; // Timestamp the event occurred\n maxScrollX: number; // Max window scroll X on a page\n maxScrollY: number; // Max window scroll Y on a page\n maxScrollHeight: number; // Max window scroll Y + window height on a page\n maxScrollWidth: number; // Max window scroll X + window width on a page\n viewportWidth: number;\n viewportHeight: number;\n pageUrl: string;\n type: 'scroll';\n};\n\nexport type ScrollEventPayload = { version: number; events: ScrollEvent[] };\n\n/**\n * This is intended to watch and update max scroll activity when loaded for a particular page.\n * A new instance should be created if the page URL changes, since by default it does not reset\n * it's max scroll state. It is intended to send very few and very small events utilizing the\n * Beacon API.\n * @see {@link BeaconTransport} for more details on Beacon API usage.\n */\nexport class ScrollWatcher {\n private timestamp = Date.now();\n private _maxScrollX: number;\n private _maxScrollY: number;\n private _maxScrollWidth: number;\n private _maxScrollHeight: number;\n private readonly transport: BeaconTransport<ScrollEventPayload>;\n private readonly config: Pick<SessionReplayJoinedConfig, 'loggerProvider' | 'interactionConfig'>;\n\n static default(\n context: Omit<SessionReplayDestinationSessionMetadata, 'deviceId'>,\n config: SessionReplayJoinedConfig,\n ): ScrollWatcher {\n return new ScrollWatcher(new BeaconTransport<ScrollEventPayload>(context, config), config);\n }\n\n constructor(\n transport: BeaconTransport<ScrollEventPayload>,\n config: Pick<SessionReplayJoinedConfig, 'loggerProvider' | 'interactionConfig'>,\n ) {\n this._maxScrollX = 0;\n this._maxScrollY = 0;\n this._maxScrollWidth = getWindowWidth();\n this._maxScrollHeight = getWindowHeight();\n this.config = config;\n\n this.transport = transport;\n }\n\n public get maxScrollX(): number {\n return this._maxScrollX;\n }\n\n public get maxScrollY(): number {\n return this._maxScrollY;\n }\n\n public get maxScrollWidth(): number {\n return this._maxScrollWidth;\n }\n\n public get maxScrollHeight(): number {\n return this._maxScrollHeight;\n }\n\n update(e: scrollPosition) {\n const now = Date.now();\n if (e.x > this._maxScrollX) {\n const width = getWindowWidth();\n this._maxScrollX = e.x;\n const maxScrollWidth = e.x + width;\n if (maxScrollWidth > this._maxScrollWidth) {\n this._maxScrollWidth = maxScrollWidth;\n }\n this.timestamp = now;\n }\n\n if (e.y > this._maxScrollY) {\n const height = getWindowHeight();\n this._maxScrollY = e.y;\n const maxScrollHeight = e.y + height;\n if (maxScrollHeight > this._maxScrollHeight) {\n this._maxScrollHeight = maxScrollHeight;\n }\n this.timestamp = now;\n }\n }\n\n hook: scrollCallback = (e: scrollPosition) => {\n this.update(e);\n };\n\n send: (deviceIdFn: () => string | undefined) => (_: PageTransitionEvent | Event) => void = (deviceIdFn) => (_) => {\n const deviceId = deviceIdFn();\n const globalScope = getGlobalScope();\n if (globalScope && deviceId) {\n this.transport.send(deviceId, {\n version: 1,\n events: [\n {\n maxScrollX: this._maxScrollX,\n maxScrollY: this._maxScrollY,\n maxScrollWidth: this._maxScrollWidth,\n maxScrollHeight: this._maxScrollHeight,\n\n viewportHeight: getWindowHeight(),\n viewportWidth: getWindowWidth(),\n pageUrl: getPageUrl(globalScope.location.href, this.config.interactionConfig?.ugcFilterRules ?? []),\n timestamp: this.timestamp,\n type: 'scroll',\n },\n ],\n });\n }\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/observers/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/observers/index.ts"],"names":[],"mappings":";;;AAAA,2CAA2C;AAC3C,uDAA6B","sourcesContent":["// Re-export all observer types and classes\nexport * from '../observers';\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ILogger } from '@amplitude/analytics-core';
|
|
2
|
-
import { record } from '@amplitude/rrweb';
|
|
3
2
|
import { LoggingConfig, SessionReplayJoinedConfig, SessionReplayJoinedConfigGenerator } from './config/types';
|
|
4
3
|
import { CustomRRwebEvent } from './constants';
|
|
5
4
|
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
|
|
6
5
|
import { EventCompressor } from './events/event-compressor';
|
|
6
|
+
import type { RecordFunction } from './utils/rrweb';
|
|
7
7
|
type PageLeaveFn = (e: PageTransitionEvent | Event) => void;
|
|
8
8
|
export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
9
9
|
name: string;
|
|
@@ -12,13 +12,14 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
|
12
12
|
identifiers: ISessionIdentifiers | undefined;
|
|
13
13
|
eventsManager?: AmplitudeSessionReplayEventsManager<'replay' | 'interaction', string>;
|
|
14
14
|
loggerProvider: ILogger;
|
|
15
|
-
recordCancelCallback: ReturnType<
|
|
15
|
+
recordCancelCallback: ReturnType<RecordFunction> | null;
|
|
16
16
|
eventCount: number;
|
|
17
17
|
eventCompressor: EventCompressor | undefined;
|
|
18
18
|
pageLeaveFns: PageLeaveFn[];
|
|
19
19
|
private scrollHook?;
|
|
20
20
|
private networkObservers?;
|
|
21
21
|
private metadata;
|
|
22
|
+
private recordFunction;
|
|
22
23
|
constructor();
|
|
23
24
|
init(apiKey: string, options: SessionReplayOptions): import("@amplitude/analytics-core").AmplitudeReturn<void>;
|
|
24
25
|
private teardownEventListeners;
|
|
@@ -43,6 +44,7 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
|
43
44
|
getBlockSelectors(): string | string[] | undefined;
|
|
44
45
|
getMaskTextSelectors(): string | undefined;
|
|
45
46
|
getRecordingPlugins(loggingConfig: LoggingConfig | undefined): Promise<import("@amplitude/rrweb-types").RecordPlugin<unknown>[] | undefined>;
|
|
47
|
+
private getRecordFunction;
|
|
46
48
|
recordEvents(shouldLogMetadata?: boolean): Promise<void>;
|
|
47
49
|
addCustomRRWebEvent: (eventName: CustomRRwebEvent, eventData?: {
|
|
48
50
|
[key: string]: any;
|
|
@@ -54,6 +56,7 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
|
54
56
|
shutdown(): void;
|
|
55
57
|
private mapSDKType;
|
|
56
58
|
private setMetadata;
|
|
59
|
+
private initializeNetworkObservers;
|
|
57
60
|
}
|
|
58
61
|
export {};
|
|
59
62
|
//# sourceMappingURL=session-replay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,OAAO,EAER,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,OAAO,EAER,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,kCAAkC,EAInC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,gBAAgB,EAMjB,MAAM,aAAa,CAAC;AAOrB,OAAO,EACL,sBAAsB,EACtB,0BAA0B,IAAI,mCAAmC,EAIjE,kBAAkB,IAAI,mBAAmB,EACzC,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAK5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,KAAK,WAAW,GAAG,CAAC,CAAC,EAAE,mBAAmB,GAAG,KAAK,KAAK,IAAI,CAAC;AAE5D,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,CAAC,EAAE,mCAAmC,CAAC,QAAQ,GAAG,aAAa,EAAE,MAAM,CAAC,CAAC;IACtF,cAAc,EAAE,OAAO,CAAC;IACxB,oBAAoB,EAAE,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAQ;IAC/D,UAAU,SAAK;IACf,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAG7C,YAAY,EAAE,WAAW,EAAE,CAAM;IACjC,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAoC;IAGpD,OAAO,CAAC,cAAc,CAA+B;;IAMrD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAIlD,OAAO,CAAC,sBAAsB,CAmB5B;cAEc,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAwFnE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAIpD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAqBrE,0BAA0B;;;IAsC1B,YAAY,aAEV;IAEF,aAAa,aAIX;IAEF;;;;OAIG;IACH,OAAO,CAAC,iBAAiB,CAIvB;IAEF,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAShC,UAAU,CAAC,sBAAsB,UAAQ;IAgB/C,YAAY;IAUZ,eAAe;IAwBf,iBAAiB,IAAI,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAWlD,oBAAoB,IAAI,MAAM,GAAG,SAAS;IAapC,mBAAmB,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS;YA2BpD,iBAAiB;IAezB,YAAY,CAAC,iBAAiB,UAAO;IAwG3C,mBAAmB,cACN,gBAAgB;;kDAmC3B;IAEF,mBAAmB,aAUjB;IAEF,WAAW;IAIX,YAAY;IAIN,KAAK,CAAC,QAAQ,UAAQ;IAI5B,QAAQ;IAMR,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,WAAW;YAyBL,0BAA0B;CAUzC"}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SessionReplay = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
var analytics_core_1 = require("@amplitude/analytics-core");
|
|
6
|
-
|
|
6
|
+
// Import only specific types to avoid pulling in the entire rrweb-types package
|
|
7
7
|
var rrweb_types_1 = require("@amplitude/rrweb-types");
|
|
8
8
|
var joined_config_1 = require("./config/joined-config");
|
|
9
9
|
var constants_1 = require("./constants");
|
|
@@ -16,15 +16,16 @@ var identifiers_1 = require("./identifiers");
|
|
|
16
16
|
var version_1 = require("./version");
|
|
17
17
|
var event_compressor_1 = require("./events/event-compressor");
|
|
18
18
|
var logger_1 = require("./logger");
|
|
19
|
-
var observers_1 = require("./observers");
|
|
20
19
|
var SessionReplay = /** @class */ (function () {
|
|
21
20
|
function SessionReplay() {
|
|
22
21
|
var _this = this;
|
|
23
22
|
this.name = '@amplitude/session-replay-browser';
|
|
24
23
|
this.recordCancelCallback = null;
|
|
25
24
|
this.eventCount = 0;
|
|
26
|
-
// Visible for testing
|
|
25
|
+
// Visible for testing only
|
|
27
26
|
this.pageLeaveFns = [];
|
|
27
|
+
// Cache the dynamically imported record function
|
|
28
|
+
this.recordFunction = null;
|
|
28
29
|
this.teardownEventListeners = function (teardown) {
|
|
29
30
|
var globalScope = (0, analytics_core_1.getGlobalScope)();
|
|
30
31
|
if (globalScope) {
|
|
@@ -88,8 +89,8 @@ var SessionReplay = /** @class */ (function () {
|
|
|
88
89
|
_a.label = 2;
|
|
89
90
|
case 2:
|
|
90
91
|
// Check first to ensure we are recording
|
|
91
|
-
if (this.recordCancelCallback) {
|
|
92
|
-
|
|
92
|
+
if (this.recordCancelCallback && this.recordFunction) {
|
|
93
|
+
this.recordFunction.addCustomEvent(eventName, tslib_1.__assign(tslib_1.__assign({}, eventData), debugInfo));
|
|
93
94
|
}
|
|
94
95
|
else {
|
|
95
96
|
this.loggerProvider.debug("Not able to add custom replay capture event ".concat(eventName, " due to no ongoing recording."));
|
|
@@ -123,23 +124,23 @@ var SessionReplay = /** @class */ (function () {
|
|
|
123
124
|
return (0, analytics_core_1.returnWrapper)(this._init(apiKey, options));
|
|
124
125
|
};
|
|
125
126
|
SessionReplay.prototype._init = function (apiKey, options) {
|
|
126
|
-
var _a, _b, _c, _d, _e, _f
|
|
127
|
+
var _a, _b, _c, _d, _e, _f;
|
|
127
128
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
128
|
-
var
|
|
129
|
-
return tslib_1.__generator(this, function (
|
|
130
|
-
switch (
|
|
129
|
+
var _g, _h, joinedConfig, localConfig, remoteConfig, scrollWatcher, managers, storeType, rrwebEventManager, error_1, typedError, payloadBatcher, interactionEventManager, error_2, typedError;
|
|
130
|
+
return tslib_1.__generator(this, function (_j) {
|
|
131
|
+
switch (_j.label) {
|
|
131
132
|
case 0:
|
|
132
133
|
this.loggerProvider = new logger_1.SafeLoggerProvider(options.loggerProvider || new analytics_core_1.Logger());
|
|
133
134
|
Object.prototype.hasOwnProperty.call(options, 'logLevel') &&
|
|
134
135
|
this.loggerProvider.enable(options.logLevel);
|
|
135
136
|
this.identifiers = new identifiers_1.SessionIdentifiers({ sessionId: options.sessionId, deviceId: options.deviceId });
|
|
136
|
-
|
|
137
|
+
_g = this;
|
|
137
138
|
return [4 /*yield*/, (0, joined_config_1.createSessionReplayJoinedConfigGenerator)(apiKey, options)];
|
|
138
139
|
case 1:
|
|
139
|
-
|
|
140
|
+
_g.joinedConfigGenerator = _j.sent();
|
|
140
141
|
return [4 /*yield*/, this.joinedConfigGenerator.generateJoinedConfig(this.identifiers.sessionId)];
|
|
141
142
|
case 2:
|
|
142
|
-
|
|
143
|
+
_h = _j.sent(), joinedConfig = _h.joinedConfig, localConfig = _h.localConfig, remoteConfig = _h.remoteConfig;
|
|
143
144
|
this.config = joinedConfig;
|
|
144
145
|
this.setMetadata(options.sessionId, joinedConfig, localConfig, remoteConfig, (_a = options.version) === null || _a === void 0 ? void 0 : _a.version, version_1.VERSION, (_b = options.version) === null || _b === void 0 ? void 0 : _b.type);
|
|
145
146
|
if (options.sessionId && ((_c = this.config.interactionConfig) === null || _c === void 0 ? void 0 : _c.enabled)) {
|
|
@@ -157,9 +158,9 @@ var SessionReplay = /** @class */ (function () {
|
|
|
157
158
|
this.loggerProvider.warn('Could not use preferred indexedDB storage, reverting to in memory option.');
|
|
158
159
|
}
|
|
159
160
|
this.loggerProvider.log("Using ".concat(storeType, " for event storage."));
|
|
160
|
-
|
|
161
|
+
_j.label = 3;
|
|
161
162
|
case 3:
|
|
162
|
-
|
|
163
|
+
_j.trys.push([3, 5, , 6]);
|
|
163
164
|
return [4 /*yield*/, (0, events_manager_1.createEventsManager)({
|
|
164
165
|
config: this.config,
|
|
165
166
|
sessionId: this.identifiers.sessionId,
|
|
@@ -167,20 +168,20 @@ var SessionReplay = /** @class */ (function () {
|
|
|
167
168
|
storeType: storeType,
|
|
168
169
|
})];
|
|
169
170
|
case 4:
|
|
170
|
-
rrwebEventManager =
|
|
171
|
+
rrwebEventManager = _j.sent();
|
|
171
172
|
managers.push({ name: 'replay', manager: rrwebEventManager });
|
|
172
173
|
return [3 /*break*/, 6];
|
|
173
174
|
case 5:
|
|
174
|
-
error_1 =
|
|
175
|
+
error_1 = _j.sent();
|
|
175
176
|
typedError = error_1;
|
|
176
177
|
this.loggerProvider.warn("Error occurred while creating replay events manager: ".concat(typedError.toString()));
|
|
177
178
|
return [3 /*break*/, 6];
|
|
178
179
|
case 6:
|
|
179
180
|
if (!((_e = this.config.interactionConfig) === null || _e === void 0 ? void 0 : _e.enabled)) return [3 /*break*/, 10];
|
|
180
181
|
payloadBatcher = this.config.interactionConfig.batch ? click_1.clickBatcher : click_1.clickNonBatcher;
|
|
181
|
-
|
|
182
|
+
_j.label = 7;
|
|
182
183
|
case 7:
|
|
183
|
-
|
|
184
|
+
_j.trys.push([7, 9, , 10]);
|
|
184
185
|
return [4 /*yield*/, (0, events_manager_1.createEventsManager)({
|
|
185
186
|
config: this.config,
|
|
186
187
|
sessionId: this.identifiers.sessionId,
|
|
@@ -191,11 +192,11 @@ var SessionReplay = /** @class */ (function () {
|
|
|
191
192
|
storeType: storeType,
|
|
192
193
|
})];
|
|
193
194
|
case 8:
|
|
194
|
-
interactionEventManager =
|
|
195
|
+
interactionEventManager = _j.sent();
|
|
195
196
|
managers.push({ name: 'interaction', manager: interactionEventManager });
|
|
196
197
|
return [3 /*break*/, 10];
|
|
197
198
|
case 9:
|
|
198
|
-
error_2 =
|
|
199
|
+
error_2 = _j.sent();
|
|
199
200
|
typedError = error_2;
|
|
200
201
|
this.loggerProvider.warn("Error occurred while creating interaction events manager: ".concat(typedError.toString()));
|
|
201
202
|
return [3 /*break*/, 10];
|
|
@@ -206,10 +207,9 @@ var SessionReplay = /** @class */ (function () {
|
|
|
206
207
|
this.eventCompressor.terminate();
|
|
207
208
|
}
|
|
208
209
|
this.eventCompressor = new event_compressor_1.EventCompressor(this.eventsManager, this.config, this.getDeviceId());
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
210
|
+
return [4 /*yield*/, this.initializeNetworkObservers()];
|
|
211
|
+
case 11:
|
|
212
|
+
_j.sent();
|
|
213
213
|
this.loggerProvider.log('Installing @amplitude/session-replay-browser.');
|
|
214
214
|
this.teardownEventListeners(false);
|
|
215
215
|
void this.initialize(true);
|
|
@@ -384,11 +384,37 @@ var SessionReplay = /** @class */ (function () {
|
|
|
384
384
|
});
|
|
385
385
|
});
|
|
386
386
|
};
|
|
387
|
+
SessionReplay.prototype.getRecordFunction = function () {
|
|
388
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
389
|
+
var record, error_4;
|
|
390
|
+
return tslib_1.__generator(this, function (_a) {
|
|
391
|
+
switch (_a.label) {
|
|
392
|
+
case 0:
|
|
393
|
+
if (this.recordFunction) {
|
|
394
|
+
return [2 /*return*/, this.recordFunction];
|
|
395
|
+
}
|
|
396
|
+
_a.label = 1;
|
|
397
|
+
case 1:
|
|
398
|
+
_a.trys.push([1, 3, , 4]);
|
|
399
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('@amplitude/rrweb-record')); })];
|
|
400
|
+
case 2:
|
|
401
|
+
record = (_a.sent()).record;
|
|
402
|
+
this.recordFunction = record;
|
|
403
|
+
return [2 /*return*/, record];
|
|
404
|
+
case 3:
|
|
405
|
+
error_4 = _a.sent();
|
|
406
|
+
this.loggerProvider.warn('Failed to load rrweb-record module:', error_4);
|
|
407
|
+
return [2 /*return*/, null];
|
|
408
|
+
case 4: return [2 /*return*/];
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
};
|
|
387
413
|
SessionReplay.prototype.recordEvents = function (shouldLogMetadata) {
|
|
388
414
|
var _a, _b, _c;
|
|
389
415
|
if (shouldLogMetadata === void 0) { shouldLogMetadata = true; }
|
|
390
416
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
391
|
-
var config, shouldRecord, sessionId, privacyConfig, interactionConfig, loggingConfig, hooks, ugcFilterRules, _d, _e,
|
|
417
|
+
var config, shouldRecord, sessionId, recordFunction, privacyConfig, interactionConfig, loggingConfig, hooks, ugcFilterRules, _d, _e, error_5;
|
|
392
418
|
var _f;
|
|
393
419
|
var _this = this;
|
|
394
420
|
return tslib_1.__generator(this, function (_g) {
|
|
@@ -401,6 +427,16 @@ var SessionReplay = /** @class */ (function () {
|
|
|
401
427
|
return [2 /*return*/];
|
|
402
428
|
}
|
|
403
429
|
this.stopRecordingEvents();
|
|
430
|
+
return [4 /*yield*/, this.getRecordFunction()];
|
|
431
|
+
case 1:
|
|
432
|
+
recordFunction = _g.sent();
|
|
433
|
+
// May be undefined if cannot import rrweb-record
|
|
434
|
+
if (!recordFunction) {
|
|
435
|
+
return [2 /*return*/];
|
|
436
|
+
}
|
|
437
|
+
return [4 /*yield*/, this.initializeNetworkObservers()];
|
|
438
|
+
case 2:
|
|
439
|
+
_g.sent();
|
|
404
440
|
(_b = this.networkObservers) === null || _b === void 0 ? void 0 : _b.start(function (event) {
|
|
405
441
|
void _this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.FETCH_REQUEST, event);
|
|
406
442
|
});
|
|
@@ -412,6 +448,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
412
448
|
eventsManager: this.eventsManager,
|
|
413
449
|
sessionId: sessionId,
|
|
414
450
|
deviceIdFn: this.getDeviceId.bind(this),
|
|
451
|
+
mirror: recordFunction.mirror,
|
|
415
452
|
ugcFilterRules: (_c = interactionConfig.ugcFilterRules) !== null && _c !== void 0 ? _c : [],
|
|
416
453
|
}),
|
|
417
454
|
scroll: this.scrollHook,
|
|
@@ -419,11 +456,11 @@ var SessionReplay = /** @class */ (function () {
|
|
|
419
456
|
: {};
|
|
420
457
|
ugcFilterRules = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) && interactionConfig.ugcFilterRules ? interactionConfig.ugcFilterRules : [];
|
|
421
458
|
this.loggerProvider.log("Session Replay capture beginning for ".concat(sessionId, "."));
|
|
422
|
-
_g.label =
|
|
423
|
-
case
|
|
424
|
-
_g.trys.push([
|
|
459
|
+
_g.label = 3;
|
|
460
|
+
case 3:
|
|
461
|
+
_g.trys.push([3, 5, , 6]);
|
|
425
462
|
_d = this;
|
|
426
|
-
_e =
|
|
463
|
+
_e = recordFunction;
|
|
427
464
|
_f = {
|
|
428
465
|
emit: function (event) {
|
|
429
466
|
if (_this.shouldOptOut()) {
|
|
@@ -445,12 +482,10 @@ var SessionReplay = /** @class */ (function () {
|
|
|
445
482
|
maskAllInputs: true,
|
|
446
483
|
maskTextClass: constants_1.MASK_TEXT_CLASS,
|
|
447
484
|
blockClass: constants_1.BLOCK_CLASS,
|
|
448
|
-
// rrweb only exposes string type through its types, but arrays are also be supported. #class, ['#class', 'id']
|
|
449
485
|
blockSelector: this.getBlockSelectors(),
|
|
450
486
|
applyBackgroundColorToBlockedElements: config.applyBackgroundColorToBlockedElements,
|
|
451
487
|
maskInputFn: (0, helpers_1.maskFn)('input', privacyConfig),
|
|
452
488
|
maskTextFn: (0, helpers_1.maskFn)('text', privacyConfig),
|
|
453
|
-
// rrweb only exposes string type through its types, but arrays are also be supported. since rrweb uses .matches() which supports arrays.
|
|
454
489
|
maskTextSelector: this.getMaskTextSelectors(),
|
|
455
490
|
recordCanvas: false,
|
|
456
491
|
errorHandler: function (error) {
|
|
@@ -471,19 +506,19 @@ var SessionReplay = /** @class */ (function () {
|
|
|
471
506
|
}
|
|
472
507
|
};
|
|
473
508
|
return [4 /*yield*/, this.getRecordingPlugins(loggingConfig)];
|
|
474
|
-
case
|
|
509
|
+
case 4:
|
|
475
510
|
_d.recordCancelCallback = _e.apply(void 0, [(_f.plugins = _g.sent(),
|
|
476
511
|
_f)]);
|
|
477
512
|
void this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.DEBUG_INFO);
|
|
478
513
|
if (shouldLogMetadata) {
|
|
479
514
|
void this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.METADATA, this.metadata);
|
|
480
515
|
}
|
|
481
|
-
return [3 /*break*/,
|
|
482
|
-
case
|
|
483
|
-
|
|
484
|
-
this.loggerProvider.warn('Failed to initialize session replay:',
|
|
485
|
-
return [3 /*break*/,
|
|
486
|
-
case
|
|
516
|
+
return [3 /*break*/, 6];
|
|
517
|
+
case 5:
|
|
518
|
+
error_5 = _g.sent();
|
|
519
|
+
this.loggerProvider.warn('Failed to initialize session replay:', error_5);
|
|
520
|
+
return [3 /*break*/, 6];
|
|
521
|
+
case 6: return [2 /*return*/];
|
|
487
522
|
}
|
|
488
523
|
});
|
|
489
524
|
});
|
|
@@ -534,6 +569,31 @@ var SessionReplay = /** @class */ (function () {
|
|
|
534
569
|
standaloneSDKVersion: standaloneSDKVersion,
|
|
535
570
|
};
|
|
536
571
|
};
|
|
572
|
+
SessionReplay.prototype.initializeNetworkObservers = function () {
|
|
573
|
+
var _a, _b, _c;
|
|
574
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
575
|
+
var NetworkObserversClass, error_6;
|
|
576
|
+
return tslib_1.__generator(this, function (_d) {
|
|
577
|
+
switch (_d.label) {
|
|
578
|
+
case 0:
|
|
579
|
+
if (!(((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.loggingConfig) === null || _b === void 0 ? void 0 : _b.network) === null || _c === void 0 ? void 0 : _c.enabled) && !this.networkObservers)) return [3 /*break*/, 4];
|
|
580
|
+
_d.label = 1;
|
|
581
|
+
case 1:
|
|
582
|
+
_d.trys.push([1, 3, , 4]);
|
|
583
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('./observers')); })];
|
|
584
|
+
case 2:
|
|
585
|
+
NetworkObserversClass = (_d.sent()).NetworkObservers;
|
|
586
|
+
this.networkObservers = new NetworkObserversClass();
|
|
587
|
+
return [3 /*break*/, 4];
|
|
588
|
+
case 3:
|
|
589
|
+
error_6 = _d.sent();
|
|
590
|
+
this.loggerProvider.warn('Failed to import or instantiate NetworkObservers:', error_6);
|
|
591
|
+
return [3 /*break*/, 4];
|
|
592
|
+
case 4: return [2 /*return*/];
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
});
|
|
596
|
+
};
|
|
537
597
|
return SessionReplay;
|
|
538
598
|
}());
|
|
539
599
|
exports.SessionReplay = SessionReplay;
|