@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.
- package/cjs/app/context.d.ts +18 -0
- package/cjs/app/context.js +48 -0
- package/cjs/app/index.d.ts +11 -6
- package/cjs/app/index.js +33 -22
- package/cjs/app/observer/iframe_observer.d.ts +4 -0
- package/cjs/app/observer/iframe_observer.js +22 -0
- package/cjs/app/observer/observer.d.ts +25 -0
- package/cjs/app/{observer.js → observer/observer.js} +82 -170
- package/cjs/app/observer/shadow_root_observer.d.ts +4 -0
- package/cjs/app/observer/shadow_root_observer.js +21 -0
- package/cjs/app/observer/top_observer.d.ts +15 -0
- package/cjs/app/observer/top_observer.js +84 -0
- package/cjs/app/sanitizer.d.ts +16 -0
- package/cjs/app/sanitizer.js +46 -0
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +7 -1
- package/cjs/modules/exception.js +8 -1
- package/cjs/modules/img.js +15 -1
- package/cjs/modules/input.d.ts +3 -1
- package/cjs/modules/input.js +6 -3
- package/cjs/modules/mouse.js +1 -1
- package/lib/app/context.d.ts +18 -0
- package/lib/app/context.js +43 -0
- package/lib/app/index.d.ts +11 -6
- package/lib/app/index.js +33 -22
- package/lib/app/observer/iframe_observer.d.ts +4 -0
- package/lib/app/observer/iframe_observer.js +19 -0
- package/lib/app/observer/observer.d.ts +25 -0
- package/lib/app/{observer.js → observer/observer.js} +82 -170
- package/lib/app/observer/shadow_root_observer.d.ts +4 -0
- package/lib/app/observer/shadow_root_observer.js +18 -0
- package/lib/app/observer/top_observer.d.ts +15 -0
- package/lib/app/observer/top_observer.js +81 -0
- package/lib/app/sanitizer.d.ts +16 -0
- package/lib/app/sanitizer.js +44 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +7 -1
- package/lib/modules/exception.js +8 -1
- package/lib/modules/img.js +16 -2
- package/lib/modules/input.d.ts +3 -1
- package/lib/modules/input.js +6 -3
- package/lib/modules/mouse.js +1 -1
- package/package.json +1 -1
- package/cjs/app/observer.d.ts +0 -47
- 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;
|
package/cjs/app/index.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import Message from "../messages/message.js";
|
|
2
2
|
import Nodes from "./nodes.js";
|
|
3
|
-
import
|
|
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
|
-
|
|
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
|
-
} &
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
251
|
-
}, false);
|
|
252
|
-
this.attachEventListener(window, 'pagehide', ()
|
|
253
|
-
|
|
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,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
|
+
}
|