@openreplay/tracker 13.0.0 → 13.0.2

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 (79) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/bun.lockb +0 -0
  3. package/cjs/app/canvas.d.ts +4 -1
  4. package/cjs/app/canvas.js +28 -13
  5. package/cjs/app/index.d.ts +23 -0
  6. package/cjs/app/index.js +23 -4
  7. package/cjs/index.js +1 -1
  8. package/coverage/clover.xml +1054 -964
  9. package/coverage/coverage-final.json +21 -21
  10. package/coverage/lcov-report/index.html +43 -43
  11. package/coverage/lcov-report/main/app/canvas.ts.html +224 -47
  12. package/coverage/lcov-report/main/app/guards.ts.html +26 -26
  13. package/coverage/lcov-report/main/app/index.html +42 -42
  14. package/coverage/lcov-report/main/app/index.ts.html +157 -37
  15. package/coverage/lcov-report/main/app/logger.ts.html +1 -1
  16. package/coverage/lcov-report/main/app/messages.gen.ts.html +244 -154
  17. package/coverage/lcov-report/main/app/nodes.ts.html +7 -4
  18. package/coverage/lcov-report/main/app/observer/iframe_observer.ts.html +1 -1
  19. package/coverage/lcov-report/main/app/observer/iframe_offsets.ts.html +1 -1
  20. package/coverage/lcov-report/main/app/observer/index.html +5 -5
  21. package/coverage/lcov-report/main/app/observer/shadow_root_observer.ts.html +1 -1
  22. package/coverage/lcov-report/main/app/observer/top_observer.ts.html +7 -4
  23. package/coverage/lcov-report/main/app/sanitizer.ts.html +2 -2
  24. package/coverage/lcov-report/main/app/session.ts.html +2 -2
  25. package/coverage/lcov-report/main/app/ticker.ts.html +1 -1
  26. package/coverage/lcov-report/main/index.html +13 -13
  27. package/coverage/lcov-report/main/index.ts.html +32 -14
  28. package/coverage/lcov-report/main/modules/Network/beaconProxy.ts.html +17 -8
  29. package/coverage/lcov-report/main/modules/Network/fetchProxy.ts.html +40 -13
  30. package/coverage/lcov-report/main/modules/Network/index.html +21 -21
  31. package/coverage/lcov-report/main/modules/Network/index.ts.html +2 -2
  32. package/coverage/lcov-report/main/modules/Network/networkMessage.ts.html +12 -6
  33. package/coverage/lcov-report/main/modules/Network/utils.ts.html +17 -8
  34. package/coverage/lcov-report/main/modules/Network/xhrProxy.ts.html +39 -12
  35. package/coverage/lcov-report/main/modules/attributeSender.ts.html +1 -1
  36. package/coverage/lcov-report/main/modules/axiosSpy.ts.html +1 -1
  37. package/coverage/lcov-report/main/modules/conditionsManager.ts.html +4 -22
  38. package/coverage/lcov-report/main/modules/connection.ts.html +1 -1
  39. package/coverage/lcov-report/main/modules/console.ts.html +1 -1
  40. package/coverage/lcov-report/main/modules/constructedStyleSheets.ts.html +3 -3
  41. package/coverage/lcov-report/main/modules/cssrules.ts.html +1 -1
  42. package/coverage/lcov-report/main/modules/exception.ts.html +1 -1
  43. package/coverage/lcov-report/main/modules/featureFlags.ts.html +1 -1
  44. package/coverage/lcov-report/main/modules/focus.ts.html +1 -1
  45. package/coverage/lcov-report/main/modules/fonts.ts.html +1 -1
  46. package/coverage/lcov-report/main/modules/img.ts.html +4 -4
  47. package/coverage/lcov-report/main/modules/index.html +24 -24
  48. package/coverage/lcov-report/main/modules/input.ts.html +1 -1
  49. package/coverage/lcov-report/main/modules/mouse.ts.html +1 -1
  50. package/coverage/lcov-report/main/modules/network.ts.html +2 -2
  51. package/coverage/lcov-report/main/modules/performance.ts.html +1 -1
  52. package/coverage/lcov-report/main/modules/scroll.ts.html +1 -1
  53. package/coverage/lcov-report/main/modules/selection.ts.html +1 -1
  54. package/coverage/lcov-report/main/modules/tabs.ts.html +1 -1
  55. package/coverage/lcov-report/main/modules/tagWatcher.ts.html +95 -92
  56. package/coverage/lcov-report/main/modules/timing.ts.html +1 -1
  57. package/coverage/lcov-report/main/modules/userTesting/SignalManager.ts.html +1 -1
  58. package/coverage/lcov-report/main/modules/userTesting/dnd.ts.html +1 -1
  59. package/coverage/lcov-report/main/modules/userTesting/index.html +1 -1
  60. package/coverage/lcov-report/main/modules/userTesting/index.ts.html +1 -1
  61. package/coverage/lcov-report/main/modules/userTesting/recorder.ts.html +1 -1
  62. package/coverage/lcov-report/main/modules/userTesting/styles.ts.html +1 -1
  63. package/coverage/lcov-report/main/modules/userTesting/utils.ts.html +1 -1
  64. package/coverage/lcov-report/main/modules/viewport.ts.html +4 -4
  65. package/coverage/lcov-report/main/utils.ts.html +181 -31
  66. package/coverage/lcov-report/webworker/BatchWriter.ts.html +1 -1
  67. package/coverage/lcov-report/webworker/MessageEncoder.gen.ts.html +31 -7
  68. package/coverage/lcov-report/webworker/PrimitiveEncoder.ts.html +1 -1
  69. package/coverage/lcov-report/webworker/QueueSender.ts.html +48 -18
  70. package/coverage/lcov-report/webworker/index.html +14 -14
  71. package/coverage/lcov-report/webworker/index.ts.html +51 -21
  72. package/coverage/lcov.info +1882 -1653
  73. package/lib/app/canvas.d.ts +4 -1
  74. package/lib/app/canvas.js +28 -13
  75. package/lib/app/index.d.ts +23 -0
  76. package/lib/app/index.js +23 -4
  77. package/lib/common/tsconfig.tsbuildinfo +1 -1
  78. package/lib/index.js +1 -1
  79. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 13.0.2
