@spotify-confidence/csr-common 0.18.8 → 0.18.10
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 +14 -0
- package/dist/index.cjs +13 -84
- package/dist/index.d.cts +80 -24
- package/dist/index.d.ts +80 -24
- package/dist/index.js +2 -80
- package/dist/session-activity-B8swR5Wg.cjs +241 -0
- package/dist/session-activity-tshS9Hua.js +170 -0
- package/dist/{types-CtBIVgp2.d.cts → types-C3mO_2YH.d.cts} +3 -1
- package/dist/{types-CtBIVgp2.d.ts → types-C3mO_2YH.d.ts} +3 -1
- package/dist/uploader/index.cjs +3 -1
- package/dist/uploader/index.d.cts +1 -1
- package/dist/uploader/index.d.ts +1 -1
- package/dist/uploader/index.js +3 -1
- package/package.json +1 -1
- package/src/events.ts +69 -22
- package/src/index.ts +8 -1
- package/src/metrics.ts +15 -0
- package/src/session-activity.test.ts +72 -0
- package/src/session-activity.ts +64 -0
- package/src/uploader/client-context.test.ts +27 -0
- package/src/uploader/client-context.ts +3 -1
- package/src/uploader/create-uploader.test.ts +72 -0
- package/src/uploader/create-uploader.ts +2 -0
- package/src/uploader/types.ts +2 -0
- package/src/url.ts +5 -0
package/dist/index.js
CHANGED
|
@@ -1,82 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Mirrors rrweb's serialized-node types but decoupled — we own the enum.
|
|
4
|
-
*/
|
|
5
|
-
let SerializedNodeType = /* @__PURE__ */ function(SerializedNodeType) {
|
|
6
|
-
SerializedNodeType[SerializedNodeType["Document"] = 0] = "Document";
|
|
7
|
-
SerializedNodeType[SerializedNodeType["DocumentType"] = 1] = "DocumentType";
|
|
8
|
-
SerializedNodeType[SerializedNodeType["Element"] = 2] = "Element";
|
|
9
|
-
SerializedNodeType[SerializedNodeType["Text"] = 3] = "Text";
|
|
10
|
-
SerializedNodeType[SerializedNodeType["CDATA"] = 4] = "CDATA";
|
|
11
|
-
SerializedNodeType[SerializedNodeType["Comment"] = 5] = "Comment";
|
|
12
|
-
return SerializedNodeType;
|
|
13
|
-
}({});
|
|
14
|
-
/**
|
|
15
|
-
* Mirrors rrweb event types but decoupled — we own the enum.
|
|
16
|
-
*/
|
|
17
|
-
let RecordingEventType = /* @__PURE__ */ function(RecordingEventType) {
|
|
18
|
-
RecordingEventType[RecordingEventType["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
19
|
-
RecordingEventType[RecordingEventType["Load"] = 1] = "Load";
|
|
20
|
-
RecordingEventType[RecordingEventType["FullSnapshot"] = 2] = "FullSnapshot";
|
|
21
|
-
RecordingEventType[RecordingEventType["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
|
|
22
|
-
RecordingEventType[RecordingEventType["Meta"] = 4] = "Meta";
|
|
23
|
-
RecordingEventType[RecordingEventType["Custom"] = 5] = "Custom";
|
|
24
|
-
RecordingEventType[RecordingEventType["Plugin"] = 6] = "Plugin";
|
|
25
|
-
return RecordingEventType;
|
|
26
|
-
}({});
|
|
27
|
-
/**
|
|
28
|
-
* Incremental snapshot sub-types.
|
|
29
|
-
*/
|
|
30
|
-
let IncrementalSource = /* @__PURE__ */ function(IncrementalSource) {
|
|
31
|
-
IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
|
|
32
|
-
IncrementalSource[IncrementalSource["MouseMove"] = 1] = "MouseMove";
|
|
33
|
-
IncrementalSource[IncrementalSource["MouseInteraction"] = 2] = "MouseInteraction";
|
|
34
|
-
IncrementalSource[IncrementalSource["Scroll"] = 3] = "Scroll";
|
|
35
|
-
IncrementalSource[IncrementalSource["ViewportResize"] = 4] = "ViewportResize";
|
|
36
|
-
IncrementalSource[IncrementalSource["Input"] = 5] = "Input";
|
|
37
|
-
IncrementalSource[IncrementalSource["TouchMove"] = 6] = "TouchMove";
|
|
38
|
-
IncrementalSource[IncrementalSource["MediaInteraction"] = 7] = "MediaInteraction";
|
|
39
|
-
IncrementalSource[IncrementalSource["StyleSheetRule"] = 8] = "StyleSheetRule";
|
|
40
|
-
IncrementalSource[IncrementalSource["CanvasMutation"] = 9] = "CanvasMutation";
|
|
41
|
-
IncrementalSource[IncrementalSource["Font"] = 10] = "Font";
|
|
42
|
-
IncrementalSource[IncrementalSource["Log"] = 11] = "Log";
|
|
43
|
-
IncrementalSource[IncrementalSource["Drag"] = 12] = "Drag";
|
|
44
|
-
IncrementalSource[IncrementalSource["StyleDeclaration"] = 13] = "StyleDeclaration";
|
|
45
|
-
IncrementalSource[IncrementalSource["Selection"] = 14] = "Selection";
|
|
46
|
-
IncrementalSource[IncrementalSource["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
|
|
47
|
-
return IncrementalSource;
|
|
48
|
-
}({});
|
|
49
|
-
/**
|
|
50
|
-
* From rrweb MouseInteractions.
|
|
51
|
-
*/
|
|
52
|
-
let MouseInteractions = /* @__PURE__ */ function(MouseInteractions) {
|
|
53
|
-
MouseInteractions[MouseInteractions["MouseUp"] = 0] = "MouseUp";
|
|
54
|
-
MouseInteractions[MouseInteractions["MouseDown"] = 1] = "MouseDown";
|
|
55
|
-
MouseInteractions[MouseInteractions["Click"] = 2] = "Click";
|
|
56
|
-
MouseInteractions[MouseInteractions["ContextMenu"] = 3] = "ContextMenu";
|
|
57
|
-
MouseInteractions[MouseInteractions["DblClick"] = 4] = "DblClick";
|
|
58
|
-
MouseInteractions[MouseInteractions["Focus"] = 5] = "Focus";
|
|
59
|
-
MouseInteractions[MouseInteractions["Blur"] = 6] = "Blur";
|
|
60
|
-
MouseInteractions[MouseInteractions["TouchStart"] = 7] = "TouchStart";
|
|
61
|
-
MouseInteractions[MouseInteractions["TouchMove_Departed"] = 8] = "TouchMove_Departed";
|
|
62
|
-
MouseInteractions[MouseInteractions["TouchEnd"] = 9] = "TouchEnd";
|
|
63
|
-
MouseInteractions[MouseInteractions["TouchCancel"] = 10] = "TouchCancel";
|
|
64
|
-
return MouseInteractions;
|
|
65
|
-
}({});
|
|
66
|
-
//#endregion
|
|
67
|
-
//#region src/url.ts
|
|
68
|
-
/**
|
|
69
|
-
* Extract only the pathname from a URL, stripping origin, query string, and
|
|
70
|
-
* hash. Used across recorder and analyzer to avoid capturing PII in route data.
|
|
71
|
-
*/
|
|
72
|
-
function stripUrl(url) {
|
|
73
|
-
try {
|
|
74
|
-
return new URL(url).pathname;
|
|
75
|
-
} catch (_e) {
|
|
76
|
-
return url;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
//#endregion
|
|
1
|
+
import { a as stripUrl, c as MouseInteractions, d as RecordingPluginName, f as SerializedNodeType, i as RecordingMetricKey, l as RecordingCustomEventTag, n as isUserInteractionEvent, o as stripUrlQueryAndHash, r as isUserInteractionMetric, s as IncrementalSource, t as isSessionActivityEvent, u as RecordingEventType } from "./session-activity-tshS9Hua.js";
|
|
80
2
|
//#region src/custom-event-limits.ts
|
|
81
3
|
const MAX_KEY_LENGTH = 128;
|
|
82
4
|
const MAX_TAG_VALUE_LENGTH = 256;
|
|
@@ -101,4 +23,4 @@ function validateMeasureValue(value) {
|
|
|
101
23
|
return null;
|
|
102
24
|
}
|
|
103
25
|
//#endregion
|
|
104
|
-
export { IncrementalSource, MAX_DISTINCT_KEYS, MAX_KEY_LENGTH, MAX_TAG_VALUE_LENGTH, MAX_VALUES_PER_KEY, MouseInteractions, RecordingEventType, SerializedNodeType, stripUrl, validateKey, validateMeasureValue, validateTagValue };
|
|
26
|
+
export { IncrementalSource, MAX_DISTINCT_KEYS, MAX_KEY_LENGTH, MAX_TAG_VALUE_LENGTH, MAX_VALUES_PER_KEY, MouseInteractions, RecordingCustomEventTag, RecordingEventType, RecordingMetricKey, RecordingPluginName, SerializedNodeType, isSessionActivityEvent, isUserInteractionEvent, isUserInteractionMetric, stripUrl, stripUrlQueryAndHash, validateKey, validateMeasureValue, validateTagValue };
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
//#region src/events.ts
|
|
2
|
+
/**
|
|
3
|
+
* Mirrors rrweb's serialized-node types but decoupled — we own the enum.
|
|
4
|
+
*/
|
|
5
|
+
let SerializedNodeType = /* @__PURE__ */ function(SerializedNodeType) {
|
|
6
|
+
SerializedNodeType[SerializedNodeType["Document"] = 0] = "Document";
|
|
7
|
+
SerializedNodeType[SerializedNodeType["DocumentType"] = 1] = "DocumentType";
|
|
8
|
+
SerializedNodeType[SerializedNodeType["Element"] = 2] = "Element";
|
|
9
|
+
SerializedNodeType[SerializedNodeType["Text"] = 3] = "Text";
|
|
10
|
+
SerializedNodeType[SerializedNodeType["CDATA"] = 4] = "CDATA";
|
|
11
|
+
SerializedNodeType[SerializedNodeType["Comment"] = 5] = "Comment";
|
|
12
|
+
return SerializedNodeType;
|
|
13
|
+
}({});
|
|
14
|
+
/**
|
|
15
|
+
* Mirrors rrweb event types but decoupled — we own the enum.
|
|
16
|
+
*/
|
|
17
|
+
let RecordingEventType = /* @__PURE__ */ function(RecordingEventType) {
|
|
18
|
+
RecordingEventType[RecordingEventType["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
19
|
+
RecordingEventType[RecordingEventType["Load"] = 1] = "Load";
|
|
20
|
+
RecordingEventType[RecordingEventType["FullSnapshot"] = 2] = "FullSnapshot";
|
|
21
|
+
RecordingEventType[RecordingEventType["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
|
|
22
|
+
RecordingEventType[RecordingEventType["Meta"] = 4] = "Meta";
|
|
23
|
+
RecordingEventType[RecordingEventType["Custom"] = 5] = "Custom";
|
|
24
|
+
RecordingEventType[RecordingEventType["Plugin"] = 6] = "Plugin";
|
|
25
|
+
return RecordingEventType;
|
|
26
|
+
}({});
|
|
27
|
+
const RecordingCustomEventTag = {
|
|
28
|
+
RageClick: "csr:rageClick",
|
|
29
|
+
FormFieldReEdit: "csr:formFieldReEdit",
|
|
30
|
+
ScrollBack: "csr:scrollBack",
|
|
31
|
+
Click: "csr:click",
|
|
32
|
+
Input: "csr:input",
|
|
33
|
+
DeadClick: "csr:deadClick",
|
|
34
|
+
TabUnfocus: "csr:tabUnfocus",
|
|
35
|
+
TabRefocus: "csr:tabRefocus",
|
|
36
|
+
RouteChange: "csr:routeChange",
|
|
37
|
+
ErrorMessage: "csr:errorMessage",
|
|
38
|
+
DialogOpened: "csr:dialogOpened",
|
|
39
|
+
IdleGap: "csr:idleGap",
|
|
40
|
+
AwayGap: "csr:awayGap"
|
|
41
|
+
};
|
|
42
|
+
const RecordingPluginName = {
|
|
43
|
+
BlockedElementLabels: "csr/blocked-element-labels@1",
|
|
44
|
+
Clipboard: "csr/clipboard@1",
|
|
45
|
+
ClickModifiers: "csr/click-modifiers@1",
|
|
46
|
+
TabVisibility: "csr:tabVisibility",
|
|
47
|
+
ConsoleLog: "rrweb/console@1",
|
|
48
|
+
NetworkRequest: "csr:networkRequest",
|
|
49
|
+
RouteChange: "csr:routeChange",
|
|
50
|
+
Tag: "csr:tag",
|
|
51
|
+
Measure: "csr:measure",
|
|
52
|
+
FlagEvaluation: "csr:flagEvaluation"
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Incremental snapshot sub-types.
|
|
56
|
+
*/
|
|
57
|
+
let IncrementalSource = /* @__PURE__ */ function(IncrementalSource) {
|
|
58
|
+
IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
|
|
59
|
+
IncrementalSource[IncrementalSource["MouseMove"] = 1] = "MouseMove";
|
|
60
|
+
IncrementalSource[IncrementalSource["MouseInteraction"] = 2] = "MouseInteraction";
|
|
61
|
+
IncrementalSource[IncrementalSource["Scroll"] = 3] = "Scroll";
|
|
62
|
+
IncrementalSource[IncrementalSource["ViewportResize"] = 4] = "ViewportResize";
|
|
63
|
+
IncrementalSource[IncrementalSource["Input"] = 5] = "Input";
|
|
64
|
+
IncrementalSource[IncrementalSource["TouchMove"] = 6] = "TouchMove";
|
|
65
|
+
IncrementalSource[IncrementalSource["MediaInteraction"] = 7] = "MediaInteraction";
|
|
66
|
+
IncrementalSource[IncrementalSource["StyleSheetRule"] = 8] = "StyleSheetRule";
|
|
67
|
+
IncrementalSource[IncrementalSource["CanvasMutation"] = 9] = "CanvasMutation";
|
|
68
|
+
IncrementalSource[IncrementalSource["Font"] = 10] = "Font";
|
|
69
|
+
IncrementalSource[IncrementalSource["Log"] = 11] = "Log";
|
|
70
|
+
IncrementalSource[IncrementalSource["Drag"] = 12] = "Drag";
|
|
71
|
+
IncrementalSource[IncrementalSource["StyleDeclaration"] = 13] = "StyleDeclaration";
|
|
72
|
+
IncrementalSource[IncrementalSource["Selection"] = 14] = "Selection";
|
|
73
|
+
IncrementalSource[IncrementalSource["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
|
|
74
|
+
return IncrementalSource;
|
|
75
|
+
}({});
|
|
76
|
+
/**
|
|
77
|
+
* From rrweb MouseInteractions.
|
|
78
|
+
*/
|
|
79
|
+
let MouseInteractions = /* @__PURE__ */ function(MouseInteractions) {
|
|
80
|
+
MouseInteractions[MouseInteractions["MouseUp"] = 0] = "MouseUp";
|
|
81
|
+
MouseInteractions[MouseInteractions["MouseDown"] = 1] = "MouseDown";
|
|
82
|
+
MouseInteractions[MouseInteractions["Click"] = 2] = "Click";
|
|
83
|
+
MouseInteractions[MouseInteractions["ContextMenu"] = 3] = "ContextMenu";
|
|
84
|
+
MouseInteractions[MouseInteractions["DblClick"] = 4] = "DblClick";
|
|
85
|
+
MouseInteractions[MouseInteractions["Focus"] = 5] = "Focus";
|
|
86
|
+
MouseInteractions[MouseInteractions["Blur"] = 6] = "Blur";
|
|
87
|
+
MouseInteractions[MouseInteractions["TouchStart"] = 7] = "TouchStart";
|
|
88
|
+
MouseInteractions[MouseInteractions["TouchMove_Departed"] = 8] = "TouchMove_Departed";
|
|
89
|
+
MouseInteractions[MouseInteractions["TouchEnd"] = 9] = "TouchEnd";
|
|
90
|
+
MouseInteractions[MouseInteractions["TouchCancel"] = 10] = "TouchCancel";
|
|
91
|
+
return MouseInteractions;
|
|
92
|
+
}({});
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/url.ts
|
|
95
|
+
/** Remove query strings and fragments, including from relative or malformed URLs. */
|
|
96
|
+
function stripUrlQueryAndHash(url) {
|
|
97
|
+
return url.split(/[?#]/, 1)[0];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extract only the pathname from a URL, stripping origin, query string, and
|
|
101
|
+
* hash. Used across recorder and analyzer to avoid capturing PII in route data.
|
|
102
|
+
*/
|
|
103
|
+
function stripUrl(url) {
|
|
104
|
+
try {
|
|
105
|
+
return new URL(url).pathname;
|
|
106
|
+
} catch (_e) {
|
|
107
|
+
return url;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/metrics.ts
|
|
112
|
+
const RecordingMetricKey = {
|
|
113
|
+
Click: "clicks",
|
|
114
|
+
Input: "inputs",
|
|
115
|
+
RageClick: "rageClicks",
|
|
116
|
+
DeadClick: "deadClicks",
|
|
117
|
+
ScrollBack: "scrollBacks",
|
|
118
|
+
TabUnfocus: "tabUnfocuses",
|
|
119
|
+
ErrorMessage: "errorMessages",
|
|
120
|
+
FailedNetworkRequest: "networkRequestsFailed",
|
|
121
|
+
NetworkRequest: "networkRequests",
|
|
122
|
+
ConsoleLog: "consoleLogs",
|
|
123
|
+
ConsoleWarning: "consoleWarnings",
|
|
124
|
+
ConsoleError: "consoleErrors",
|
|
125
|
+
RouteChange: "routeChanges"
|
|
126
|
+
};
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/session-activity.ts
|
|
129
|
+
const USER_INTERACTION_SOURCES = new Set([
|
|
130
|
+
1,
|
|
131
|
+
2,
|
|
132
|
+
3,
|
|
133
|
+
5,
|
|
134
|
+
6,
|
|
135
|
+
7,
|
|
136
|
+
12,
|
|
137
|
+
14
|
|
138
|
+
]);
|
|
139
|
+
const USER_INTERACTION_TAGS = new Set([
|
|
140
|
+
RecordingCustomEventTag.Click,
|
|
141
|
+
RecordingCustomEventTag.Input,
|
|
142
|
+
RecordingCustomEventTag.RageClick,
|
|
143
|
+
RecordingCustomEventTag.DeadClick,
|
|
144
|
+
RecordingCustomEventTag.ScrollBack,
|
|
145
|
+
RecordingCustomEventTag.TabUnfocus,
|
|
146
|
+
RecordingCustomEventTag.TabRefocus,
|
|
147
|
+
RecordingCustomEventTag.FormFieldReEdit,
|
|
148
|
+
RecordingCustomEventTag.RouteChange
|
|
149
|
+
]);
|
|
150
|
+
const USER_INTERACTION_PLUGINS = new Set([RecordingPluginName.RouteChange]);
|
|
151
|
+
const USER_INTERACTION_METRIC_KEYS = new Set([
|
|
152
|
+
RecordingMetricKey.Click,
|
|
153
|
+
RecordingMetricKey.Input,
|
|
154
|
+
RecordingMetricKey.RageClick,
|
|
155
|
+
RecordingMetricKey.DeadClick,
|
|
156
|
+
RecordingMetricKey.ScrollBack,
|
|
157
|
+
RecordingMetricKey.TabUnfocus,
|
|
158
|
+
RecordingMetricKey.RouteChange
|
|
159
|
+
]);
|
|
160
|
+
const isObject = (value) => typeof value === "object" && value !== null;
|
|
161
|
+
const isUserInteractionEvent = (event) => {
|
|
162
|
+
if (!isObject(event) || !isObject(event.data)) return false;
|
|
163
|
+
if (event.type === 3) return typeof event.data.source === "number" && USER_INTERACTION_SOURCES.has(event.data.source);
|
|
164
|
+
if (event.type === 5) return typeof event.data.tag === "string" && USER_INTERACTION_TAGS.has(event.data.tag);
|
|
165
|
+
return event.type === 6 && typeof event.data.plugin === "string" && USER_INTERACTION_PLUGINS.has(event.data.plugin);
|
|
166
|
+
};
|
|
167
|
+
const isUserInteractionMetric = (metricKey) => USER_INTERACTION_METRIC_KEYS.has(metricKey);
|
|
168
|
+
const isSessionActivityEvent = (event) => isObject(event) && event.type === 4 || isUserInteractionEvent(event);
|
|
169
|
+
//#endregion
|
|
170
|
+
Object.defineProperty(exports, "IncrementalSource", {
|
|
171
|
+
enumerable: true,
|
|
172
|
+
get: function() {
|
|
173
|
+
return IncrementalSource;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
Object.defineProperty(exports, "MouseInteractions", {
|
|
177
|
+
enumerable: true,
|
|
178
|
+
get: function() {
|
|
179
|
+
return MouseInteractions;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
Object.defineProperty(exports, "RecordingCustomEventTag", {
|
|
183
|
+
enumerable: true,
|
|
184
|
+
get: function() {
|
|
185
|
+
return RecordingCustomEventTag;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
Object.defineProperty(exports, "RecordingEventType", {
|
|
189
|
+
enumerable: true,
|
|
190
|
+
get: function() {
|
|
191
|
+
return RecordingEventType;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
Object.defineProperty(exports, "RecordingMetricKey", {
|
|
195
|
+
enumerable: true,
|
|
196
|
+
get: function() {
|
|
197
|
+
return RecordingMetricKey;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
Object.defineProperty(exports, "RecordingPluginName", {
|
|
201
|
+
enumerable: true,
|
|
202
|
+
get: function() {
|
|
203
|
+
return RecordingPluginName;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
Object.defineProperty(exports, "SerializedNodeType", {
|
|
207
|
+
enumerable: true,
|
|
208
|
+
get: function() {
|
|
209
|
+
return SerializedNodeType;
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
Object.defineProperty(exports, "isSessionActivityEvent", {
|
|
213
|
+
enumerable: true,
|
|
214
|
+
get: function() {
|
|
215
|
+
return isSessionActivityEvent;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
Object.defineProperty(exports, "isUserInteractionEvent", {
|
|
219
|
+
enumerable: true,
|
|
220
|
+
get: function() {
|
|
221
|
+
return isUserInteractionEvent;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
Object.defineProperty(exports, "isUserInteractionMetric", {
|
|
225
|
+
enumerable: true,
|
|
226
|
+
get: function() {
|
|
227
|
+
return isUserInteractionMetric;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
Object.defineProperty(exports, "stripUrl", {
|
|
231
|
+
enumerable: true,
|
|
232
|
+
get: function() {
|
|
233
|
+
return stripUrl;
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
Object.defineProperty(exports, "stripUrlQueryAndHash", {
|
|
237
|
+
enumerable: true,
|
|
238
|
+
get: function() {
|
|
239
|
+
return stripUrlQueryAndHash;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
//#region src/events.ts
|
|
2
|
+
/**
|
|
3
|
+
* Mirrors rrweb's serialized-node types but decoupled — we own the enum.
|
|
4
|
+
*/
|
|
5
|
+
let SerializedNodeType = /* @__PURE__ */ function(SerializedNodeType) {
|
|
6
|
+
SerializedNodeType[SerializedNodeType["Document"] = 0] = "Document";
|
|
7
|
+
SerializedNodeType[SerializedNodeType["DocumentType"] = 1] = "DocumentType";
|
|
8
|
+
SerializedNodeType[SerializedNodeType["Element"] = 2] = "Element";
|
|
9
|
+
SerializedNodeType[SerializedNodeType["Text"] = 3] = "Text";
|
|
10
|
+
SerializedNodeType[SerializedNodeType["CDATA"] = 4] = "CDATA";
|
|
11
|
+
SerializedNodeType[SerializedNodeType["Comment"] = 5] = "Comment";
|
|
12
|
+
return SerializedNodeType;
|
|
13
|
+
}({});
|
|
14
|
+
/**
|
|
15
|
+
* Mirrors rrweb event types but decoupled — we own the enum.
|
|
16
|
+
*/
|
|
17
|
+
let RecordingEventType = /* @__PURE__ */ function(RecordingEventType) {
|
|
18
|
+
RecordingEventType[RecordingEventType["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
19
|
+
RecordingEventType[RecordingEventType["Load"] = 1] = "Load";
|
|
20
|
+
RecordingEventType[RecordingEventType["FullSnapshot"] = 2] = "FullSnapshot";
|
|
21
|
+
RecordingEventType[RecordingEventType["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
|
|
22
|
+
RecordingEventType[RecordingEventType["Meta"] = 4] = "Meta";
|
|
23
|
+
RecordingEventType[RecordingEventType["Custom"] = 5] = "Custom";
|
|
24
|
+
RecordingEventType[RecordingEventType["Plugin"] = 6] = "Plugin";
|
|
25
|
+
return RecordingEventType;
|
|
26
|
+
}({});
|
|
27
|
+
const RecordingCustomEventTag = {
|
|
28
|
+
RageClick: "csr:rageClick",
|
|
29
|
+
FormFieldReEdit: "csr:formFieldReEdit",
|
|
30
|
+
ScrollBack: "csr:scrollBack",
|
|
31
|
+
Click: "csr:click",
|
|
32
|
+
Input: "csr:input",
|
|
33
|
+
DeadClick: "csr:deadClick",
|
|
34
|
+
TabUnfocus: "csr:tabUnfocus",
|
|
35
|
+
TabRefocus: "csr:tabRefocus",
|
|
36
|
+
RouteChange: "csr:routeChange",
|
|
37
|
+
ErrorMessage: "csr:errorMessage",
|
|
38
|
+
DialogOpened: "csr:dialogOpened",
|
|
39
|
+
IdleGap: "csr:idleGap",
|
|
40
|
+
AwayGap: "csr:awayGap"
|
|
41
|
+
};
|
|
42
|
+
const RecordingPluginName = {
|
|
43
|
+
BlockedElementLabels: "csr/blocked-element-labels@1",
|
|
44
|
+
Clipboard: "csr/clipboard@1",
|
|
45
|
+
ClickModifiers: "csr/click-modifiers@1",
|
|
46
|
+
TabVisibility: "csr:tabVisibility",
|
|
47
|
+
ConsoleLog: "rrweb/console@1",
|
|
48
|
+
NetworkRequest: "csr:networkRequest",
|
|
49
|
+
RouteChange: "csr:routeChange",
|
|
50
|
+
Tag: "csr:tag",
|
|
51
|
+
Measure: "csr:measure",
|
|
52
|
+
FlagEvaluation: "csr:flagEvaluation"
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Incremental snapshot sub-types.
|
|
56
|
+
*/
|
|
57
|
+
let IncrementalSource = /* @__PURE__ */ function(IncrementalSource) {
|
|
58
|
+
IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
|
|
59
|
+
IncrementalSource[IncrementalSource["MouseMove"] = 1] = "MouseMove";
|
|
60
|
+
IncrementalSource[IncrementalSource["MouseInteraction"] = 2] = "MouseInteraction";
|
|
61
|
+
IncrementalSource[IncrementalSource["Scroll"] = 3] = "Scroll";
|
|
62
|
+
IncrementalSource[IncrementalSource["ViewportResize"] = 4] = "ViewportResize";
|
|
63
|
+
IncrementalSource[IncrementalSource["Input"] = 5] = "Input";
|
|
64
|
+
IncrementalSource[IncrementalSource["TouchMove"] = 6] = "TouchMove";
|
|
65
|
+
IncrementalSource[IncrementalSource["MediaInteraction"] = 7] = "MediaInteraction";
|
|
66
|
+
IncrementalSource[IncrementalSource["StyleSheetRule"] = 8] = "StyleSheetRule";
|
|
67
|
+
IncrementalSource[IncrementalSource["CanvasMutation"] = 9] = "CanvasMutation";
|
|
68
|
+
IncrementalSource[IncrementalSource["Font"] = 10] = "Font";
|
|
69
|
+
IncrementalSource[IncrementalSource["Log"] = 11] = "Log";
|
|
70
|
+
IncrementalSource[IncrementalSource["Drag"] = 12] = "Drag";
|
|
71
|
+
IncrementalSource[IncrementalSource["StyleDeclaration"] = 13] = "StyleDeclaration";
|
|
72
|
+
IncrementalSource[IncrementalSource["Selection"] = 14] = "Selection";
|
|
73
|
+
IncrementalSource[IncrementalSource["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
|
|
74
|
+
return IncrementalSource;
|
|
75
|
+
}({});
|
|
76
|
+
/**
|
|
77
|
+
* From rrweb MouseInteractions.
|
|
78
|
+
*/
|
|
79
|
+
let MouseInteractions = /* @__PURE__ */ function(MouseInteractions) {
|
|
80
|
+
MouseInteractions[MouseInteractions["MouseUp"] = 0] = "MouseUp";
|
|
81
|
+
MouseInteractions[MouseInteractions["MouseDown"] = 1] = "MouseDown";
|
|
82
|
+
MouseInteractions[MouseInteractions["Click"] = 2] = "Click";
|
|
83
|
+
MouseInteractions[MouseInteractions["ContextMenu"] = 3] = "ContextMenu";
|
|
84
|
+
MouseInteractions[MouseInteractions["DblClick"] = 4] = "DblClick";
|
|
85
|
+
MouseInteractions[MouseInteractions["Focus"] = 5] = "Focus";
|
|
86
|
+
MouseInteractions[MouseInteractions["Blur"] = 6] = "Blur";
|
|
87
|
+
MouseInteractions[MouseInteractions["TouchStart"] = 7] = "TouchStart";
|
|
88
|
+
MouseInteractions[MouseInteractions["TouchMove_Departed"] = 8] = "TouchMove_Departed";
|
|
89
|
+
MouseInteractions[MouseInteractions["TouchEnd"] = 9] = "TouchEnd";
|
|
90
|
+
MouseInteractions[MouseInteractions["TouchCancel"] = 10] = "TouchCancel";
|
|
91
|
+
return MouseInteractions;
|
|
92
|
+
}({});
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/url.ts
|
|
95
|
+
/** Remove query strings and fragments, including from relative or malformed URLs. */
|
|
96
|
+
function stripUrlQueryAndHash(url) {
|
|
97
|
+
return url.split(/[?#]/, 1)[0];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extract only the pathname from a URL, stripping origin, query string, and
|
|
101
|
+
* hash. Used across recorder and analyzer to avoid capturing PII in route data.
|
|
102
|
+
*/
|
|
103
|
+
function stripUrl(url) {
|
|
104
|
+
try {
|
|
105
|
+
return new URL(url).pathname;
|
|
106
|
+
} catch (_e) {
|
|
107
|
+
return url;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/metrics.ts
|
|
112
|
+
const RecordingMetricKey = {
|
|
113
|
+
Click: "clicks",
|
|
114
|
+
Input: "inputs",
|
|
115
|
+
RageClick: "rageClicks",
|
|
116
|
+
DeadClick: "deadClicks",
|
|
117
|
+
ScrollBack: "scrollBacks",
|
|
118
|
+
TabUnfocus: "tabUnfocuses",
|
|
119
|
+
ErrorMessage: "errorMessages",
|
|
120
|
+
FailedNetworkRequest: "networkRequestsFailed",
|
|
121
|
+
NetworkRequest: "networkRequests",
|
|
122
|
+
ConsoleLog: "consoleLogs",
|
|
123
|
+
ConsoleWarning: "consoleWarnings",
|
|
124
|
+
ConsoleError: "consoleErrors",
|
|
125
|
+
RouteChange: "routeChanges"
|
|
126
|
+
};
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/session-activity.ts
|
|
129
|
+
const USER_INTERACTION_SOURCES = new Set([
|
|
130
|
+
1,
|
|
131
|
+
2,
|
|
132
|
+
3,
|
|
133
|
+
5,
|
|
134
|
+
6,
|
|
135
|
+
7,
|
|
136
|
+
12,
|
|
137
|
+
14
|
|
138
|
+
]);
|
|
139
|
+
const USER_INTERACTION_TAGS = new Set([
|
|
140
|
+
RecordingCustomEventTag.Click,
|
|
141
|
+
RecordingCustomEventTag.Input,
|
|
142
|
+
RecordingCustomEventTag.RageClick,
|
|
143
|
+
RecordingCustomEventTag.DeadClick,
|
|
144
|
+
RecordingCustomEventTag.ScrollBack,
|
|
145
|
+
RecordingCustomEventTag.TabUnfocus,
|
|
146
|
+
RecordingCustomEventTag.TabRefocus,
|
|
147
|
+
RecordingCustomEventTag.FormFieldReEdit,
|
|
148
|
+
RecordingCustomEventTag.RouteChange
|
|
149
|
+
]);
|
|
150
|
+
const USER_INTERACTION_PLUGINS = new Set([RecordingPluginName.RouteChange]);
|
|
151
|
+
const USER_INTERACTION_METRIC_KEYS = new Set([
|
|
152
|
+
RecordingMetricKey.Click,
|
|
153
|
+
RecordingMetricKey.Input,
|
|
154
|
+
RecordingMetricKey.RageClick,
|
|
155
|
+
RecordingMetricKey.DeadClick,
|
|
156
|
+
RecordingMetricKey.ScrollBack,
|
|
157
|
+
RecordingMetricKey.TabUnfocus,
|
|
158
|
+
RecordingMetricKey.RouteChange
|
|
159
|
+
]);
|
|
160
|
+
const isObject = (value) => typeof value === "object" && value !== null;
|
|
161
|
+
const isUserInteractionEvent = (event) => {
|
|
162
|
+
if (!isObject(event) || !isObject(event.data)) return false;
|
|
163
|
+
if (event.type === 3) return typeof event.data.source === "number" && USER_INTERACTION_SOURCES.has(event.data.source);
|
|
164
|
+
if (event.type === 5) return typeof event.data.tag === "string" && USER_INTERACTION_TAGS.has(event.data.tag);
|
|
165
|
+
return event.type === 6 && typeof event.data.plugin === "string" && USER_INTERACTION_PLUGINS.has(event.data.plugin);
|
|
166
|
+
};
|
|
167
|
+
const isUserInteractionMetric = (metricKey) => USER_INTERACTION_METRIC_KEYS.has(metricKey);
|
|
168
|
+
const isSessionActivityEvent = (event) => isObject(event) && event.type === 4 || isUserInteractionEvent(event);
|
|
169
|
+
//#endregion
|
|
170
|
+
export { stripUrl as a, MouseInteractions as c, RecordingPluginName as d, SerializedNodeType as f, RecordingMetricKey as i, RecordingCustomEventTag as l, isUserInteractionEvent as n, stripUrlQueryAndHash as o, isUserInteractionMetric as r, IncrementalSource as s, isSessionActivityEvent as t, RecordingEventType as u };
|
|
@@ -22,7 +22,7 @@ type UserAgentContext = {
|
|
|
22
22
|
screenWidth?: number;
|
|
23
23
|
screenHeight?: number;
|
|
24
24
|
devicePixelRatio?: number; /** Initial document URI — without query/hash to avoid leaking PII. */
|
|
25
|
-
uri?: string;
|
|
25
|
+
uri?: string; /** Document referrer — without query/hash to avoid leaking PII. */
|
|
26
26
|
referrer?: string;
|
|
27
27
|
};
|
|
28
28
|
interface ClientContext {
|
|
@@ -102,6 +102,8 @@ interface Frame {
|
|
|
102
102
|
eventCounter: number;
|
|
103
103
|
/** Opaque payload from the recorder. */
|
|
104
104
|
data: unknown;
|
|
105
|
+
/** Whether the frame should refresh the backend's session inactivity timeout. */
|
|
106
|
+
userActivity?: boolean;
|
|
105
107
|
/** Set only on the first frame emitted after the tab was adopted into a different session. */
|
|
106
108
|
adoptedFromSessionId?: string;
|
|
107
109
|
/** Epoch millis of the adoption event. */
|
|
@@ -22,7 +22,7 @@ type UserAgentContext = {
|
|
|
22
22
|
screenWidth?: number;
|
|
23
23
|
screenHeight?: number;
|
|
24
24
|
devicePixelRatio?: number; /** Initial document URI — without query/hash to avoid leaking PII. */
|
|
25
|
-
uri?: string;
|
|
25
|
+
uri?: string; /** Document referrer — without query/hash to avoid leaking PII. */
|
|
26
26
|
referrer?: string;
|
|
27
27
|
};
|
|
28
28
|
interface ClientContext {
|
|
@@ -102,6 +102,8 @@ interface Frame {
|
|
|
102
102
|
eventCounter: number;
|
|
103
103
|
/** Opaque payload from the recorder. */
|
|
104
104
|
data: unknown;
|
|
105
|
+
/** Whether the frame should refresh the backend's session inactivity timeout. */
|
|
106
|
+
userActivity?: boolean;
|
|
105
107
|
/** Set only on the first frame emitted after the tab was adopted into a different session. */
|
|
106
108
|
adoptedFromSessionId?: string;
|
|
107
109
|
/** Epoch millis of the adoption event. */
|
package/dist/uploader/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
+
const require_session_activity = require("../session-activity-B8swR5Wg.cjs");
|
|
24
25
|
let bowser = require("bowser");
|
|
25
26
|
bowser = __toESM(bowser, 1);
|
|
26
27
|
//#region src/uploader/client-context.ts
|
|
@@ -45,7 +46,7 @@ function collectUserAgentContext() {
|
|
|
45
46
|
screenHeight: window.screen.height,
|
|
46
47
|
devicePixelRatio: window.devicePixelRatio,
|
|
47
48
|
uri: `${window.location.origin}${window.location.pathname}`,
|
|
48
|
-
referrer: document.referrer
|
|
49
|
+
referrer: require_session_activity.stripUrlQueryAndHash(document.referrer)
|
|
49
50
|
};
|
|
50
51
|
}
|
|
51
52
|
//#endregion
|
|
@@ -184,6 +185,7 @@ async function createUploader(opts) {
|
|
|
184
185
|
tabId: effectiveTabId,
|
|
185
186
|
eventCounter: counter,
|
|
186
187
|
data: event,
|
|
188
|
+
userActivity: require_session_activity.isSessionActivityEvent(event),
|
|
187
189
|
...nextAdoptionMeta ?? {}
|
|
188
190
|
};
|
|
189
191
|
counter += 1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ContextValue, i as ClientContext, o as UserAgentContext, r as Uploader, s as collectUserAgentContext, t as CreateUploaderOptions } from "../types-
|
|
1
|
+
import { a as ContextValue, i as ClientContext, o as UserAgentContext, r as Uploader, s as collectUserAgentContext, t as CreateUploaderOptions } from "../types-C3mO_2YH.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/uploader/create-uploader.d.ts
|
|
4
4
|
declare function createUploader(opts: CreateUploaderOptions): Promise<Uploader | null>;
|
package/dist/uploader/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ContextValue, i as ClientContext, o as UserAgentContext, r as Uploader, s as collectUserAgentContext, t as CreateUploaderOptions } from "../types-
|
|
1
|
+
import { a as ContextValue, i as ClientContext, o as UserAgentContext, r as Uploader, s as collectUserAgentContext, t as CreateUploaderOptions } from "../types-C3mO_2YH.js";
|
|
2
2
|
|
|
3
3
|
//#region src/uploader/create-uploader.d.ts
|
|
4
4
|
declare function createUploader(opts: CreateUploaderOptions): Promise<Uploader | null>;
|
package/dist/uploader/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { o as stripUrlQueryAndHash, t as isSessionActivityEvent } from "../session-activity-tshS9Hua.js";
|
|
1
2
|
import Bowser from "bowser";
|
|
2
3
|
//#region src/uploader/client-context.ts
|
|
3
4
|
function collectUserAgentContext() {
|
|
@@ -21,7 +22,7 @@ function collectUserAgentContext() {
|
|
|
21
22
|
screenHeight: window.screen.height,
|
|
22
23
|
devicePixelRatio: window.devicePixelRatio,
|
|
23
24
|
uri: `${window.location.origin}${window.location.pathname}`,
|
|
24
|
-
referrer: document.referrer
|
|
25
|
+
referrer: stripUrlQueryAndHash(document.referrer)
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
//#endregion
|
|
@@ -160,6 +161,7 @@ async function createUploader(opts) {
|
|
|
160
161
|
tabId: effectiveTabId,
|
|
161
162
|
eventCounter: counter,
|
|
162
163
|
data: event,
|
|
164
|
+
userActivity: isSessionActivityEvent(event),
|
|
163
165
|
...nextAdoptionMeta ?? {}
|
|
164
166
|
};
|
|
165
167
|
counter += 1;
|