@spotify-confidence/session-recording 0.18.9 → 0.18.11
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/CHANGELOG.md +19 -0
- package/dist/index.cjs +78 -3
- package/dist/index.js +78 -3
- package/package.json +3 -3
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.18.11](https://github.com/spotify/confidence-sdk-js/compare/session-recording-v0.18.10...session-recording-v0.18.11) (2026-08-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Dependencies
|
|
7
|
+
|
|
8
|
+
* The following workspace dependencies were updated
|
|
9
|
+
* dependencies
|
|
10
|
+
* @spotify-confidence/csr-common bumped to 0.18.8
|
|
11
|
+
* @spotify-confidence/csr-recorder bumped to 0.17.16
|
|
12
|
+
|
|
13
|
+
## [0.18.10](https://github.com/spotify/confidence-sdk-js/compare/session-recording-v0.18.9...session-recording-v0.18.10) (2026-08-20)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Dependencies
|
|
17
|
+
|
|
18
|
+
* The following workspace dependencies were updated
|
|
19
|
+
* dependencies
|
|
20
|
+
* @spotify-confidence/csr-recorder bumped to 0.17.15
|
|
21
|
+
|
|
3
22
|
## [0.18.9](https://github.com/spotify/confidence-sdk-js/compare/session-recording-v0.18.8...session-recording-v0.18.9) (2026-08-20)
|
|
4
23
|
|
|
5
24
|
|
package/dist/index.cjs
CHANGED
|
@@ -21,7 +21,7 @@ function validateMeasureValue(value) {
|
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region ../csr-recorder/src/types.ts
|
|
23
23
|
const DEFAULT_MASK_SELECTORS = ["[data-csr-mask]"];
|
|
24
|
-
const DEFAULT_BLOCK_SELECTORS = ["[data-csr-block]"];
|
|
24
|
+
const DEFAULT_BLOCK_SELECTORS = ["[data-csr-block]", "video"];
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region ../csr-recorder/src/route-parameterizer.ts
|
|
27
27
|
const SEGMENT_PATTERNS = [
|
|
@@ -83,6 +83,7 @@ var Recorder = class Recorder {
|
|
|
83
83
|
onEvent;
|
|
84
84
|
state = "idle";
|
|
85
85
|
visibilityHandler = null;
|
|
86
|
+
pageShowHandler = null;
|
|
86
87
|
originalFetch = null;
|
|
87
88
|
originalXhrOpen = null;
|
|
88
89
|
originalXhrSend = null;
|
|
@@ -128,6 +129,12 @@ var Recorder = class Recorder {
|
|
|
128
129
|
};
|
|
129
130
|
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
130
131
|
}
|
|
132
|
+
if (typeof window !== "undefined") {
|
|
133
|
+
this.pageShowHandler = (event) => {
|
|
134
|
+
if (event.persisted) this.engine.takeFullSnapshot();
|
|
135
|
+
};
|
|
136
|
+
window.addEventListener("pageshow", this.pageShowHandler);
|
|
137
|
+
}
|
|
131
138
|
if (config?.captureNetworkRequests) this.patchNetwork();
|
|
132
139
|
if (config?.captureRouteChanges !== false) this.patchRouting();
|
|
133
140
|
}
|
|
@@ -314,6 +321,10 @@ var Recorder = class Recorder {
|
|
|
314
321
|
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
315
322
|
this.visibilityHandler = null;
|
|
316
323
|
}
|
|
324
|
+
if (this.pageShowHandler) {
|
|
325
|
+
window.removeEventListener("pageshow", this.pageShowHandler);
|
|
326
|
+
this.pageShowHandler = null;
|
|
327
|
+
}
|
|
317
328
|
this.restoreNetwork();
|
|
318
329
|
this.restoreRouting();
|
|
319
330
|
this.engine.stop();
|
|
@@ -11127,6 +11138,63 @@ const ALL_CONSOLE_LEVELS = [
|
|
|
11127
11138
|
"debug",
|
|
11128
11139
|
"info"
|
|
11129
11140
|
];
|
|
11141
|
+
const BLOCKED_ELEMENT_ATTRIBUTE = "data-csr-blocked-element";
|
|
11142
|
+
function labelBlockedElement(node) {
|
|
11143
|
+
if (node.type === 2 && node.tagName !== void 0 && node.attributes !== void 0 && typeof node.attributes.rr_width === "string" && typeof node.attributes.rr_height === "string") {
|
|
11144
|
+
node.attributes[BLOCKED_ELEMENT_ATTRIBUTE] = node.tagName;
|
|
11145
|
+
node.tagName = "div";
|
|
11146
|
+
}
|
|
11147
|
+
node.childNodes?.forEach(labelBlockedElement);
|
|
11148
|
+
}
|
|
11149
|
+
/**
|
|
11150
|
+
* rrweb strips blocked elements down to their dimensions, but retains their
|
|
11151
|
+
* original tag name. Rebuild them as inert divs and keep the tag name as safe
|
|
11152
|
+
* metadata so players can render a useful placeholder label.
|
|
11153
|
+
*/
|
|
11154
|
+
function blockedElementLabelsPlugin() {
|
|
11155
|
+
return {
|
|
11156
|
+
name: "csr/blocked-element-labels@1",
|
|
11157
|
+
options: {},
|
|
11158
|
+
observer: () => () => {},
|
|
11159
|
+
eventProcessor: (event) => {
|
|
11160
|
+
if (event.type === EventType.FullSnapshot) labelBlockedElement(event.data.node);
|
|
11161
|
+
else if (event.type === EventType.IncrementalSnapshot && event.data.source === IncrementalSource.Mutation) event.data.adds.forEach((add) => labelBlockedElement(add.node));
|
|
11162
|
+
return event;
|
|
11163
|
+
}
|
|
11164
|
+
};
|
|
11165
|
+
}
|
|
11166
|
+
/**
|
|
11167
|
+
* Record clipboard actions and their DOM target without reading clipboard
|
|
11168
|
+
* contents. The resulting rrweb Plugin events can explain otherwise
|
|
11169
|
+
* surprising input changes during analysis.
|
|
11170
|
+
*/
|
|
11171
|
+
function clipboardActionsPlugin() {
|
|
11172
|
+
let getId;
|
|
11173
|
+
return {
|
|
11174
|
+
name: "csr/clipboard@1",
|
|
11175
|
+
options: {},
|
|
11176
|
+
getMirror: ({ nodeMirror }) => {
|
|
11177
|
+
getId = (node) => nodeMirror.getId(node);
|
|
11178
|
+
},
|
|
11179
|
+
observer: (callback, win) => {
|
|
11180
|
+
const handlers = [
|
|
11181
|
+
"copy",
|
|
11182
|
+
"cut",
|
|
11183
|
+
"paste"
|
|
11184
|
+
].map((action) => {
|
|
11185
|
+
const handler = (event) => {
|
|
11186
|
+
callback({
|
|
11187
|
+
action,
|
|
11188
|
+
targetId: event.target instanceof win.Node ? getId?.(event.target) ?? -1 : -1
|
|
11189
|
+
});
|
|
11190
|
+
};
|
|
11191
|
+
win.document.addEventListener(action, handler, true);
|
|
11192
|
+
return () => win.document.removeEventListener(action, handler, true);
|
|
11193
|
+
});
|
|
11194
|
+
return () => handlers.forEach((remove) => remove());
|
|
11195
|
+
}
|
|
11196
|
+
};
|
|
11197
|
+
}
|
|
11130
11198
|
/**
|
|
11131
11199
|
* rrweb does not include modifier keys in mouse-interaction events. Capture
|
|
11132
11200
|
* the native click first, then add its safe, non-text metadata to the rrweb
|
|
@@ -11179,7 +11247,11 @@ var RrwebEngine = class {
|
|
|
11179
11247
|
start(config, onEvent) {
|
|
11180
11248
|
const maskSelectors = config.maskSelectors ?? DEFAULT_MASK_SELECTORS;
|
|
11181
11249
|
const blockSelectors = config.blockSelectors ?? DEFAULT_BLOCK_SELECTORS;
|
|
11182
|
-
const plugins = [
|
|
11250
|
+
const plugins = [
|
|
11251
|
+
clickModifiersPlugin(),
|
|
11252
|
+
clipboardActionsPlugin(),
|
|
11253
|
+
blockedElementLabelsPlugin()
|
|
11254
|
+
];
|
|
11183
11255
|
const { captureConsoleLogs } = config;
|
|
11184
11256
|
if (captureConsoleLogs) {
|
|
11185
11257
|
const levels = captureConsoleLogs === true ? ALL_CONSOLE_LEVELS : captureConsoleLogs.levels;
|
|
@@ -11201,6 +11273,9 @@ var RrwebEngine = class {
|
|
|
11201
11273
|
slimDOMOptions: "all"
|
|
11202
11274
|
}) ?? null;
|
|
11203
11275
|
}
|
|
11276
|
+
takeFullSnapshot() {
|
|
11277
|
+
takeFullSnapshot(true);
|
|
11278
|
+
}
|
|
11204
11279
|
stop() {
|
|
11205
11280
|
this.stopFn?.();
|
|
11206
11281
|
this.stopFn = null;
|
|
@@ -11251,7 +11326,7 @@ function observeFlags(onFlagWrite) {
|
|
|
11251
11326
|
}
|
|
11252
11327
|
//#endregion
|
|
11253
11328
|
//#region src/version.ts
|
|
11254
|
-
const SDK_VERSION = "0.18.
|
|
11329
|
+
const SDK_VERSION = "0.18.11";
|
|
11255
11330
|
//#endregion
|
|
11256
11331
|
//#region src/index.ts
|
|
11257
11332
|
const DEFAULT_API_URL = "https://recording.confidence.dev";
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ function validateMeasureValue(value) {
|
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region ../csr-recorder/src/types.ts
|
|
22
22
|
const DEFAULT_MASK_SELECTORS = ["[data-csr-mask]"];
|
|
23
|
-
const DEFAULT_BLOCK_SELECTORS = ["[data-csr-block]"];
|
|
23
|
+
const DEFAULT_BLOCK_SELECTORS = ["[data-csr-block]", "video"];
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region ../csr-recorder/src/route-parameterizer.ts
|
|
26
26
|
const SEGMENT_PATTERNS = [
|
|
@@ -82,6 +82,7 @@ var Recorder = class Recorder {
|
|
|
82
82
|
onEvent;
|
|
83
83
|
state = "idle";
|
|
84
84
|
visibilityHandler = null;
|
|
85
|
+
pageShowHandler = null;
|
|
85
86
|
originalFetch = null;
|
|
86
87
|
originalXhrOpen = null;
|
|
87
88
|
originalXhrSend = null;
|
|
@@ -127,6 +128,12 @@ var Recorder = class Recorder {
|
|
|
127
128
|
};
|
|
128
129
|
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
129
130
|
}
|
|
131
|
+
if (typeof window !== "undefined") {
|
|
132
|
+
this.pageShowHandler = (event) => {
|
|
133
|
+
if (event.persisted) this.engine.takeFullSnapshot();
|
|
134
|
+
};
|
|
135
|
+
window.addEventListener("pageshow", this.pageShowHandler);
|
|
136
|
+
}
|
|
130
137
|
if (config?.captureNetworkRequests) this.patchNetwork();
|
|
131
138
|
if (config?.captureRouteChanges !== false) this.patchRouting();
|
|
132
139
|
}
|
|
@@ -313,6 +320,10 @@ var Recorder = class Recorder {
|
|
|
313
320
|
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
314
321
|
this.visibilityHandler = null;
|
|
315
322
|
}
|
|
323
|
+
if (this.pageShowHandler) {
|
|
324
|
+
window.removeEventListener("pageshow", this.pageShowHandler);
|
|
325
|
+
this.pageShowHandler = null;
|
|
326
|
+
}
|
|
316
327
|
this.restoreNetwork();
|
|
317
328
|
this.restoreRouting();
|
|
318
329
|
this.engine.stop();
|
|
@@ -11108,6 +11119,63 @@ const ALL_CONSOLE_LEVELS = [
|
|
|
11108
11119
|
"debug",
|
|
11109
11120
|
"info"
|
|
11110
11121
|
];
|
|
11122
|
+
const BLOCKED_ELEMENT_ATTRIBUTE = "data-csr-blocked-element";
|
|
11123
|
+
function labelBlockedElement(node) {
|
|
11124
|
+
if (node.type === 2 && node.tagName !== void 0 && node.attributes !== void 0 && typeof node.attributes.rr_width === "string" && typeof node.attributes.rr_height === "string") {
|
|
11125
|
+
node.attributes[BLOCKED_ELEMENT_ATTRIBUTE] = node.tagName;
|
|
11126
|
+
node.tagName = "div";
|
|
11127
|
+
}
|
|
11128
|
+
node.childNodes?.forEach(labelBlockedElement);
|
|
11129
|
+
}
|
|
11130
|
+
/**
|
|
11131
|
+
* rrweb strips blocked elements down to their dimensions, but retains their
|
|
11132
|
+
* original tag name. Rebuild them as inert divs and keep the tag name as safe
|
|
11133
|
+
* metadata so players can render a useful placeholder label.
|
|
11134
|
+
*/
|
|
11135
|
+
function blockedElementLabelsPlugin() {
|
|
11136
|
+
return {
|
|
11137
|
+
name: "csr/blocked-element-labels@1",
|
|
11138
|
+
options: {},
|
|
11139
|
+
observer: () => () => {},
|
|
11140
|
+
eventProcessor: (event) => {
|
|
11141
|
+
if (event.type === EventType.FullSnapshot) labelBlockedElement(event.data.node);
|
|
11142
|
+
else if (event.type === EventType.IncrementalSnapshot && event.data.source === IncrementalSource.Mutation) event.data.adds.forEach((add) => labelBlockedElement(add.node));
|
|
11143
|
+
return event;
|
|
11144
|
+
}
|
|
11145
|
+
};
|
|
11146
|
+
}
|
|
11147
|
+
/**
|
|
11148
|
+
* Record clipboard actions and their DOM target without reading clipboard
|
|
11149
|
+
* contents. The resulting rrweb Plugin events can explain otherwise
|
|
11150
|
+
* surprising input changes during analysis.
|
|
11151
|
+
*/
|
|
11152
|
+
function clipboardActionsPlugin() {
|
|
11153
|
+
let getId;
|
|
11154
|
+
return {
|
|
11155
|
+
name: "csr/clipboard@1",
|
|
11156
|
+
options: {},
|
|
11157
|
+
getMirror: ({ nodeMirror }) => {
|
|
11158
|
+
getId = (node) => nodeMirror.getId(node);
|
|
11159
|
+
},
|
|
11160
|
+
observer: (callback, win) => {
|
|
11161
|
+
const handlers = [
|
|
11162
|
+
"copy",
|
|
11163
|
+
"cut",
|
|
11164
|
+
"paste"
|
|
11165
|
+
].map((action) => {
|
|
11166
|
+
const handler = (event) => {
|
|
11167
|
+
callback({
|
|
11168
|
+
action,
|
|
11169
|
+
targetId: event.target instanceof win.Node ? getId?.(event.target) ?? -1 : -1
|
|
11170
|
+
});
|
|
11171
|
+
};
|
|
11172
|
+
win.document.addEventListener(action, handler, true);
|
|
11173
|
+
return () => win.document.removeEventListener(action, handler, true);
|
|
11174
|
+
});
|
|
11175
|
+
return () => handlers.forEach((remove) => remove());
|
|
11176
|
+
}
|
|
11177
|
+
};
|
|
11178
|
+
}
|
|
11111
11179
|
/**
|
|
11112
11180
|
* rrweb does not include modifier keys in mouse-interaction events. Capture
|
|
11113
11181
|
* the native click first, then add its safe, non-text metadata to the rrweb
|
|
@@ -11160,7 +11228,11 @@ var RrwebEngine = class {
|
|
|
11160
11228
|
start(config, onEvent) {
|
|
11161
11229
|
const maskSelectors = config.maskSelectors ?? DEFAULT_MASK_SELECTORS;
|
|
11162
11230
|
const blockSelectors = config.blockSelectors ?? DEFAULT_BLOCK_SELECTORS;
|
|
11163
|
-
const plugins = [
|
|
11231
|
+
const plugins = [
|
|
11232
|
+
clickModifiersPlugin(),
|
|
11233
|
+
clipboardActionsPlugin(),
|
|
11234
|
+
blockedElementLabelsPlugin()
|
|
11235
|
+
];
|
|
11164
11236
|
const { captureConsoleLogs } = config;
|
|
11165
11237
|
if (captureConsoleLogs) {
|
|
11166
11238
|
const levels = captureConsoleLogs === true ? ALL_CONSOLE_LEVELS : captureConsoleLogs.levels;
|
|
@@ -11182,6 +11254,9 @@ var RrwebEngine = class {
|
|
|
11182
11254
|
slimDOMOptions: "all"
|
|
11183
11255
|
}) ?? null;
|
|
11184
11256
|
}
|
|
11257
|
+
takeFullSnapshot() {
|
|
11258
|
+
takeFullSnapshot(true);
|
|
11259
|
+
}
|
|
11185
11260
|
stop() {
|
|
11186
11261
|
this.stopFn?.();
|
|
11187
11262
|
this.stopFn = null;
|
|
@@ -11232,7 +11307,7 @@ function observeFlags(onFlagWrite) {
|
|
|
11232
11307
|
}
|
|
11233
11308
|
//#endregion
|
|
11234
11309
|
//#region src/version.ts
|
|
11235
|
-
const SDK_VERSION = "0.18.
|
|
11310
|
+
const SDK_VERSION = "0.18.11";
|
|
11236
11311
|
//#endregion
|
|
11237
11312
|
//#region src/index.ts
|
|
11238
11313
|
const DEFAULT_API_URL = "https://recording.confidence.dev";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spotify-confidence/session-recording",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "0.18.
|
|
4
|
+
"version": "0.18.11",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/spotify/confidence-sdk-js.git",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@spotify-confidence/csr-common": "0.18.
|
|
45
|
-
"@spotify-confidence/csr-recorder": "0.17.
|
|
44
|
+
"@spotify-confidence/csr-common": "0.18.8",
|
|
45
|
+
"@spotify-confidence/csr-recorder": "0.17.16"
|
|
46
46
|
},
|
|
47
47
|
"module": "./dist/index.js",
|
|
48
48
|
"exports": {
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = '0.18.
|
|
1
|
+
export const SDK_VERSION = '0.18.11';
|