@openreplay/tracker 12.0.11 → 12.1.0-beta.99

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.
@@ -0,0 +1,37 @@
1
+ import { FromWorkerData, ToWorkerData, WorkerAuth, WorkerStart } from '../../common/interaction.js';
2
+ import App from '../index.js';
3
+ import QueueSender from './QueueSender.js';
4
+ declare enum WorkerStatus {
5
+ NotActive = 0,
6
+ Starting = 1,
7
+ Stopping = 2,
8
+ Active = 3,
9
+ Stopped = 4
10
+ }
11
+ interface TypedWorker extends Omit<Worker, 'postMessage'> {
12
+ postMessage(data: ToWorkerData): void;
13
+ }
14
+ declare class WebWorkerManager {
15
+ private readonly app;
16
+ private readonly worker;
17
+ private readonly onError;
18
+ sendIntervalID: ReturnType<typeof setInterval> | null;
19
+ restartTimeoutID: ReturnType<typeof setTimeout> | null;
20
+ workerStatus: WorkerStatus;
21
+ sender: QueueSender | null;
22
+ constructor(app: App, worker: TypedWorker, onError: (ctx: string, e: any) => any);
23
+ finalize: () => void;
24
+ resetWebWorker: () => void;
25
+ resetSender: () => void;
26
+ reset: () => void;
27
+ initiateRestart: () => void;
28
+ initiateFailure: (reason: string) => void;
29
+ processMessage: (data: ToWorkerData | null) => void;
30
+ startWorker: (data: WorkerStart) => void;
31
+ stopWorker: () => void;
32
+ authorizeWorker: (data: WorkerAuth) => void;
33
+ sendCompressedBatch: (data: Uint8Array) => void;
34
+ sendUncompressedBatch: (data: Uint8Array) => void;
35
+ postMessage: (data: FromWorkerData) => void;
36
+ }
37
+ export default WebWorkerManager;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const QueueSender_js_1 = __importDefault(require("./QueueSender.js"));
7
+ var WorkerStatus;
8
+ (function (WorkerStatus) {
9
+ WorkerStatus[WorkerStatus["NotActive"] = 0] = "NotActive";
10
+ WorkerStatus[WorkerStatus["Starting"] = 1] = "Starting";
11
+ WorkerStatus[WorkerStatus["Stopping"] = 2] = "Stopping";
12
+ WorkerStatus[WorkerStatus["Active"] = 3] = "Active";
13
+ WorkerStatus[WorkerStatus["Stopped"] = 4] = "Stopped";
14
+ })(WorkerStatus || (WorkerStatus = {}));
15
+ const AUTO_SEND_INTERVAL = 10 * 1000;
16
+ const rebroadcastEvents = ['queue_empty', 'not_init', 'restart'];
17
+ class WebWorkerManager {
18
+ constructor(app, worker, onError) {
19
+ this.app = app;
20
+ this.worker = worker;
21
+ this.onError = onError;
22
+ this.sendIntervalID = null;
23
+ this.restartTimeoutID = null;
24
+ this.workerStatus = WorkerStatus.NotActive;
25
+ this.sender = null;
26
+ this.finalize = () => {
27
+ this.worker.postMessage({ type: 'writer_finalize' });
28
+ };
29
+ this.resetWebWorker = () => {
30
+ this.worker.postMessage({ type: 'reset_writer' });
31
+ };
32
+ this.resetSender = () => {
33
+ if (!this.sender) {
34
+ return;
35
+ }
36
+ this.sender.clean();
37
+ setTimeout(() => {
38
+ this.sender = null;
39
+ }, 20);
40
+ };
41
+ this.reset = () => {
42
+ this.workerStatus = WorkerStatus.Stopping;
43
+ if (this.sendIntervalID !== null) {
44
+ clearInterval(this.sendIntervalID);
45
+ this.sendIntervalID = null;
46
+ }
47
+ this.resetSender();
48
+ this.resetWebWorker();
49
+ setTimeout(() => {
50
+ this.workerStatus = WorkerStatus.NotActive;
51
+ }, 100);
52
+ };
53
+ this.initiateRestart = () => {
54
+ if (this.workerStatus === WorkerStatus.Stopped) {
55
+ return;
56
+ }
57
+ this.postMessage({ type: 'restart' });
58
+ this.reset();
59
+ };
60
+ this.initiateFailure = (reason) => {
61
+ if ([WorkerStatus.Stopped, WorkerStatus.Stopping, WorkerStatus.NotActive].includes(this.workerStatus)) {
62
+ return;
63
+ }
64
+ this.postMessage({ type: 'failure', reason });
65
+ this.reset();
66
+ };
67
+ this.processMessage = (data) => {
68
+ if (data === null) {
69
+ this.finalize();
70
+ return;
71
+ }
72
+ if (data.type === 'batch' && Array.isArray(data.data)) {
73
+ data.data.forEach((message) => {
74
+ if (message[0] === 55 /* MType.SetPageVisibility */) {
75
+ // document is hidden
76
+ if (message[1]) {
77
+ this.restartTimeoutID = setTimeout(() => this.initiateRestart(), 30 * 60 * 1000);
78
+ }
79
+ else {
80
+ if (this.restartTimeoutID) {
81
+ clearTimeout(this.restartTimeoutID);
82
+ }
83
+ }
84
+ }
85
+ });
86
+ this.worker.postMessage({ type: 'to_writer', data: data.data });
87
+ }
88
+ };
89
+ this.startWorker = (data) => {
90
+ this.sender = new QueueSender_js_1.default(data.ingestPoint, () => {
91
+ // onUnauthorised
92
+ this.initiateRestart();
93
+ }, (reason) => {
94
+ // onFailure
95
+ this.initiateFailure(reason);
96
+ }, data.connAttemptCount, data.connAttemptGap, (batch) => {
97
+ this.postMessage({ type: 'compress', batch });
98
+ });
99
+ if (this.sendIntervalID === null) {
100
+ this.sendIntervalID = setInterval(this.finalize, AUTO_SEND_INTERVAL);
101
+ }
102
+ this.worker.postMessage(data);
103
+ return;
104
+ };
105
+ this.stopWorker = () => {
106
+ this.finalize();
107
+ this.reset();
108
+ return;
109
+ };
110
+ this.authorizeWorker = (data) => {
111
+ if (!this.sender) {
112
+ console.debug('OR WebWorker: sender not initialised. Received auth.');
113
+ this.initiateRestart();
114
+ return;
115
+ }
116
+ this.sender.authorise(data.token);
117
+ if (data.beaconSizeLimit) {
118
+ this.worker.postMessage({ type: 'beacon_size_limit', data: data.beaconSizeLimit });
119
+ }
120
+ return;
121
+ };
122
+ this.sendCompressedBatch = (data) => {
123
+ if (!this.sender) {
124
+ console.debug('OR Worker: sender not init. Compressed batch');
125
+ this.initiateRestart();
126
+ return;
127
+ }
128
+ this.sender?.sendCompressed(data);
129
+ return;
130
+ };
131
+ this.sendUncompressedBatch = (data) => {
132
+ if (!this.sender) {
133
+ console.debug('OR Worker: sender not init. Compressed batch.');
134
+ this.initiateRestart();
135
+ return;
136
+ }
137
+ if (data) {
138
+ this.sender.sendUncompressed(data);
139
+ return;
140
+ }
141
+ };
142
+ this.postMessage = (data) => {
143
+ this.app.handleWorkerMsg(data);
144
+ };
145
+ this.worker.onerror = (e) => {
146
+ this.onError('webworker_error', e);
147
+ };
148
+ this.worker.onmessage = ({ data }) => {
149
+ if (rebroadcastEvents.includes(data.type)) {
150
+ this.postMessage(data);
151
+ return;
152
+ }
153
+ switch (data.type) {
154
+ case 'status':
155
+ this.workerStatus = data.data;
156
+ return;
157
+ case 'batch_ready':
158
+ if (this.sender) {
159
+ this.app.debug.log('Openreplay: msg batch to sender: ', data.data);
160
+ this.sender.push(data.data);
161
+ }
162
+ }
163
+ };
164
+ }
165
+ }
166
+ exports.default = WebWorkerManager;
@@ -3,7 +3,61 @@ export interface Options {
3
3
  connAttemptCount?: number;
4
4
  connAttemptGap?: number;
5
5
  }
