@openreplay/tracker 3.4.13 → 3.4.17-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/cjs/app/context.d.ts +18 -0
  2. package/cjs/app/context.js +48 -0
  3. package/cjs/app/index.d.ts +11 -6
  4. package/cjs/app/index.js +33 -22
  5. package/cjs/app/observer/iframe_observer.d.ts +4 -0
  6. package/cjs/app/observer/iframe_observer.js +22 -0
  7. package/cjs/app/observer/observer.d.ts +25 -0
  8. package/cjs/app/{observer.js → observer/observer.js} +82 -170
  9. package/cjs/app/observer/shadow_root_observer.d.ts +4 -0
  10. package/cjs/app/observer/shadow_root_observer.js +21 -0
  11. package/cjs/app/observer/top_observer.d.ts +15 -0
  12. package/cjs/app/observer/top_observer.js +84 -0
  13. package/cjs/app/sanitizer.d.ts +16 -0
  14. package/cjs/app/sanitizer.js +46 -0
  15. package/cjs/index.d.ts +1 -0
  16. package/cjs/index.js +7 -1
  17. package/cjs/modules/exception.js +8 -1
  18. package/cjs/modules/img.js +15 -1
  19. package/cjs/modules/input.d.ts +3 -1
  20. package/cjs/modules/input.js +6 -3
  21. package/cjs/modules/mouse.js +1 -1
  22. package/lib/app/context.d.ts +18 -0
  23. package/lib/app/context.js +43 -0
  24. package/lib/app/index.d.ts +11 -6
  25. package/lib/app/index.js +33 -22
  26. package/lib/app/observer/iframe_observer.d.ts +4 -0
  27. package/lib/app/observer/iframe_observer.js +19 -0
  28. package/lib/app/observer/observer.d.ts +25 -0
  29. package/lib/app/{observer.js → observer/observer.js} +82 -170
  30. package/lib/app/observer/shadow_root_observer.d.ts +4 -0
  31. package/lib/app/observer/shadow_root_observer.js +18 -0
  32. package/lib/app/observer/top_observer.d.ts +15 -0
  33. package/lib/app/observer/top_observer.js +81 -0
  34. package/lib/app/sanitizer.d.ts +16 -0
  35. package/lib/app/sanitizer.js +44 -1
  36. package/lib/index.d.ts +1 -0
  37. package/lib/index.js +7 -1
  38. package/lib/modules/exception.js +8 -1
  39. package/lib/modules/img.js +16 -2
  40. package/lib/modules/input.d.ts +3 -1
  41. package/lib/modules/input.js +6 -3
  42. package/lib/modules/mouse.js +1 -1
  43. package/package.json +1 -1
  44. package/cjs/app/observer.d.ts +0 -47
  45. package/lib/app/observer.d.ts +0 -47
