@amplitude/session-replay-browser 1.14.3 → 1.15.1-beta.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.
- package/lib/cjs/config/local-config.d.ts +2 -1
- package/lib/cjs/config/local-config.d.ts.map +1 -1
- package/lib/cjs/config/local-config.js +2 -0
- package/lib/cjs/config/local-config.js.map +1 -1
- package/lib/cjs/config/types.d.ts +2 -0
- package/lib/cjs/config/types.d.ts.map +1 -1
- package/lib/cjs/config/types.js.map +1 -1
- package/lib/cjs/events/base-events-store.d.ts +31 -0
- package/lib/cjs/events/base-events-store.d.ts.map +1 -0
- package/lib/cjs/events/base-events-store.js +47 -0
- package/lib/cjs/events/base-events-store.js.map +1 -0
- package/lib/cjs/events/event-compressor.js +2 -2
- package/lib/cjs/events/event-compressor.js.map +1 -1
- package/lib/cjs/events/events-idb-store.d.ts +16 -40
- package/lib/cjs/events/events-idb-store.d.ts.map +1 -1
- package/lib/cjs/events/events-idb-store.js +146 -139
- package/lib/cjs/events/events-idb-store.js.map +1 -1
- package/lib/cjs/events/events-manager.d.ts +3 -2
- package/lib/cjs/events/events-manager.d.ts.map +1 -1
- package/lib/cjs/events/events-manager.js +51 -18
- package/lib/cjs/events/events-manager.js.map +1 -1
- package/lib/cjs/events/events-memory-store.d.ts +15 -0
- package/lib/cjs/events/events-memory-store.d.ts.map +1 -0
- package/lib/cjs/events/events-memory-store.js +84 -0
- package/lib/cjs/events/events-memory-store.js.map +1 -0
- package/lib/cjs/helpers.d.ts +1 -0
- package/lib/cjs/helpers.d.ts.map +1 -1
- package/lib/cjs/hooks/click.d.ts.map +1 -1
- package/lib/cjs/hooks/click.js +3 -0
- package/lib/cjs/hooks/click.js.map +1 -1
- package/lib/cjs/index.d.ts +1 -1
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +26 -18
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/track-destination.d.ts.map +1 -1
- package/lib/cjs/track-destination.js +3 -4
- package/lib/cjs/track-destination.js.map +1 -1
- package/lib/cjs/typings/session-replay.d.ts +20 -12
- package/lib/cjs/typings/session-replay.d.ts.map +1 -1
- package/lib/cjs/typings/session-replay.js.map +1 -1
- package/lib/cjs/version.d.ts +1 -1
- package/lib/cjs/version.d.ts.map +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/cjs/version.js.map +1 -1
- package/lib/esm/config/local-config.d.ts +2 -1
- package/lib/esm/config/local-config.d.ts.map +1 -1
- package/lib/esm/config/local-config.js +2 -0
- package/lib/esm/config/local-config.js.map +1 -1
- package/lib/esm/config/types.d.ts +2 -0
- package/lib/esm/config/types.d.ts.map +1 -1
- package/lib/esm/config/types.js.map +1 -1
- package/lib/esm/events/base-events-store.d.ts +31 -0
- package/lib/esm/events/base-events-store.d.ts.map +1 -0
- package/lib/esm/events/base-events-store.js +45 -0
- package/lib/esm/events/base-events-store.js.map +1 -0
- package/lib/esm/events/event-compressor.js +1 -1
- package/lib/esm/events/event-compressor.js.map +1 -1
- package/lib/esm/events/events-idb-store.d.ts +16 -40
- package/lib/esm/events/events-idb-store.d.ts.map +1 -1
- package/lib/esm/events/events-idb-store.js +146 -138
- package/lib/esm/events/events-idb-store.js.map +1 -1
- package/lib/esm/events/events-manager.d.ts +3 -2
- package/lib/esm/events/events-manager.d.ts.map +1 -1
- package/lib/esm/events/events-manager.js +51 -18
- package/lib/esm/events/events-manager.js.map +1 -1
- package/lib/esm/events/events-memory-store.d.ts +15 -0
- package/lib/esm/events/events-memory-store.d.ts.map +1 -0
- package/lib/esm/events/events-memory-store.js +82 -0
- package/lib/esm/events/events-memory-store.js.map +1 -0
- package/lib/esm/helpers.d.ts +1 -0
- package/lib/esm/helpers.d.ts.map +1 -1
- package/lib/esm/hooks/click.d.ts.map +1 -1
- package/lib/esm/hooks/click.js +3 -0
- package/lib/esm/hooks/click.js.map +1 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +26 -18
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/track-destination.d.ts.map +1 -1
- package/lib/esm/track-destination.js +3 -4
- package/lib/esm/track-destination.js.map +1 -1
- package/lib/esm/typings/session-replay.d.ts +20 -12
- package/lib/esm/typings/session-replay.d.ts.map +1 -1
- package/lib/esm/typings/session-replay.js.map +1 -1
- package/lib/esm/version.d.ts +1 -1
- package/lib/esm/version.d.ts.map +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/esm/version.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/local-config.d.ts +2 -1
- package/lib/scripts/config/local-config.d.ts.map +1 -1
- package/lib/scripts/config/types.d.ts +2 -0
- package/lib/scripts/config/types.d.ts.map +1 -1
- package/lib/scripts/events/base-events-store.d.ts +31 -0
- package/lib/scripts/events/base-events-store.d.ts.map +1 -0
- package/lib/scripts/events/events-idb-store.d.ts +16 -40
- package/lib/scripts/events/events-idb-store.d.ts.map +1 -1
- package/lib/scripts/events/events-manager.d.ts +3 -2
- package/lib/scripts/events/events-manager.d.ts.map +1 -1
- package/lib/scripts/events/events-memory-store.d.ts +15 -0
- package/lib/scripts/events/events-memory-store.d.ts.map +1 -0
- package/lib/scripts/helpers.d.ts +1 -0
- package/lib/scripts/helpers.d.ts.map +1 -1
- package/lib/scripts/hooks/click.d.ts.map +1 -1
- package/lib/scripts/index.d.ts +1 -1
- package/lib/scripts/index.d.ts.map +1 -1
- package/lib/scripts/session-replay.d.ts.map +1 -1
- package/lib/scripts/track-destination.d.ts.map +1 -1
- package/lib/scripts/typings/session-replay.d.ts +20 -12
- package/lib/scripts/typings/session-replay.d.ts.map +1 -1
- package/lib/scripts/version.d.ts +1 -1
- package/lib/scripts/version.d.ts.map +1 -1
- package/package.json +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-compressor.js","sourceRoot":"","sources":["../../../src/events/event-compressor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"event-compressor.js","sourceRoot":"","sources":["../../../src/events/event-compressor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { eventWithTime } from '@amplitude/rrweb-types';\nimport { SessionReplayJoinedConfig } from 'src/config/types';\nimport { SessionReplayEventsManager } from 'src/typings/session-replay';\nimport { pack } from '@amplitude/rrweb-packer';\nimport { getGlobalScope } from '@amplitude/analytics-client-common';\n\ninterface TaskQueue {\n event: eventWithTime;\n sessionId: number;\n}\n\nconst DEFAULT_TIMEOUT = 2000;\nexport class EventCompressor {\n taskQueue: TaskQueue[] = [];\n isProcessing = false;\n eventsManager?: SessionReplayEventsManager<'replay' | 'interaction', string>;\n config: SessionReplayJoinedConfig;\n deviceId: string | undefined;\n canUseIdleCallback: boolean | undefined;\n timeout: number;\n\n constructor(\n eventsManager: SessionReplayEventsManager<'replay' | 'interaction', string>,\n config: SessionReplayJoinedConfig,\n deviceId: string | undefined,\n ) {\n const globalScope = getGlobalScope();\n this.canUseIdleCallback = globalScope && 'requestIdleCallback' in globalScope;\n this.eventsManager = eventsManager;\n this.config = config;\n this.deviceId = deviceId;\n this.timeout = config.performanceConfig?.timeout || DEFAULT_TIMEOUT;\n }\n\n // Schedule processing during idle time\n public scheduleIdleProcessing(): void {\n if (!this.isProcessing) {\n this.isProcessing = true;\n requestIdleCallback(\n (idleDeadline) => {\n this.processQueue(idleDeadline);\n },\n { timeout: this.timeout },\n );\n }\n }\n\n // Add an event to the task queue if idle callback is supported or compress the event directly\n public enqueueEvent(event: eventWithTime, sessionId: number): void {\n if (this.canUseIdleCallback && this.config.performanceConfig?.enabled) {\n this.config.loggerProvider.debug('Enqueuing event for processing during idle time.');\n this.taskQueue.push({ event, sessionId });\n this.scheduleIdleProcessing();\n } else {\n this.config.loggerProvider.debug('Processing event without idle callback.');\n this.addCompressedEvent(event, sessionId);\n }\n }\n\n // Process the task queue during idle time\n public processQueue(idleDeadline: IdleDeadline): void {\n // Process tasks while there's idle time or until the max number of tasks is reached\n while (this.taskQueue.length > 0 && (idleDeadline.timeRemaining() > 0 || idleDeadline.didTimeout)) {\n const task = this.taskQueue.shift();\n if (task) {\n const { event, sessionId } = task;\n this.addCompressedEvent(event, sessionId);\n }\n }\n\n // If there are still tasks in the queue, schedule the next idle callback\n if (this.taskQueue.length > 0) {\n requestIdleCallback(\n (idleDeadline) => {\n this.processQueue(idleDeadline);\n },\n { timeout: this.timeout },\n );\n } else {\n this.isProcessing = false;\n }\n }\n\n compressEvent = (event: eventWithTime) => {\n const packedEvent = pack(event);\n return JSON.stringify(packedEvent);\n };\n\n public addCompressedEvent = (event: eventWithTime, sessionId: number) => {\n const compressedEvent = this.compressEvent(event);\n\n if (this.eventsManager && this.deviceId) {\n this.eventsManager.addEvent({\n event: { type: 'replay', data: compressedEvent },\n sessionId,\n deviceId: this.deviceId,\n });\n }\n };\n}\n"]}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
import { Logger as ILogger } from '@amplitude/analytics-types';
|
|
2
1
|
import { DBSchema, IDBPDatabase } from 'idb';
|
|
3
|
-
import {
|
|
2
|
+
import { EventType, Events, SendingSequencesReturn } from '../typings/session-replay';
|
|
3
|
+
import { BaseEventsStore, InstanceArgs as BaseInstanceArgs } from './base-events-store';
|
|
4
4
|
export declare const currentSequenceKey = "sessionCurrentSequence";
|
|
5
5
|
export declare const sequencesToSendKey = "sequencesToSend";
|
|
6
6
|
export declare const remoteConfigKey = "remoteConfig";
|
|
7
7
|
export interface SessionReplayDB extends DBSchema {
|
|
8
8
|
sessionCurrentSequence: {
|
|
9
9
|
key: number;
|
|
10
|
-
value:
|
|
11
|
-
sessionId: number;
|
|
12
|
-
events: Events;
|
|
13
|
-
};
|
|
10
|
+
value: Omit<SendingSequencesReturn<number>, 'sequenceId'>;
|
|
14
11
|
};
|
|
15
12
|
sequencesToSend: {
|
|
16
13
|
key: number;
|
|
17
|
-
value:
|
|
14
|
+
value: Omit<SendingSequencesReturn<number>, 'sequenceId'>;
|
|
18
15
|
indexes: {
|
|
19
16
|
sessionId: number;
|
|
20
17
|
};
|
|
@@ -26,31 +23,17 @@ export declare const defineObjectStores: (db: IDBPDatabase<SessionReplayDB>) =>
|
|
|
26
23
|
currentSequenceStore: import("idb").IDBPObjectStore<SessionReplayDB, ArrayLike<"sessionCurrentSequence" | "sequencesToSend">, "sessionCurrentSequence", "versionchange"> | undefined;
|
|
27
24
|
};
|
|
28
25
|
export declare const createStore: (dbName: string) => Promise<IDBPDatabase<SessionReplayDB>>;
|
|
29
|
-
|
|
26
|
+
type InstanceArgs = {
|
|
30
27
|
apiKey: string;
|
|
31
|
-
db: IDBPDatabase<SessionReplayDB
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
loggerProvider: ILogger;
|
|
41
|
-
apiKey: string;
|
|
42
|
-
minInterval?: number;
|
|
43
|
-
maxInterval?: number;
|
|
44
|
-
});
|
|
45
|
-
initialize(type: EventType, sessionId?: number): Promise<void>;
|
|
46
|
-
/**
|
|
47
|
-
* Determines whether to send the events list to the backend and start a new
|
|
48
|
-
* empty events list, based on the size of the list as well as the last time sent
|
|
49
|
-
* @param nextEventString
|
|
50
|
-
* @returns boolean
|
|
51
|
-
*/
|
|
52
|
-
shouldSplitEventsList: (events: Events, nextEventString: string) => boolean;
|
|
53
|
-
getSequencesToSend: () => Promise<Required<SendingSequencesIDBInput>[] | undefined>;
|
|
28
|
+
db: IDBPDatabase<SessionReplayDB>;
|
|
29
|
+
} & BaseInstanceArgs;
|
|
30
|
+
export declare class SessionReplayEventsIDBStore extends BaseEventsStore<number> {
|
|
31
|
+
private readonly apiKey;
|
|
32
|
+
private readonly db;
|
|
33
|
+
constructor(args: InstanceArgs);
|
|
34
|
+
static new(type: EventType, args: Omit<InstanceArgs, 'db'>, sessionId?: number): Promise<SessionReplayEventsIDBStore | undefined>;
|
|
35
|
+
getCurrentSequenceEvents(sessionId?: number): Promise<Omit<SendingSequencesReturn<number>, "sequenceId">[] | undefined>;
|
|
36
|
+
getSequencesToSend: () => Promise<SendingSequencesReturn<number>[] | undefined>;
|
|
54
37
|
storeCurrentSequence: (sessionId: number) => Promise<{
|
|
55
38
|
sessionId: number;
|
|
56
39
|
sequenceId: number;
|
|
@@ -62,15 +45,8 @@ export declare class SessionReplayEventsIDBStore implements AmplitudeSessionRepl
|
|
|
62
45
|
sequenceId: number;
|
|
63
46
|
} | undefined>;
|
|
64
47
|
storeSendingEvents: (sessionId: number, events: Events) => Promise<number | undefined>;
|
|
65
|
-
cleanUpSessionEventsStore: (
|
|
48
|
+
cleanUpSessionEventsStore: (_sessionId: number, sequenceId?: number) => Promise<void>;
|
|
66
49
|
transitionFromKeyValStore: (sessionId?: number) => Promise<void>;
|
|
67
50
|
}
|
|
68
|
-
export
|
|
69
|
-
loggerProvider: ILogger;
|
|
70
|
-
apiKey: string;
|
|
71
|
-
type: EventType;
|
|
72
|
-
minInterval?: number | undefined;
|
|
73
|
-
maxInterval?: number | undefined;
|
|
74
|
-
sessionId?: number | undefined;
|
|
75
|
-
}) => Promise<SessionReplayEventsIDBStore>;
|
|
51
|
+
export {};
|
|
76
52
|
//# sourceMappingURL=events-idb-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-idb-store.d.ts","sourceRoot":"","sources":["../../../src/events/events-idb-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"events-idb-store.d.ts","sourceRoot":"","sources":["../../../src/events/events-idb-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAU,MAAM,KAAK,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGxF,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAC3D,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AACpD,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC/C,sBAAsB,EAAE;QACtB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;KAC3D,CAAC;IACF,eAAe,EAAE;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;QAC1D,OAAO,EAAE;YAAE,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KAChC,CAAC;CACH;AAED,eAAO,MAAM,oBAAoB,QAAgB,QAAQ,WAAW,GAAG,IAAI,CA4B1E,CAAC;AAUF,eAAO,MAAM,kBAAkB,OAAQ,aAAa,eAAe,CAAC;;;CAmBnE,CAAC;AAEF,eAAO,MAAM,WAAW,WAAkB,MAAM,2CAI/C,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;CACnC,GAAG,gBAAgB,CAAC;AAErB,qBAAa,2BAA4B,SAAQ,eAAe,CAAC,MAAM,CAAC;IACtE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAgC;gBAEvC,IAAI,EAAE,YAAY;WAMjB,GAAG,CACd,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAC9B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC;IAiB7C,wBAAwB,CAAC,SAAS,CAAC,EAAE,MAAM;IAiBjD,kBAAkB,QAAa,QAAQ,uBAAuB,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAmBlF;IAEF,oBAAoB,cAAqB,MAAM;;;;mBAuB7C;IAEF,yBAAyB,cAAqB,MAAM,SAAS,MAAM;;;;mBAuCjE;IAEF,kBAAkB,cAAqB,MAAM,iDAW3C;IAEF,yBAAyB,eAAsB,MAAM,eAAe,MAAM,mBASxE;IAEF,yBAAyB,eAAsB,MAAM,mBA6EnD;CACH"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { __assign, __awaiter, __generator } from "tslib";
|
|
1
|
+
import { __assign, __awaiter, __extends, __generator, __values } from "tslib";
|
|
2
2
|
import { getGlobalScope } from '@amplitude/analytics-client-common';
|
|
3
3
|
import { STORAGE_PREFIX } from '@amplitude/analytics-core';
|
|
4
4
|
import { openDB } from 'idb';
|
|
5
|
-
import { MAX_EVENT_LIST_SIZE_IN_BYTES, MAX_INTERVAL, MIN_INTERVAL } from '../constants';
|
|
6
5
|
import { STORAGE_FAILURE } from '../messages';
|
|
6
|
+
import { BaseEventsStore } from './base-events-store';
|
|
7
7
|
import { RecordingStatus } from './legacy-idb-types';
|
|
8
8
|
export var currentSequenceKey = 'sessionCurrentSequence';
|
|
9
9
|
export var sequencesToSendKey = 'sequencesToSend';
|
|
@@ -82,63 +82,48 @@ export var createStore = function (dbName) { return __awaiter(void 0, void 0, vo
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
}); };
|
|
85
|
-
var SessionReplayEventsIDBStore = /** @class */ (function () {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
var _this = this;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
this.timeAtLastSplit = null;
|
|
92
|
-
/**
|
|
93
|
-
* Determines whether to send the events list to the backend and start a new
|
|
94
|
-
* empty events list, based on the size of the list as well as the last time sent
|
|
95
|
-
* @param nextEventString
|
|
96
|
-
* @returns boolean
|
|
97
|
-
*/
|
|
98
|
-
this.shouldSplitEventsList = function (events, nextEventString) {
|
|
99
|
-
var sizeOfNextEvent = new Blob([nextEventString]).size;
|
|
100
|
-
var sizeOfEventsList = new Blob(events).size;
|
|
101
|
-
if (sizeOfEventsList + sizeOfNextEvent >= _this.maxPersistedEventsSize) {
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
if (_this.timeAtLastSplit !== null &&
|
|
105
|
-
_this.interval &&
|
|
106
|
-
Date.now() - _this.timeAtLastSplit > _this.interval &&
|
|
107
|
-
events.length) {
|
|
108
|
-
_this.interval = Math.min(_this.maxInterval, _this.interval + _this.minInterval);
|
|
109
|
-
_this.timeAtLastSplit = Date.now();
|
|
110
|
-
return true;
|
|
111
|
-
}
|
|
112
|
-
return false;
|
|
113
|
-
};
|
|
114
|
-
this.getSequencesToSend = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
115
|
-
var sequencesToSend, e_1;
|
|
116
|
-
var _a;
|
|
85
|
+
var SessionReplayEventsIDBStore = /** @class */ (function (_super) {
|
|
86
|
+
__extends(SessionReplayEventsIDBStore, _super);
|
|
87
|
+
function SessionReplayEventsIDBStore(args) {
|
|
88
|
+
var _this = _super.call(this, args) || this;
|
|
89
|
+
_this.getSequencesToSend = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
90
|
+
var sequences, cursor, _a, sessionId, events, e_1;
|
|
117
91
|
return __generator(this, function (_b) {
|
|
118
92
|
switch (_b.label) {
|
|
119
93
|
case 0:
|
|
120
|
-
_b.trys.push([0,
|
|
121
|
-
|
|
94
|
+
_b.trys.push([0, 5, , 6]);
|
|
95
|
+
sequences = [];
|
|
96
|
+
return [4 /*yield*/, this.db.transaction('sequencesToSend').store.openCursor()];
|
|
122
97
|
case 1:
|
|
123
|
-
|
|
124
|
-
|
|
98
|
+
cursor = _b.sent();
|
|
99
|
+
_b.label = 2;
|
|
125
100
|
case 2:
|
|
101
|
+
if (!cursor) return [3 /*break*/, 4];
|
|
102
|
+
_a = cursor.value, sessionId = _a.sessionId, events = _a.events;
|
|
103
|
+
sequences.push({
|
|
104
|
+
events: events,
|
|
105
|
+
sequenceId: cursor.key,
|
|
106
|
+
sessionId: sessionId,
|
|
107
|
+
});
|
|
108
|
+
return [4 /*yield*/, cursor.continue()];
|
|
109
|
+
case 3:
|
|
110
|
+
cursor = _b.sent();
|
|
111
|
+
return [3 /*break*/, 2];
|
|
112
|
+
case 4: return [2 /*return*/, sequences];
|
|
113
|
+
case 5:
|
|
126
114
|
e_1 = _b.sent();
|
|
127
115
|
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_1));
|
|
128
|
-
return [3 /*break*/,
|
|
129
|
-
case
|
|
116
|
+
return [3 /*break*/, 6];
|
|
117
|
+
case 6: return [2 /*return*/, undefined];
|
|
130
118
|
}
|
|
131
119
|
});
|
|
132
120
|
}); };
|
|
133
|
-
|
|
121
|
+
_this.storeCurrentSequence = function (sessionId) { return __awaiter(_this, void 0, void 0, function () {
|
|
134
122
|
var currentSequenceData, sequenceId, e_2;
|
|
135
123
|
return __generator(this, function (_a) {
|
|
136
124
|
switch (_a.label) {
|
|
137
125
|
case 0:
|
|
138
126
|
_a.trys.push([0, 4, , 5]);
|
|
139
|
-
if (!this.db) {
|
|
140
|
-
return [2 /*return*/, undefined];
|
|
141
|
-
}
|
|
142
127
|
return [4 /*yield*/, this.db.get(currentSequenceKey, sessionId)];
|
|
143
128
|
case 1:
|
|
144
129
|
currentSequenceData = _a.sent();
|
|
@@ -163,55 +148,46 @@ var SessionReplayEventsIDBStore = /** @class */ (function () {
|
|
|
163
148
|
}
|
|
164
149
|
});
|
|
165
150
|
}); };
|
|
166
|
-
|
|
151
|
+
_this.addEventToCurrentSequence = function (sessionId, event) { return __awaiter(_this, void 0, void 0, function () {
|
|
167
152
|
var tx, sequenceEvents, eventsToSend, updatedEvents, sequenceId, e_3;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
switch (_b.label) {
|
|
153
|
+
return __generator(this, function (_a) {
|
|
154
|
+
switch (_a.label) {
|
|
171
155
|
case 0:
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
_b.label = 1;
|
|
176
|
-
case 1:
|
|
177
|
-
_b.trys.push([1, 11, , 12]);
|
|
178
|
-
tx = (_a = this.db) === null || _a === void 0 ? void 0 : _a.transaction(currentSequenceKey, 'readwrite');
|
|
179
|
-
if (!tx) {
|
|
180
|
-
return [2 /*return*/];
|
|
181
|
-
}
|
|
156
|
+
_a.trys.push([0, 10, , 11]);
|
|
157
|
+
tx = this.db.transaction(currentSequenceKey, 'readwrite');
|
|
182
158
|
return [4 /*yield*/, tx.store.get(sessionId)];
|
|
183
|
-
case
|
|
184
|
-
sequenceEvents =
|
|
185
|
-
if (!!sequenceEvents) return [3 /*break*/,
|
|
159
|
+
case 1:
|
|
160
|
+
sequenceEvents = _a.sent();
|
|
161
|
+
if (!!sequenceEvents) return [3 /*break*/, 3];
|
|
186
162
|
return [4 /*yield*/, tx.store.put({ sessionId: sessionId, events: [event] })];
|
|
187
|
-
case
|
|
188
|
-
|
|
163
|
+
case 2:
|
|
164
|
+
_a.sent();
|
|
189
165
|
return [2 /*return*/];
|
|
190
|
-
case
|
|
166
|
+
case 3:
|
|
191
167
|
eventsToSend = void 0;
|
|
192
|
-
if (!this.shouldSplitEventsList(sequenceEvents.events, event)) return [3 /*break*/,
|
|
168
|
+
if (!this.shouldSplitEventsList(sequenceEvents.events, event)) return [3 /*break*/, 5];
|
|
193
169
|
eventsToSend = sequenceEvents.events;
|
|
194
170
|
// set store to empty array
|
|
195
171
|
return [4 /*yield*/, tx.store.put({ sessionId: sessionId, events: [event] })];
|
|
196
|
-
case
|
|
172
|
+
case 4:
|
|
197
173
|
// set store to empty array
|
|
198
|
-
|
|
199
|
-
return [3 /*break*/,
|
|
200
|
-
case
|
|
174
|
+
_a.sent();
|
|
175
|
+
return [3 /*break*/, 7];
|
|
176
|
+
case 5:
|
|
201
177
|
updatedEvents = sequenceEvents.events.concat(event);
|
|
202
178
|
return [4 /*yield*/, tx.store.put({ sessionId: sessionId, events: updatedEvents })];
|
|
203
|
-
case
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
case
|
|
207
|
-
case
|
|
208
|
-
|
|
179
|
+
case 6:
|
|
180
|
+
_a.sent();
|
|
181
|
+
_a.label = 7;
|
|
182
|
+
case 7: return [4 /*yield*/, tx.done];
|
|
183
|
+
case 8:
|
|
184
|
+
_a.sent();
|
|
209
185
|
if (!eventsToSend) {
|
|
210
186
|
return [2 /*return*/, undefined];
|
|
211
187
|
}
|
|
212
188
|
return [4 /*yield*/, this.storeSendingEvents(sessionId, eventsToSend)];
|
|
213
|
-
case
|
|
214
|
-
sequenceId =
|
|
189
|
+
case 9:
|
|
190
|
+
sequenceId = _a.sent();
|
|
215
191
|
if (!sequenceId) {
|
|
216
192
|
return [2 /*return*/, undefined];
|
|
217
193
|
}
|
|
@@ -220,56 +196,59 @@ var SessionReplayEventsIDBStore = /** @class */ (function () {
|
|
|
220
196
|
sessionId: sessionId,
|
|
221
197
|
sequenceId: sequenceId,
|
|
222
198
|
}];
|
|
223
|
-
case
|
|
224
|
-
e_3 =
|
|
199
|
+
case 10:
|
|
200
|
+
e_3 = _a.sent();
|
|
225
201
|
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_3));
|
|
226
|
-
return [3 /*break*/,
|
|
227
|
-
case
|
|
202
|
+
return [3 /*break*/, 11];
|
|
203
|
+
case 11: return [2 /*return*/, undefined];
|
|
228
204
|
}
|
|
229
205
|
});
|
|
230
206
|
}); };
|
|
231
|
-
|
|
207
|
+
_this.storeSendingEvents = function (sessionId, events) { return __awaiter(_this, void 0, void 0, function () {
|
|
232
208
|
var sequenceId, e_4;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
switch (_b.label) {
|
|
209
|
+
return __generator(this, function (_a) {
|
|
210
|
+
switch (_a.label) {
|
|
236
211
|
case 0:
|
|
237
|
-
|
|
238
|
-
return [4 /*yield*/,
|
|
212
|
+
_a.trys.push([0, 2, , 3]);
|
|
213
|
+
return [4 /*yield*/, this.db.put(sequencesToSendKey, {
|
|
239
214
|
sessionId: sessionId,
|
|
240
215
|
events: events,
|
|
241
|
-
})
|
|
216
|
+
})];
|
|
242
217
|
case 1:
|
|
243
|
-
sequenceId =
|
|
218
|
+
sequenceId = _a.sent();
|
|
244
219
|
return [2 /*return*/, sequenceId];
|
|
245
220
|
case 2:
|
|
246
|
-
e_4 =
|
|
221
|
+
e_4 = _a.sent();
|
|
247
222
|
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_4));
|
|
248
223
|
return [3 /*break*/, 3];
|
|
249
224
|
case 3: return [2 /*return*/, undefined];
|
|
250
225
|
}
|
|
251
226
|
});
|
|
252
227
|
}); };
|
|
253
|
-
|
|
228
|
+
_this.cleanUpSessionEventsStore = function (_sessionId, sequenceId) { return __awaiter(_this, void 0, void 0, function () {
|
|
254
229
|
var e_5;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
switch (_b.label) {
|
|
230
|
+
return __generator(this, function (_a) {
|
|
231
|
+
switch (_a.label) {
|
|
258
232
|
case 0:
|
|
259
|
-
|
|
260
|
-
|
|
233
|
+
if (!sequenceId) {
|
|
234
|
+
return [2 /*return*/];
|
|
235
|
+
}
|
|
236
|
+
_a.label = 1;
|
|
261
237
|
case 1:
|
|
262
|
-
|
|
263
|
-
return [
|
|
238
|
+
_a.trys.push([1, 3, , 4]);
|
|
239
|
+
return [4 /*yield*/, this.db.delete(sequencesToSendKey, sequenceId)];
|
|
264
240
|
case 2:
|
|
265
|
-
|
|
241
|
+
_a.sent();
|
|
242
|
+
return [3 /*break*/, 4];
|
|
243
|
+
case 3:
|
|
244
|
+
e_5 = _a.sent();
|
|
266
245
|
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_5));
|
|
267
|
-
return [3 /*break*/,
|
|
268
|
-
case
|
|
246
|
+
return [3 /*break*/, 4];
|
|
247
|
+
case 4: return [2 /*return*/];
|
|
269
248
|
}
|
|
270
249
|
});
|
|
271
250
|
}); };
|
|
272
|
-
|
|
251
|
+
_this.transitionFromKeyValStore = function (sessionId) { return __awaiter(_this, void 0, void 0, function () {
|
|
273
252
|
var keyValDb, transitionCurrentSessionSequences_1, storageKey, getAllRequest_1, transitionPromise, globalScope, e_6, e_7;
|
|
274
253
|
var _this = this;
|
|
275
254
|
return __generator(this, function (_a) {
|
|
@@ -374,56 +353,85 @@ var SessionReplayEventsIDBStore = /** @class */ (function () {
|
|
|
374
353
|
}
|
|
375
354
|
});
|
|
376
355
|
}); };
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
this.minInterval = minInterval !== null && minInterval !== void 0 ? minInterval : MIN_INTERVAL;
|
|
381
|
-
this.interval = 0;
|
|
356
|
+
_this.apiKey = args.apiKey;
|
|
357
|
+
_this.db = args.db;
|
|
358
|
+
return _this;
|
|
382
359
|
}
|
|
383
|
-
SessionReplayEventsIDBStore.
|
|
360
|
+
SessionReplayEventsIDBStore.new = function (type, args, sessionId) {
|
|
384
361
|
return __awaiter(this, void 0, void 0, function () {
|
|
385
|
-
var dbSuffix, dbName,
|
|
386
|
-
return __generator(this, function (
|
|
387
|
-
switch (
|
|
362
|
+
var dbSuffix, dbName, db, eventsIDBStore, e_8;
|
|
363
|
+
return __generator(this, function (_a) {
|
|
364
|
+
switch (_a.label) {
|
|
388
365
|
case 0:
|
|
389
|
-
|
|
366
|
+
_a.trys.push([0, 3, , 4]);
|
|
390
367
|
dbSuffix = type === 'replay' ? '' : "_".concat(type);
|
|
391
|
-
dbName = "".concat(
|
|
392
|
-
_a = this;
|
|
368
|
+
dbName = "".concat(args.apiKey.substring(0, 10), "_amp_session_replay_events").concat(dbSuffix);
|
|
393
369
|
return [4 /*yield*/, createStore(dbName)];
|
|
394
370
|
case 1:
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return [4 /*yield*/,
|
|
371
|
+
db = _a.sent();
|
|
372
|
+
eventsIDBStore = new SessionReplayEventsIDBStore(__assign(__assign({}, args), { db: db }));
|
|
373
|
+
return [4 /*yield*/, eventsIDBStore.transitionFromKeyValStore(sessionId)];
|
|
398
374
|
case 2:
|
|
399
|
-
|
|
400
|
-
return [
|
|
375
|
+
_a.sent();
|
|
376
|
+
return [2 /*return*/, eventsIDBStore];
|
|
401
377
|
case 3:
|
|
402
|
-
e_8 =
|
|
403
|
-
|
|
378
|
+
e_8 = _a.sent();
|
|
379
|
+
args.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_8));
|
|
404
380
|
return [3 /*break*/, 4];
|
|
405
381
|
case 4: return [2 /*return*/];
|
|
406
382
|
}
|
|
407
383
|
});
|
|
408
384
|
});
|
|
409
385
|
};
|
|
386
|
+
SessionReplayEventsIDBStore.prototype.getCurrentSequenceEvents = function (sessionId) {
|
|
387
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
388
|
+
var events, allEvents, _a, _b, events, e_9_1;
|
|
389
|
+
var e_9, _c;
|
|
390
|
+
return __generator(this, function (_d) {
|
|
391
|
+
switch (_d.label) {
|
|
392
|
+
case 0:
|
|
393
|
+
if (!sessionId) return [3 /*break*/, 2];
|
|
394
|
+
return [4 /*yield*/, this.db.get('sessionCurrentSequence', sessionId)];
|
|
395
|
+
case 1:
|
|
396
|
+
events = _d.sent();
|
|
397
|
+
if (!events) {
|
|
398
|
+
return [2 /*return*/, undefined];
|
|
399
|
+
}
|
|
400
|
+
return [2 /*return*/, [events]];
|
|
401
|
+
case 2:
|
|
402
|
+
allEvents = [];
|
|
403
|
+
_d.label = 3;
|
|
404
|
+
case 3:
|
|
405
|
+
_d.trys.push([3, 8, 9, 10]);
|
|
406
|
+
return [4 /*yield*/, this.db.getAll('sessionCurrentSequence')];
|
|
407
|
+
case 4:
|
|
408
|
+
_a = __values.apply(void 0, [_d.sent()]), _b = _a.next();
|
|
409
|
+
_d.label = 5;
|
|
410
|
+
case 5:
|
|
411
|
+
if (!!_b.done) return [3 /*break*/, 7];
|
|
412
|
+
events = _b.value;
|
|
413
|
+
allEvents.push(events);
|
|
414
|
+
_d.label = 6;
|
|
415
|
+
case 6:
|
|
416
|
+
_b = _a.next();
|
|
417
|
+
return [3 /*break*/, 5];
|
|
418
|
+
case 7: return [3 /*break*/, 10];
|
|
419
|
+
case 8:
|
|
420
|
+
e_9_1 = _d.sent();
|
|
421
|
+
e_9 = { error: e_9_1 };
|
|
422
|
+
return [3 /*break*/, 10];
|
|
423
|
+
case 9:
|
|
424
|
+
try {
|
|
425
|
+
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
426
|
+
}
|
|
427
|
+
finally { if (e_9) throw e_9.error; }
|
|
428
|
+
return [7 /*endfinally*/];
|
|
429
|
+
case 10: return [2 /*return*/, allEvents];
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
};
|
|
410
434
|
return SessionReplayEventsIDBStore;
|
|
411
|
-
}());
|
|
435
|
+
}(BaseEventsStore));
|
|
412
436
|
export { SessionReplayEventsIDBStore };
|
|
413
|
-
export var createEventsIDBStore = function (_a) {
|
|
414
|
-
var loggerProvider = _a.loggerProvider, apiKey = _a.apiKey, sessionId = _a.sessionId, type = _a.type, minInterval = _a.minInterval, maxInterval = _a.maxInterval;
|
|
415
|
-
return __awaiter(void 0, void 0, void 0, function () {
|
|
416
|
-
var eventsIDBStore;
|
|
417
|
-
return __generator(this, function (_b) {
|
|
418
|
-
switch (_b.label) {
|
|
419
|
-
case 0:
|
|
420
|
-
eventsIDBStore = new SessionReplayEventsIDBStore({ loggerProvider: loggerProvider, apiKey: apiKey, minInterval: minInterval, maxInterval: maxInterval });
|
|
421
|
-
return [4 /*yield*/, eventsIDBStore.initialize(type, sessionId)];
|
|
422
|
-
case 1:
|
|
423
|
-
_b.sent();
|
|
424
|
-
return [2 /*return*/, eventsIDBStore];
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
});
|
|
428
|
-
};
|
|
429
437
|
//# sourceMappingURL=events-idb-store.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-idb-store.js","sourceRoot":"","sources":["../../../src/events/events-idb-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getGlobalScope } from '@amplitude/analytics-client-common';\nimport { STORAGE_PREFIX } from '@amplitude/analytics-core';\nimport { Logger as ILogger } from '@amplitude/analytics-types';\nimport { DBSchema, IDBPDatabase, openDB } from 'idb';\nimport { MAX_EVENT_LIST_SIZE_IN_BYTES, MAX_INTERVAL, MIN_INTERVAL } from '../constants';\nimport { STORAGE_FAILURE } from '../messages';\nimport {\n SessionReplayEventsIDBStore as AmplitudeSessionReplayEventsIDBStore,\n EventType,\n Events,\n SendingSequencesIDBInput,\n SendingSequencesIDBReturn,\n} from '../typings/session-replay';\nimport { IDBStore, IDBStoreSession, RecordingStatus } from './legacy-idb-types';\n\nexport const currentSequenceKey = 'sessionCurrentSequence';\nexport const sequencesToSendKey = 'sequencesToSend';\nexport const remoteConfigKey = 'remoteConfig';\n\nexport interface SessionReplayDB extends DBSchema {\n sessionCurrentSequence: {\n key: number;\n value: {\n sessionId: number;\n events: Events;\n };\n };\n sequencesToSend: {\n key: number;\n value: SendingSequencesIDBInput;\n indexes: { sessionId: number };\n };\n}\n\nexport const keyValDatabaseExists = function (): Promise<IDBDatabase | void> {\n const globalScope = getGlobalScope();\n return new Promise((resolve, reject) => {\n if (!globalScope) {\n return reject(new Error('Global scope not found'));\n }\n\n if (!globalScope.indexedDB) {\n return reject(new Error('Session Replay: cannot find indexedDB'));\n }\n\n try {\n const request = globalScope.indexedDB.open('keyval-store');\n request.onupgradeneeded = function () {\n if (request.result.version === 1) {\n request.result.close();\n request.transaction && request.transaction.abort();\n globalScope.indexedDB.deleteDatabase('keyval-store');\n resolve();\n }\n };\n request.onsuccess = function () {\n resolve(request.result);\n };\n } catch (e) {\n reject(e);\n }\n });\n};\n\nconst batchPromiseAll = async (promiseBatch: Promise<any>[]) => {\n while (promiseBatch.length > 0) {\n const chunkSize = 10;\n const batch = promiseBatch.splice(0, chunkSize);\n await Promise.all(batch);\n }\n};\n\nexport const defineObjectStores = (db: IDBPDatabase<SessionReplayDB>) => {\n let sequencesStore;\n let currentSequenceStore;\n if (!db.objectStoreNames.contains(currentSequenceKey)) {\n currentSequenceStore = db.createObjectStore(currentSequenceKey, {\n keyPath: 'sessionId',\n });\n }\n if (!db.objectStoreNames.contains(sequencesToSendKey)) {\n sequencesStore = db.createObjectStore(sequencesToSendKey, {\n keyPath: 'sequenceId',\n autoIncrement: true,\n });\n sequencesStore.createIndex('sessionId', 'sessionId');\n }\n return {\n sequencesStore,\n currentSequenceStore,\n };\n};\n\nexport const createStore = async (dbName: string) => {\n return await openDB<SessionReplayDB>(dbName, 1, {\n upgrade: defineObjectStores,\n });\n};\nexport class SessionReplayEventsIDBStore implements AmplitudeSessionReplayEventsIDBStore {\n apiKey: string;\n db: IDBPDatabase<SessionReplayDB> | undefined;\n loggerProvider: ILogger;\n storageKey = '';\n maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;\n interval: number;\n timeAtLastSplit: number | null = null;\n\n private readonly minInterval: number;\n private readonly maxInterval: number;\n\n constructor({\n loggerProvider,\n apiKey,\n minInterval,\n maxInterval,\n }: {\n loggerProvider: ILogger;\n apiKey: string;\n minInterval?: number;\n maxInterval?: number;\n }) {\n this.loggerProvider = loggerProvider;\n this.apiKey = apiKey;\n this.maxInterval = maxInterval ?? MAX_INTERVAL;\n this.minInterval = minInterval ?? MIN_INTERVAL;\n this.interval = 0;\n }\n\n async initialize(type: EventType, sessionId?: number) {\n try {\n const dbSuffix = type === 'replay' ? '' : `_${type}`;\n const dbName = `${this.apiKey.substring(0, 10)}_amp_session_replay_events${dbSuffix}`;\n this.db = await createStore(dbName);\n this.timeAtLastSplit = Date.now(); // Initialize this so we have a point of comparison when events are recorded\n await this.transitionFromKeyValStore(sessionId);\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\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 = (events: Events, nextEventString: string): boolean => {\n const sizeOfNextEvent = new Blob([nextEventString]).size;\n const sizeOfEventsList = new Blob(events).size;\n if (sizeOfEventsList + sizeOfNextEvent >= this.maxPersistedEventsSize) {\n return true;\n }\n if (\n this.timeAtLastSplit !== null &&\n this.interval &&\n Date.now() - this.timeAtLastSplit > this.interval &&\n events.length\n ) {\n this.interval = Math.min(this.maxInterval, this.interval + this.minInterval);\n this.timeAtLastSplit = Date.now();\n return true;\n }\n return false;\n };\n\n getSequencesToSend = async () => {\n try {\n const sequencesToSend = (await this.db?.getAll<'sequencesToSend'>(\n sequencesToSendKey,\n )) as SendingSequencesIDBReturn[];\n\n return sequencesToSend;\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n storeCurrentSequence = async (sessionId: number) => {\n try {\n if (!this.db) {\n return undefined;\n }\n const currentSequenceData = await this.db.get<'sessionCurrentSequence'>(currentSequenceKey, sessionId);\n if (!currentSequenceData) {\n return undefined;\n }\n\n const sequenceId = await this.db.put<'sequencesToSend'>(sequencesToSendKey, {\n sessionId: sessionId,\n events: currentSequenceData.events,\n });\n\n await this.db.put<'sessionCurrentSequence'>(currentSequenceKey, { sessionId, events: [] });\n\n return {\n ...currentSequenceData,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n addEventToCurrentSequence = async (sessionId: number, event: string) => {\n if (this.interval === 0) {\n this.interval = this.minInterval;\n }\n\n try {\n const tx = this.db?.transaction<'sessionCurrentSequence', 'readwrite'>(currentSequenceKey, 'readwrite');\n if (!tx) {\n return;\n }\n const sequenceEvents = await tx.store.get(sessionId);\n if (!sequenceEvents) {\n await tx.store.put({ sessionId, events: [event] });\n return;\n }\n let eventsToSend;\n if (this.shouldSplitEventsList(sequenceEvents.events, event)) {\n eventsToSend = sequenceEvents.events;\n // set store to empty array\n await tx.store.put({ sessionId, events: [event] });\n } else {\n // add event to array\n const updatedEvents = sequenceEvents.events.concat(event);\n await tx.store.put({ sessionId, events: updatedEvents });\n }\n\n await tx.done;\n if (!eventsToSend) {\n return undefined;\n }\n\n const sequenceId = await this.storeSendingEvents(sessionId, eventsToSend);\n\n if (!sequenceId) {\n return undefined;\n }\n\n return {\n events: eventsToSend,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n storeSendingEvents = async (sessionId: number, events: Events) => {\n try {\n const sequenceId = await this.db?.put<'sequencesToSend'>(sequencesToSendKey, {\n sessionId: sessionId,\n events: events,\n });\n return sequenceId;\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n cleanUpSessionEventsStore = async (sequenceId: number) => {\n try {\n await this.db?.delete<'sequencesToSend'>(sequencesToSendKey, sequenceId);\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n };\n\n transitionFromKeyValStore = async (sessionId?: number) => {\n try {\n const keyValDb = await keyValDatabaseExists();\n if (!keyValDb) {\n return;\n }\n\n const transitionCurrentSessionSequences = async (numericSessionId: number, sessionStore: IDBStoreSession) => {\n const currentSessionSequences = sessionStore.sessionSequences;\n const promisesToBatch: Promise<number | SendingSequencesIDBReturn | undefined>[] = [];\n\n Object.keys(currentSessionSequences).forEach((sequenceId) => {\n const numericSequenceId = parseInt(sequenceId, 10);\n const sequence = currentSessionSequences[numericSequenceId];\n if (numericSequenceId === sessionStore.currentSequenceId) {\n const eventAddPromises: Promise<SendingSequencesIDBReturn | undefined>[] = sequence.events.map(\n async (event) => this.addEventToCurrentSequence(numericSessionId, event),\n );\n promisesToBatch.concat(eventAddPromises);\n } else if (sequence.status !== RecordingStatus.SENT) {\n promisesToBatch.push(this.storeSendingEvents(numericSessionId, sequence.events));\n }\n });\n\n await batchPromiseAll(promisesToBatch);\n };\n\n const storageKey = `${STORAGE_PREFIX}_${this.apiKey.substring(0, 10)}`;\n try {\n const getAllRequest = keyValDb.transaction('keyval').objectStore('keyval').getAll(storageKey);\n const transitionPromise = new Promise<void>((resolve) => {\n getAllRequest.onsuccess = async (e) => {\n const storedReplaySessionContextList = e && ((e.target as IDBRequest).result as IDBStore[]);\n const storedReplaySessionContexts = storedReplaySessionContextList && storedReplaySessionContextList[0];\n if (storedReplaySessionContexts) {\n const promisesToBatch: Promise<any>[] = [];\n\n Object.keys(storedReplaySessionContexts).forEach((storedSessionId) => {\n const numericSessionId = parseInt(storedSessionId, 10);\n const oldSessionStore = storedReplaySessionContexts[numericSessionId];\n\n if (sessionId === numericSessionId) {\n promisesToBatch.push(transitionCurrentSessionSequences(numericSessionId, oldSessionStore));\n } else {\n const oldSessionSequences = oldSessionStore.sessionSequences;\n Object.keys(oldSessionSequences).forEach((sequenceId) => {\n const numericSequenceId = parseInt(sequenceId, 10);\n if (oldSessionSequences[numericSequenceId].status !== RecordingStatus.SENT) {\n promisesToBatch.push(\n this.storeSendingEvents(numericSessionId, oldSessionSequences[numericSequenceId].events),\n );\n }\n });\n }\n });\n\n await batchPromiseAll(promisesToBatch);\n }\n resolve();\n };\n });\n\n await transitionPromise;\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.indexedDB.deleteDatabase('keyval-store');\n }\n } catch (e) {\n this.loggerProvider.warn(`Failed to transition session replay events from keyval to new store: ${e as string}`);\n }\n } catch (e) {\n this.loggerProvider.warn(\n `Failed to access keyval store: ${\n e as string\n }. For more information, visit: https://www.docs.developers.amplitude.com/session-replay/sdks/standalone/#indexeddb-best-practices`,\n );\n }\n };\n}\n\nexport const createEventsIDBStore = async ({\n loggerProvider,\n apiKey,\n sessionId,\n type,\n minInterval,\n maxInterval,\n}: {\n loggerProvider: ILogger;\n apiKey: string;\n type: EventType;\n minInterval?: number;\n maxInterval?: number;\n sessionId?: number;\n}) => {\n const eventsIDBStore = new SessionReplayEventsIDBStore({ loggerProvider, apiKey, minInterval, maxInterval });\n await eventsIDBStore.initialize(type, sessionId);\n return eventsIDBStore;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"events-idb-store.js","sourceRoot":"","sources":["../../../src/events/events-idb-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getGlobalScope } from '@amplitude/analytics-client-common';\nimport { STORAGE_PREFIX } from '@amplitude/analytics-core';\nimport { DBSchema, IDBPDatabase, openDB } from 'idb';\nimport { STORAGE_FAILURE } from '../messages';\nimport { EventType, Events, SendingSequencesReturn } from '../typings/session-replay';\nimport { BaseEventsStore, InstanceArgs as BaseInstanceArgs } from './base-events-store';\nimport { IDBStore, IDBStoreSession, RecordingStatus } from './legacy-idb-types';\n\nexport const currentSequenceKey = 'sessionCurrentSequence';\nexport const sequencesToSendKey = 'sequencesToSend';\nexport const remoteConfigKey = 'remoteConfig';\n\nexport interface SessionReplayDB extends DBSchema {\n sessionCurrentSequence: {\n key: number;\n value: Omit<SendingSequencesReturn<number>, 'sequenceId'>;\n };\n sequencesToSend: {\n key: number;\n value: Omit<SendingSequencesReturn<number>, 'sequenceId'>;\n indexes: { sessionId: number };\n };\n}\n\nexport const keyValDatabaseExists = function (): Promise<IDBDatabase | void> {\n const globalScope = getGlobalScope();\n return new Promise((resolve, reject) => {\n if (!globalScope) {\n return reject(new Error('Global scope not found'));\n }\n\n if (!globalScope.indexedDB) {\n return reject(new Error('Session Replay: cannot find indexedDB'));\n }\n\n try {\n const request = globalScope.indexedDB.open('keyval-store');\n request.onupgradeneeded = function () {\n if (request.result.version === 1) {\n request.result.close();\n request.transaction && request.transaction.abort();\n globalScope.indexedDB.deleteDatabase('keyval-store');\n resolve();\n }\n };\n request.onsuccess = function () {\n resolve(request.result);\n };\n } catch (e) {\n reject(e);\n }\n });\n};\n\nconst batchPromiseAll = async (promiseBatch: Promise<any>[]) => {\n while (promiseBatch.length > 0) {\n const chunkSize = 10;\n const batch = promiseBatch.splice(0, chunkSize);\n await Promise.all(batch);\n }\n};\n\nexport const defineObjectStores = (db: IDBPDatabase<SessionReplayDB>) => {\n let sequencesStore;\n let currentSequenceStore;\n if (!db.objectStoreNames.contains(currentSequenceKey)) {\n currentSequenceStore = db.createObjectStore(currentSequenceKey, {\n keyPath: 'sessionId',\n });\n }\n if (!db.objectStoreNames.contains(sequencesToSendKey)) {\n sequencesStore = db.createObjectStore(sequencesToSendKey, {\n keyPath: 'sequenceId',\n autoIncrement: true,\n });\n sequencesStore.createIndex('sessionId', 'sessionId');\n }\n return {\n sequencesStore,\n currentSequenceStore,\n };\n};\n\nexport const createStore = async (dbName: string) => {\n return await openDB<SessionReplayDB>(dbName, 1, {\n upgrade: defineObjectStores,\n });\n};\n\ntype InstanceArgs = {\n apiKey: string;\n db: IDBPDatabase<SessionReplayDB>;\n} & BaseInstanceArgs;\n\nexport class SessionReplayEventsIDBStore extends BaseEventsStore<number> {\n private readonly apiKey: string;\n private readonly db: IDBPDatabase<SessionReplayDB>;\n\n constructor(args: InstanceArgs) {\n super(args);\n this.apiKey = args.apiKey;\n this.db = args.db;\n }\n\n static async new(\n type: EventType,\n args: Omit<InstanceArgs, 'db'>,\n sessionId?: number,\n ): Promise<SessionReplayEventsIDBStore | undefined> {\n try {\n const dbSuffix = type === 'replay' ? '' : `_${type}`;\n const dbName = `${args.apiKey.substring(0, 10)}_amp_session_replay_events${dbSuffix}`;\n const db = await createStore(dbName);\n const eventsIDBStore = new SessionReplayEventsIDBStore({\n ...args,\n db,\n });\n await eventsIDBStore.transitionFromKeyValStore(sessionId);\n return eventsIDBStore;\n } catch (e) {\n args.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return;\n }\n\n async getCurrentSequenceEvents(sessionId?: number) {\n if (sessionId) {\n const events = await this.db.get('sessionCurrentSequence', sessionId);\n if (!events) {\n return undefined;\n }\n return [events];\n }\n\n const allEvents = [];\n for (const events of await this.db.getAll('sessionCurrentSequence')) {\n allEvents.push(events);\n }\n\n return allEvents;\n }\n\n getSequencesToSend = async (): Promise<SendingSequencesReturn<number>[] | undefined> => {\n try {\n const sequences: SendingSequencesReturn<number>[] = [];\n let cursor = await this.db.transaction('sequencesToSend').store.openCursor();\n while (cursor) {\n const { sessionId, events } = cursor.value;\n sequences.push({\n events,\n sequenceId: cursor.key,\n sessionId,\n });\n cursor = await cursor.continue();\n }\n\n return sequences;\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n storeCurrentSequence = async (sessionId: number) => {\n try {\n const currentSequenceData = await this.db.get<'sessionCurrentSequence'>(currentSequenceKey, sessionId);\n if (!currentSequenceData) {\n return undefined;\n }\n\n const sequenceId = await this.db.put<'sequencesToSend'>(sequencesToSendKey, {\n sessionId: sessionId,\n events: currentSequenceData.events,\n });\n\n await this.db.put<'sessionCurrentSequence'>(currentSequenceKey, { sessionId, events: [] });\n\n return {\n ...currentSequenceData,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n addEventToCurrentSequence = async (sessionId: number, event: string) => {\n try {\n const tx = this.db.transaction<'sessionCurrentSequence', 'readwrite'>(currentSequenceKey, 'readwrite');\n const sequenceEvents = await tx.store.get(sessionId);\n if (!sequenceEvents) {\n await tx.store.put({ sessionId, events: [event] });\n return;\n }\n let eventsToSend;\n if (this.shouldSplitEventsList(sequenceEvents.events, event)) {\n eventsToSend = sequenceEvents.events;\n // set store to empty array\n await tx.store.put({ sessionId, events: [event] });\n } else {\n // add event to array\n const updatedEvents = sequenceEvents.events.concat(event);\n await tx.store.put({ sessionId, events: updatedEvents });\n }\n\n await tx.done;\n if (!eventsToSend) {\n return undefined;\n }\n\n const sequenceId = await this.storeSendingEvents(sessionId, eventsToSend);\n\n if (!sequenceId) {\n return undefined;\n }\n\n return {\n events: eventsToSend,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n storeSendingEvents = async (sessionId: number, events: Events) => {\n try {\n const sequenceId = await this.db.put<'sequencesToSend'>(sequencesToSendKey, {\n sessionId: sessionId,\n events: events,\n });\n return sequenceId;\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n };\n\n cleanUpSessionEventsStore = async (_sessionId: number, sequenceId?: number) => {\n if (!sequenceId) {\n return;\n }\n try {\n await this.db.delete<'sequencesToSend'>(sequencesToSendKey, sequenceId);\n } catch (e) {\n this.loggerProvider.warn(`${STORAGE_FAILURE}: ${e as string}`);\n }\n };\n\n transitionFromKeyValStore = async (sessionId?: number) => {\n try {\n const keyValDb = await keyValDatabaseExists();\n if (!keyValDb) {\n return;\n }\n\n const transitionCurrentSessionSequences = async (numericSessionId: number, sessionStore: IDBStoreSession) => {\n const currentSessionSequences = sessionStore.sessionSequences;\n const promisesToBatch: Promise<number | SendingSequencesReturn<number> | undefined>[] = [];\n\n Object.keys(currentSessionSequences).forEach((sequenceId) => {\n const numericSequenceId = parseInt(sequenceId, 10);\n const sequence = currentSessionSequences[numericSequenceId];\n if (numericSequenceId === sessionStore.currentSequenceId) {\n const eventAddPromises: Promise<SendingSequencesReturn<number> | undefined>[] = sequence.events.map(\n async (event) => this.addEventToCurrentSequence(numericSessionId, event),\n );\n promisesToBatch.concat(eventAddPromises);\n } else if (sequence.status !== RecordingStatus.SENT) {\n promisesToBatch.push(this.storeSendingEvents(numericSessionId, sequence.events));\n }\n });\n\n await batchPromiseAll(promisesToBatch);\n };\n\n const storageKey = `${STORAGE_PREFIX}_${this.apiKey.substring(0, 10)}`;\n try {\n const getAllRequest = keyValDb.transaction('keyval').objectStore('keyval').getAll(storageKey);\n const transitionPromise = new Promise<void>((resolve) => {\n getAllRequest.onsuccess = async (e) => {\n const storedReplaySessionContextList = e && ((e.target as IDBRequest).result as IDBStore[]);\n const storedReplaySessionContexts = storedReplaySessionContextList && storedReplaySessionContextList[0];\n if (storedReplaySessionContexts) {\n const promisesToBatch: Promise<any>[] = [];\n\n Object.keys(storedReplaySessionContexts).forEach((storedSessionId) => {\n const numericSessionId = parseInt(storedSessionId, 10);\n const oldSessionStore = storedReplaySessionContexts[numericSessionId];\n\n if (sessionId === numericSessionId) {\n promisesToBatch.push(transitionCurrentSessionSequences(numericSessionId, oldSessionStore));\n } else {\n const oldSessionSequences = oldSessionStore.sessionSequences;\n Object.keys(oldSessionSequences).forEach((sequenceId) => {\n const numericSequenceId = parseInt(sequenceId, 10);\n if (oldSessionSequences[numericSequenceId].status !== RecordingStatus.SENT) {\n promisesToBatch.push(\n this.storeSendingEvents(numericSessionId, oldSessionSequences[numericSequenceId].events),\n );\n }\n });\n }\n });\n\n await batchPromiseAll(promisesToBatch);\n }\n resolve();\n };\n });\n\n await transitionPromise;\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.indexedDB.deleteDatabase('keyval-store');\n }\n } catch (e) {\n this.loggerProvider.warn(`Failed to transition session replay events from keyval to new store: ${e as string}`);\n }\n } catch (e) {\n this.loggerProvider.warn(\n `Failed to access keyval store: ${\n e as string\n }. For more information, visit: https://www.docs.developers.amplitude.com/session-replay/sdks/standalone/#indexeddb-best-practices`,\n );\n }\n };\n}\n"]}
|