@oxvo/browser 7.1.0 → 7.3.4
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/README.md +32 -0
- package/dist/cjs/common/interaction.d.ts +12 -1
- package/dist/cjs/common/messages.gen.d.ts +4 -7
- package/dist/cjs/entry.js +2382 -1191
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +2329 -1179
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/app/canvas.d.ts +13 -0
- package/dist/cjs/main/app/cross_domain_iframe.d.ts +44 -0
- package/dist/cjs/main/app/index.d.ts +63 -15
- package/dist/cjs/main/app/messages.gen.d.ts +2 -1
- package/dist/cjs/main/app/observer/observer.d.ts +16 -0
- package/dist/cjs/main/app/sanitizer.d.ts +5 -3
- package/dist/cjs/main/app/session.d.ts +1 -0
- package/dist/cjs/main/entry.d.ts +5 -5
- package/dist/cjs/main/index.d.ts +17 -1
- package/dist/cjs/main/modules/analytics/batcher.d.ts +6 -1
- package/dist/cjs/main/modules/analytics/index.d.ts +10 -0
- package/dist/cjs/main/modules/input.d.ts +2 -1
- package/dist/cjs/main/modules/markerWatcher.d.ts +4 -8
- package/dist/cjs/main/modules/mouse.d.ts +1 -0
- package/dist/cjs/main/modules/tagMatcher.d.ts +28 -0
- package/dist/cjs/main/singleton.d.ts +24 -0
- package/dist/cjs/main/utils.d.ts +2 -0
- package/dist/cjs/package.json +1 -0
- package/dist/lib/common/interaction.d.ts +12 -1
- package/dist/lib/common/messages.gen.d.ts +4 -7
- package/dist/lib/entry.js +2382 -1191
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +2329 -1179
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/app/canvas.d.ts +13 -0
- package/dist/lib/main/app/cross_domain_iframe.d.ts +44 -0
- package/dist/lib/main/app/index.d.ts +63 -15
- package/dist/lib/main/app/messages.gen.d.ts +2 -1
- package/dist/lib/main/app/observer/observer.d.ts +16 -0
- package/dist/lib/main/app/sanitizer.d.ts +5 -3
- package/dist/lib/main/app/session.d.ts +1 -0
- package/dist/lib/main/entry.d.ts +5 -5
- package/dist/lib/main/index.d.ts +17 -1
- package/dist/lib/main/modules/analytics/batcher.d.ts +6 -1
- package/dist/lib/main/modules/analytics/index.d.ts +10 -0
- package/dist/lib/main/modules/input.d.ts +2 -1
- package/dist/lib/main/modules/markerWatcher.d.ts +4 -8
- package/dist/lib/main/modules/mouse.d.ts +1 -0
- package/dist/lib/main/modules/tagMatcher.d.ts +28 -0
- package/dist/lib/main/singleton.d.ts +24 -0
- package/dist/lib/main/utils.d.ts +2 -0
- package/dist/types/common/interaction.d.ts +12 -1
- package/dist/types/common/messages.gen.d.ts +4 -7
- package/dist/types/main/app/canvas.d.ts +13 -0
- package/dist/types/main/app/cross_domain_iframe.d.ts +44 -0
- package/dist/types/main/app/index.d.ts +63 -15
- package/dist/types/main/app/messages.gen.d.ts +2 -1
- package/dist/types/main/app/observer/observer.d.ts +16 -0
- package/dist/types/main/app/sanitizer.d.ts +5 -3
- package/dist/types/main/app/session.d.ts +1 -0
- package/dist/types/main/entry.d.ts +5 -5
- package/dist/types/main/index.d.ts +17 -1
- package/dist/types/main/modules/analytics/batcher.d.ts +6 -1
- package/dist/types/main/modules/analytics/index.d.ts +10 -0
- package/dist/types/main/modules/input.d.ts +2 -1
- package/dist/types/main/modules/markerWatcher.d.ts +4 -8
- package/dist/types/main/modules/mouse.d.ts +1 -0
- package/dist/types/main/modules/tagMatcher.d.ts +28 -0
- package/dist/types/main/singleton.d.ts +24 -0
- package/dist/types/main/utils.d.ts +2 -0
- package/package.json +14 -14
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type Message from './messages.gen.js';
|
|
2
|
+
export declare const CROSS_DOMAIN_IFRAME_PROTOCOL_VERSION: 1;
|
|
3
|
+
export declare const CROSS_DOMAIN_IFRAME_ALLOWED_MESSAGE_TYPES: ReadonlySet<number>;
|
|
4
|
+
export type CrossDomainIframeEnvelope = {
|
|
5
|
+
protocolVersion: typeof CROSS_DOMAIN_IFRAME_PROTOCOL_VERSION;
|
|
6
|
+
context: string;
|
|
7
|
+
nonce: string;
|
|
8
|
+
capability: string;
|
|
9
|
+
};
|
|
10
|
+
export type CrossDomainIframeHandshake = Omit<CrossDomainIframeEnvelope, 'capability'> & {
|
|
11
|
+
projectKey: string;
|
|
12
|
+
};
|
|
13
|
+
export type CrossDomainIframeSession = {
|
|
14
|
+
sessionID: string;
|
|
15
|
+
projectID?: string;
|
|
16
|
+
startedAt: number;
|
|
17
|
+
delayMs: number;
|
|
18
|
+
userUUID: string;
|
|
19
|
+
};
|
|
20
|
+
export type CrossDomainIframeCanvas = {
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
quality?: 'low' | 'medium' | 'high';
|
|
23
|
+
fps?: number;
|
|
24
|
+
framesSupport?: boolean;
|
|
25
|
+
};
|
|
26
|
+
type ParsedIframeBatch = {
|
|
27
|
+
messages: Message[];
|
|
28
|
+
bytes: number;
|
|
29
|
+
} | null;
|
|
30
|
+
export declare function normalizeCrossDomainOrigin(value: unknown): string | null;
|
|
31
|
+
export declare function normalizeCrossDomainOrigins(values: unknown): Set<string>;
|
|
32
|
+
export declare function createCrossDomainSecret(): string | null;
|
|
33
|
+
export declare function parseCrossDomainHandshake(data: unknown, expectedLine: string, expectedProjectKey: string): CrossDomainIframeHandshake | null;
|
|
34
|
+
export declare function matchesCrossDomainEnvelope(data: unknown, expectedLine: string, expected: CrossDomainIframeEnvelope): data is Record<string, unknown> & CrossDomainIframeEnvelope;
|
|
35
|
+
export declare function parseCrossDomainFrameInit(data: unknown, expectedLine: string, expected: Pick<CrossDomainIframeEnvelope, 'context' | 'nonce'>): (CrossDomainIframeEnvelope & {
|
|
36
|
+
id: number;
|
|
37
|
+
frameOrderNumber: number;
|
|
38
|
+
frameLevel: number;
|
|
39
|
+
capabilityExpiresAt: number;
|
|
40
|
+
session: CrossDomainIframeSession;
|
|
41
|
+
canvas?: CrossDomainIframeCanvas;
|
|
42
|
+
}) | null;
|
|
43
|
+
export declare function parseCrossDomainIframeBatch(messages: unknown): ParsedIframeBatch;
|
|
44
|
+
export {};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { Options as WebworkerOptions } from '../../common/interaction.js';
|
|
2
2
|
import AttributeSender from '../modules/attributeSender.js';
|
|
3
3
|
import type { Options as NetworkOptions } from '../modules/network.js';
|
|
4
|
+
import type TagMatcher from '../modules/tagMatcher.js';
|
|
4
5
|
import Logger, { ILogLevel } from './logger.js';
|
|
5
6
|
import Message from './messages.gen.js';
|
|
6
7
|
import Nodes from './nodes/index.js';
|
|
7
8
|
import type { Options as ObserverOptions } from './observer/top_observer.js';
|
|
8
9
|
import Observer from './observer/top_observer.js';
|
|
9
10
|
import type { Options as SanitizerOptions } from './sanitizer.js';
|
|
10
|
-
import Sanitizer from './sanitizer.js';
|
|
11
|
+
import Sanitizer, { SanitizeLevel } from './sanitizer.js';
|
|
11
12
|
import type { Options as SessOptions } from './session.js';
|
|
12
13
|
import Session from './session.js';
|
|
13
14
|
import Ticker from './ticker.js';
|
|
@@ -29,6 +30,7 @@ export interface StartOptions {
|
|
|
29
30
|
interface OnStartInfo {
|
|
30
31
|
sessionID: string;
|
|
31
32
|
sessionToken: string;
|
|
33
|
+
assistToken?: string;
|
|
32
34
|
userUUID: string;
|
|
33
35
|
}
|
|
34
36
|
declare const CANCELED: "canceled";
|
|
@@ -64,6 +66,7 @@ type AppOptions = {
|
|
|
64
66
|
__is_snippet: boolean;
|
|
65
67
|
__debug_report_edp: string | null;
|
|
66
68
|
__debug__?: ILogLevel;
|
|
69
|
+
__local_debug?: boolean;
|
|
67
70
|
localStorage: Storage | null;
|
|
68
71
|
sessionStorage: Storage | null;
|
|
69
72
|
forceSingleTab?: boolean;
|
|
@@ -95,11 +98,16 @@ type AppOptions = {
|
|
|
95
98
|
* */
|
|
96
99
|
enabled?: boolean;
|
|
97
100
|
/**
|
|
98
|
-
* used
|
|
99
|
-
*
|
|
100
|
-
* @default '*'
|
|
101
|
+
* Exact parent origin used by a tracker running inside a child iframe.
|
|
102
|
+
* Wildcards are rejected.
|
|
101
103
|
* */
|
|
102
104
|
parentDomain?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Exact child origins allowed to join the top-level recording. The
|
|
107
|
+
* cross-domain listener is not installed unless this list is non-empty.
|
|
108
|
+
* Wildcards are rejected.
|
|
109
|
+
* */
|
|
110
|
+
childOrigins?: string[];
|
|
103
111
|
};
|
|
104
112
|
networkCapture?: NetworkOptions;
|
|
105
113
|
/**
|
|
@@ -129,6 +137,7 @@ export default class App {
|
|
|
129
137
|
readonly ticker: Ticker;
|
|
130
138
|
readonly projectKey: string;
|
|
131
139
|
readonly sanitizer: Sanitizer;
|
|
140
|
+
private readonly resanitizeCallbacks;
|
|
132
141
|
readonly debug: Logger;
|
|
133
142
|
readonly notify: Logger;
|
|
134
143
|
readonly session: Session;
|
|
@@ -159,29 +168,52 @@ export default class App {
|
|
|
159
168
|
private canvasRecorder;
|
|
160
169
|
private conditionsManager;
|
|
161
170
|
private readonly markerWatcher;
|
|
171
|
+
private readonly bootstrapAttempts;
|
|
172
|
+
private offlineRecordingSessionToken;
|
|
173
|
+
get tagMatcher(): TagMatcher;
|
|
162
174
|
private canStart;
|
|
163
175
|
private rootId;
|
|
164
176
|
private pageFrames;
|
|
165
177
|
private frameOderNumber;
|
|
166
178
|
private frameLevel;
|
|
167
179
|
private emptyBatchCounter;
|
|
180
|
+
private readonly crossDomainChildOrigins;
|
|
181
|
+
private readonly crossDomainParentOrigin;
|
|
182
|
+
private readonly crossDomainFrameNonce;
|
|
183
|
+
private crossDomainFrameCapability;
|
|
184
|
+
private crossDomainFrameCapabilityExpiresAt;
|
|
185
|
+
private crossDomainFrameSession;
|
|
186
|
+
private crossDomainFrameCanvas;
|
|
187
|
+
private crossDomainResumeAfterHandshake;
|
|
188
|
+
private crossDomainConnectionRequested;
|
|
189
|
+
private readonly crossDomainFrames;
|
|
190
|
+
private readonly crossDomainEnvelopeBudgets;
|
|
191
|
+
private readonly pendingCrossDomainFrames;
|
|
192
|
+
private crossDomainAuthorizationGeneration;
|
|
193
|
+
private nextCrossDomainFrameOrder;
|
|
194
|
+
private crossDomainCanvasConfig;
|
|
168
195
|
constructor(projectKey: string, sessionToken: string | undefined, options: Partial<Options>, signalError: (error: string, apis: string[]) => void, insideIframe: boolean);
|
|
169
196
|
/** used by child iframes for crossdomain only */
|
|
170
197
|
parentActive: boolean;
|
|
171
198
|
checkStatus: () => boolean;
|
|
199
|
+
private postToParent;
|
|
200
|
+
private postHandshakeToParent;
|
|
201
|
+
private applyCrossDomainFrameInit;
|
|
202
|
+
private clearCrossDomainFrameAuthorization;
|
|
172
203
|
parentCrossDomainFrameListener: (event: MessageEvent) => void;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
204
|
+
private findCrossDomainFrame;
|
|
205
|
+
private revokeCrossDomainFrame;
|
|
206
|
+
private pruneDetachedCrossDomainFrames;
|
|
207
|
+
private currentCrossDomainSession;
|
|
208
|
+
private frameInitPayload;
|
|
209
|
+
private rotateCrossDomainFrameCapability;
|
|
210
|
+
private crossDomainFrameNeedsRotation;
|
|
211
|
+
private postToCrossDomainFrame;
|
|
212
|
+
private consumeCrossDomainEnvelopeBudget;
|
|
213
|
+
private establishCrossDomainFrame;
|
|
214
|
+
private validatedCrossDomainFrame;
|
|
215
|
+
private consumeCrossDomainFrameBudget;
|
|
178
216
|
crossDomainIframeListener: (event: MessageEvent) => void;
|
|
179
|
-
/**
|
|
180
|
-
* { command : [remaining iframes] }
|
|
181
|
-
* + order of commands
|
|
182
|
-
**/
|
|
183
|
-
pollingQueue: Record<string, any>;
|
|
184
|
-
private readonly addCommand;
|
|
185
217
|
bootChildrenFrames: () => Promise<void>;
|
|
186
218
|
killChildrenFrames: () => void;
|
|
187
219
|
signalIframeTracker: () => void;
|
|
@@ -218,6 +250,15 @@ export default class App {
|
|
|
218
250
|
checkRequiredVersion(version: string): boolean;
|
|
219
251
|
private getTrackerInfo;
|
|
220
252
|
private buildStartPayload;
|
|
253
|
+
private getBootstrapAttemptStorageKey;
|
|
254
|
+
private isValidBootstrapAttempt;
|
|
255
|
+
private removeStoredBootstrapAttempt;
|
|
256
|
+
private loadBootstrapAttempt;
|
|
257
|
+
private getOrCreateBootstrapAttempt;
|
|
258
|
+
private clearBootstrapAttempt;
|
|
259
|
+
private buildBootstrapIntentFingerprint;
|
|
260
|
+
private parseBootstrapIntent;
|
|
261
|
+
private bootstrapIntentsMatch;
|
|
221
262
|
getSessionMeta(): {
|
|
222
263
|
userUUID: string | null;
|
|
223
264
|
projectKey: string;
|
|
@@ -290,10 +331,17 @@ export default class App {
|
|
|
290
331
|
* */
|
|
291
332
|
uploadOfflineRecording(): Promise<void>;
|
|
292
333
|
prevOpts: StartOptions;
|
|
334
|
+
private userStartCallback?;
|
|
335
|
+
private startCrossDomainFrame;
|
|
293
336
|
private _start;
|
|
294
337
|
restartCanvasTracking: () => void;
|
|
338
|
+
attachResanitizeCallback: (cb: (node: Node, id: number) => void) => void;
|
|
339
|
+
callResanitizeCallbacks: (node: Node, id: number) => void;
|
|
340
|
+
resanitize: (el?: Element) => void;
|
|
341
|
+
checkSanitization: (el: Node) => SanitizeLevel | undefined;
|
|
295
342
|
flushBuffer: (buffer: Message[]) => Promise<unknown>;
|
|
296
343
|
waitStart(): Promise<unknown>;
|
|
344
|
+
private waitCrossDomainStart;
|
|
297
345
|
waitStarted(): Promise<unknown>;
|
|
298
346
|
waitStatus(status: ActivityState): Promise<unknown>;
|
|
299
347
|
/**
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as Messages from '../../common/messages.gen.js';
|
|
2
2
|
export { default, Type } from '../../common/messages.gen.js';
|
|
3
|
+
export type MessageFieldType = 'number' | 'string' | 'boolean';
|
|
4
|
+
export declare const MESSAGE_FIELD_TYPES: Readonly<Record<number, readonly MessageFieldType[]>>;
|
|
3
5
|
export declare function Timestamp(timestamp: number): Messages.Timestamp;
|
|
4
6
|
export declare function SetPageLocationDeprecated(url: string, referrer: string, navigationStart: number): Messages.SetPageLocationDeprecated;
|
|
5
7
|
export declare function SetViewportSize(width: number, height: number): Messages.SetViewportSize;
|
|
@@ -62,7 +64,6 @@ export declare function AdoptedSSRemoveOwner(sheetID: number, id: number): Messa
|
|
|
62
64
|
export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;
|
|
63
65
|
export declare function Zustand(mutation: string, state: string): Messages.Zustand;
|
|
64
66
|
export declare function BatchMetadata(version: number, pageNo: number, firstIndex: number, timestamp: number, location: string): Messages.BatchMetadata;
|
|
65
|
-
export declare function PartitionedMessage(partNo: number, partTotal: number): Messages.PartitionedMessage;
|
|
66
67
|
export declare function NetworkRequest(type: string, method: string, url: string, request: string, response: string, status: number, timestamp: number, duration: number, transferredBodySize: number): Messages.NetworkRequest;
|
|
67
68
|
export declare function WSChannel(chType: string, channelName: string, data: string, timestamp: number, dir: string, messageType: string): Messages.WSChannel;
|
|
68
69
|
export declare function ResourceTiming(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string, transferredSize: number, cached: boolean, queueing: number, dnsLookup: number, initialConnection: number, ssl: number, contentDownload: number, total: number, stalled: number): Messages.ResourceTiming;
|
|
@@ -28,6 +28,12 @@ export default abstract class Observer {
|
|
|
28
28
|
private readonly inlineRemoteCss;
|
|
29
29
|
private readonly inlinerOptions;
|
|
30
30
|
private readonly domParser;
|
|
31
|
+
/**
|
|
32
|
+
* Bumped on every disconnect(). Stale async CSS-inlining callbacks from a
|
|
33
|
+
* previous session (e.g. agent reload → tracker restart) compare against
|
|
34
|
+
* this and bail instead of sending messages that reference vanished node ids.
|
|
35
|
+
*/
|
|
36
|
+
private generation;
|
|
31
37
|
constructor(app: App, isTopContext?: boolean, options?: Options);
|
|
32
38
|
private clear;
|
|
33
39
|
/**
|
|
@@ -47,6 +53,16 @@ export default abstract class Observer {
|
|
|
47
53
|
private commitNode;
|
|
48
54
|
private commitNodes;
|
|
49
55
|
protected observeRoot(node: Node, beforeCommit: (id?: number) => unknown, nodeToBind?: Node): void;
|
|
56
|
+
/**
|
|
57
|
+
* Re-evaluates sanitization for every tracked node in `root`'s subtree against
|
|
58
|
+
* the current DOM and re-emits whatever changed. Pass the highest node you
|
|
59
|
+
* changed (or the document root) so inherited levels propagate correctly.
|
|
60
|
+
*/
|
|
61
|
+
resanitizeSubtree(root: Node): void;
|
|
62
|
+
private resanitizeNode;
|
|
63
|
+
private recreateSubtree;
|
|
64
|
+
private clearSubtreeRegistration;
|
|
65
|
+
private reemitNode;
|
|
50
66
|
disconnect(): void;
|
|
51
67
|
}
|
|
52
68
|
export {};
|
|
@@ -35,8 +35,7 @@ export interface Options {
|
|
|
35
35
|
}
|
|
36
36
|
export declare const stringWiper: (input: string) => string;
|
|
37
37
|
export default class Sanitizer {
|
|
38
|
-
private readonly
|
|
39
|
-
private readonly hidden;
|
|
38
|
+
private readonly levels;
|
|
40
39
|
private readonly options;
|
|
41
40
|
readonly maskAllByDefault: boolean;
|
|
42
41
|
private readonly app;
|
|
@@ -44,7 +43,10 @@ export default class Sanitizer {
|
|
|
44
43
|
app: App;
|
|
45
44
|
options?: Partial<Options>;
|
|
46
45
|
});
|
|
47
|
-
|
|
46
|
+
computeLevel(node: Node, parentLevel: SanitizeLevel): SanitizeLevel;
|
|
47
|
+
getLevel(id: number): SanitizeLevel;
|
|
48
|
+
setLevel(id: number, level: SanitizeLevel): SanitizeLevel;
|
|
49
|
+
handleNode(id: number, parentID: number, node: Node): void;
|
|
48
50
|
sanitize(id: number, data: string): string;
|
|
49
51
|
isObscured(id: number): boolean;
|
|
50
52
|
isHidden(id: number): boolean;
|
|
@@ -47,6 +47,7 @@ export default class Session {
|
|
|
47
47
|
getSessionSecret: (projectKey?: string) => string | undefined;
|
|
48
48
|
getRawSecretWithProject: () => string | null;
|
|
49
49
|
setSessionSecret: (token: string, projectKey: string) => void;
|
|
50
|
+
clearSessionSecret: () => void;
|
|
50
51
|
applySessionHash(hash: string): void;
|
|
51
52
|
getSessionHash(): string | undefined;
|
|
52
53
|
getTabId(): string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import TrackerClass from './index';
|
|
2
|
-
export { default as App } from './app/index';
|
|
3
|
-
export { default as browser, default as oxvosessions } from './singleton';
|
|
4
|
-
export { SanitizeLevel, Messages, Options } from './index';
|
|
5
|
-
export { default as Analytics } from './modules/analytics/index';
|
|
1
|
+
import TrackerClass from './index.js';
|
|
2
|
+
export { default as App } from './app/index.js';
|
|
3
|
+
export { default as browser, default as oxvosessions } from './singleton.js';
|
|
4
|
+
export { SanitizeLevel, Messages, Options } from './index.js';
|
|
5
|
+
export { default as Analytics } from './modules/analytics/index.js';
|
|
6
6
|
export default TrackerClass;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import App from './app/index';
|
|
1
|
+
import App from './app/index.js';
|
|
2
2
|
export { default as App } from './app/index.js';
|
|
3
3
|
import * as _Messages from './app/messages.gen.js';
|
|
4
4
|
export declare const Messages: typeof _Messages;
|
|
@@ -27,6 +27,7 @@ export type Options = Partial<AppOptions & ConsoleOptions & ExceptionOptions & I
|
|
|
27
27
|
resetTabOnWindowOpen?: boolean;
|
|
28
28
|
networkCapture?: Partial<NetworkOptions>;
|
|
29
29
|
mouse?: Partial<MouseHandlerOptions>;
|
|
30
|
+
customAttributes?: string[];
|
|
30
31
|
devAllowInsecure?: boolean;
|
|
31
32
|
css: CssRulesOptions;
|
|
32
33
|
webAnimations?: WapOptions;
|
|
@@ -46,6 +47,21 @@ export default class API {
|
|
|
46
47
|
checkDoNotTrack: () => boolean | undefined;
|
|
47
48
|
signalStartIssue: (reason: string, missingApi: string[]) => void;
|
|
48
49
|
restartCanvasTracking: () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Re-evaluates sanitization against the current DOM and re-emits whatever
|
|
52
|
+
* changed, updating already-recorded nodes mid-session. Call after toggling
|
|
53
|
+
* `data-oxvosessions-*` attributes or after changing whatever your `domSanitizer`
|
|
54
|
+
* keys on (class/id/etc).
|
|
55
|
+
*
|
|
56
|
+
* @param el - the highest node you changed; omit to re-scan the whole document;
|
|
57
|
+
* scanning the entire doc is O(dom size)
|
|
58
|
+
* */
|
|
59
|
+
resanitize: (el?: Element) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Returns the sanitization level the tracker currently has for a node
|
|
62
|
+
* (0 = Plain, 1 = Obscured, 2 = Hidden), or undefined if it isn't tracked.
|
|
63
|
+
* */
|
|
64
|
+
checkSanitization: (el: Node) => import("./app/sanitizer.js").SanitizeLevel | undefined;
|
|
49
65
|
use<T>(fn: (app: App | null, options?: Partial<Options>) => T): T;
|
|
50
66
|
isActive(): boolean;
|
|
51
67
|
/**
|
|
@@ -15,13 +15,15 @@ declare class Batcher {
|
|
|
15
15
|
private readonly backendUrl;
|
|
16
16
|
private readonly getToken;
|
|
17
17
|
private readonly init;
|
|
18
|
+
private readonly standalone;
|
|
18
19
|
private readonly autosendInterval;
|
|
19
20
|
private readonly retryTimeout;
|
|
20
21
|
private readonly retryLimit;
|
|
21
22
|
private readonly apiEdp;
|
|
22
23
|
private batch;
|
|
23
24
|
private intervalId;
|
|
24
|
-
|
|
25
|
+
private stopped;
|
|
26
|
+
constructor(backendUrl: string, getToken: () => string | null, init: () => Promise<void>, standalone: boolean);
|
|
25
27
|
getBatches(): {
|
|
26
28
|
data: {
|
|
27
29
|
user_actions: PeopleEvent[];
|
|
@@ -38,8 +40,11 @@ declare class Batcher {
|
|
|
38
40
|
dedupePeopleEvents(): PeopleEvent[];
|
|
39
41
|
private squashPeopleEvents;
|
|
40
42
|
private sendBatch;
|
|
43
|
+
private paused;
|
|
44
|
+
private onVisibilityChange;
|
|
41
45
|
startAutosend(): void;
|
|
42
46
|
flush(): void;
|
|
43
47
|
stop(): void;
|
|
48
|
+
restart(): void;
|
|
44
49
|
}
|
|
45
50
|
export default Batcher;
|
|
@@ -32,6 +32,7 @@ export default class Analytics {
|
|
|
32
32
|
private readonly getTimestamp;
|
|
33
33
|
private readonly setUserId;
|
|
34
34
|
private readonly standalone;
|
|
35
|
+
private pendingStartAttempt;
|
|
35
36
|
/**
|
|
36
37
|
* @param localStorage Class or Object that implements Storage-like interface that stores
|
|
37
38
|
* values persistently like window.localStorage or any other file-based storage
|
|
@@ -50,7 +51,16 @@ export default class Analytics {
|
|
|
50
51
|
constructor(options: Options);
|
|
51
52
|
_getToken: () => string | null;
|
|
52
53
|
_getTimestamp: () => number;
|
|
54
|
+
private loadStartAttempt;
|
|
55
|
+
private isValidStartAttempt;
|
|
56
|
+
private startAttempt;
|
|
57
|
+
private clearStartAttempt;
|
|
53
58
|
init: () => Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Used by tracker when running in blundled mode
|
|
61
|
+
*/
|
|
62
|
+
onStart: () => void;
|
|
63
|
+
onStop: () => void;
|
|
54
64
|
reset: () => void;
|
|
55
65
|
/**
|
|
56
66
|
* COMPATIBILITY LAYER
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type App from '../app/index.js';
|
|
2
2
|
type TextFieldElement = HTMLInputElement | HTMLTextAreaElement;
|
|
3
|
-
export declare function getInputLabel(node: TextFieldElement): string;
|
|
3
|
+
export declare function getInputLabel(node: TextFieldElement, customAttributes?: string[]): string;
|
|
4
4
|
export declare const InputMode: {
|
|
5
5
|
readonly Plain: 0;
|
|
6
6
|
readonly Obscured: 1;
|
|
@@ -29,6 +29,7 @@ export interface Options {
|
|
|
29
29
|
* will override other settings.
|
|
30
30
|
* */
|
|
31
31
|
inputPrivacyMode: InputModeT;
|
|
32
|
+
customAttributes?: string[];
|
|
32
33
|
}
|
|
33
34
|
export default function (app: App, opts: Partial<Options>): void;
|
|
34
35
|
export {};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import TagMatcher, { type Tag } from './tagMatcher.js';
|
|
1
2
|
export declare const WATCHED_MARKERS_KEY = "__or__watched_markers__";
|
|
2
3
|
declare class MarkerWatcher {
|
|
3
4
|
interval: ReturnType<typeof setInterval> | null;
|
|
4
|
-
tags:
|
|
5
|
-
|
|
6
|
-
selector: string;
|
|
7
|
-
}[];
|
|
5
|
+
tags: Tag[];
|
|
6
|
+
readonly matcher: TagMatcher;
|
|
8
7
|
observer: IntersectionObserver;
|
|
9
8
|
private readonly sessionStorage;
|
|
10
9
|
private readonly errLog;
|
|
@@ -15,10 +14,7 @@ declare class MarkerWatcher {
|
|
|
15
14
|
onMarkerHit: (markerId: number) => void;
|
|
16
15
|
});
|
|
17
16
|
fetchTags(ingest: string, token: string): Promise<void>;
|
|
18
|
-
setTags(tags:
|
|
19
|
-
id: number;
|
|
20
|
-
selector: string;
|
|
21
|
-
}[]): void;
|
|
17
|
+
setTags(tags: Tag[]): void;
|
|
22
18
|
onMarkerRendered(markerId: number): void;
|
|
23
19
|
clear(): void;
|
|
24
20
|
}
|
|
@@ -8,6 +8,7 @@ export interface MouseHandlerOptions {
|
|
|
8
8
|
* default 7 = 210ms
|
|
9
9
|
* */
|
|
10
10
|
trackingOffset?: number;
|
|
11
|
+
customAttributes?: string[];
|
|
11
12
|
}
|
|
12
13
|
export default function (app: App, options?: MouseHandlerOptions): void;
|
|
13
14
|
export declare function getCSSPath(el: any): string | false;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type Tag = {
|
|
2
|
+
id: number;
|
|
3
|
+
selector: string;
|
|
4
|
+
location?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Two-tier tag matching:
|
|
8
|
+
* 1. Fast fingerprint lookup by id, data-attr,
|
|
9
|
+
* or class from the selector's last segment
|
|
10
|
+
* 2. Fallback iteration using native element.matches()
|
|
11
|
+
*/
|
|
12
|
+
declare class TagMatcher {
|
|
13
|
+
private tags;
|
|
14
|
+
private byId;
|
|
15
|
+
private byDataAttr;
|
|
16
|
+
private byClass;
|
|
17
|
+
private fallback;
|
|
18
|
+
setTags(tags: Tag[]): void;
|
|
19
|
+
getTags(): Tag[];
|
|
20
|
+
/** Match element, its parent, or direct children against known tag selectors */
|
|
21
|
+
match(el: Element): Tag | null;
|
|
22
|
+
private matchExact;
|
|
23
|
+
clear(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare function matchesLocation(tag: {
|
|
26
|
+
location?: string;
|
|
27
|
+
}): boolean;
|
|
28
|
+
export default TagMatcher;
|
|
@@ -97,6 +97,30 @@ declare class BrowserSingleton {
|
|
|
97
97
|
forceFlushBatch(): void;
|
|
98
98
|
getSessionMeta(): import("./app/session.js").SessionInfo | null;
|
|
99
99
|
getTabId(): string | null;
|
|
100
|
+
/**
|
|
101
|
+
* Re-evaluates sanitization against the current DOM and re-emits whatever
|
|
102
|
+
* changed, updating already-recorded nodes mid-session. Call after toggling
|
|
103
|
+
* `data-oxvosessions-*` attributes or after changing whatever your `domSanitizer`
|
|
104
|
+
* keys on (class/id/etc).
|
|
105
|
+
*
|
|
106
|
+
* @param el - the highest node you changed; omit to re-scan the whole document.
|
|
107
|
+
* */
|
|
108
|
+
resanitize(el?: Element): void;
|
|
109
|
+
/**
|
|
110
|
+
* Returns the sanitization level the tracker currently has for a node
|
|
111
|
+
* (0 = Plain, 1 = Obscured, 2 = Hidden), or undefined if it isn't tracked.
|
|
112
|
+
* */
|
|
113
|
+
checkSanitization(el: Node): import("./index.js").SanitizeLevel | undefined;
|
|
114
|
+
incident(options: {
|
|
115
|
+
label?: string;
|
|
116
|
+
startTime: number;
|
|
117
|
+
endTime?: number;
|
|
118
|
+
}): void;
|
|
119
|
+
/**
|
|
120
|
+
* Use custom token for analytics events without session recording.
|
|
121
|
+
* */
|
|
122
|
+
setAnalyticsToken(token: string): void;
|
|
123
|
+
getAnalyticsToken(): string | undefined;
|
|
100
124
|
}
|
|
101
125
|
declare const browser: BrowserSingleton;
|
|
102
126
|
export default browser;
|
|
@@ -11,6 +11,8 @@ export declare const DOCS_HOST = "https://docs.oxvo.com";
|
|
|
11
11
|
export declare function isLoopbackHost(hostname: string): boolean;
|
|
12
12
|
export declare function canUseTrackerOrigin(protocol: string, hostname: string, devAllowInsecure?: boolean): boolean;
|
|
13
13
|
export declare function deprecationWarn(nameOfFeature: string, useInstead: string, docsPath?: string): void;
|
|
14
|
+
export declare function getCustomAttributeLabel(e: Element, customAttributes?: string[]): string;
|
|
15
|
+
export declare function getClassSelector(e: Element): string;
|
|
14
16
|
export declare function getLabelAttribute(e: Element): string | null;
|
|
15
17
|
export declare function hasOxvoSessionsAttribute(e: Element, attr: string): boolean;
|
|
16
18
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxvo/browser",
|
|
3
3
|
"description": "OxvoSessions Browser SDK for session replay and frontend observability.",
|
|
4
|
-
"version": "7.
|
|
4
|
+
"version": "7.3.4",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser-sdk",
|
|
7
7
|
"session-replay",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"./cjs": {
|
|
25
25
|
"require": "./dist/cjs/entry.js",
|
|
26
|
-
"
|
|
26
|
+
"import": "./dist/lib/entry.js",
|
|
27
|
+
"types": "./dist/lib/main/entry.d.ts"
|
|
27
28
|
}
|
|
28
29
|
},
|
|
29
30
|
"files": [
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"clean": "rm -Rf build && rm -Rf dist",
|
|
43
44
|
"build:common": "tsc -b src/common",
|
|
44
45
|
"compile": "tsc --project src/main/tsconfig.json",
|
|
45
|
-
"create-types": "mkdir dist/lib/ dist/cjs && cp -r dist/types/* dist/lib/ && cp -r dist/types/* dist/cjs/",
|
|
46
|
+
"create-types": "mkdir dist/lib/ dist/cjs && cp -r dist/types/* dist/lib/ && cp -r dist/types/* dist/cjs/ && printf '{\"type\":\"commonjs\"}\\n' > dist/cjs/package.json",
|
|
46
47
|
"build": "bun run clean && bun compile && bun create-types && rollup --config rollup.config.js",
|
|
47
48
|
"test": "jest --coverage=false",
|
|
48
49
|
"test:ci": "jest --coverage=true",
|
|
@@ -51,24 +52,24 @@
|
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@oxvo/network-instrumentation": "file:../../networkProxy",
|
|
54
|
-
"@babel/core": "^7.
|
|
55
|
+
"@babel/core": "^7.29.0",
|
|
55
56
|
"@jest/globals": "^29.7.0",
|
|
56
57
|
"@rollup/plugin-babel": "^6.1.0",
|
|
57
|
-
"@rollup/plugin-commonjs": "^
|
|
58
|
-
"@rollup/plugin-node-resolve": "^
|
|
59
|
-
"@rollup/plugin-replace": "^6.0.
|
|
58
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
59
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
60
|
+
"@rollup/plugin-replace": "^6.0.3",
|
|
60
61
|
"@rollup/plugin-terser": "0.4.4",
|
|
61
62
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
62
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
63
|
-
"@typescript-eslint/parser": "^8.
|
|
64
|
-
"eslint": "^9.
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
64
|
+
"@typescript-eslint/parser": "^8.54.0",
|
|
65
|
+
"eslint": "^9.39.2",
|
|
65
66
|
"eslint-config-prettier": "^9.1.0",
|
|
66
|
-
"eslint-plugin-prettier": "^5.5.
|
|
67
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
67
68
|
"jest": "^30.2.0",
|
|
68
69
|
"jest-environment-jsdom": "^30.2.0",
|
|
69
|
-
"prettier": "^3.
|
|
70
|
+
"prettier": "^3.8.1",
|
|
70
71
|
"replace-in-files": "^2.0.3",
|
|
71
|
-
"rollup": "^4.
|
|
72
|
+
"rollup": "^4.57.1",
|
|
72
73
|
"semver": "^6.3.0",
|
|
73
74
|
"ts-jest": "^29.4.6",
|
|
74
75
|
"tslib": "^2.8.1",
|
|
@@ -77,7 +78,6 @@
|
|
|
77
78
|
"dependencies": {
|
|
78
79
|
"error-stack-parser": "^2.1.4",
|
|
79
80
|
"error-stack-parser-es": "^0.1.5",
|
|
80
|
-
"fflate": "^0.8.2",
|
|
81
81
|
"web-vitals": "^5.1.0"
|
|
82
82
|
},
|
|
83
83
|
"engines": {
|