@openreplay/tracker 12.1.0-beta.99 → 13.0.1

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.
Files changed (95) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/bun.lockb +0 -0
  3. package/cjs/app/canvas.d.ts +2 -1
  4. package/cjs/app/canvas.js +27 -13
  5. package/cjs/app/index.d.ts +15 -8
  6. package/cjs/app/index.js +134 -88
  7. package/cjs/app/messages.gen.d.ts +2 -2
  8. package/cjs/app/messages.gen.js +8 -8
  9. package/cjs/common/interaction.d.ts +21 -56
  10. package/cjs/common/messages.gen.d.ts +7 -7
  11. package/cjs/index.js +2 -2
  12. package/coverage/clover.xml +1054 -964
  13. package/coverage/coverage-final.json +21 -21
  14. package/coverage/lcov-report/index.html +43 -43
  15. package/coverage/lcov-report/main/app/canvas.ts.html +224 -47
  16. package/coverage/lcov-report/main/app/guards.ts.html +26 -26
  17. package/coverage/lcov-report/main/app/index.html +42 -42
  18. package/coverage/lcov-report/main/app/index.ts.html +157 -37
  19. package/coverage/lcov-report/main/app/logger.ts.html +1 -1
  20. package/coverage/lcov-report/main/app/messages.gen.ts.html +244 -154
  21. package/coverage/lcov-report/main/app/nodes.ts.html +7 -4
  22. package/coverage/lcov-report/main/app/observer/iframe_observer.ts.html +1 -1
  23. package/coverage/lcov-report/main/app/observer/iframe_offsets.ts.html +1 -1
  24. package/coverage/lcov-report/main/app/observer/index.html +5 -5
  25. package/coverage/lcov-report/main/app/observer/shadow_root_observer.ts.html +1 -1
  26. package/coverage/lcov-report/main/app/observer/top_observer.ts.html +7 -4
  27. package/coverage/lcov-report/main/app/sanitizer.ts.html +2 -2
  28. package/coverage/lcov-report/main/app/session.ts.html +2 -2
  29. package/coverage/lcov-report/main/app/ticker.ts.html +1 -1
  30. package/coverage/lcov-report/main/index.html +13 -13
  31. package/coverage/lcov-report/main/index.ts.html +32 -14
  32. package/coverage/lcov-report/main/modules/Network/beaconProxy.ts.html +17 -8
  33. package/coverage/lcov-report/main/modules/Network/fetchProxy.ts.html +40 -13
  34. package/coverage/lcov-report/main/modules/Network/index.html +21 -21
  35. package/coverage/lcov-report/main/modules/Network/index.ts.html +2 -2
  36. package/coverage/lcov-report/main/modules/Network/networkMessage.ts.html +12 -6
  37. package/coverage/lcov-report/main/modules/Network/utils.ts.html +17 -8
  38. package/coverage/lcov-report/main/modules/Network/xhrProxy.ts.html +39 -12
  39. package/coverage/lcov-report/main/modules/attributeSender.ts.html +1 -1
  40. package/coverage/lcov-report/main/modules/axiosSpy.ts.html +1 -1
  41. package/coverage/lcov-report/main/modules/conditionsManager.ts.html +4 -22
  42. package/coverage/lcov-report/main/modules/connection.ts.html +1 -1
  43. package/coverage/lcov-report/main/modules/console.ts.html +1 -1
  44. package/coverage/lcov-report/main/modules/constructedStyleSheets.ts.html +3 -3
  45. package/coverage/lcov-report/main/modules/cssrules.ts.html +1 -1
  46. package/coverage/lcov-report/main/modules/exception.ts.html +1 -1
  47. package/coverage/lcov-report/main/modules/featureFlags.ts.html +1 -1
  48. package/coverage/lcov-report/main/modules/focus.ts.html +1 -1
  49. package/coverage/lcov-report/main/modules/fonts.ts.html +1 -1
  50. package/coverage/lcov-report/main/modules/img.ts.html +4 -4
  51. package/coverage/lcov-report/main/modules/index.html +24 -24
  52. package/coverage/lcov-report/main/modules/input.ts.html +1 -1
  53. package/coverage/lcov-report/main/modules/mouse.ts.html +1 -1
  54. package/coverage/lcov-report/main/modules/network.ts.html +2 -2
  55. package/coverage/lcov-report/main/modules/performance.ts.html +1 -1
  56. package/coverage/lcov-report/main/modules/scroll.ts.html +1 -1
  57. package/coverage/lcov-report/main/modules/selection.ts.html +1 -1
  58. package/coverage/lcov-report/main/modules/tabs.ts.html +1 -1
  59. package/coverage/lcov-report/main/modules/tagWatcher.ts.html +95 -92
  60. package/coverage/lcov-report/main/modules/timing.ts.html +1 -1
  61. package/coverage/lcov-report/main/modules/userTesting/SignalManager.ts.html +1 -1
  62. package/coverage/lcov-report/main/modules/userTesting/dnd.ts.html +1 -1
  63. package/coverage/lcov-report/main/modules/userTesting/index.html +1 -1
  64. package/coverage/lcov-report/main/modules/userTesting/index.ts.html +1 -1
  65. package/coverage/lcov-report/main/modules/userTesting/recorder.ts.html +1 -1
  66. package/coverage/lcov-report/main/modules/userTesting/styles.ts.html +1 -1
  67. package/coverage/lcov-report/main/modules/userTesting/utils.ts.html +1 -1
  68. package/coverage/lcov-report/main/modules/viewport.ts.html +4 -4
  69. package/coverage/lcov-report/main/utils.ts.html +181 -31
  70. package/coverage/lcov-report/webworker/BatchWriter.ts.html +1 -1
  71. package/coverage/lcov-report/webworker/MessageEncoder.gen.ts.html +31 -7
  72. package/coverage/lcov-report/webworker/PrimitiveEncoder.ts.html +1 -1
  73. package/coverage/lcov-report/webworker/QueueSender.ts.html +48 -18
  74. package/coverage/lcov-report/webworker/index.html +14 -14
  75. package/coverage/lcov-report/webworker/index.ts.html +51 -21
  76. package/coverage/lcov.info +1882 -1653
  77. package/lib/app/canvas.d.ts +2 -1
  78. package/lib/app/canvas.js +27 -13
  79. package/lib/app/index.d.ts +15 -8
  80. package/lib/app/index.js +134 -88
  81. package/lib/app/messages.gen.d.ts +2 -2
  82. package/lib/app/messages.gen.js +4 -4
  83. package/lib/common/interaction.d.ts +21 -56
  84. package/lib/common/messages.gen.d.ts +7 -7
  85. package/lib/common/tsconfig.tsbuildinfo +1 -1
  86. package/lib/index.js +2 -2
  87. package/package.json +2 -2
  88. package/cjs/app/workerManager/QueueSender.d.ts +0 -25
  89. package/cjs/app/workerManager/QueueSender.js +0 -133
  90. package/cjs/app/workerManager/index.d.ts +0 -37
  91. package/cjs/app/workerManager/index.js +0 -166
  92. package/lib/app/workerManager/QueueSender.d.ts +0 -25
  93. package/lib/app/workerManager/QueueSender.js +0 -130
  94. package/lib/app/workerManager/index.d.ts +0 -37
  95. package/lib/app/workerManager/index.js +0 -161
