@openreplay/tracker 3.6.3 → 3.6.5

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/.eslintignore +8 -0
  2. package/cjs/app/guards.js +1 -2
  3. package/cjs/app/index.d.ts +15 -13
  4. package/cjs/app/index.js +56 -40
  5. package/cjs/app/logger.js +6 -3
  6. package/cjs/app/observer/iframe_observer.d.ts +1 -1
  7. package/cjs/app/observer/iframe_observer.js +1 -1
  8. package/cjs/app/observer/observer.d.ts +2 -3
  9. package/cjs/app/observer/observer.js +38 -40
  10. package/cjs/app/observer/shadow_root_observer.d.ts +1 -1
  11. package/cjs/app/observer/shadow_root_observer.js +1 -1
  12. package/cjs/app/observer/top_observer.d.ts +2 -2
  13. package/cjs/app/observer/top_observer.js +12 -11
  14. package/cjs/app/sanitizer.d.ts +1 -1
  15. package/cjs/app/sanitizer.js +5 -5
  16. package/cjs/app/session.d.ts +14 -2
  17. package/cjs/app/session.js +19 -6
  18. package/cjs/app/ticker.d.ts +1 -1
  19. package/cjs/common/messages.d.ts +1 -1
  20. package/cjs/common/messages.js +69 -120
  21. package/cjs/common/webworker.d.ts +3 -3
  22. package/cjs/index.d.ts +9 -8
  23. package/cjs/index.js +34 -28
  24. package/cjs/modules/connection.d.ts +1 -1
  25. package/cjs/modules/console.d.ts +1 -1
  26. package/cjs/modules/console.js +5 -5
  27. package/cjs/modules/cssrules.d.ts +1 -1
  28. package/cjs/modules/cssrules.js +3 -3
  29. package/cjs/modules/exception.d.ts +2 -2
  30. package/cjs/modules/exception.js +7 -6
  31. package/cjs/modules/img.d.ts +1 -1
  32. package/cjs/modules/img.js +15 -12
  33. package/cjs/modules/input.d.ts +1 -1
  34. package/cjs/modules/input.js +15 -15
  35. package/cjs/modules/longtasks.d.ts +1 -1
  36. package/cjs/modules/longtasks.js +13 -5
  37. package/cjs/modules/mouse.d.ts +1 -1
  38. package/cjs/modules/mouse.js +10 -12
  39. package/cjs/modules/performance.d.ts +1 -1
  40. package/cjs/modules/scroll.d.ts +1 -1
  41. package/cjs/modules/timing.d.ts +1 -1
  42. package/cjs/modules/timing.js +12 -24
  43. package/cjs/modules/viewport.d.ts +1 -1
  44. package/cjs/utils.js +7 -7
  45. package/cjs/vendors/finder/finder.js +53 -48
  46. package/lib/app/guards.js +1 -2
  47. package/lib/app/index.d.ts +15 -13
  48. package/lib/app/index.js +65 -49
  49. package/lib/app/logger.js +6 -3
  50. package/lib/app/observer/iframe_observer.d.ts +1 -1
  51. package/lib/app/observer/iframe_observer.js +3 -3
  52. package/lib/app/observer/observer.d.ts +2 -3
  53. package/lib/app/observer/observer.js +40 -42
  54. package/lib/app/observer/shadow_root_observer.d.ts +1 -1
  55. package/lib/app/observer/shadow_root_observer.js +3 -3
  56. package/lib/app/observer/top_observer.d.ts +2 -2
  57. package/lib/app/observer/top_observer.js +17 -16
  58. package/lib/app/sanitizer.d.ts +1 -1
  59. package/lib/app/sanitizer.js +7 -7
  60. package/lib/app/session.d.ts +14 -2
  61. package/lib/app/session.js +19 -6
  62. package/lib/app/ticker.d.ts +1 -1
  63. package/lib/common/messages.d.ts +1 -1
  64. package/lib/common/messages.js +69 -120
  65. package/lib/common/tsconfig.tsbuildinfo +1 -1
  66. package/lib/common/webworker.d.ts +3 -3
  67. package/lib/index.d.ts +9 -8
  68. package/lib/index.js +49 -43
  69. package/lib/modules/connection.d.ts +1 -1
  70. package/lib/modules/connection.js +1 -1
  71. package/lib/modules/console.d.ts +1 -1
  72. package/lib/modules/console.js +8 -8
  73. package/lib/modules/cssrules.d.ts +1 -1
  74. package/lib/modules/cssrules.js +5 -5
  75. package/lib/modules/exception.d.ts +2 -2
  76. package/lib/modules/exception.js +8 -7
  77. package/lib/modules/img.d.ts +1 -1
  78. package/lib/modules/img.js +18 -15
  79. package/lib/modules/input.d.ts +1 -1
  80. package/lib/modules/input.js +18 -18
  81. package/lib/modules/longtasks.d.ts +1 -1
  82. package/lib/modules/longtasks.js +14 -6
  83. package/lib/modules/mouse.d.ts +1 -1
  84. package/lib/modules/mouse.js +14 -16
  85. package/lib/modules/performance.d.ts +1 -1
  86. package/lib/modules/performance.js +2 -2
  87. package/lib/modules/scroll.d.ts +1 -1
  88. package/lib/modules/scroll.js +2 -2
  89. package/lib/modules/timing.d.ts +1 -1
  90. package/lib/modules/timing.js +15 -27
  91. package/lib/modules/viewport.d.ts +1 -1
  92. package/lib/modules/viewport.js +1 -1
  93. package/lib/utils.js +7 -7
  94. package/lib/vendors/finder/finder.js +53 -48
  95. package/package.json +28 -10