@@ -0,0 +1,18 @@
1
+ export interface Window extends globalThis.Window {
2
+ HTMLInputElement: typeof HTMLInputElement;
3
+ HTMLLinkElement: typeof HTMLLinkElement;
4
+ HTMLStyleElement: typeof HTMLStyleElement;
5
+ SVGStyleElement: typeof SVGStyleElement;
6
+ HTMLIFrameElement: typeof HTMLIFrameElement;
7
+ Text: typeof Text;
8
+ Element: typeof Element;
9
+ ShadowRoot: typeof ShadowRoot;
10
+ }
11
+ declare type WindowConstructor = Document | Element | Text | ShadowRoot | HTMLInputElement | HTMLLinkElement | HTMLStyleElement | HTMLIFrameElement;
12
+ declare type Constructor<T> = {
13
+ new (...args: any[]): T;
14
+ name: string;
15
+ };
16
+ export declare function isInstance<T extends WindowConstructor>(node: Node, constr: Constructor<T>): node is T;
17
+ export declare function inDocument(node: Node): boolean;
18
+ export {};
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.inDocument = exports.isInstance = void 0;
4
+ // TODO: we need a type expert here so we won't have to ignore the lines
5
+ // TODO: use it everywhere (static function; export from which file? <-- global Window typing required)
6
+ function isInstance(node, constr) {
7
+ const doc = node.ownerDocument;
8
+ if (!doc) { // null if Document
9
+ return constr.name === 'Document';
10
+ }
11
+ let context =
12
+ // @ts-ignore (for EI, Safary)
13
+ doc.parentWindow ||
14
+ doc.defaultView; // TODO: smart global typing for Window object
15
+ while (context.parent && context.parent !== context) {
16
+ // @ts-ignore
17
+ if (node instanceof context[constr.name]) {
18
+ return true;
19
+ }
20
+ // @ts-ignore
21
+ context = context.parent;
22
+ }
23
+ // @ts-ignore
24
+ return node instanceof context[constr.name];
25
+ }
26
+ exports.isInstance = isInstance;
27
+ function inDocument(node) {
28
+ const doc = node.ownerDocument;
29
+ if (!doc) {
30
+ return false;
31
+ }
32
+ if (doc.contains(node)) {
33
+ return true;
34
+ }
35
+ let context =
36
+ // @ts-ignore (for EI, Safary)
37
+ doc.parentWindow ||
38
+ doc.defaultView;
39
+ while (context.parent && context.parent !== context) {
40
+ if (context.document.contains(node)) {
41
+ return true;
42
+ }
43
+ // @ts-ignore
44
+ context = context.parent;
45
+ }
46
+ return false;
47
+ }
48
+ exports.inDocument = inDocument;
@@ -1,19 +1,21 @@
1
1
  import Message from "../messages/message.js";
2
2
  import Nodes from "./nodes.js";
3
- import Observer from "./observer.js";
3
+ import Sanitizer from "./sanitizer.js";
4
4
  import Ticker from "./ticker.js";
5
- import type { Options as ObserverOptions } from "./observer.js";
5
+ import type { Options as ObserverOptions } from "./observer/top_observer.js";
6
+ import type { Options as SanitizerOptions } from "./sanitizer.js";
6
7
  import type { Options as WebworkerOptions } from "../messages/webworker.js";
7
8
  export interface OnStartInfo {
8
9
  sessionID: string;
9
10
  sessionToken: string;
10
11
  userUUID: string;
11
12
  }