@@ -4,6 +4,7 @@ interface Options {
4
4
  quality: 'low' | 'medium' | 'high';
5
5
  isDebug?: boolean;
6
6
  fixedScaling?: boolean;
7
+ useAnimationFrame?: boolean;
7
8
  }
8
9
  declare class CanvasRecorder {
9
10
  private readonly app;
@@ -17,7 +18,7 @@ declare class CanvasRecorder {
17
18
  captureCanvas: (node: Node) => void;
18
19
  recordCanvas: (node: Node, id: number) => void;
19
20
  sendSnaps(images: {
20
- data: string;
21
+ data: Blob;
21
22
  id: number;
22
23
  }[], canvasId: number, createdAt: number): void;
23
24
  clear(): void;
package/lib/app/canvas.js CHANGED
@@ -56,6 +56,17 @@ class CanvasRecorder {
56
56
  };
57
57
  const canvasMsg = CanvasNode(id.toString(), ts);
58
58
  this.app.send(canvasMsg);
59
+ const captureFn = (canvas) => {
60
+ captureSnapshot(canvas, this.options.quality, this.snapshots[id].dummy, this.options.fixedScaling, (blob) => {
61
+ if (!blob)
62
+ return;
63
+ this.snapshots[id].images.push({ id: this.app.timestamp(), data: blob });
64
+ if (this.snapshots[id].images.length > 9) {
65
+ this.sendSnaps(this.snapshots[id].images, id, this.snapshots[id].createdAt);
66
+ this.snapshots[id].images = [];
67
+ }
68
+ });
69
+ };
59
70
  const int = setInterval(() => {
60
71
  const cid = this.app.nodes.getID(node);
61
72
  const canvas = cid ? this.app.nodes.getNode(cid) : undefined;
@@ -65,11 +76,13 @@ class CanvasRecorder {
65
76
  }
66
77
  else {
67
78
  if (!this.snapshots[id].paused) {
68
- const snapshot = captureSnapshot(canvas, this.options.quality, this.snapshots[id].dummy, this.options.fixedScaling);
69
- this.snapshots[id].images.push({ id: this.app.timestamp(), data: snapshot });
70
- if (this.snapshots[id].images.length > 9) {
71
- this.sendSnaps(this.snapshots[id].images, id, this.snapshots[id].createdAt);
72
- this.snapshots[id].images = [];
79
+ if (this.options.useAnimationFrame) {
80
+ requestAnimationFrame(() => {
81
+ captureFn(canvas);
82
+ });
83
+ }
84
+ else {
85
+ captureFn(canvas);
73
86
  }
74
87
  }
75
88
  }
@@ -92,12 +105,12 @@ class CanvasRecorder {
92
105
  }
93
106
  const formData = new FormData();
94
107
  images.forEach((snapshot) => {
95
- const blob = dataUrlToBlob(snapshot.data);
108
+ const blob = snapshot.data;
96
109
  if (!blob)
97
110
  return;
98
- formData.append('snapshot', blob[0], `${createdAt}_${canvasId}_${snapshot.id}.jpeg`);
111
+ formData.append('snapshot', blob, `${createdAt}_${canvasId}_${snapshot.id}.webp`);
99
112
  if (this.options.isDebug) {
100
- saveImageData(snapshot.data, `${createdAt}_${canvasId}_${snapshot.id}.jpeg`);
113
+ saveImageData(blob, `${createdAt}_${canvasId}_${snapshot.id}.webp`);
101
114
  }
102
115
  });
103
116
  fetch(this.app.options.ingestPoint + '/v1/web/images', {
@@ -124,8 +137,8 @@ const qualityInt = {
124
137
  medium: 0.55,
125
138
  high: 0.8,
126
139
  };
127
- function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false) {
128
- const imageFormat = 'image/jpeg'; // or /png'
140
+ function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false, onBlob) {
141
+ const imageFormat = 'image/webp';
129
142
  if (fixedScaling) {
130
143
  const canvasScaleRatio = window.devicePixelRatio || 1;
131
144
  dummy.width = canvas.width / canvasScaleRatio;
@@ -135,10 +148,10 @@ function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false
135
148
  return '';
136
149
  }
137
150
  ctx.drawImage(canvas, 0, 0, dummy.width, dummy.height);
138
- return dummy.toDataURL(imageFormat, qualityInt[quality]);
151
+ dummy.toBlob(onBlob, imageFormat, qualityInt[quality]);
139
152
  }
140
153
  else {
141
- return canvas.toDataURL(imageFormat, qualityInt[quality]);
154
+ canvas.toBlob(onBlob, imageFormat, qualityInt[quality]);
142
155
  }
143
156
  }
144
157
  function dataUrlToBlob(dataUrl) {
@@ -157,7 +170,8 @@ function dataUrlToBlob(dataUrl) {
157
170
  }
158
171
  return [new Blob([u8arr], { type: mime }), u8arr];
159
172
  }
160
- function saveImageData(imageDataUrl, name) {
173
+ function saveImageData(imageDataBlob, name) {
174
+ const imageDataUrl = URL.createObjectURL(imageDataBlob);
161
175
  const link = document.createElement('a');
162
176
  link.href = imageDataUrl;
163
177
  link.download = name;
@@ -11,12 +11,13 @@ 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, FromWorkerData } from '../common/interaction.js';
14
+ import type { Options as WebworkerOptions } from '../common/interaction.js';
15
15
  export interface StartOptions {
16
16
  userID?: string;
17
17
  metadata?: Record<string, string>;
18
18
  forceNew?: boolean;
19
19
  sessionHash?: string;
20
+ assistOnly?: boolean;
20
21
  }
21
22
  interface OnStartInfo {
22
23
  sessionID: string;
@@ -57,6 +58,12 @@ type AppOptions = {
57
58
  disableStringDict?: boolean;
58
59
  assistSocketHost?: string;
59
60
  disableCanvas?: boolean;
61
+ canvas: {
62
+ disableCanvas?: boolean;
63
+ fixedCanvasScaling?: boolean;
64
+ __save_canvas_locally?: boolean;
65
+ useAnimationFrame?: boolean;
66
+ };
60
67
  /** @deprecated */
61
68
  onStart?: StartCallback;
62
69
  network?: NetworkOptions;
@@ -90,20 +97,20 @@ export default class App {
90
97
  private readonly revID;
91
98
  private activityState;
92
99
  private readonly version;
93
- private readonly workerManager?;
100
+ private readonly worker?;
101
+ attributeSender: AttributeSender;
102
+ featureFlags: FeatureFlags;
103
+ socketMode: boolean;
94
104
  private compressionThreshold;
95
105
  private restartAttempts;
96
106
  private readonly bc;
97
107
  private readonly contextId;
98
- attributeSender: AttributeSender;
99
108
  private canvasRecorder;
100
109
  private uxtManager;
101
110
  private conditionsManager;
102
- featureFlags: FeatureFlags;
103
111
  private readonly tagWatcher;
104
112
  constructor(projectKey: string, sessionToken: string | undefined, options: Partial<Options>, signalError: (error: string, apis: string[]) => void);
105
- handleWorkerMsg(data: FromWorkerData): void;
106
- private readonly _debug;
113
+ private _debug;
107
114
  private _usingOldFetchPlugin;
108
115
  send(message: Message, urgent?: boolean): void;
109
116
  /**
@@ -161,7 +168,7 @@ export default class App {
161
168
  private checkSessionToken;
162
169
  /**
163
170
  * start buffering messages without starting the actual session, which gives
164
- * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
171
+ * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger
165
172
  * and we will then send buffered batch, so it won't get lost
166
173
  * */
167
174
  coldStart(startOpts?: StartOptions, conditional?: boolean): Promise<void>;
@@ -179,7 +186,7 @@ export default class App {
179
186
  /**
180
187
  * Saves the captured messages in localStorage (or whatever is used in its place)
181
188
  *
182
- * Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
189
+ * Then when this.offlineRecording is called, it will preload this messages and clear the storage item
183
190
  *
184
191
  * Keeping the size of local storage reasonable is up to the end users of this library
185
192
  * */
package/lib/app/index.js CHANGED
@@ -15,7 +15,6 @@ import AttributeSender from '../modules/attributeSender.js';
15
15
  import CanvasRecorder from './canvas.js';
16
16
  import UserTestManager from '../modules/userTesting/index.js';
17
17
  import TagWatcher from '../modules/tagWatcher.js';
18
- import WebWorkerManager from './workerManager/index.js';
19
18
  const CANCELED = 'canceled';
20
19
  const uxtStorageKey = 'or_uxt_active';
21
20
  const bufferStorageKey = 'or_buffer_1';
@@ -52,26 +51,13 @@ export default class App {
52
51
  this.stopCallbacks = [];
53
52
  this.commitCallbacks = [];
54
53
  this.activityState = ActivityState.NotActive;
55
- this.version = '12.1.0-beta.99'; // TODO: version compatability check inside each plugin.
54
+ this.version = '13.0.1'; // TODO: version compatability check inside each plugin.
55
+ this.socketMode = false;
56
56
  this.compressionThreshold = 24 * 1000;
57
57
  this.restartAttempts = 0;
58
58
  this.bc = null;
59
59
  this.canvasRecorder = null;
60
60
  this.conditionsManager = null;
61
- this._debug = (context, e) => {
62
- if (this.options.__debug_report_edp !== null) {
63
- void fetch(this.options.__debug_report_edp, {
64
- method: 'POST',
65
- headers: { 'Content-Type': 'application/json' },
66
- body: JSON.stringify({
67
- context,
68
- // @ts-ignore
69
- error: `${e}`,
70
- }),
71
- });
72
- }
73
- this.debug.error('OpenReplay error: ', context, e);
74
- };
75
61
  this._usingOldFetchPlugin = false;
76
62
  this.coldStartCommitN = 0;
77
63
  this.delay = 0;
@@ -103,6 +89,18 @@ export default class App {
103
89
  });
104
90
  };
105
91
  this.onUxtCb = [];
92
+ if (Object.keys(options).findIndex((k) => ['fixedCanvasScaling', 'disableCanvas'].includes(k)) !==
93
+ -1) {
94
+ console.warn('Openreplay: canvas options are moving to separate key "canvas" in next update. Please update your configuration.');
95
+ options = {
96
+ ...options,
97
+ canvas: {
98
+ __save_canvas_locally: options.__save_canvas_locally,
99
+ fixedCanvasScaling: options.fixedCanvasScaling,
100
+ disableCanvas: options.disableCanvas,
101
+ },
102
+ };
103
+ }
106
104
  this.contextId = Math.random().toString(36).slice(2);
107
105
  this.projectKey = projectKey;
108
106
  this.networkOptions = options.network;
@@ -127,6 +125,13 @@ export default class App {
127
125
  assistSocketHost: '',
128
126
  fixedCanvasScaling: false,
129
127
  disableCanvas: false,
128
+ assistOnly: false,
129
+ canvas: {
130
+ disableCanvas: false,
131
+ fixedCanvasScaling: false,
132
+ __save_canvas_locally: false,
133
+ useAnimationFrame: false,
134
+ },
130
135
  }, options);
131
136
  if (!this.options.forceSingleTab && globalThis && 'BroadcastChannel' in globalThis) {
132
137
  const host = location.hostname.split('.').slice(-2).join('_');
@@ -161,11 +166,51 @@ export default class App {
161
166
  this.session.applySessionHash(sessionToken);
162
167
  }
163
168
  try {
164
- const webworker = new Worker(URL.createObjectURL(new Blob(['"use strict";const t="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class i{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(i){const s=t.encode(i),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}class s extends i{encode(t){switch(t[0]){case 0:case 11:case 114:case 115:return this.uint(t[1]);case 4:case 44:case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:case 20:case 38:case 70:case 75:case 76:case 77:case 82:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:case 24:case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 12:case 61:case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:case 17:case 50:case 54:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:case 27:case 30:case 41:case 45:case 46:case 63:case 64:case 79:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 28:case 29:case 42:case 117:case 118:return this.string(t[1]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 48:case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 55:return this.boolean(t[1]);case 57:case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:case 120:return this.int(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 67:case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 83:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 84:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 116:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10]);case 119:return this.string(t[1])&&this.uint(t[2]);case 121:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.uint(t[4])}}}class e{constructor(t,i,e,n,r,h){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.tabId=r,this.onOfflineEnd=h,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty)return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url],i=[118,this.tabId];this.writeType(t),this.writeFields(t),this.writeWithSize(i),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if("q_end"===t[0])return this.finaliseBatch(),this.onOfflineEnd();0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new s(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)?this.finaliseBatch():console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder=new s(this.beaconSize),this.prepare()))}finaliseBatch(){if(this.isEmpty)return;const t=this.encoder.flush();this.onBatch(t),this.prepare()}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active",t[t.Stopped=4]="Stopped"}(n||(n={}));let r=null,h=n.NotActive;function a(t){postMessage({type:"status",data:t}),h=t}function u(){r&&r.finaliseBatch()}function c(){a(n.Stopping),null!==f&&(clearInterval(f),f=null),r&&(r.clean(),r=null),setTimeout((()=>{a(n.NotActive)}),100)}function o(){h!==n.Stopped&&(postMessage({type:"restart"}),c())}let f=null;self.onmessage=({data:t})=>{if(null!=t){if("writer_finalize"===t.type)return u(),h=n.Stopped;if("reset_writer"!==t.type){if("forceFlushBatch"!==t.type){if("to_writer"===t.type){let i=!1;t.data.forEach((t=>{r?r.writeMessage(t):i||(i=!0,postMessage({type:"not_init"}),o())}))}return"start"===t.type?(h=n.Starting,r=new e(t.pageNo,t.timestamp,t.url,(t=>{postMessage({type:"batch_ready",data:t},[t.buffer])}),t.tabId,(()=>postMessage({type:"queue_empty"}))),null===f&&(f=setInterval(u,1e4)),h=n.Active):"beacon_size_limit"===t.type?r?void(t.beaconSizeLimit&&r.setBeaconSizeLimit(t.beaconSizeLimit)):(console.debug("OR WebWorker: writer not initialised. Received auth."),void o()):void("restart"===t.type&&o())}u()}else c()}else u()};'], { type: 'text/javascript' })));
165
- this.workerManager = new WebWorkerManager(this, webworker, this._debug);
169
+ this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,s,i,e=10,n=250,h,r){this.onUnauthorised=s,this.onFailure=i,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.onCompress=h,this.pageNo=r,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.lastBatchNum=0,this.ingestURL=t+"/v1/web/i",this.isCompressing=void 0!==h}getQueueStatus(){return 0===this.queue.length&&!this.busy}authorise(t){this.token=t,this.busy||this.sendNext()}push(t){if(this.busy||!this.token)this.queue.push(t);else if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t);else{const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}}sendNext(){const t=this.queue.shift();if(t)if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t);else{const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}else this.busy=!1}retry(t,s,i){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout((()=>this.sendBatch(t,s,i)),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t,s,i){const e=i?.toString().replace(/^([^_]+)_([^_]+).*/,"$1_$2_$3");this.busy=!0;const n={Authorization:`Bearer ${this.token}`};s&&(n["Content-Encoding"]="gzip"),null!==this.token?fetch(`${this.ingestURL}?batch=${this.pageNo??"noPageNum"}_${e??"noBatchNum"}`,{body:t,method:"POST",headers:n,keepalive:t.length<65536}).then((e=>{if(401===e.status)return this.busy=!1,void this.onUnauthorised();e.status>=400?this.retry(t,s,`${i??"noBatchNum"}_network:${e.status}`):(this.attemptsCount=0,this.sendNext())})).catch((e=>{console.warn("OpenReplay:",e),this.retry(t,s,`${i??"noBatchNum"}_reject:${e.message}`)})):setTimeout((()=>{this.sendBatch(t,s,`${i??"noBatchNum"}_newToken`)}),500)}sendCompressed(t){const s=++this.lastBatchNum;this.sendBatch(t,!0,s)}sendUncompressed(t){const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}clean(){this.sendNext(),setTimeout((()=>{this.token=null,this.queue.length=0}),10)}}const s="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let e=-1;for(let n=0,h=0,r=0;r!==s;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===s){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){i[e+=1]=240|n>>>18,i[e+=1]=128|n>>>12&63,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n;continue}}n<=127?i[e+=1]=0|n:n<=2047?(i[e+=1]=192|n>>>6,i[e+=1]=128|63&n):(i[e+=1]=224|n>>>12,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n)}return i.subarray(0,e+1)}};class i{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,s){this.data.set(t,s)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const i=s.encode(t),e=i.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(i,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}class e extends i{encode(t){switch(t[0]){case 0:case 11:case 114:case 115:return this.uint(t[1]);case 4:case 44:case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:case 20:case 38:case 70:case 75:case 76:case 77:case 82:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:case 24:case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 12:case 61:case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:case 17:case 50:case 54:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:case 27:case 30:case 41:case 45:case 46:case 63:case 64:case 79:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 28:case 29:case 42:case 117:case 118:return this.string(t[1]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 48:case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 55:return this.boolean(t[1]);case 57:case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:case 120:return this.int(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 67:case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 83:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 84:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 116:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10]);case 119:return this.string(t[1])&&this.uint(t[2]);case 121:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.uint(t[4])}}}class n{constructor(t,s,i,n,h,r){this.pageNo=t,this.timestamp=s,this.url=i,this.onBatch=n,this.tabId=h,this.onOfflineEnd=r,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new e(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,s){for(let s=0;s<3;s++)this.sizeBuffer[s]=t>>8*s;this.encoder.set(this.sizeBuffer,s)}prepare(){if(!this.encoder.isEmpty)return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url],s=[118,this.tabId];this.writeType(t),this.writeFields(t),this.writeWithSize(s),this.isEmpty=!0}writeWithSize(t){const s=this.encoder;if(!this.writeType(t)||!s.skip(3))return!1;const i=s.getCurrentOffset(),e=this.writeFields(t);if(e){const e=s.getCurrentOffset()-i;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,i-3),s.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if("q_end"===t[0])return this.finaliseBatch(),this.onOfflineEnd();0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new e(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)?this.finaliseBatch():console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder=new e(this.beaconSize),this.prepare()))}finaliseBatch(){if(this.isEmpty)return;const t=this.encoder.flush();this.onBatch(t),this.prepare()}clean(){this.encoder.reset()}}var h;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active",t[t.Stopped=4]="Stopped"}(h||(h={}));let r=null,a=null,u=h.NotActive;function o(){a&&a.finaliseBatch()}function c(){return new Promise((t=>{u=h.Stopping,null!==l&&(clearInterval(l),l=null),a&&(a.clean(),a=null),r&&(r.clean(),setTimeout((()=>{r=null}),20)),setTimeout((()=>{u=h.NotActive,t(null)}),100)}))}function p(){u!==h.Stopped&&(postMessage("a_stop"),c().then((()=>{postMessage("a_start")})))}let g,l=null;self.onmessage=({data:s})=>{if(null!=s){if("stop"===s)return o(),void c().then((()=>{u=h.Stopped}));if("forceFlushBatch"!==s){if(!Array.isArray(s)){if("compressed"===s.type){if(!r)return console.debug("OR WebWorker: sender not initialised. Compressed batch."),void p();s.batch&&r.sendCompressed(s.batch)}if("uncompressed"===s.type){if(!r)return console.debug("OR WebWorker: sender not initialised. Uncompressed batch."),void p();s.batch&&r.sendUncompressed(s.batch)}return"start"===s.type?(u=h.Starting,r=new t(s.ingestPoint,(()=>{p()}),(t=>{!function(t){postMessage({type:"failure",reason:t}),c()}(t)}),s.connAttemptCount,s.connAttemptGap,(t=>{postMessage({type:"compress",batch:t},[t.buffer])}),s.pageNo),a=new n(s.pageNo,s.timestamp,s.url,(t=>{r&&r.push(t)}),s.tabId,(()=>postMessage({type:"queue_empty"}))),null===l&&(l=setInterval(o,1e4)),u=h.Active):"auth"===s.type?r?a?(r.authorise(s.token),void(s.beaconSizeLimit&&a.setBeaconSizeLimit(s.beaconSizeLimit))):(console.debug("OR WebWorker: writer not initialised. Received auth."),void p()):(console.debug("OR WebWorker: sender not initialised. Received auth."),void p()):void 0}if(a){const t=a;s.forEach((s=>{55===s[0]&&(s[1]?g=setTimeout((()=>p()),18e5):clearTimeout(g)),t.writeMessage(s)}))}else postMessage("not_init"),p()}else o()}else o()};'], { type: 'text/javascript' })));
170
+ this.worker.onerror = (e) => {
171
+ this._debug('webworker_error', e);
172
+ };
173
+ this.worker.onmessage = ({ data }) => {
174
+ // handling 401 auth restart (new token assignment)
175
+ if (data === 'a_stop') {
176
+ this.stop(false);
177
+ }
178
+ else if (data === 'a_start') {
179
+ void this.start({}, true);
180
+ }
181
+ else if (data === 'not_init') {
182
+ this.debug.warn('OR WebWorker: writer not initialised. Restarting tracker');
183
+ }
184
+ else if (data.type === 'failure') {
185
+ this.stop(false);
186
+ this.debug.error('worker_failed', data.reason);
187
+ this._debug('worker_failed', data.reason);
188
+ }
189
+ else if (data.type === 'compress') {
190
+ const batch = data.batch;
191
+ const batchSize = batch.byteLength;
192
+ if (batchSize > this.compressionThreshold) {
193
+ gzip(data.batch, { mtime: 0 }, (err, result) => {
194
+ if (err) {
195
+ this.debug.error('Openreplay compression error:', err);
196
+ this.worker?.postMessage({ type: 'uncompressed', batch: batch });
197
+ }
198
+ else {
199
+ this.worker?.postMessage({ type: 'compressed', batch: result });
200
+ }
201
+ });
202
+ }
203
+ else {
204
+ this.worker?.postMessage({ type: 'uncompressed', batch: batch });
205
+ }
206
+ }
207
+ else if (data.type === 'queue_empty') {
208
+ this.onSessionSent();
209
+ }
210
+ };
166
211
  const alertWorker = () => {
167
- if (this.workerManager) {
168
- this.workerManager.processMessage(null);
212
+ if (this.worker) {
213
+ this.worker.postMessage(null);
169
214
  }
170
215
  };
171
216
  // keep better tactics, discard others?
@@ -184,7 +229,7 @@ export default class App {
184
229
  // yes, there are someone out there
185
230
  resp: 'never-gonna-let-you-down',
186
231
  // you stole someone's identity
187
- regen: 'never-gonna-run-around-and-desert-you',
232
+ reg: 'never-gonna-run-around-and-desert-you',
188
233
  };
189
234
  if (this.bc) {
190
235
  this.bc.postMessage({
@@ -202,7 +247,7 @@ export default class App {
202
247
  const sessionToken = ev.data.token;
203
248
  this.session.setSessionToken(sessionToken);
204
249
  }
205
- if (ev.data.line === proto.regen) {
250
+ if (ev.data.line === proto.reg) {
206
251
  const sessionToken = ev.data.token;
207
252
  this.session.regenerateTabId();
208
253
  this.session.setSessionToken(sessionToken);
@@ -211,7 +256,7 @@ export default class App {
211
256
  const token = this.session.getSessionToken();
212
257
  if (token && this.bc) {
213
258
  this.bc.postMessage({
214
- line: ev.data.source === thisTab ? proto.regen : proto.resp,
259
+ line: ev.data.source === thisTab ? proto.reg : proto.resp,
215
260
  token,
216
261
  source: thisTab,
217
262
  context: this.contextId,
@@ -221,44 +266,19 @@ export default class App {
221
266
  };
222
267
  }
223
268
  }
224
- handleWorkerMsg(data) {
225
- if (data.type === 'restart') {
226
- this.stop(false);
227
- void this.start({}, true);
228
- }
229
- else if (data.type === 'not_init') {
230
- this.debug.warn('OR WebWorker: writer not initialised; restarting worker');
231
- }
232
- else if (data.type === 'failure') {
233
- this.stop(false);
234
- this.debug.error('worker_failed', data.reason);
235
- this._debug('worker_failed', data.reason);
236
- }
237
- else if (data.type === 'compress') {
238
- const batch = data.batch;
239
- const batchSize = batch.byteLength;
240
- if (batchSize > this.compressionThreshold) {
241
- gzip(data.batch, { mtime: 0 }, (err, result) => {
242
- if (err) {
243
- this.debug.error('Openreplay compression error:', err);
244
- this.stop(false);
245
- if (this.restartAttempts < 3) {
246
- this.restartAttempts += 1;
247
- void this.start({}, true);
248
- }
249
- }
250
- else {
251
- this.workerManager?.sendCompressedBatch(result);
252
- }
253
- });
254
- }
255
- else {
256
- this.workerManager?.sendUncompressedBatch(batch);
257
- }
258
- }
259
- else if (data.type === 'queue_empty') {
260
- this.onSessionSent();
269
+ _debug(context, e) {
270
+ if (this.options.__debug_report_edp !== null) {
271
+ void fetch(this.options.__debug_report_edp, {
272
+ method: 'POST',
273
+ headers: { 'Content-Type': 'application/json' },
274
+ body: JSON.stringify({
275
+ context,
276
+ // @ts-ignore
277
+ error: `${e}`,
278
+ }),
279
+ });
261
280
  }
281
+ this.debug.error('OpenReplay error: ', context, e);
262
282
  }
263
283
  send(message, urgent = false) {
264
284
  if (this.activityState === ActivityState.NotActive) {
@@ -298,15 +318,31 @@ export default class App {
298
318
  * every ~30ms
299
319
  * */
300
320
  _nCommit() {
301
- if (this.workerManager !== undefined && this.messages.length) {
302
- requestIdleCb(() => {
303
- this.messages.unshift(TabData(this.session.getTabId()));
304
- this.messages.unshift(Timestamp(this.timestamp()));
305
- // why I need to add opt chaining?
306
- this.workerManager?.processMessage({ type: 'batch', data: this.messages });
307
- this.commitCallbacks.forEach((cb) => cb(this.messages));
308
- this.messages.length = 0;
309
- });
321
+ if (this.socketMode) {
322
+ this.messages.unshift(TabData(this.session.getTabId()));
323
+ this.messages.unshift(Timestamp(this.timestamp()));
324
+ this.commitCallbacks.forEach((cb) => cb(this.messages));
325
+ this.messages.length = 0;
326
+ return;
327
+ }
328
+ if (this.worker !== undefined && this.messages.length) {
329
+ try {
330
+ requestIdleCb(() => {
331
+ this.messages.unshift(TabData(this.session.getTabId()));
332
+ this.messages.unshift(Timestamp(this.timestamp()));
333
+ // why I need to add opt chaining?
334
+ this.worker?.postMessage(this.messages);
335
+ this.commitCallbacks.forEach((cb) => cb(this.messages));
336
+ this.messages.length = 0;
337
+ });
338
+ }
339
+ catch (e) {
340
+ this._debug('worker_commit', e);
341
+ this.stop(true);
342
+ setTimeout(() => {
343
+ void this.start();
344
+ }, 500);
345
+ }
310
346
  }
311
347
  }
312
348
  /**
@@ -334,7 +370,7 @@ export default class App {
334
370
  }
335
371
  }
336
372
  postToWorker(messages) {
337
- this.workerManager?.processMessage({ type: 'batch', data: messages });
373
+ this.worker?.postMessage(messages);
338
374
  this.commitCallbacks.forEach((cb) => cb(messages));
339
375
  messages.length = 0;
340
376
  }
@@ -481,7 +517,7 @@ export default class App {
481
517
  }
482
518
  /**
483
519
  * start buffering messages without starting the actual session, which gives
484
- * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
520
+ * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger
485
521
  * and we will then send buffered batch, so it won't get lost
486
522
  * */
487
523
  async coldStart(startOpts = {}, conditional) {
@@ -617,7 +653,7 @@ export default class App {
617
653
  /**
618
654
  * Saves the captured messages in localStorage (or whatever is used in its place)
619
655
  *
620
- * Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
656
+ * Then when this.offlineRecording is called, it will preload this messages and clear the storage item
621
657
  *
622
658
  * Keeping the size of local storage reasonable is up to the end users of this library
623
659
  * */
@@ -646,7 +682,7 @@ export default class App {
646
682
  async uploadOfflineRecording() {
647
683
  this.stop(false);
648
684
  const timestamp = now();
649
- this.workerManager?.processMessage({
685
+ this.worker?.postMessage({
650
686
  type: 'start',
651
687
  pageNo: this.session.incPageNo(),
652
688
  ingestPoint: this.options.ingestPoint,
@@ -674,7 +710,8 @@ export default class App {
674
710
  }),
675
711
  });
676
712
  const { token, userBrowser, userCity, userCountry, userDevice, userOS, userState, beaconSizeLimit, projectID, } = await r.json();
677
- this.workerManager?.authorizeWorker({
713
+ this.worker?.postMessage({
714
+ type: 'auth',
678
715
  token,
679
716
  beaconSizeLimit,
680
717
  });
@@ -698,7 +735,7 @@ export default class App {
698
735
  if (isColdStart && this.coldInterval) {
699
736
  clearInterval(this.coldInterval);
700
737
  }
701
- if (!this.workerManager) {
738
+ if (!this.worker) {
702
739
  const reason = 'No worker found: perhaps, CSP is not set.';
703
740
  this.signalError(reason, []);
704
741
  return Promise.resolve(UnsuccessfulStart(reason));
@@ -725,7 +762,7 @@ export default class App {
725
762
  metadata: startOpts.metadata,
726
763
  });
727
764
  const timestamp = now();
728
- this.workerManager?.startWorker({
765
+ this.worker.postMessage({
729
766
  type: 'start',
730
767
  pageNo: this.session.incPageNo(),
731
768
  ingestPoint: this.options.ingestPoint,
@@ -756,6 +793,7 @@ export default class App {
756
793
  jsHeapSizeLimit,
757
794
  timezone: getTimezone(),
758
795
  condition: conditionName,
796
+ assistOnly: startOpts.assistOnly ?? this.socketMode,
759
797
  }),
760
798
  })
761
799
  .then((r) => {
@@ -771,7 +809,7 @@ export default class App {
771
809
  }
772
810
  })
773
811
  .then(async (r) => {
774
- if (!this.workerManager) {
812
+ if (!this.worker) {
775
813
  const reason = 'no worker found after start request (this might not happen)';
776
814
  this.signalError(reason, []);
777
815
  return Promise.reject(reason);
@@ -785,7 +823,7 @@ export default class App {
785
823
  delay, // derived from token
786
824
  sessionID, // derived from token
787
825
  startTimestamp, // real startTS (server time), derived from sessionID
788
- userBrowser, userCity, userCountry, userDevice, userOS, userState, canvasEnabled, canvasQuality, canvasFPS, } = r;
826
+ userBrowser, userCity, userCountry, userDevice, userOS, userState, canvasEnabled, canvasQuality, canvasFPS, assistOnly: socketOnly, } = r;
789
827
  if (typeof token !== 'string' ||
790
828
  typeof userUUID !== 'string' ||
791
829
  (typeof startTimestamp !== 'number' && typeof startTimestamp !== 'undefined') ||
@@ -811,10 +849,17 @@ export default class App {
811
849
  timestamp: startTimestamp || timestamp,
812
850
  projectID,
813
851
  });
814
- this.workerManager?.authorizeWorker({
815
- token,
816
- beaconSizeLimit,
817
- });
852
+ if (socketOnly) {
853
+ this.socketMode = true;
854
+ this.worker.postMessage('stop');
855
+ }
856
+ else {
857
+ this.worker.postMessage({
858
+ type: 'auth',
859
+ token,
860
+ beaconSizeLimit,
861
+ });
862
+ }
818
863
  if (!isNewSession && token === sessionToken) {
819
864
  this.debug.log('continuing session on new tab', this.session.getTabId());
820
865
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
@@ -831,14 +876,15 @@ export default class App {
831
876
  void this.featureFlags.reloadFlags();
832
877
  await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
833
878
  this.activityState = ActivityState.Active;
834
- if (canvasEnabled && !this.options.disableCanvas) {
879
+ if (canvasEnabled && !this.options.canvas.disableCanvas) {
835
880
  this.canvasRecorder =
836
881
  this.canvasRecorder ??
837
882
  new CanvasRecorder(this, {
838
883
  fps: canvasFPS,
839
884
  quality: canvasQuality,
840
- isDebug: this.options.__save_canvas_locally,
841
- fixedScaling: this.options.fixedCanvasScaling,
885
+ isDebug: this.options.canvas.__save_canvas_locally,
886
+ fixedScaling: this.options.canvas.fixedCanvasScaling,
887
+ useAnimationFrame: this.options.canvas.useAnimationFrame,
842
888
  });
843
889
  this.canvasRecorder.startTracking();
844
890
  }
@@ -946,7 +992,7 @@ export default class App {
946
992
  }
947
993
  }
948
994
  forceFlushBatch() {
949
- this.workerManager?.processMessage({ type: 'forceFlushBatch' });
995
+ this.worker?.postMessage('forceFlushBatch');
950
996
  }
951
997
  getTabId() {
952
998
  return this.session.getTabId();
@@ -983,8 +1029,8 @@ export default class App {
983
1029
  this.stopCallbacks.forEach((cb) => cb());
984
1030
  this.debug.log('OpenReplay tracking stopped.');
985
1031
  this.tagWatcher.clear();
986
- if (this.workerManager && stopWorker) {
987
- this.workerManager?.stopWorker();
1032
+ if (this.worker && stopWorker) {
1033
+ this.worker.postMessage('stop');
988
1034
  }
989
1035
  this.canvasRecorder?.clear();
990
1036
  }
@@ -31,7 +31,7 @@ export declare function Fetch(method: string, url: string, request: string, resp
31
31
  export declare function Profiler(name: string, duration: number, args: string, result: string): Messages.Profiler;
32
32
  export declare function OTable(key: string, value: string): Messages.OTable;
33
33
  export declare function StateAction(type: string): Messages.StateAction;
34
- export declare function Redux(action: string, state: string, duration: number): Messages.Redux;
34
+ export declare function ReduxDeprecated(action: string, state: string, duration: number): Messages.ReduxDeprecated;
35
35
  export declare function Vuex(mutation: string, state: string): Messages.Vuex;
36
36
  export declare function MobX(type: string, payload: string): Messages.MobX;
37
37
  export declare function NgRx(action: string, state: string, duration: number): Messages.NgRx;
@@ -72,4 +72,4 @@ export declare function TabChange(tabId: string): Messages.TabChange;
72
72
  export declare function TabData(tabId: string): Messages.TabData;
73
73
  export declare function CanvasNode(nodeId: string, timestamp: number): Messages.CanvasNode;
74
74
  export declare function TagTrigger(tagId: number): Messages.TagTrigger;
75
- export declare function ReduxNew(action: string, state: string, duration: number, actionTime: number): Messages.ReduxNew;
75
+ export declare function Redux(action: string, state: string, duration: number, actionTime: number): Messages.Redux;
@@ -241,9 +241,9 @@ export function StateAction(type) {
241
241
  type,
242
242
  ];
243
243
  }
244
- export function Redux(action, state, duration) {
244
+ export function ReduxDeprecated(action, state, duration) {
245
245
  return [
246
- 44 /* Messages.Type.Redux */,
246
+ 44 /* Messages.Type.ReduxDeprecated */,
247
247
  action,
248
248
  state,
249
249
  duration,
@@ -580,9 +580,9 @@ export function TagTrigger(tagId) {
580
580
  tagId,
581
581
  ];
582
582
  }
583
- export function ReduxNew(action, state, duration, actionTime) {
583
+ export function Redux(action, state, duration, actionTime) {
584
584
  return [
585
- 121 /* Messages.Type.ReduxNew */,
585
+ 121 /* Messages.Type.Redux */,
586
586
  action,
587
587
  state,
588
588
  duration,