@@ -13,13 +13,9 @@ function isIgnored(node) {
13
13
  if (tag === 'LINK') {
14
14
  const rel = node.getAttribute('rel');
15
15
  const as = node.getAttribute('as');
16
- return !((rel === null || rel === void 0 ? void 0 : rel.includes('stylesheet')) || as === "style" || as === "font");
16
+ return !((rel === null || rel === void 0 ? void 0 : rel.includes('stylesheet')) || as === 'style' || as === 'font');
17
17
  }
18
- return (tag === 'SCRIPT' ||
19
- tag === 'NOSCRIPT' ||
20
- tag === 'META' ||
21
- tag === 'TITLE' ||
22
- tag === 'BASE');
18
+ return (tag === 'SCRIPT' || tag === 'NOSCRIPT' || tag === 'META' || tag === 'TITLE' || tag === 'BASE');
23
19
  }
24
20
  function isObservable(node) {
25
21
  if ((0, guards_js_1.isRootNode)(node)) {
@@ -32,17 +28,11 @@ function isObservable(node) {
32
28
  - fix unbinding logic + send all removals first (ensure sequence is correct)
33
29
  - use document as a 0-node in the upper context (should be updated in player at first)
34
30
  */
35
- /*
36
- Nikita:
37
- - rn we only send unbind event for parent (all child nodes will be cut in the live replay anyways)
38
- to prevent sending 1k+ unbinds for child nodes and making replay file bigger than it should be
39
- */
40
31
  var RecentsType;
41
32
  (function (RecentsType) {
42
33
  RecentsType[RecentsType["New"] = 0] = "New";
43
34
  RecentsType[RecentsType["Removed"] = 1] = "Removed";
44
35
  RecentsType[RecentsType["Changed"] = 2] = "Changed";
45
- RecentsType[RecentsType["RemovedChild"] = 3] = "RemovedChild";
46
36
  })(RecentsType || (RecentsType = {}));
47
37
  class Observer {
48
38
  constructor(app, isTopContext = false) {
@@ -54,7 +44,8 @@ class Observer {
54
44
  this.attributesMap = new Map();
55
45
  this.textSet = new Set();
56
46
  this.observer = new MutationObserver(this.app.safe((mutations) => {
57
- for (const mutation of mutations) { // mutations order is sequential
47
+ for (const mutation of mutations) {
48
+ // mutations order is sequential
58
49
  const target = mutation.target;
59
50
  const type = mutation.type;
60
51
  if (!isObservable(target)) {
@@ -62,7 +53,10 @@ class Observer {
62
53
  }
63
54
  if (type === 'childList') {
64
55
  for (let i = 0; i < mutation.removedNodes.length; i++) {
65
- this.bindTree(mutation.removedNodes[i], true);
56
+ // Should be the same as bindTree(mutation.removedNodes[i]), but logic needs to be be untied
57
+ if (isObservable(mutation.removedNodes[i])) {
58
+ this.bindNode(mutation.removedNodes[i]);
59
+ }
66
60
  }
67
61
  for (let i = 0; i < mutation.addedNodes.length; i++) {
68
62
  this.bindTree(mutation.addedNodes[i]);
@@ -83,7 +77,7 @@ class Observer {
83
77
  }
84
78
  let attr = this.attributesMap.get(id);
85
79
  if (attr === undefined) {
86
- this.attributesMap.set(id, attr = new Set());
80
+ this.attributesMap.set(id, (attr = new Set()));
87
81
  }
88
82
  attr.add(name);
89
83
  continue;
@@ -131,7 +125,7 @@ class Observer {
131
125
  return;
132
126
  }
133
127
  if (name === 'value' &&
134
- (0, guards_js_1.hasTag)(node, "INPUT") &&
128
+ (0, guards_js_1.hasTag)(node, 'INPUT') &&
135
129
  node.type !== 'button' &&
136
130
  node.type !== 'reset' &&
137
131
  node.type !== 'submit') {
@@ -141,7 +135,7 @@ class Observer {
141
135
  this.app.send(new messages_js_1.RemoveNodeAttribute(id, name));
142
136
  return;
143
137
  }
144
- if (name === 'style' || name === 'href' && (0, guards_js_1.hasTag)(node, "LINK")) {
138
+ if (name === 'style' || (name === 'href' && (0, guards_js_1.hasTag)(node, 'LINK'))) {
145
139
  this.app.send(new messages_js_1.SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
146
140
  return;
147
141
  }
@@ -151,7 +145,7 @@ class Observer {
151
145
  this.app.send(new messages_js_1.SetNodeAttribute(id, name, value));
152
146
  }
153
147
  sendNodeData(id, parentElement, data) {
154
- if ((0, guards_js_1.hasTag)(parentElement, "STYLE") || (0, guards_js_1.hasTag)(parentElement, "style")) {
148
+ if ((0, guards_js_1.hasTag)(parentElement, 'STYLE') || (0, guards_js_1.hasTag)(parentElement, 'style')) {
155
149
  this.app.send(new messages_js_1.SetCSSDataURLBased(id, data, this.app.getBaseHref()));
156
150
  return;
157
151
  }
@@ -163,40 +157,43 @@ class Observer {
163
157
  if (isNew) {
164
158
  this.recents.set(id, RecentsType.New);
165
159
  }
166
- else if (this.recents.get(id) !== RecentsType.New) { // can we do just `else` here?
160
+ else if (this.recents.get(id) !== RecentsType.New) {
167
161
  this.recents.set(id, RecentsType.Removed);
168
162
  }
169
163
  }
170
- unbindChildNode(node) {
171
- const [id] = this.app.nodes.registerNode(node);
172
- this.recents.set(id, RecentsType.RemovedChild);
173
- }
174
- bindTree(node, isChildUnbinding = false) {
164
+ bindTree(node) {
175
165
  if (!isObservable(node)) {
176
166
  return;
177
167
  }
178
168
  this.bindNode(node);
179
169
  const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
180
- acceptNode: (node) => isIgnored(node)
181
- || (this.app.nodes.getID(node) !== undefined && !isChildUnbinding)
170
+ acceptNode: (node) => isIgnored(node) || this.app.nodes.getID(node) !== undefined
182
171
  ? NodeFilter.FILTER_REJECT
183
172
  : NodeFilter.FILTER_ACCEPT,
184
173
  },
185
174
  // @ts-ignore
186
175
  false);
187
176
  while (walker.nextNode()) {
188
- if (isChildUnbinding) {
189
- this.unbindChildNode(walker.currentNode);
190
- }
191
- else {
192
- this.bindNode(walker.currentNode);
193
- }
177
+ this.bindNode(walker.currentNode);
194
178
  }
195
179
  }
196
- unbindNode(node) {
180
+ unbindTree(node) {
197
181
  const id = this.app.nodes.unregisterNode(node);
198
182
  if (id !== undefined && this.recents.get(id) === RecentsType.Removed) {
199
- this.app.send(new messages_js_1.RemoveNode(id));
183
+ // Sending RemoveNode only for parent to maintain
184
+ this.app.send((0, messages_js_1.RemoveNode)(id));
185
+ // Unregistering all the children in order to clear the memory
186
+ const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
187
+ acceptNode: (node) => isIgnored(node) || this.app.nodes.getID(node) === undefined
188
+ ? NodeFilter.FILTER_REJECT
189
+ : NodeFilter.FILTER_ACCEPT,
190
+ },
191
+ // @ts-ignore
192
+ false);
193
+ while (walker.nextNode()) {
194
+ this.app.nodes.unregisterNode(walker.currentNode);
195
+ }
196
+ // MBTODO: count and send RemovedNodesCount (for the page crash detection in heuristics)
200
197
  }
201
198
  }
202
199
  // A top-consumption function on the infinite lists test. (~1% of performance resources)
@@ -209,20 +206,20 @@ class Observer {
209
206
  // Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
210
207
  // TODO: get rid of "special" cases (there is an issue with CreateDocument altered behaviour though)
211
208
  // TODO: Clean the logic (though now it workd fine)
212
- if (!(0, guards_js_1.hasTag)(node, "HTML") || !this.isTopContext) {
209
+ if (!(0, guards_js_1.hasTag)(node, 'HTML') || !this.isTopContext) {
213
210
  if (parent === null) {
214
211
  // Sometimes one observation contains attribute mutations for the removimg node, which gets ignored here.
215
- // That shouldn't affect the visual rendering ( should it? )
216
- this.unbindNode(node);
212
+ // That shouldn't affect the visual rendering ( should it? maybe when transition applied? )
213
+ this.unbindTree(node);
217
214
  return false;
218
215
  }
219
216
  parentID = this.app.nodes.getID(parent);
220
217
  if (parentID === undefined) {
221
- this.unbindNode(node);
218
+ this.unbindTree(node);
222
219
  return false;
223
220
  }
224
221
  if (!this.commitNode(parentID)) {
225
- this.unbindNode(node);
222
+ this.unbindTree(node);
226
223
  return false;
227
224
  }
228
225
  this.app.sanitizer.handleNode(id, parentID, node);
@@ -317,7 +314,8 @@ class Observer {
317
314
  });
318
315
  this.clear();
319
316
  }
320
- // ISSSUE
317
+ // ISSSUE (nodeToBinde should be the same as node. Look at the comment about 0-node at the beginning of the file.)
318
+ // TODO: use one observer instance for all iframes/shadowRoots (composition instiad of inheritance)
321
319
  observeRoot(node, beforeCommit, nodeToBind = node) {
322
320
  this.observer.observe(node, {
323
321
  childList: true,
@@ -1,4 +1,4 @@
1
- import Observer from "./observer.js";
1
+ import Observer from './observer.js';
2
2
  export default class ShadowRootObserver extends Observer {
3
3
  observe(el: Element): void;
4
4
  }
@@ -11,7 +11,7 @@ class ShadowRootObserver extends observer_js_1.default {
11
11
  } // log
12
12
  this.observeRoot(shRoot, (rootID) => {
13
13
  if (rootID === undefined) {
14
- console.log("OpenReplay: Shadow Root was not bound");
14
+ console.log('OpenReplay: Shadow Root was not bound');
15
15
  return;
16
16
  }
17
17
  this.app.send((0, messages_js_1.CreateIFrameDocument)(hostID, rootID));
@@ -1,5 +1,5 @@
1
- import Observer from "./observer.js";
2
- import App from "../index.js";
1
+ import Observer from './observer.js';
2
+ import App from '../index.js';
3
3
  export interface Options {
4
4
  captureIFrames: boolean;
5
5
  }
@@ -13,18 +13,18 @@ class TopObserver extends observer_js_1.default {
13
13
  this.iframeObservers = [];
14
14
  this.shadowRootObservers = [];
15
15
  this.options = Object.assign({
16
- captureIFrames: true
16
+ captureIFrames: true,
17
17
  }, options);
18
18
  // IFrames
19
- this.app.nodes.attachNodeCallback(node => {
20
- if ((0, guards_js_1.hasTag)(node, "IFRAME") &&
21
- ((this.options.captureIFrames && !(0, utils_js_1.hasOpenreplayAttribute)(node, "obscured"))
22
- || (0, utils_js_1.hasOpenreplayAttribute)(node, "capture"))) {
19
+ this.app.nodes.attachNodeCallback((node) => {
20
+ if ((0, guards_js_1.hasTag)(node, 'IFRAME') &&
21
+ ((this.options.captureIFrames && !(0, utils_js_1.hasOpenreplayAttribute)(node, 'obscured')) ||
22
+ (0, utils_js_1.hasOpenreplayAttribute)(node, 'capture'))) {
23
23
  this.handleIframe(node);
24
24
  }
25
25
  });
26
26
  // ShadowDOM
27
- this.app.nodes.attachNodeCallback(node => {
27
+ this.app.nodes.attachNodeCallback((node) => {
28
28
  if ((0, guards_js_1.isElementNode)(node) && node.shadowRoot !== null) {
29
29
  this.handleShadowRoot(node.shadowRoot);
30
30
  }
@@ -48,7 +48,7 @@ class TopObserver extends observer_js_1.default {
48
48
  this.iframeObservers.push(observer);
49
49
  observer.observe(iframe);
50
50
  });
51
- iframe.addEventListener("load", handle); // why app.attachEventListener not working?
51
+ iframe.addEventListener('load', handle); // why app.attachEventListener not working?
52
52
  handle();
53
53
  }
54
54
  handleShadowRoot(shRoot) {
@@ -60,14 +60,15 @@ class TopObserver extends observer_js_1.default {
60
60
  // Protection from several subsequent calls?
61
61
  const observer = this;
62
62
  Element.prototype.attachShadow = function () {
63
+ // eslint-disable-next-line
63
64
  const shadow = attachShadowNativeFn.apply(this, arguments);
64
65
  observer.handleShadowRoot(shadow);
65
66
  return shadow;
66
67
  };
67
68
  // Can observe documentElement (<html>) here, because it is not supposed to be changing.
68
69
  // However, it is possible in some exotic cases and may cause an ignorance of the newly created <html>
69
- // In this case context.document have to be observed, but this will cause
70
- // the change in the re-player behaviour caused by CreateDocument message:
70
+ // In this case context.document have to be observed, but this will cause
71
+ // the change in the re-player behaviour caused by CreateDocument message:
71
72
  // the 0-node ("fRoot") will become #document rather than documentElement as it is now.
72
73
  // Alternatively - observe(#document) then bindNode(documentElement)
73
74
  this.observeRoot(window.document, () => {
@@ -76,9 +77,9 @@ class TopObserver extends observer_js_1.default {
76
77
  }
77
78
  disconnect() {
78
79
  Element.prototype.attachShadow = attachShadowNativeFn;
79
- this.iframeObservers.forEach(o => o.disconnect());
80
+ this.iframeObservers.forEach((o) => o.disconnect());
80
81
  this.iframeObservers = [];
81
- this.shadowRootObservers.forEach(o => o.disconnect());
82
+ this.shadowRootObservers.forEach((o) => o.disconnect());
82
83
  this.shadowRootObservers = [];
83
84
  super.disconnect();
84
85
  }
@@ -1,4 +1,4 @@
1
- import type App from "./index.js";
1
+ import type App from './index.js';
2
2
  export interface Options {
3
3
  obscureTextEmails: boolean;
4
4
  obscureTextNumbers: boolean;
@@ -14,20 +14,20 @@ class Sanitizer {
14
14
  }
15
15
  handleNode(id, parentID, node) {
16
16
  if (this.masked.has(parentID) ||
17
- ((0, guards_js_1.isElementNode)(node) &&
18
- (0, utils_js_1.hasOpenreplayAttribute)(node, 'masked'))) {
17
+ ((0, guards_js_1.isElementNode)(node) && (0, utils_js_1.hasOpenreplayAttribute)(node, 'masked'))) {
19
18
  this.masked.add(id);
20
19
  }
21
20
  if (this.maskedContainers.has(parentID) ||
22
- ((0, guards_js_1.isElementNode)(node) &&
23
- (0, utils_js_1.hasOpenreplayAttribute)(node, 'htmlmasked'))) {
21
+ ((0, guards_js_1.isElementNode)(node) && (0, utils_js_1.hasOpenreplayAttribute)(node, 'htmlmasked'))) {
24
22
  this.maskedContainers.add(id);
25
23
  }
26
24
  }
27
25
  sanitize(id, data) {
28
26
  if (this.masked.has(id)) {
29
27
  // TODO: is it the best place to put trim() ? Might trimmed spaces be considered in layout in certain cases?
30
- return data.trim().replace(/[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/g, '█');
28
+ return data
29
+ .trim()
30
+ .replace(/[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/g, '█');
31
31
  }
32
32
  if (this.options.obscureTextNumbers) {
33
33
  data = data.replace(/\d/g, '0');
@@ -1,14 +1,26 @@
1
+ import type App from './index.js';
1
2
  interface SessionInfo {
2
- sessionID: string | null;
3
+ sessionID: string | undefined;
3
4
  metadata: Record<string, string>;
4
5
  userID: string | null;
6
+ timestamp: number;
7
+ projectID?: string;
5
8
  }
6
9
  declare type OnUpdateCallback = (i: Partial<SessionInfo>) => void;
10
+ export declare type Options = {
11
+ session_token_key: string;
12
+ session_pageno_key: string;
13
+ };
7
14
  export default class Session {
15
+ private readonly app;
16
+ private readonly options;
8
17
  private metadata;
9
18
  private userID;
10
19
  private sessionID;
11
- private callbacks;
20
+ private readonly callbacks;
21
+ private timestamp;
22
+ private projectID;
23
+ constructor(app: App, options: Options);
12
24
  attachUpdateCallback(cb: OnUpdateCallback): void;
13
25
  private handleUpdate;
14
26
  update(newInfo: Partial<SessionInfo>): void;
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  class Session {
4
- constructor() {
4
+ constructor(app, options) {
5
+ this.app = app;
6
+ this.options = options;
5
7
  this.metadata = {};
6
8
  this.userID = null;
7
- this.sessionID = null;
8
9
  this.callbacks = [];
10
+ this.timestamp = 0;
9
11
  }
10
12
  attachUpdateCallback(cb) {
11
13
  this.callbacks.push(cb);
@@ -17,18 +19,25 @@ class Session {
17
19
  if (newInfo.sessionID == null) {
18
20
  delete newInfo.sessionID;
19
21
  }
20
- this.callbacks.forEach(cb => cb(newInfo));
22
+ this.callbacks.forEach((cb) => cb(newInfo));
21
23
  }
22
24
  update(newInfo) {
23
- if (newInfo.userID !== undefined) { // TODO clear nullable/undefinable types
25
+ if (newInfo.userID !== undefined) {
26
+ // TODO clear nullable/undefinable types
24
27
  this.userID = newInfo.userID;
25
28
  }
26
29
  if (newInfo.metadata !== undefined) {
27
- Object.entries(newInfo.metadata).forEach(([k, v]) => this.metadata[k] = v);
30
+ Object.entries(newInfo.metadata).forEach(([k, v]) => (this.metadata[k] = v));
28
31
  }
29
32
  if (newInfo.sessionID !== undefined) {
30
33
  this.sessionID = newInfo.sessionID;
31
34
  }
35
+ if (newInfo.timestamp !== undefined) {
36
+ this.timestamp = newInfo.timestamp;
37
+ }
38
+ if (newInfo.projectID !== undefined) {
39
+ this.projectID = newInfo.projectID;
40
+ }
32
41
  this.handleUpdate(newInfo);
33
42
  }
34
43
  setMetadata(key, value) {
@@ -44,12 +53,16 @@ class Session {
44
53
  sessionID: this.sessionID,
45
54
  metadata: this.metadata,
46
55
  userID: this.userID,
56
+ timestamp: this.timestamp,
57
+ projectID: this.projectID,
47
58
  };
48
59
  }
49
60
  reset() {
61
+ this.app.sessionStorage.removeItem(this.options.session_token_key);
50
62
  this.metadata = {};
51
63
  this.userID = null;
52
- this.sessionID = null;
64
+ this.sessionID = undefined;
65
+ this.timestamp = 0;
53
66
  }
54
67
  }
55
68
  exports.default = Session;
@@ -1,4 +1,4 @@
1
- import App from "./index.js";
1
+ import App from './index.js';
2
2
  declare type Callback = () => void;
3
3
  export default class Ticker {
4
4
  private readonly app;
@@ -1,4 +1,4 @@
1
- import type { Writer, Message } from "./types.js";
1
+ import type { Writer, Message } from './types.js';
2
2
  export default Message;
3
3
  export declare const classes: Map<number, Function>;
4
4
  declare class _BatchMeta implements Message {