@amplitude/session-replay-browser 1.2.1 → 1.2.3
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/lib/cjs/config.d.ts +0 -3
- package/lib/cjs/config.d.ts.map +1 -1
- package/lib/cjs/config.js +0 -9
- package/lib/cjs/config.js.map +1 -1
- package/lib/cjs/events-manager.d.ts +49 -0
- package/lib/cjs/events-manager.d.ts.map +1 -0
- package/lib/cjs/events-manager.js +157 -0
- package/lib/cjs/events-manager.js.map +1 -0
- package/lib/cjs/identifiers.d.ts +9 -0
- package/lib/cjs/identifiers.d.ts.map +1 -0
- package/lib/cjs/identifiers.js +18 -0
- package/lib/cjs/identifiers.js.map +1 -0
- package/lib/cjs/session-idb-store.d.ts +15 -0
- package/lib/cjs/session-idb-store.d.ts.map +1 -0
- package/lib/cjs/session-idb-store.js +107 -0
- package/lib/cjs/session-idb-store.js.map +1 -0
- package/lib/cjs/session-replay.d.ts +5 -41
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +55 -406
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/track-destination.d.ts +27 -0
- package/lib/cjs/track-destination.d.ts.map +1 -0
- package/lib/cjs/track-destination.js +201 -0
- package/lib/cjs/track-destination.js.map +1 -0
- package/lib/cjs/typings/session-replay.d.ts +45 -7
- package/lib/cjs/typings/session-replay.d.ts.map +1 -1
- package/lib/cjs/typings/session-replay.js.map +1 -1
- package/lib/esm/config.d.ts +0 -3
- package/lib/esm/config.d.ts.map +1 -1
- package/lib/esm/config.js +0 -9
- package/lib/esm/config.js.map +1 -1
- package/lib/esm/events-manager.d.ts +49 -0
- package/lib/esm/events-manager.d.ts.map +1 -0
- package/lib/esm/events-manager.js +155 -0
- package/lib/esm/events-manager.js.map +1 -0
- package/lib/esm/identifiers.d.ts +9 -0
- package/lib/esm/identifiers.d.ts.map +1 -0
- package/lib/esm/identifiers.js +16 -0
- package/lib/esm/identifiers.js.map +1 -0
- package/lib/esm/session-idb-store.d.ts +15 -0
- package/lib/esm/session-idb-store.d.ts.map +1 -0
- package/lib/esm/session-idb-store.js +105 -0
- package/lib/esm/session-idb-store.js.map +1 -0
- package/lib/esm/session-replay.d.ts +5 -41
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +59 -410
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/track-destination.d.ts +27 -0
- package/lib/esm/track-destination.d.ts.map +1 -0
- package/lib/esm/track-destination.js +199 -0
- package/lib/esm/track-destination.js.map +1 -0
- package/lib/esm/typings/session-replay.d.ts +45 -7
- package/lib/esm/typings/session-replay.d.ts.map +1 -1
- package/lib/esm/typings/session-replay.js.map +1 -1
- package/lib/scripts/amplitude-min.js +1 -1
- package/lib/scripts/amplitude-min.js.gz +0 -0
- package/lib/scripts/amplitude-min.umd.js +1 -1
- package/lib/scripts/amplitude-min.umd.js.gz +0 -0
- package/lib/scripts/config.d.ts +0 -3
- package/lib/scripts/config.d.ts.map +1 -1
- package/lib/scripts/events-manager.d.ts +49 -0
- package/lib/scripts/events-manager.d.ts.map +1 -0
- package/lib/scripts/identifiers.d.ts +9 -0
- package/lib/scripts/identifiers.d.ts.map +1 -0
- package/lib/scripts/session-idb-store.d.ts +15 -0
- package/lib/scripts/session-idb-store.d.ts.map +1 -0
- package/lib/scripts/session-replay.d.ts +5 -41
- package/lib/scripts/session-replay.d.ts.map +1 -1
- package/lib/scripts/track-destination.d.ts +27 -0
- package/lib/scripts/track-destination.d.ts.map +1 -0
- package/lib/scripts/typings/session-replay.d.ts +45 -7
- package/lib/scripts/typings/session-replay.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { __awaiter, __generator } from "tslib";
|
|
2
|
+
import { MAX_EVENT_LIST_SIZE_IN_BYTES, MAX_INTERVAL, MIN_INTERVAL } from './constants';
|
|
3
|
+
import { RecordingStatus, } from './typings/session-replay';
|
|
4
|
+
import { SessionReplaySessionIDBStore } from './session-idb-store';
|
|
5
|
+
import { SessionReplayTrackDestination } from './track-destination';
|
|
6
|
+
var SessionReplayEventsManager = /** @class */ (function () {
|
|
7
|
+
function SessionReplayEventsManager(_a) {
|
|
8
|
+
var config = _a.config;
|
|
9
|
+
var _this = this;
|
|
10
|
+
this.events = [];
|
|
11
|
+
this.currentSequenceId = 0;
|
|
12
|
+
this.maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;
|
|
13
|
+
this.interval = MIN_INTERVAL;
|
|
14
|
+
this.timeAtLastSend = null;
|
|
15
|
+
/**
|
|
16
|
+
* Determines whether to send the events list to the backend and start a new
|
|
17
|
+
* empty events list, based on the size of the list as well as the last time sent
|
|
18
|
+
* @param nextEventString
|
|
19
|
+
* @returns boolean
|
|
20
|
+
*/
|
|
21
|
+
this.shouldSplitEventsList = function (nextEventString) {
|
|
22
|
+
var sizeOfNextEvent = new Blob([nextEventString]).size;
|
|
23
|
+
var sizeOfEventsList = new Blob(_this.events).size;
|
|
24
|
+
if (sizeOfEventsList + sizeOfNextEvent >= _this.maxPersistedEventsSize) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (_this.timeAtLastSend !== null && Date.now() - _this.timeAtLastSend > _this.interval && _this.events.length) {
|
|
28
|
+
_this.interval = Math.min(MAX_INTERVAL, _this.interval + MIN_INTERVAL);
|
|
29
|
+
_this.timeAtLastSend = Date.now();
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
};
|
|
34
|
+
this.config = config;
|
|
35
|
+
this.trackDestination = new SessionReplayTrackDestination({ loggerProvider: this.config.loggerProvider });
|
|
36
|
+
this.sessionIDBStore = new SessionReplaySessionIDBStore({
|
|
37
|
+
loggerProvider: this.config.loggerProvider,
|
|
38
|
+
apiKey: this.config.apiKey,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
SessionReplayEventsManager.prototype.initialize = function (_a) {
|
|
42
|
+
var sessionId = _a.sessionId, deviceId = _a.deviceId, _b = _a.shouldSendStoredEvents, shouldSendStoredEvents = _b === void 0 ? false : _b;
|
|
43
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
44
|
+
var storedReplaySessions, storedSequencesForSession, storedSeqId, lastSequence;
|
|
45
|
+
return __generator(this, function (_c) {
|
|
46
|
+
switch (_c.label) {
|
|
47
|
+
case 0:
|
|
48
|
+
this.timeAtLastSend = Date.now(); // Initialize this so we have a point of comparison when events are recorded
|
|
49
|
+
return [4 /*yield*/, this.sessionIDBStore.getAllSessionDataFromStore()];
|
|
50
|
+
case 1:
|
|
51
|
+
storedReplaySessions = _c.sent();
|
|
52
|
+
storedSequencesForSession = storedReplaySessions && storedReplaySessions[sessionId];
|
|
53
|
+
if (storedReplaySessions && storedSequencesForSession && storedSequencesForSession.sessionSequences) {
|
|
54
|
+
storedSeqId = storedSequencesForSession.currentSequenceId;
|
|
55
|
+
lastSequence = storedSequencesForSession.sessionSequences[storedSeqId];
|
|
56
|
+
if (lastSequence && lastSequence.status !== RecordingStatus.RECORDING) {
|
|
57
|
+
this.currentSequenceId = storedSeqId + 1;
|
|
58
|
+
this.events = [];
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Pick up recording where it was left off in another tab or window
|
|
62
|
+
this.currentSequenceId = storedSeqId;
|
|
63
|
+
this.events = (lastSequence === null || lastSequence === void 0 ? void 0 : lastSequence.events) || [];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (shouldSendStoredEvents && storedReplaySessions) {
|
|
67
|
+
this.sendStoredEvents({ storedReplaySessions: storedReplaySessions, deviceId: deviceId, sessionId: sessionId });
|
|
68
|
+
}
|
|
69
|
+
return [2 /*return*/];
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
SessionReplayEventsManager.prototype.sendStoredEvents = function (_a) {
|
|
75
|
+
var storedReplaySessions = _a.storedReplaySessions, sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
76
|
+
for (var storedSessionId in storedReplaySessions) {
|
|
77
|
+
var storedSequences = storedReplaySessions[storedSessionId].sessionSequences;
|
|
78
|
+
for (var storedSeqId in storedSequences) {
|
|
79
|
+
var seq = storedSequences[storedSeqId];
|
|
80
|
+
var numericSeqId = parseInt(storedSeqId, 10);
|
|
81
|
+
var numericSessionId = parseInt(storedSessionId, 10);
|
|
82
|
+
if (numericSessionId === sessionId && numericSeqId === this.currentSequenceId) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (seq.events && seq.events.length && seq.status === RecordingStatus.RECORDING) {
|
|
86
|
+
this.sendEventsList({
|
|
87
|
+
events: seq.events,
|
|
88
|
+
sequenceId: numericSeqId,
|
|
89
|
+
sessionId: numericSessionId,
|
|
90
|
+
deviceId: deviceId,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
SessionReplayEventsManager.prototype.resetSequence = function () {
|
|
97
|
+
this.events = [];
|
|
98
|
+
this.currentSequenceId = 0;
|
|
99
|
+
};
|
|
100
|
+
SessionReplayEventsManager.prototype.addEvent = function (_a) {
|
|
101
|
+
var event = _a.event, sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
102
|
+
var shouldSplit = this.shouldSplitEventsList(event);
|
|
103
|
+
if (shouldSplit) {
|
|
104
|
+
this.sendEventsList({
|
|
105
|
+
events: this.events,
|
|
106
|
+
sequenceId: this.currentSequenceId,
|
|
107
|
+
sessionId: sessionId,
|
|
108
|
+
deviceId: deviceId,
|
|
109
|
+
});
|
|
110
|
+
this.events = [];
|
|
111
|
+
this.currentSequenceId++;
|
|
112
|
+
}
|
|
113
|
+
this.events.push(event);
|
|
114
|
+
void this.sessionIDBStore.storeEventsForSession(this.events, this.currentSequenceId, sessionId);
|
|
115
|
+
};
|
|
116
|
+
SessionReplayEventsManager.prototype.sendEvents = function (_a) {
|
|
117
|
+
var sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
118
|
+
if (this.events.length && sessionId) {
|
|
119
|
+
this.sendEventsList({
|
|
120
|
+
events: this.events,
|
|
121
|
+
sequenceId: this.currentSequenceId,
|
|
122
|
+
sessionId: sessionId,
|
|
123
|
+
deviceId: deviceId,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
SessionReplayEventsManager.prototype.sendEventsList = function (_a) {
|
|
128
|
+
var events = _a.events, sequenceId = _a.sequenceId, sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
129
|
+
this.trackDestination.sendEventsList({
|
|
130
|
+
events: events,
|
|
131
|
+
sequenceId: sequenceId,
|
|
132
|
+
sessionId: sessionId,
|
|
133
|
+
flushMaxRetries: this.config.flushMaxRetries,
|
|
134
|
+
apiKey: this.config.apiKey,
|
|
135
|
+
deviceId: deviceId,
|
|
136
|
+
sampleRate: this.config.sampleRate,
|
|
137
|
+
serverZone: this.config.serverZone,
|
|
138
|
+
onComplete: this.sessionIDBStore.cleanUpSessionEventsStore.bind(this.sessionIDBStore),
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
SessionReplayEventsManager.prototype.flush = function (useRetry) {
|
|
142
|
+
if (useRetry === void 0) { useRetry = false; }
|
|
143
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
144
|
+
return __generator(this, function (_a) {
|
|
145
|
+
if (this.trackDestination) {
|
|
146
|
+
return [2 /*return*/, this.trackDestination.flush(useRetry)];
|
|
147
|
+
}
|
|
148
|
+
return [2 /*return*/];
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
return SessionReplayEventsManager;
|
|
153
|
+
}());
|
|
154
|
+
export { SessionReplayEventsManager };
|
|
155
|
+
//# sourceMappingURL=events-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-manager.js","sourceRoot":"","sources":["../../src/events-manager.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,4BAA4B,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAML,eAAe,GAEhB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AAEpE;IAUE,oCAAY,EAA2C;YAAzC,MAAM,YAAA;QAApB,iBAOC;QAhBD,WAAM,GAAW,EAAE,CAAC;QACpB,sBAAiB,GAAG,CAAC,CAAC;QACtB,2BAAsB,GAAG,4BAA4B,CAAC;QACtD,aAAQ,GAAG,YAAY,CAAC;QACxB,mBAAc,GAAkB,IAAI,CAAC;QAgGrC;;;;;WAKG;QACH,0BAAqB,GAAG,UAAC,eAAuB;YAC9C,IAAM,eAAe,GAAG,IAAI,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;YACzD,IAAM,gBAAgB,GAAG,IAAI,IAAI,CAAC,KAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YACpD,IAAI,gBAAgB,GAAG,eAAe,IAAI,KAAI,CAAC,sBAAsB,EAAE;gBACrE,OAAO,IAAI,CAAC;aACb;YACD,IAAI,KAAI,CAAC,cAAc,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAI,CAAC,cAAc,GAAG,KAAI,CAAC,QAAQ,IAAI,KAAI,CAAC,MAAM,CAAC,MAAM,EAAE;gBAC1G,KAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,KAAI,CAAC,QAAQ,GAAG,YAAY,CAAC,CAAC;gBACrE,KAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACjC,OAAO,IAAI,CAAC;aACb;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QA5GA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,gBAAgB,GAAG,IAAI,6BAA6B,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,eAAe,GAAG,IAAI,4BAA4B,CAAC;YACtD,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc;YAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;SAC3B,CAAC,CAAC;IACL,CAAC;IAEK,+CAAU,GAAhB,UAAiB,EAQhB;YAPC,SAAS,eAAA,EACT,QAAQ,cAAA,EACR,8BAA8B,EAA9B,sBAAsB,mBAAG,KAAK,KAAA;;;;;;wBAM9B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,4EAA4E;wBACjF,qBAAM,IAAI,CAAC,eAAe,CAAC,0BAA0B,EAAE,EAAA;;wBAA9E,oBAAoB,GAAG,SAAuD;wBAE9E,yBAAyB,GAAG,oBAAoB,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;wBAC1F,IAAI,oBAAoB,IAAI,yBAAyB,IAAI,yBAAyB,CAAC,gBAAgB,EAAE;4BAC7F,WAAW,GAAG,yBAAyB,CAAC,iBAAiB,CAAC;4BAC1D,YAAY,GAAG,yBAAyB,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;4BAC7E,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,KAAK,eAAe,CAAC,SAAS,EAAE;gCACrE,IAAI,CAAC,iBAAiB,GAAG,WAAW,GAAG,CAAC,CAAC;gCACzC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;6BAClB;iCAAM;gCACL,mEAAmE;gCACnE,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC;gCACrC,IAAI,CAAC,MAAM,GAAG,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,KAAI,EAAE,CAAC;6BAC1C;yBACF;wBACD,IAAI,sBAAsB,IAAI,oBAAoB,EAAE;4BAClD,IAAI,CAAC,gBAAgB,CAAC,EAAE,oBAAoB,sBAAA,EAAE,QAAQ,UAAA,EAAE,SAAS,WAAA,EAAE,CAAC,CAAC;yBACtE;;;;;KACF;IAED,qDAAgB,GAAhB,UAAiB,EAQhB;YAPC,oBAAoB,0BAAA,EACpB,SAAS,eAAA,EACT,QAAQ,cAAA;QAMR,KAAK,IAAM,eAAe,IAAI,oBAAoB,EAAE;YAClD,IAAM,eAAe,GAAG,oBAAoB,CAAC,eAAe,CAAC,CAAC,gBAAgB,CAAC;YAC/E,KAAK,IAAM,WAAW,IAAI,eAAe,EAAE;gBACzC,IAAM,GAAG,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;gBACzC,IAAM,YAAY,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;gBAC/C,IAAM,gBAAgB,GAAG,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;gBACvD,IAAI,gBAAgB,KAAK,SAAS,IAAI,YAAY,KAAK,IAAI,CAAC,iBAAiB,EAAE;oBAC7E,SAAS;iBACV;gBAED,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,eAAe,CAAC,SAAS,EAAE;oBAC/E,IAAI,CAAC,cAAc,CAAC;wBAClB,MAAM,EAAE,GAAG,CAAC,MAAM;wBAClB,UAAU,EAAE,YAAY;wBACxB,SAAS,EAAE,gBAAgB;wBAC3B,QAAQ,UAAA;qBACT,CAAC,CAAC;iBACJ;aACF;SACF;IACH,CAAC;IAED,kDAAa,GAAb;QACE,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,6CAAQ,GAAR,UAAS,EAAsF;YAApF,KAAK,WAAA,EAAE,SAAS,eAAA,EAAE,QAAQ,cAAA;QACnC,IAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,WAAW,EAAE;YACf,IAAI,CAAC,cAAc,CAAC;gBAClB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,UAAU,EAAE,IAAI,CAAC,iBAAiB;gBAClC,SAAS,WAAA;gBACT,QAAQ,UAAA;aACT,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,iBAAiB,EAAE,CAAC;SAC1B;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,KAAK,IAAI,CAAC,eAAe,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAClG,CAAC;IAsBD,+CAAU,GAAV,UAAW,EAAgE;YAA9D,SAAS,eAAA,EAAE,QAAQ,cAAA;QAC9B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,SAAS,EAAE;YACnC,IAAI,CAAC,cAAc,CAAC;gBAClB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,UAAU,EAAE,IAAI,CAAC,iBAAiB;gBAClC,SAAS,WAAA;gBACT,QAAQ,UAAA;aACT,CAAC,CAAC;SACJ;IACH,CAAC;IAED,mDAAc,GAAd,UAAe,EAUd;YATC,MAAM,YAAA,EACN,UAAU,gBAAA,EACV,SAAS,eAAA,EACT,QAAQ,cAAA;QAOR,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC;YACnC,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,SAAS;YACpB,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe;YAC5C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAC1B,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;YAClC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;YAClC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;SACtF,CAAC,CAAC;IACL,CAAC;IAEK,0CAAK,GAAX,UAAY,QAAgB;QAAhB,yBAAA,EAAA,gBAAgB;;;gBAC1B,IAAI,IAAI,CAAC,gBAAgB,EAAE;oBACzB,sBAAO,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAC;iBAC9C;;;;KACF;IACH,iCAAC;AAAD,CAAC,AAjKD,IAiKC","sourcesContent":["import { MAX_EVENT_LIST_SIZE_IN_BYTES, MAX_INTERVAL, MIN_INTERVAL } from './constants';\nimport {\n SessionReplayEventsManager as AmplitudeSessionReplayEventsManager,\n SessionReplaySessionIDBStore as AmplitudeSessionReplayEventsStorage,\n SessionReplayTrackDestination as AmplitudeSessionReplayTrackDestination,\n Events,\n IDBStore,\n RecordingStatus,\n SessionReplayConfig,\n} from './typings/session-replay';\n\nimport { SessionReplaySessionIDBStore } from './session-idb-store';\nimport { SessionReplayTrackDestination } from './track-destination';\n\nexport class SessionReplayEventsManager implements AmplitudeSessionReplayEventsManager {\n events: Events = [];\n currentSequenceId = 0;\n maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;\n interval = MIN_INTERVAL;\n timeAtLastSend: number | null = null;\n sessionIDBStore: AmplitudeSessionReplayEventsStorage;\n trackDestination: AmplitudeSessionReplayTrackDestination;\n config: SessionReplayConfig;\n\n constructor({ config }: { config: SessionReplayConfig }) {\n this.config = config;\n this.trackDestination = new SessionReplayTrackDestination({ loggerProvider: this.config.loggerProvider });\n this.sessionIDBStore = new SessionReplaySessionIDBStore({\n loggerProvider: this.config.loggerProvider,\n apiKey: this.config.apiKey,\n });\n }\n\n async initialize({\n sessionId,\n deviceId,\n shouldSendStoredEvents = false,\n }: {\n sessionId: number;\n deviceId: string;\n shouldSendStoredEvents?: boolean;\n }) {\n this.timeAtLastSend = Date.now(); // Initialize this so we have a point of comparison when events are recorded\n const storedReplaySessions = await this.sessionIDBStore.getAllSessionDataFromStore();\n\n const storedSequencesForSession = storedReplaySessions && storedReplaySessions[sessionId];\n if (storedReplaySessions && storedSequencesForSession && storedSequencesForSession.sessionSequences) {\n const storedSeqId = storedSequencesForSession.currentSequenceId;\n const lastSequence = storedSequencesForSession.sessionSequences[storedSeqId];\n if (lastSequence && lastSequence.status !== RecordingStatus.RECORDING) {\n this.currentSequenceId = storedSeqId + 1;\n this.events = [];\n } else {\n // Pick up recording where it was left off in another tab or window\n this.currentSequenceId = storedSeqId;\n this.events = lastSequence?.events || [];\n }\n }\n if (shouldSendStoredEvents && storedReplaySessions) {\n this.sendStoredEvents({ storedReplaySessions, deviceId, sessionId });\n }\n }\n\n sendStoredEvents({\n storedReplaySessions,\n sessionId,\n deviceId,\n }: {\n storedReplaySessions: IDBStore;\n sessionId: number;\n deviceId: string;\n }) {\n for (const storedSessionId in storedReplaySessions) {\n const storedSequences = storedReplaySessions[storedSessionId].sessionSequences;\n for (const storedSeqId in storedSequences) {\n const seq = storedSequences[storedSeqId];\n const numericSeqId = parseInt(storedSeqId, 10);\n const numericSessionId = parseInt(storedSessionId, 10);\n if (numericSessionId === sessionId && numericSeqId === this.currentSequenceId) {\n continue;\n }\n\n if (seq.events && seq.events.length && seq.status === RecordingStatus.RECORDING) {\n this.sendEventsList({\n events: seq.events,\n sequenceId: numericSeqId,\n sessionId: numericSessionId,\n deviceId,\n });\n }\n }\n }\n }\n\n resetSequence() {\n this.events = [];\n this.currentSequenceId = 0;\n }\n\n addEvent({ event, sessionId, deviceId }: { event: string; sessionId: number; deviceId: string }) {\n const shouldSplit = this.shouldSplitEventsList(event);\n if (shouldSplit) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId,\n deviceId,\n });\n this.events = [];\n this.currentSequenceId++;\n }\n this.events.push(event);\n void this.sessionIDBStore.storeEventsForSession(this.events, this.currentSequenceId, sessionId);\n }\n\n /**\n * Determines whether to send the events list to the backend and start a new\n * empty events list, based on the size of the list as well as the last time sent\n * @param nextEventString\n * @returns boolean\n */\n shouldSplitEventsList = (nextEventString: string): boolean => {\n const sizeOfNextEvent = new Blob([nextEventString]).size;\n const sizeOfEventsList = new Blob(this.events).size;\n if (sizeOfEventsList + sizeOfNextEvent >= this.maxPersistedEventsSize) {\n return true;\n }\n if (this.timeAtLastSend !== null && Date.now() - this.timeAtLastSend > this.interval && this.events.length) {\n this.interval = Math.min(MAX_INTERVAL, this.interval + MIN_INTERVAL);\n this.timeAtLastSend = Date.now();\n return true;\n }\n return false;\n };\n\n sendEvents({ sessionId, deviceId }: { sessionId: number; deviceId: string }) {\n if (this.events.length && sessionId) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId,\n deviceId,\n });\n }\n }\n\n sendEventsList({\n events,\n sequenceId,\n sessionId,\n deviceId,\n }: {\n events: string[];\n sequenceId: number;\n sessionId: number;\n deviceId: string;\n }) {\n this.trackDestination.sendEventsList({\n events: events,\n sequenceId: sequenceId,\n sessionId: sessionId,\n flushMaxRetries: this.config.flushMaxRetries,\n apiKey: this.config.apiKey,\n deviceId: deviceId,\n sampleRate: this.config.sampleRate,\n serverZone: this.config.serverZone,\n onComplete: this.sessionIDBStore.cleanUpSessionEventsStore.bind(this.sessionIDBStore),\n });\n }\n\n async flush(useRetry = false) {\n if (this.trackDestination) {\n return this.trackDestination.flush(useRetry);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Logger as ILogger } from '@amplitude/analytics-types';
|
|
2
|
+
import { SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
|
|
3
|
+
export declare class SessionIdentifiers implements ISessionIdentifiers {
|
|
4
|
+
deviceId?: string | undefined;
|
|
5
|
+
sessionId?: number | undefined;
|
|
6
|
+
sessionReplayId?: string | undefined;
|
|
7
|
+
constructor(options: SessionReplayOptions, loggerProvider: ILogger);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=identifiers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identifiers.d.ts","sourceRoot":"","sources":["../../src/identifiers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,IAAI,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE3G,qBAAa,kBAAmB,YAAW,mBAAmB;IAC5D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEzB,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,OAAO;CAUnE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { generateSessionReplayId } from './helpers';
|
|
2
|
+
var SessionIdentifiers = /** @class */ (function () {
|
|
3
|
+
function SessionIdentifiers(options, loggerProvider) {
|
|
4
|
+
this.deviceId = options.deviceId;
|
|
5
|
+
this.sessionId = options.sessionId;
|
|
6
|
+
if (options.sessionId && options.deviceId) {
|
|
7
|
+
this.sessionReplayId = generateSessionReplayId(options.sessionId, options.deviceId);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
loggerProvider.error('Please provide both sessionId and deviceId.');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return SessionIdentifiers;
|
|
14
|
+
}());
|
|
15
|
+
export { SessionIdentifiers };
|
|
16
|
+
//# sourceMappingURL=identifiers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identifiers.js","sourceRoot":"","sources":["../../src/identifiers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAGpD;IAKE,4BAAY,OAA6B,EAAE,cAAuB;QAChE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QAEnC,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE;YACzC,IAAI,CAAC,eAAe,GAAG,uBAAuB,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;SACrF;aAAM;YACL,cAAc,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;SACrE;IACH,CAAC;IACH,yBAAC;AAAD,CAAC,AAfD,IAeC","sourcesContent":["import { Logger as ILogger } from '@amplitude/analytics-types';\nimport { generateSessionReplayId } from './helpers';\nimport { SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';\n\nexport class SessionIdentifiers implements ISessionIdentifiers {\n deviceId?: string | undefined;\n sessionId?: number | undefined;\n sessionReplayId?: string | undefined;\n\n constructor(options: SessionReplayOptions, loggerProvider: ILogger) {\n this.deviceId = options.deviceId;\n this.sessionId = options.sessionId;\n\n if (options.sessionId && options.deviceId) {\n this.sessionReplayId = generateSessionReplayId(options.sessionId, options.deviceId);\n } else {\n loggerProvider.error('Please provide both sessionId and deviceId.');\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Logger as ILogger } from '@amplitude/analytics-types';
|
|
2
|
+
import { SessionReplaySessionIDBStore as AmplitudeSessionReplaySessionIDBStore, Events, IDBStore } from './typings/session-replay';
|
|
3
|
+
export declare class SessionReplaySessionIDBStore implements AmplitudeSessionReplaySessionIDBStore {
|
|
4
|
+
apiKey: string | undefined;
|
|
5
|
+
storageKey: string;
|
|
6
|
+
loggerProvider: ILogger;
|
|
7
|
+
constructor({ apiKey, loggerProvider }: {
|
|
8
|
+
apiKey: string;
|
|
9
|
+
loggerProvider: ILogger;
|
|
10
|
+
});
|
|
11
|
+
getAllSessionDataFromStore: () => Promise<IDBStore | undefined>;
|
|
12
|
+
storeEventsForSession: (events: Events, sequenceId: number, sessionId: number) => Promise<void>;
|
|
13
|
+
cleanUpSessionEventsStore: (sessionId: number, sequenceId: number) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=session-idb-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-idb-store.d.ts","sourceRoot":"","sources":["../../src/session-idb-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAI/D,OAAO,EACL,4BAA4B,IAAI,qCAAqC,EACrE,MAAM,EACN,QAAQ,EAGT,MAAM,0BAA0B,CAAC;AAElC,qBAAa,4BAA6B,YAAW,qCAAqC;IACxF,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,UAAU,SAAM;IAChB,cAAc,EAAE,OAAO,CAAC;gBACZ,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE;IAKnF,0BAA0B,sCASxB;IAEF,qBAAqB,+BAAsC,MAAM,aAAa,MAAM,mBAyBlF;IAEF,yBAAyB,cAAqB,MAAM,cAAc,MAAM,mBAiCtE;CACH"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { __assign, __awaiter, __generator, __read } from "tslib";
|
|
2
|
+
import * as IDBKeyVal from 'idb-keyval';
|
|
3
|
+
import { MAX_IDB_STORAGE_LENGTH, STORAGE_PREFIX, defaultSessionStore } from './constants';
|
|
4
|
+
import { STORAGE_FAILURE } from './messages';
|
|
5
|
+
import { RecordingStatus, } from './typings/session-replay';
|
|
6
|
+
var SessionReplaySessionIDBStore = /** @class */ (function () {
|
|
7
|
+
function SessionReplaySessionIDBStore(_a) {
|
|
8
|
+
var apiKey = _a.apiKey, loggerProvider = _a.loggerProvider;
|
|
9
|
+
var _this = this;
|
|
10
|
+
this.storageKey = '';
|
|
11
|
+
this.getAllSessionDataFromStore = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
12
|
+
var storedReplaySessionContexts, e_1;
|
|
13
|
+
return __generator(this, function (_a) {
|
|
14
|
+
switch (_a.label) {
|
|
15
|
+
case 0:
|
|
16
|
+
_a.trys.push([0, 2, , 3]);
|
|
17
|
+
return [4 /*yield*/, IDBKeyVal.get(this.storageKey)];
|
|
18
|
+
case 1:
|
|
19
|
+
storedReplaySessionContexts = _a.sent();
|
|
20
|
+
return [2 /*return*/, storedReplaySessionContexts];
|
|
21
|
+
case 2:
|
|
22
|
+
e_1 = _a.sent();
|
|
23
|
+
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_1));
|
|
24
|
+
return [3 /*break*/, 3];
|
|
25
|
+
case 3: return [2 /*return*/, undefined];
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}); };
|
|
29
|
+
this.storeEventsForSession = function (events, sequenceId, sessionId) { return __awaiter(_this, void 0, void 0, function () {
|
|
30
|
+
var e_2;
|
|
31
|
+
return __generator(this, function (_a) {
|
|
32
|
+
switch (_a.label) {
|
|
33
|
+
case 0:
|
|
34
|
+
_a.trys.push([0, 2, , 3]);
|
|
35
|
+
return [4 /*yield*/, IDBKeyVal.update(this.storageKey, function (sessionMap) {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
if (sessionMap === void 0) { sessionMap = {}; }
|
|
38
|
+
var session = sessionMap[sessionId] || __assign({}, defaultSessionStore);
|
|
39
|
+
session.currentSequenceId = sequenceId;
|
|
40
|
+
var currentSequence = (session.sessionSequences && session.sessionSequences[sequenceId]) || {};
|
|
41
|
+
currentSequence.events = events;
|
|
42
|
+
currentSequence.status = RecordingStatus.RECORDING;
|
|
43
|
+
return __assign(__assign({}, sessionMap), (_a = {}, _a[sessionId] = __assign(__assign({}, session), { sessionSequences: __assign(__assign({}, session.sessionSequences), (_b = {}, _b[sequenceId] = currentSequence, _b)) }), _a));
|
|
44
|
+
})];
|
|
45
|
+
case 1:
|
|
46
|
+
_a.sent();
|
|
47
|
+
return [3 /*break*/, 3];
|
|
48
|
+
case 2:
|
|
49
|
+
e_2 = _a.sent();
|
|
50
|
+
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_2));
|
|
51
|
+
return [3 /*break*/, 3];
|
|
52
|
+
case 3: return [2 /*return*/];
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}); };
|
|
56
|
+
this.cleanUpSessionEventsStore = function (sessionId, sequenceId) { return __awaiter(_this, void 0, void 0, function () {
|
|
57
|
+
var e_3;
|
|
58
|
+
return __generator(this, function (_a) {
|
|
59
|
+
switch (_a.label) {
|
|
60
|
+
case 0:
|
|
61
|
+
_a.trys.push([0, 2, , 3]);
|
|
62
|
+
return [4 /*yield*/, IDBKeyVal.update(this.storageKey, function (sessionMap) {
|
|
63
|
+
if (sessionMap === void 0) { sessionMap = {}; }
|
|
64
|
+
var session = sessionMap[sessionId];
|
|
65
|
+
var sequenceToUpdate = (session === null || session === void 0 ? void 0 : session.sessionSequences) && session.sessionSequences[sequenceId];
|
|
66
|
+
if (!sequenceToUpdate) {
|
|
67
|
+
return sessionMap;
|
|
68
|
+
}
|
|
69
|
+
sequenceToUpdate.events = [];
|
|
70
|
+
sequenceToUpdate.status = RecordingStatus.SENT;
|
|
71
|
+
// Delete sent sequences for current session
|
|
72
|
+
Object.entries(session.sessionSequences).forEach(function (_a) {
|
|
73
|
+
var _b = __read(_a, 2), storedSeqId = _b[0], sequence = _b[1];
|
|
74
|
+
var numericStoredSeqId = parseInt(storedSeqId, 10);
|
|
75
|
+
if (sequence.status === RecordingStatus.SENT && sequenceId !== numericStoredSeqId) {
|
|
76
|
+
delete session.sessionSequences[numericStoredSeqId];
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// Delete any sessions that are older than 3 days
|
|
80
|
+
Object.keys(sessionMap).forEach(function (sessionId) {
|
|
81
|
+
var numericSessionId = parseInt(sessionId, 10);
|
|
82
|
+
if (Date.now() - numericSessionId >= MAX_IDB_STORAGE_LENGTH) {
|
|
83
|
+
delete sessionMap[numericSessionId];
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return sessionMap;
|
|
87
|
+
})];
|
|
88
|
+
case 1:
|
|
89
|
+
_a.sent();
|
|
90
|
+
return [3 /*break*/, 3];
|
|
91
|
+
case 2:
|
|
92
|
+
e_3 = _a.sent();
|
|
93
|
+
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_3));
|
|
94
|
+
return [3 /*break*/, 3];
|
|
95
|
+
case 3: return [2 /*return*/];
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}); };
|
|
99
|
+
this.loggerProvider = loggerProvider;
|
|
100
|
+
this.storageKey = "".concat(STORAGE_PREFIX, "_").concat(apiKey.substring(0, 10));
|
|
101
|
+
}
|
|
102
|
+
return SessionReplaySessionIDBStore;
|
|
103
|
+
}());
|
|
104
|
+
export { SessionReplaySessionIDBStore };
|
|
105
|
+
//# sourceMappingURL=session-idb-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-idb-store.js","sourceRoot":"","sources":["../../src/session-idb-store.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,SAAS,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAKL,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAElC;IAIE,sCAAY,EAAuE;YAArE,MAAM,YAAA,EAAE,cAAc,oBAAA;QAApC,iBAGC;QALD,eAAU,GAAG,EAAE,CAAC;QAOhB,+BAA0B,GAAG;;;;;;wBAEiC,qBAAM,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAA;;wBAAxF,2BAA2B,GAAyB,SAAoC;wBAE9F,sBAAO,2BAA2B,EAAC;;;wBAEnC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,UAAG,eAAe,eAAK,GAAW,CAAE,CAAC,CAAC;;4BAEjE,sBAAO,SAAS,EAAC;;;aAClB,CAAC;QAEF,0BAAqB,GAAG,UAAO,MAAc,EAAE,UAAkB,EAAE,SAAiB;;;;;;wBAEhF,qBAAM,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,UAAC,UAAyB;;gCAAzB,2BAAA,EAAA,eAAyB;gCAChE,IAAM,OAAO,GAAoB,UAAU,CAAC,SAAS,CAAC,iBAAS,mBAAmB,CAAE,CAAC;gCACrF,OAAO,CAAC,iBAAiB,GAAG,UAAU,CAAC;gCAEvC,IAAM,eAAe,GAAG,CAAC,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;gCAEjG,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC;gCAChC,eAAe,CAAC,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC;gCAEnD,6BACK,UAAU,gBACZ,SAAS,0BACL,OAAO,KACV,gBAAgB,wBACX,OAAO,CAAC,gBAAgB,gBAC1B,UAAU,IAAG,eAAe,gBAGjC;4BACJ,CAAC,CAAC,EAAA;;wBAnBF,SAmBE,CAAC;;;;wBAEH,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,UAAG,eAAe,eAAK,GAAW,CAAE,CAAC,CAAC;;;;;aAElE,CAAC;QAEF,8BAAyB,GAAG,UAAO,SAAiB,EAAE,UAAkB;;;;;;wBAEpE,qBAAM,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,UAAC,UAAyB;gCAAzB,2BAAA,EAAA,eAAyB;gCAChE,IAAM,OAAO,GAAoB,UAAU,CAAC,SAAS,CAAC,CAAC;gCACvD,IAAM,gBAAgB,GAAG,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,gBAAgB,KAAI,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;gCAC3F,IAAI,CAAC,gBAAgB,EAAE;oCACrB,OAAO,UAAU,CAAC;iCACnB;gCAED,gBAAgB,CAAC,MAAM,GAAG,EAAE,CAAC;gCAC7B,gBAAgB,CAAC,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC;gCAE/C,4CAA4C;gCAC5C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,UAAC,EAAuB;wCAAvB,KAAA,aAAuB,EAAtB,WAAW,QAAA,EAAE,QAAQ,QAAA;oCACtE,IAAM,kBAAkB,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;oCACrD,IAAI,QAAQ,CAAC,MAAM,KAAK,eAAe,CAAC,IAAI,IAAI,UAAU,KAAK,kBAAkB,EAAE;wCACjF,OAAO,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;qCACrD;gCACH,CAAC,CAAC,CAAC;gCAEH,iDAAiD;gCACjD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAC,SAAiB;oCAChD,IAAM,gBAAgB,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;oCACjD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,IAAI,sBAAsB,EAAE;wCAC3D,OAAO,UAAU,CAAC,gBAAgB,CAAC,CAAC;qCACrC;gCACH,CAAC,CAAC,CAAC;gCAEH,OAAO,UAAU,CAAC;4BACpB,CAAC,CAAC,EAAA;;wBA3BF,SA2BE,CAAC;;;;wBAEH,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,UAAG,eAAe,eAAK,GAAW,CAAE,CAAC,CAAC;;;;;aAElE,CAAC;QA3EA,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,UAAG,cAAc,cAAI,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAE,CAAC;IACnE,CAAC;IA0EH,mCAAC;AAAD,CAAC,AAjFD,IAiFC","sourcesContent":["import { Logger as ILogger } from '@amplitude/analytics-types';\nimport * as IDBKeyVal from 'idb-keyval';\nimport { MAX_IDB_STORAGE_LENGTH, STORAGE_PREFIX, defaultSessionStore } from './constants';\nimport { STORAGE_FAILURE } from './messages';\nimport {\n SessionReplaySessionIDBStore as AmplitudeSessionReplaySessionIDBStore,\n Events,\n IDBStore,\n IDBStoreSession,\n RecordingStatus,\n} from './typings/session-replay';\n\nexport class SessionReplaySessionIDBStore implements AmplitudeSessionReplaySessionIDBStore {\n apiKey: string | undefined;\n storageKey = '';\n loggerProvider: ILogger;\n constructor({ apiKey, loggerProvider }: { apiKey: string; loggerProvider: ILogger }) {\n this.loggerProvider = loggerProvider;\n this.storageKey = `${STORAGE_PREFIX}_${apiKey.substring(0, 10)}`;\n }\n\n getAllSessionDataFromStore = async () => {\n try {\n const storedReplaySessionContexts: IDBStore | undefined = await IDBKeyVal.get(this.storageKey);\n\n return storedReplaySessionContexts;\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n storeEventsForSession = async (events: Events, sequenceId: number, sessionId: number) => {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore = {}): IDBStore => {\n const session: IDBStoreSession = sessionMap[sessionId] || { ...defaultSessionStore };\n session.currentSequenceId = sequenceId;\n\n const currentSequence = (session.sessionSequences && session.sessionSequences[sequenceId]) || {};\n\n currentSequence.events = events;\n currentSequence.status = RecordingStatus.RECORDING;\n\n return {\n ...sessionMap,\n [sessionId]: {\n ...session,\n sessionSequences: {\n ...session.sessionSequences,\n [sequenceId]: currentSequence,\n },\n },\n };\n });\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n };\n\n cleanUpSessionEventsStore = async (sessionId: number, sequenceId: number) => {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore = {}): IDBStore => {\n const session: IDBStoreSession = sessionMap[sessionId];\n const sequenceToUpdate = session?.sessionSequences && session.sessionSequences[sequenceId];\n if (!sequenceToUpdate) {\n return sessionMap;\n }\n\n sequenceToUpdate.events = [];\n sequenceToUpdate.status = RecordingStatus.SENT;\n\n // Delete sent sequences for current session\n Object.entries(session.sessionSequences).forEach(([storedSeqId, sequence]) => {\n const numericStoredSeqId = parseInt(storedSeqId, 10);\n if (sequence.status === RecordingStatus.SENT && sequenceId !== numericStoredSeqId) {\n delete session.sessionSequences[numericStoredSeqId];\n }\n });\n\n // Delete any sessions that are older than 3 days\n Object.keys(sessionMap).forEach((sessionId: string) => {\n const numericSessionId = parseInt(sessionId, 10);\n if (Date.now() - numericSessionId >= MAX_IDB_STORAGE_LENGTH) {\n delete sessionMap[numericSessionId];\n }\n });\n\n return sessionMap;\n });\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n };\n}\n"]}
|
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import { Logger as ILogger } from '@amplitude/analytics-types';
|
|
2
2
|
import { record } from '@amplitude/rrweb';
|
|
3
|
-
import { AmplitudeSessionReplay,
|
|
3
|
+
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, SessionIdentifiers as ISessionIdentifiers, SessionReplayConfig as ISessionReplayConfig, SessionReplayOptions } from './typings/session-replay';
|
|
4
4
|
export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
5
5
|
name: string;
|
|
6
6
|
config: ISessionReplayConfig | undefined;
|
|
7
|
+
identifiers: ISessionIdentifiers | undefined;
|
|
8
|
+
eventsManager: AmplitudeSessionReplayEventsManager | undefined;
|
|
7
9
|
loggerProvider: ILogger;
|
|
8
|
-
storageKey: string;
|
|
9
|
-
retryTimeout: number;
|
|
10
|
-
events: Events;
|
|
11
|
-
currentSequenceId: number;
|
|
12
|
-
private scheduled;
|
|
13
|
-
queue: SessionReplayContext[];
|
|
14
10
|
stopRecordingEvents: ReturnType<typeof record> | null;
|
|
15
|
-
maxPersistedEventsSize: number;
|
|
16
|
-
interval: number;
|
|
17
|
-
timeAtLastSend: number | null;
|
|
18
11
|
constructor();
|
|
19
12
|
init(apiKey: string, options: SessionReplayOptions): import("@amplitude/analytics-types").AmplitudeReturn<void>;
|
|
20
13
|
protected _init(apiKey: string, options: SessionReplayOptions): Promise<void>;
|
|
21
14
|
setSessionId(sessionId: number, deviceId?: string): void;
|
|
22
15
|
getSessionReplayDebugPropertyValue(): string;
|
|
23
16
|
getSessionReplayProperties(): {
|
|
24
|
-
[
|
|
17
|
+
[key: string]: string | null;
|
|
25
18
|
};
|
|
26
19
|
blurListener: () => void;
|
|
27
20
|
focusListener: () => void;
|
|
@@ -30,39 +23,10 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
|
30
23
|
shouldOptOut(): boolean | undefined;
|
|
31
24
|
getShouldRecord(ignoreFocus?: boolean): boolean;
|
|
32
25
|
getBlockSelectors(): string | string[] | undefined;
|
|
33
|
-
sendStoredEvents(storedReplaySessions: IDBStore): void;
|
|
34
26
|
recordEvents(): void;
|
|
35
|
-
/**
|
|
36
|
-
* Determines whether to send the events list to the backend and start a new
|
|
37
|
-
* empty events list, based on the size of the list as well as the last time sent
|
|
38
|
-
* @param nextEventString
|
|
39
|
-
* @returns boolean
|
|
40
|
-
*/
|
|
41
|
-
shouldSplitEventsList: (nextEventString: string) => boolean;
|
|
42
|
-
sendEventsList({ events, sequenceId, sessionId }: {
|
|
43
|
-
events: string[];
|
|
44
|
-
sequenceId: number;
|
|
45
|
-
sessionId: number;
|
|
46
|
-
}): void;
|
|
47
|
-
addToQueue(...list: SessionReplayContext[]): void;
|
|
48
|
-
schedule(timeout: number): void;
|
|
49
|
-
flush(useRetry?: boolean): Promise<void>;
|
|
50
|
-
getSampleRate(): number;
|
|
51
|
-
getServerUrl(): "https://api-sr.amplitude.com/sessions/v2/track" | "https://api-sr.eu.amplitude.com/sessions/v2/track" | "https://api-sr.stag2.amplitude.com//sessions/v2/track";
|
|
52
27
|
getDeviceId(): string | undefined;
|
|
53
28
|
getSessionId(): number | undefined;
|
|
54
|
-
|
|
55
|
-
handleReponse(status: number, context: SessionReplayContext): void;
|
|
56
|
-
handleSuccessResponse(context: SessionReplayContext): void;
|
|
57
|
-
handleOtherResponse(context: SessionReplayContext): void;
|
|
58
|
-
getAllSessionEventsFromStore(): Promise<IDBStore | undefined>;
|
|
59
|
-
storeEventsForSession(events: Events, sequenceId: number, sessionId: number): Promise<void>;
|
|
60
|
-
cleanUpSessionEventsStore(sessionId: number, sequenceId: number): Promise<void>;
|
|
61
|
-
completeRequest({ context, err, success }: {
|
|
62
|
-
context: SessionReplayContext;
|
|
63
|
-
err?: string;
|
|
64
|
-
success?: string;
|
|
65
|
-
}): void;
|
|
29
|
+
flush(useRetry?: boolean): Promise<void>;
|
|
66
30
|
shutdown(): void;
|
|
67
31
|
}
|
|
68
32
|
//# sourceMappingURL=session-replay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAQ,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAWhD,OAAO,EACL,sBAAsB,EACtB,0BAA0B,IAAI,mCAAmC,EACjE,kBAAkB,IAAI,mBAAmB,EACzC,mBAAmB,IAAI,oBAAoB,EAC3C,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,qBAAa,aAAc,YAAW,sBAAsB;IAC1D,IAAI,SAAuC;IAC3C,MAAM,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACzC,WAAW,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,mCAAmC,GAAG,SAAS,CAAC;IAC/D,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAQ;;IAM7D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;cAIlC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAsBnE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAwBjD,kCAAkC;IAUlC,0BAA0B;;;IAwB1B,YAAY,aAEV;IAEF,aAAa,aAEX;IAEF,0BAA0B,CAAC,SAAS,CAAC,EAAE,MAAM;IAiBvC,UAAU,CAAC,sBAAsB,UAAQ;IAkB/C,YAAY;IAUZ,eAAe,CAAC,WAAW,UAAQ;IA8BnC,iBAAiB,IAAI,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAIlD,YAAY;IAkCZ,WAAW;IAUX,YAAY;IAIN,KAAK,CAAC,QAAQ,UAAQ;IAM5B,QAAQ;CAST"}
|