12
- export declare type Options = {
13
+ declare type AppOptions = {
13
14
  revID: string;
14
15
  node_id: string;
15
16
  session_token_key: string;
16
17
  session_pageno_key: string;
18
+ session_reset_key: string;
17
19
  local_uuid_key: string;
18
20
  ingestPoint: string;
19
21
  resourceBaseHref: string | null;
@@ -21,7 +23,8 @@ export declare type Options = {
21
23
  __debug_report_edp: string | null;
22
24
  __debug_log: boolean;
23
25
  onStart?: (info: OnStartInfo) => void;
24
- } & ObserverOptions & WebworkerOptions;
26
+ } & WebworkerOptions;
27
+ export declare type Options = AppOptions & ObserverOptions & SanitizerOptions;
25
28
  declare type Callback = () => void;
26
29
  declare type CommitCallback = (messages: Array<Message>) => void;
27
30
  export declare const DEFAULT_INGEST_POINT = "https://api.openreplay.com/ingest";
@@ -29,8 +32,9 @@ export default class App {
29
32
  readonly nodes: Nodes;
30
33
  readonly ticker: Ticker;
31
34
  readonly projectKey: string;
35
+ readonly sanitizer: Sanitizer;
32
36
  private readonly messages;
33
- readonly observer: Observer;
37
+ private readonly observer;
34
38
  private readonly startCallbacks;
35
39
  private readonly stopCallbacks;
36
40
  private readonly commitCallbacks;
@@ -40,7 +44,7 @@ export default class App {
40
44
  private isActive;
41
45
  private version;
42
46
  private readonly worker?;
43
- constructor(projectKey: string, sessionToken: string | null | undefined, opts: Partial<Options>);
47
+ constructor(projectKey: string, sessionToken: string | null | undefined, options: Partial<Options>);
44
48
  private _debug;
45
49
  send(message: Message, urgent?: boolean): void;
46
50
  private commit;
@@ -58,6 +62,7 @@ export default class App {
58
62
  resolveResourceURL(resourceURL: string): string;
59
63
  isServiceURL(url: string): boolean;
60
64
  active(): boolean;
65
+ resetNextPageSession(flag: boolean): void;
61
66
  private _start;
62
67
  start(reset?: boolean): Promise<OnStartInfo>;
63
68
  stop(): void;
package/cjs/app/index.js CHANGED
@@ -4,42 +4,42 @@ exports.DEFAULT_INGEST_POINT = void 0;
4
4
  const utils_js_1 = require("../utils.js");
5
5
  const index_js_1 = require("../messages/index.js");
6
6
  const nodes_js_1 = require("./nodes.js");
7
- const observer_js_1 = require("./observer.js");
7
+ const top_observer_js_1 = require("./observer/top_observer.js");
8
+ const sanitizer_js_1 = require("./sanitizer.js");
8
9
  const ticker_js_1 = require("./ticker.js");
9
10
  const performance_js_1 = require("../modules/performance.js");
10
11
  // TODO: use backendHost only
11
12
  exports.DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
12
13
  class App {
13
- constructor(projectKey, sessionToken, opts) {
14
+ constructor(projectKey, sessionToken, options) {
14
15
  this.messages = [];
15
16
  this.startCallbacks = [];
16
17
  this.stopCallbacks = [];
17
18
  this.commitCallbacks = [];
18
19
  this._sessionID = null;
19
20
  this.isActive = false;
20
- this.version = '3.4.13';
21
+ this.version = '3.4.17-beta.0';
21
22
  this.projectKey = projectKey;
22
23
  this.options = Object.assign({
23
24
  revID: '',
24
25
  node_id: '__openreplay_id',
25
26
  session_token_key: '__openreplay_token',
26
27
  session_pageno_key: '__openreplay_pageno',
28
+ session_reset_key: '__openreplay_reset',
27
29
  local_uuid_key: '__openreplay_uuid',
28
30
  ingestPoint: exports.DEFAULT_INGEST_POINT,
29
31
  resourceBaseHref: null,
30
32
  __is_snippet: false,
31
33
  __debug_report_edp: null,
32
34
  __debug_log: false,
33
- obscureTextEmails: true,
34
- obscureTextNumbers: false,
35
- captureIFrames: false,
36
- }, opts);
35
+ }, options);
37
36
  if (sessionToken != null) {
38
37
  sessionStorage.setItem(this.options.session_token_key, sessionToken);
39
38
  }
40
39
  this.revID = this.options.revID;
40
+ this.sanitizer = new sanitizer_js_1.default(this, options);
41
41
  this.nodes = new nodes_js_1.default(this.options.node_id);
42
- this.observer = new observer_js_1.default(this, this.options);
42
+ this.observer = new top_observer_js_1.default(this, options);
43
43
  this.ticker = new ticker_js_1.default(this);
44
44
  this.ticker.attach(() => this.commit());
45
45
  try {
@@ -181,6 +181,14 @@ class App {
181
181
  active() {
182
182
  return this.isActive;
183
183
  }
184
+ resetNextPageSession(flag) {
185
+ if (flag) {
186
+ sessionStorage.setItem(this.options.session_reset_key, 't');
187
+ }
188
+ else {
189
+ sessionStorage.removeItem(this.options.session_reset_key);
190
+ }
191
+ }
184
192
  _start(reset) {
185
193
  if (!this.isActive) {
186
194
  if (!this.worker) {
@@ -203,18 +211,20 @@ class App {
203
211
  connAttemptGap: this.options.connAttemptGap,
204
212
  };
205
213
  this.worker.postMessage(messageData); // brings delay of 10th ms?
206
- let token = sessionStorage.getItem(this.options.session_token_key);
207
- const tokenIsActive = localStorage.getItem("__or_at_" + token);
208
- if (tokenIsActive) {
209
- token = null;
210
- }
214
+ // let token = sessionStorage.getItem(this.options.session_token_key)
215
+ // const tokenIsActive = localStorage.getItem("__or_at_" + token)
216
+ // if (tokenIsActive) {
217
+ // token = null
218
+ // }
219
+ const sReset = sessionStorage.getItem(this.options.session_reset_key);
220
+ sessionStorage.removeItem(this.options.session_reset_key);
211
221
  return window.fetch(this.options.ingestPoint + '/v1/web/start', {
212
222
  method: 'POST',
213
223
  headers: {
214
224
  'Content-Type': 'application/json',
215
225
  },
216
226
  body: JSON.stringify({
217
- token,
227
+ token: sessionStorage.getItem(this.options.session_token_key),
218
228
  userUUID: localStorage.getItem(this.options.local_uuid_key),
219
229
  projectKey: this.projectKey,
220
230
  revID: this.revID,
@@ -223,7 +233,7 @@ class App {
223
233
  isSnippet: this.options.__is_snippet,
224
234
  deviceMemory: performance_js_1.deviceMemory,
225
235
  jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit,
226
- reset,
236
+ reset: reset || sReset !== null,
227
237
  }),
228
238
  })
229
239
  .then(r => {
@@ -245,13 +255,13 @@ class App {
245
255
  }
246
256
  sessionStorage.setItem(this.options.session_token_key, token);
247
257
  localStorage.setItem(this.options.local_uuid_key, userUUID);
248
- localStorage.setItem("__or_at_" + token, "true");
249
- this.attachEventListener(window, 'beforeunload', () => {
250
- localStorage.removeItem("__or_at_" + token);
251
- }, false);
252
- this.attachEventListener(window, 'pagehide', () => {
253
- localStorage.removeItem("__or_at_" + token);
254
- }, false);
258
+ // localStorage.setItem("__or_at_" + token, "true")
259
+ // this.attachEventListener(window, 'beforeunload', ()=>{
260
+ // localStorage.removeItem("__or_at_" + token)
261
+ // }, false);
262
+ // this.attachEventListener(window, 'pagehide', ()=>{
263
+ // localStorage.removeItem("__or_at_" + token)
264
+ // }, false);
255
265
  if (typeof sessionID === 'string') {
256
266
  this._sessionID = sessionID;
257
267
  }
@@ -301,6 +311,7 @@ class App {
301
311
  if (this.worker) {
302
312
  this.worker.postMessage("stop");
303
313
  }
314
+ this.sanitizer.clear();
304
315
  this.observer.disconnect();
305
316
  this.nodes.clear();
306
317
  this.ticker.stop();
@@ -0,0 +1,4 @@
1
+ import Observer from "./observer.js";
2
+ export default class IFrameObserver extends Observer {
3
+ observe(iframe: HTMLIFrameElement): void;
4
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const observer_js_1 = require("./observer.js");
4
+ const index_js_1 = require("../../messages/index.js");
5
+ class IFrameObserver extends observer_js_1.default {
6
+ observe(iframe) {
7
+ const doc = iframe.contentDocument;
8
+ const hostID = this.app.nodes.getID(iframe);
9
+ if (!doc || hostID === undefined) {
10
+ return;
11
+ } //log TODO common app.logger
12
+ // Have to observe document, because the inner <html> might be changed
13
+ this.observeRoot(doc, (docID) => {
14
+ if (docID === undefined) {
15
+ console.log("OpenReplay: Iframe document not bound");
16
+ return;
17
+ }
18
+ this.app.send((0, index_js_1.CreateIFrameDocument)(hostID, docID));
19
+ });
20
+ }
21
+ }
22
+ exports.default = IFrameObserver;
@@ -0,0 +1,25 @@
1
+ import App from "../index.js";
2
+ export default abstract class Observer {
3
+ protected readonly app: App;
4
+ protected readonly context: Window;
5
+ private readonly observer;
6
+ private readonly commited;
7
+ private readonly recents;
8
+ private readonly myNodes;
9
+ private readonly indexes;
10
+ private readonly attributesList;
11
+ private readonly textSet;
12
+ private readonly inUpperContext;
13
+ constructor(app: App, context?: Window);
14
+ private clear;
15
+ private sendNodeAttribute;
16
+ private sendNodeData;
17
+ private bindNode;
18
+ private bindTree;
19
+ private unbindNode;
20
+ private _commitNode;
21
+ private commitNode;
22
+ private commitNodes;
23
+ protected observeRoot(node: Node, beforeCommit: (id?: number) => unknown, nodeToBind?: Node): void;
24
+ disconnect(): void;
25
+ }