6
- type Start = {
6
+ export type ToWorkerData = null | Stop | Batch | WorkerStart | BeaconSizeLimit | ToWriterData | ForceFlushBatch | CheckQueue | ResetWriter | WriterFinalize;
7
+ export type FromWorkerData = Restart | Failure | NotInit | Compress | QEmpty | Status | BatchReady;
8
+ type BatchReady = {
9
+ type: 'batch_ready';
10
+ data: Uint8Array;
11
+ };
12
+ type Status = {
13
+ type: 'status';
14
+ data: number;
15
+ };
16
+ type Compress = {
17
+ type: 'compress';
18
+ batch: Uint8Array;
19
+ };
20
+ type Restart = {
21
+ type: 'restart';
22
+ };
23
+ type NotInit = {
24
+ type: 'not_init';
25
+ };
26
+ type Stop = {
27
+ type: 'stop';
28
+ };
29
+ type Batch = {
30
+ type: 'batch';
31
+ data: Array<Message>;
32
+ };
33
+ type ForceFlushBatch = {
34
+ type: 'forceFlushBatch';
35
+ };
36
+ type CheckQueue = {
37
+ type: 'check_queue';
38
+ };
39
+ type WriterFinalize = {
40
+ type: 'writer_finalize';
41
+ };
42
+ type ResetWriter = {
43
+ type: 'reset_writer';
44
+ };
45
+ type BeaconSizeLimit = {
46
+ type: 'beacon_size_limit';
47
+ data: number;
48
+ };
49
+ type ToWriterData = {
50
+ type: 'to_writer';
51
+ data: Array<Message>;
52
+ };
53
+ type Failure = {
54
+ type: 'failure';
55
+ reason: string;
56
+ };
57
+ type QEmpty = {
58
+ type: 'queue_empty';
59
+ };
60
+ export type WorkerStart = {
7
61
  type: 'start';
8
62
  ingestPoint: string;
9
63
  pageNo: number;
@@ -11,27 +65,8 @@ type Start = {
11
65
  url: string;
12
66
  tabId: string;
13
67
  } & Options;
14
- type Auth = {
15
- type: 'auth';
68
+ export type WorkerAuth = {
16
69
  token: string;
17
70
  beaconSizeLimit?: number;
18
71
  };
19
- export type ToWorkerData = null | 'stop' | Start | Auth | Array<Message> | {
20
- type: 'compressed';
21
- batch: Uint8Array;
22
- } | {
23
- type: 'uncompressed';
24
- batch: Uint8Array;
25
- } | 'forceFlushBatch' | 'check_queue';
26
- type Failure = {
27
- type: 'failure';
28
- reason: string;
29
- };
30
- type QEmpty = {
31
- type: 'queue_empty';
32
- };
33
- export type FromWorkerData = 'a_stop' | 'a_start' | Failure | 'not_init' | {
34
- type: 'compress';
35
- batch: Uint8Array;
36
- } | QEmpty;
37
72
  export {};
@@ -30,7 +30,7 @@ export declare const enum Type {
30
30
  Profiler = 40,
31
31
  OTable = 41,
32
32
  StateAction = 42,
33
- ReduxDeprecated = 44,
33
+ Redux = 44,
34
34
  Vuex = 45,
35
35
  MobX = 46,
36
36
  NgRx = 47,
@@ -71,7 +71,7 @@ export declare const enum Type {
71
71
  TabData = 118,
72
72
  CanvasNode = 119,
73
73
  TagTrigger = 120,
74
- Redux = 121
74
+ ReduxNew = 121
75
75
  }
76
76
  export type Timestamp = [
77
77
  Type.Timestamp,
@@ -252,8 +252,8 @@ export type StateAction = [
252
252
  Type.StateAction,
253
253
  string
254
254
  ];
255
- export type ReduxDeprecated = [
256
- Type.ReduxDeprecated,
255
+ export type Redux = [
256
+ Type.Redux,
257
257
  string,
258
258
  string,
259
259
  number
@@ -509,12 +509,12 @@ export type TagTrigger = [
509
509
  Type.TagTrigger,
510
510
  number
511
511
  ];
512
- export type Redux = [
513
- Type.Redux,
512
+ export type ReduxNew = [
513
+ Type.ReduxNew,
514
514
  string,
515
515
  string,
516
516
  number,
517
517
  number
518
518
  ];
519
- type Message = Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequestDeprecated | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | ReduxDeprecated | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | StringDict | SetNodeAttributeDict | ResourceTimingDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadata | PartitionedMessage | NetworkRequest | WSChannel | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTiming | TabChange | TabData | CanvasNode | TagTrigger | Redux;
519
+ type Message = Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequestDeprecated | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | StringDict | SetNodeAttributeDict | ResourceTimingDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadata | PartitionedMessage | NetworkRequest | WSChannel | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTiming | TabChange | TabData | CanvasNode | TagTrigger | ReduxNew;
520
520
  export default Message;
package/cjs/index.js CHANGED
@@ -97,7 +97,7 @@ class API {
97
97
  const orig = this.options.ingestPoint || index_js_1.DEFAULT_INGEST_POINT;
98
98
  req.open('POST', orig + '/v1/web/not-started');
99
99
  req.send(JSON.stringify({
100
- trackerVersion: '12.0.11',
100
+ trackerVersion: '12.1.0-beta.99',
101
101
  projectKey: this.options.projectKey,
102
102
  doNotTrack,
103
103
  reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
@@ -11,7 +11,7 @@ import type { Options as ObserverOptions } from './observer/top_observer.js';
11
11
  import type { Options as SanitizerOptions } from './sanitizer.js';
12
12
  import type { Options as SessOptions } from './session.js';
13
13
  import type { Options as NetworkOptions } from '../modules/network.js';
14
- import type { Options as WebworkerOptions } from '../common/interaction.js';
14
+ import type { Options as WebworkerOptions, FromWorkerData } from '../common/interaction.js';
15
15
  export interface StartOptions {
16
16
  userID?: string;
17
17
  metadata?: Record<string, string>;
@@ -90,7 +90,7 @@ export default class App {
90
90
  private readonly revID;
91
91
  private activityState;
92
92
  private readonly version;
93
- private readonly worker?;
93
+ private readonly workerManager?;
94
94
  private compressionThreshold;
95
95
  private restartAttempts;
96
96
  private readonly bc;
@@ -100,9 +100,10 @@ export default class App {
100
100
  private uxtManager;
101
101
  private conditionsManager;
102
102
  featureFlags: FeatureFlags;
103
- private tagWatcher;
103
+ private readonly tagWatcher;
104
104
  constructor(projectKey: string, sessionToken: string | undefined, options: Partial<Options>, signalError: (error: string, apis: string[]) => void);
105
- private _debug;
105
+ handleWorkerMsg(data: FromWorkerData): void;
106
+ private readonly _debug;
106
107
  private _usingOldFetchPlugin;
107
108
  send(message: Message, urgent?: boolean): void;
108
109
  /**
@@ -160,7 +161,7 @@ export default class App {
160
161
  private checkSessionToken;
161
162
  /**
162
163
  * start buffering messages without starting the actual session, which gives
163
- * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger
164
+ * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
164
165
  * and we will then send buffered batch, so it won't get lost
165
166
  * */
166
167
  coldStart(startOpts?: StartOptions, conditional?: boolean): Promise<void>;
@@ -178,7 +179,7 @@ export default class App {
178
179
  /**
179
180
  * Saves the captured messages in localStorage (or whatever is used in its place)
180
181
  *
181
- * Then when this.offlineRecording is called, it will preload this messages and clear the storage item
182
+ * Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
182
183
  *
183
184
  * Keeping the size of local storage reasonable is up to the end users of this library
184
185
  * */