@amplitude/session-replay-browser 1.24.1 → 1.25.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 (63) hide show
  1. package/README.md +12 -0
  2. package/lib/cjs/hooks/click.d.ts +3 -1
  3. package/lib/cjs/hooks/click.d.ts.map +1 -1
  4. package/lib/cjs/hooks/click.js +4 -4
  5. package/lib/cjs/hooks/click.js.map +1 -1
  6. package/lib/cjs/hooks/scroll.d.ts +1 -1
  7. package/lib/cjs/hooks/scroll.d.ts.map +1 -1
  8. package/lib/cjs/hooks/scroll.js +7 -8
  9. package/lib/cjs/hooks/scroll.js.map +1 -1
  10. package/lib/cjs/observers/index.d.ts +2 -0
  11. package/lib/cjs/observers/index.d.ts.map +1 -0
  12. package/lib/cjs/observers/index.js +6 -0
  13. package/lib/cjs/observers/index.js.map +1 -0
  14. package/lib/cjs/session-replay.d.ts +5 -2
  15. package/lib/cjs/session-replay.d.ts.map +1 -1
  16. package/lib/cjs/session-replay.js +98 -38
  17. package/lib/cjs/session-replay.js.map +1 -1
  18. package/lib/cjs/utils/rrweb.d.ts +34 -0
  19. package/lib/cjs/utils/rrweb.d.ts.map +1 -0
  20. package/lib/cjs/utils/rrweb.js +49 -0
  21. package/lib/cjs/utils/rrweb.js.map +1 -0
  22. package/lib/cjs/version.d.ts +1 -1
  23. package/lib/cjs/version.js +1 -1
  24. package/lib/cjs/version.js.map +1 -1
  25. package/lib/esm/hooks/click.d.ts +3 -1
  26. package/lib/esm/hooks/click.d.ts.map +1 -1
  27. package/lib/esm/hooks/click.js +4 -4
  28. package/lib/esm/hooks/click.js.map +1 -1
  29. package/lib/esm/hooks/scroll.d.ts +1 -1
  30. package/lib/esm/hooks/scroll.d.ts.map +1 -1
  31. package/lib/esm/hooks/scroll.js +1 -2
  32. package/lib/esm/hooks/scroll.js.map +1 -1
  33. package/lib/esm/observers/index.d.ts +2 -0
  34. package/lib/esm/observers/index.d.ts.map +1 -0
  35. package/lib/esm/observers/index.js +3 -0
  36. package/lib/esm/observers/index.js.map +1 -0
  37. package/lib/esm/session-replay.d.ts +5 -2
  38. package/lib/esm/session-replay.d.ts.map +1 -1
  39. package/lib/esm/session-replay.js +98 -38
  40. package/lib/esm/session-replay.js.map +1 -1
  41. package/lib/esm/utils/rrweb.d.ts +34 -0
  42. package/lib/esm/utils/rrweb.d.ts.map +1 -0
  43. package/lib/esm/utils/rrweb.js +42 -0
  44. package/lib/esm/utils/rrweb.js.map +1 -0
  45. package/lib/esm/version.d.ts +1 -1
  46. package/lib/esm/version.js +1 -1
  47. package/lib/esm/version.js.map +1 -1
  48. package/lib/scripts/observers-min.js +2 -0
  49. package/lib/scripts/observers-min.js.gz +0 -0
  50. package/lib/scripts/observers-min.js.map +1 -0
  51. package/lib/scripts/rrweb-record-min.js +2 -0
  52. package/lib/scripts/rrweb-record-min.js.gz +0 -0
  53. package/lib/scripts/rrweb-record-min.js.map +1 -0
  54. package/lib/scripts/session-replay-browser-esm.js +1 -1
  55. package/lib/scripts/session-replay-browser-esm.js.gz +0 -0
  56. package/lib/scripts/session-replay-browser-esm.js.map +1 -1
  57. package/lib/scripts/session-replay-browser-min.js +1 -1
  58. package/lib/scripts/session-replay-browser-min.js.gz +0 -0
  59. package/lib/scripts/session-replay-browser-min.js.map +1 -1
  60. package/lib/scripts/session-replay-min.js +2 -0
  61. package/lib/scripts/session-replay-min.js.gz +0 -0
  62. package/lib/scripts/session-replay-min.js.map +1 -0
  63. package/package.json +5 -3
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
+
@@ -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,EAAqB,MAAM,wBAAwB,CAAC;AAErF,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,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"}
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"}
@@ -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("@amplitude/rrweb");
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 = rrweb_1.record.mirror.getNode(e.id);
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.utils.getWindowScroll(globalScope), scrollX = _a.left, scrollY = _a.top;
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":"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","sourcesContent":["import { mouseInteractionCallBack, MouseInteractions } from '@amplitude/rrweb-types';\nimport { record, utils } from '@amplitude/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 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, 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 = record.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 } = utils.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
+ {"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;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,uCAAuC,EAAE,MAAM,2BAA2B,CAAC;AAKpF,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"}
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"}
@@ -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("@amplitude/rrweb");
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":"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","sourcesContent":["import { utils } from '@amplitude/rrweb';\nimport { 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\nconst { getWindowHeight, getWindowWidth } = utils;\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"]}
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,2 @@
1
+ export * from '../observers';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var tslib_1 = require("tslib");
4
+ // Re-export all observer types and classes
5
+ tslib_1.__exportStar(require("../observers"), exports);
6
+ //# sourceMappingURL=index.js.map
@@ -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<typeof record> | null;
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;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,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;AAI5D,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,OAAO,MAAM,CAAC,GAAG,IAAI,CAAQ;IAC9D,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;;IAMpD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAIlD,OAAO,CAAC,sBAAsB,CAmB5B;cAEc,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IA2FnE,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;IA0B5D,YAAY,CAAC,iBAAiB,UAAO;IA+F3C,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;CAwBpB"}
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
- var rrweb_1 = require("@amplitude/rrweb");
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
- rrweb_1.record.addCustomEvent(eventName, tslib_1.__assign(tslib_1.__assign({}, eventData), debugInfo));
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, _g, _h;
127
+ var _a, _b, _c, _d, _e, _f;
127
128
  return tslib_1.__awaiter(this, void 0, void 0, function () {
128
- var _j, _k, joinedConfig, localConfig, remoteConfig, scrollWatcher, managers, storeType, rrwebEventManager, error_1, typedError, payloadBatcher, interactionEventManager, error_2, typedError;
129
- return tslib_1.__generator(this, function (_l) {
130
- switch (_l.label) {
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
- _j = this;
137
+ _g = this;
137
138
  return [4 /*yield*/, (0, joined_config_1.createSessionReplayJoinedConfigGenerator)(apiKey, options)];
138
139
  case 1:
139
- _j.joinedConfigGenerator = _l.sent();
140
+ _g.joinedConfigGenerator = _j.sent();
140
141
  return [4 /*yield*/, this.joinedConfigGenerator.generateJoinedConfig(this.identifiers.sessionId)];
141
142
  case 2:
142
- _k = _l.sent(), joinedConfig = _k.joinedConfig, localConfig = _k.localConfig, remoteConfig = _k.remoteConfig;
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
- _l.label = 3;
161
+ _j.label = 3;
161
162
  case 3:
162
- _l.trys.push([3, 5, , 6]);
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 = _l.sent();
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 = _l.sent();
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
- _l.label = 7;
182
+ _j.label = 7;
182
183
  case 7:
183
- _l.trys.push([7, 9, , 10]);
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 = _l.sent();
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 = _l.sent();
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
- // Initialize network observers if logging is enabled
210
- if ((_h = (_g = this.config.loggingConfig) === null || _g === void 0 ? void 0 : _g.network) === null || _h === void 0 ? void 0 : _h.enabled) {
211
- this.networkObservers = new observers_1.NetworkObservers();
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, error_4;
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 = 1;
423
- case 1:
424
- _g.trys.push([1, 3, , 4]);
459
+ _g.label = 3;
460
+ case 3:
461
+ _g.trys.push([3, 5, , 6]);
425
462
  _d = this;
426
- _e = rrweb_1.record;
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 2:
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*/, 4];
482
- case 3:
483
- error_4 = _g.sent();
484
- this.loggerProvider.warn('Failed to initialize session replay:', error_4);
485
- return [3 /*break*/, 4];
486
- case 4: return [2 /*return*/];
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;