2
+
3
+ - more file extensions for canvas
4
+
5
+ # 13.0.1
6
+
7
+ - moved canvas snapshots to webp, additional option to utilize useAnimationFrame method (for webgl)
8
+ - simpler, faster canvas recording manager
9
+
1
10
  # 13.0.0
2
11
 
3
12
  - `assistOnly` flag for tracker options (EE only feature)
package/bun.lockb CHANGED
Binary file
@@ -4,6 +4,8 @@ interface Options {
4
4
  quality: 'low' | 'medium' | 'high';
5
5
  isDebug?: boolean;
6
6
  fixedScaling?: boolean;
7
+ useAnimationFrame?: boolean;
8
+ fileExt?: 'webp' | 'png' | 'jpeg' | 'avif';
7
9
  }
8
10
  declare class CanvasRecorder {
9
11
  private readonly app;
@@ -11,13 +13,14 @@ declare class CanvasRecorder {
11
13
  private snapshots;
12
14
  private readonly intervals;
13
15
  private readonly interval;
16
+ private readonly fileExt;
14
17
  constructor(app: App, options: Options);
15
18
  startTracking(): void;
16
19
  restartTracking: () => void;
17
20
  captureCanvas: (node: Node) => void;
18
21
  recordCanvas: (node: Node, id: number) => void;
19
22
  sendSnaps(images: {
20
- data: string;
23
+ data: Blob;
21
24
  id: number;
22
25
  }[], canvasId: number, createdAt: number): void;
23
26
  clear(): void;
package/cjs/app/canvas.js CHANGED
@@ -58,6 +58,17 @@ class CanvasRecorder {
58
58
  };
59
59
  const canvasMsg = (0, messages_gen_js_1.CanvasNode)(id.toString(), ts);
60
60
  this.app.send(canvasMsg);
61
+ const captureFn = (canvas) => {
62
+ captureSnapshot(canvas, this.options.quality, this.snapshots[id].dummy, this.options.fixedScaling, this.fileExt, (blob) => {
63
+ if (!blob)
64
+ return;
65
+ this.snapshots[id].images.push({ id: this.app.timestamp(), data: blob });
66
+ if (this.snapshots[id].images.length > 9) {
67
+ this.sendSnaps(this.snapshots[id].images, id, this.snapshots[id].createdAt);
68
+ this.snapshots[id].images = [];
69
+ }
70
+ });
71
+ };
61
72
  const int = setInterval(() => {
62
73
  const cid = this.app.nodes.getID(node);
63
74
  const canvas = cid ? this.app.nodes.getNode(cid) : undefined;
@@ -67,17 +78,20 @@ class CanvasRecorder {
67
78
  }
68
79
  else {
69
80
  if (!this.snapshots[id].paused) {
70
- const snapshot = captureSnapshot(canvas, this.options.quality, this.snapshots[id].dummy, this.options.fixedScaling);
71
- this.snapshots[id].images.push({ id: this.app.timestamp(), data: snapshot });
72
- if (this.snapshots[id].images.length > 9) {
73
- this.sendSnaps(this.snapshots[id].images, id, this.snapshots[id].createdAt);
74
- this.snapshots[id].images = [];
81
+ if (this.options.useAnimationFrame) {
82
+ requestAnimationFrame(() => {
83
+ captureFn(canvas);
84
+ });
85
+ }
86
+ else {
87
+ captureFn(canvas);
75
88
  }
76
89
  }
77
90
  }
78
91
  }, this.interval);
79
92
  this.intervals.push(int);
80
93
  };
94
+ this.fileExt = options.fileExt ?? 'webp';
81
95
  this.interval = 1000 / options.fps;
82
96
  }
83
97
  startTracking() {
@@ -94,12 +108,12 @@ class CanvasRecorder {
94
108
  }
95
109
  const formData = new FormData();
96
110
  images.forEach((snapshot) => {
97
- const blob = dataUrlToBlob(snapshot.data);
111
+ const blob = snapshot.data;
98
112
  if (!blob)
99
113
  return;
100
- formData.append('snapshot', blob[0], `${createdAt}_${canvasId}_${snapshot.id}.jpeg`);
114
+ formData.append('snapshot', blob, `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}`);
101
115
  if (this.options.isDebug) {
102
- saveImageData(snapshot.data, `${createdAt}_${canvasId}_${snapshot.id}.jpeg`);
116
+ saveImageData(blob, `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}`);
103
117
  }
104
118
  });
105
119
  fetch(this.app.options.ingestPoint + '/v1/web/images', {
@@ -126,8 +140,8 @@ const qualityInt = {
126
140
  medium: 0.55,
127
141
  high: 0.8,
128
142
  };
129
- function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false) {
130
- const imageFormat = 'image/jpeg'; // or /png'
143
+ function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false, fileExt, onBlob) {
144
+ const imageFormat = `image/${fileExt}`;
131
145
  if (fixedScaling) {
132
146
  const canvasScaleRatio = window.devicePixelRatio || 1;
133
147
  dummy.width = canvas.width / canvasScaleRatio;
@@ -137,10 +151,10 @@ function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false
137
151
  return '';
138
152
  }
139
153
  ctx.drawImage(canvas, 0, 0, dummy.width, dummy.height);
140
- return dummy.toDataURL(imageFormat, qualityInt[quality]);
154
+ dummy.toBlob(onBlob, imageFormat, qualityInt[quality]);
141
155
  }
142
156
  else {
143
- return canvas.toDataURL(imageFormat, qualityInt[quality]);
157
+ canvas.toBlob(onBlob, imageFormat, qualityInt[quality]);
144
158
  }
145
159
  }
146
160
  function dataUrlToBlob(dataUrl) {
@@ -159,7 +173,8 @@ function dataUrlToBlob(dataUrl) {
159
173
  }
160
174
  return [new Blob([u8arr], { type: mime }), u8arr];
161
175
  }
162
- function saveImageData(imageDataUrl, name) {
176
+ function saveImageData(imageDataBlob, name) {
177
+ const imageDataUrl = URL.createObjectURL(imageDataBlob);
163
178
  const link = document.createElement('a');
164
179
  link.href = imageDataUrl;
165
180
  link.download = name;
@@ -50,14 +50,37 @@ type AppOptions = {
50
50
  __is_snippet: boolean;
51
51
  __debug_report_edp: string | null;
52
52
  __debug__?: ILogLevel;
53
+ /** @deprecated see canvas prop */
53
54
  __save_canvas_locally?: boolean;
55
+ /** @deprecated see canvas prop */
54
56
  fixedCanvasScaling?: boolean;
55
57
  localStorage: Storage | null;
56
58
  sessionStorage: Storage | null;
57
59
  forceSingleTab?: boolean;
60
+ /** Sometimes helps to prevent session breaking due to dict reset */
58
61
  disableStringDict?: boolean;
59
62
  assistSocketHost?: string;
63
+ /** @deprecated see canvas prop */
60
64
  disableCanvas?: boolean;
65
+ canvas: {
66
+ disableCanvas?: boolean;
67
+ /**
68
+ * If you expect HI-DPI users mostly, this will render canvas
69
+ * in 1:1 pixel ratio
70
+ * */
71
+ fixedCanvasScaling?: boolean;
72
+ __save_canvas_locally?: boolean;
73
+ /**
74
+ * Use with care since it hijacks one frame each time it captures
75
+ * snapshot for every canvas
76
+ * */
77
+ useAnimationFrame?: boolean;
78
+ /**
79
+ * Use webp unless it produces too big images
80
+ * @default webp
81
+ * */
82
+ fileExt?: 'webp' | 'png' | 'jpeg' | 'avif';
83
+ };
61
84
  /** @deprecated */
62
85
  onStart?: StartCallback;
63
86
  network?: NetworkOptions;
package/cjs/app/index.js CHANGED
@@ -80,7 +80,7 @@ class App {
80
80
  this.stopCallbacks = [];
81
81
  this.commitCallbacks = [];
82
82
  this.activityState = ActivityState.NotActive;
83
- this.version = '13.0.0'; // TODO: version compatability check inside each plugin.
83
+ this.version = '13.0.2'; // TODO: version compatability check inside each plugin.
84
84
  this.socketMode = false;
85
85
  this.compressionThreshold = 24 * 1000;
86
86
  this.restartAttempts = 0;
@@ -118,6 +118,18 @@ class App {
118
118
  });
119
119
  };
120
120
  this.onUxtCb = [];
121
+ if (Object.keys(options).findIndex((k) => ['fixedCanvasScaling', 'disableCanvas'].includes(k)) !==
122
+ -1) {
123
+ console.warn('Openreplay: canvas options are moving to separate key "canvas" in next update. Please update your configuration.');
124
+ options = {
125
+ ...options,
126
+ canvas: {
127
+ __save_canvas_locally: options.__save_canvas_locally,
128
+ fixedCanvasScaling: options.fixedCanvasScaling,
129
+ disableCanvas: options.disableCanvas,
130
+ },
131
+ };
132
+ }
121
133
  this.contextId = Math.random().toString(36).slice(2);
122
134
  this.projectKey = projectKey;
123
135
  this.networkOptions = options.network;
@@ -143,6 +155,12 @@ class App {
143
155
  fixedCanvasScaling: false,
144
156
  disableCanvas: false,
145
157
  assistOnly: false,
158
+ canvas: {
159
+ disableCanvas: false,
160
+ fixedCanvasScaling: false,
161
+ __save_canvas_locally: false,
162
+ useAnimationFrame: false,
163
+ },
146
164
  }, options);
147
165
  if (!this.options.forceSingleTab && globalThis && 'BroadcastChannel' in globalThis) {
148
166
  const host = location.hostname.split('.').slice(-2).join('_');
@@ -887,14 +905,15 @@ class App {
887
905
  void this.featureFlags.reloadFlags();
888
906
  await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
889
907
  this.activityState = ActivityState.Active;
890
- if (canvasEnabled && !this.options.disableCanvas) {
908
+ if (canvasEnabled && !this.options.canvas.disableCanvas) {
891
909
  this.canvasRecorder =
892
910
  this.canvasRecorder ??
893
911
  new canvas_js_1.default(this, {
894
912
  fps: canvasFPS,
895
913
  quality: canvasQuality,
896
- isDebug: this.options.__save_canvas_locally,
897
- fixedScaling: this.options.fixedCanvasScaling,
914
+ isDebug: this.options.canvas.__save_canvas_locally,
915
+ fixedScaling: this.options.canvas.fixedCanvasScaling,
916
+ useAnimationFrame: this.options.canvas.useAnimationFrame,
898
917
  });
899
918
  this.canvasRecorder.startTracking();
900
919
  }
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: '13.0.0',
100
+ trackerVersion: '13.0.2',
101
101
  projectKey: this.options.projectKey,
102
102
  doNotTrack,
103
103
  reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,