@v-tilt/browser 1.1.4 → 1.2.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/dist/array.js +1 -1
- package/dist/array.js.map +1 -1
- package/dist/array.no-external.js +1 -1
- package/dist/array.no-external.js.map +1 -1
- package/dist/entrypoints/array.d.ts +1 -0
- package/dist/entrypoints/external-scripts-loader.d.ts +24 -0
- package/dist/entrypoints/module.es.d.ts +1 -0
- package/dist/entrypoints/recorder.d.ts +23 -0
- package/dist/extensions/replay/index.d.ts +13 -0
- package/dist/extensions/replay/session-recording-utils.d.ts +92 -0
- package/dist/extensions/replay/session-recording-wrapper.d.ts +61 -0
- package/dist/extensions/replay/session-recording.d.ts +95 -0
- package/dist/extensions/replay/types.d.ts +211 -0
- package/dist/external-scripts-loader.js +2 -0
- package/dist/external-scripts-loader.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.d.ts +271 -8
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.d.ts +271 -8
- package/dist/module.no-external.js +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/dist/recorder.js +2 -0
- package/dist/recorder.js.map +1 -0
- package/dist/session.d.ts +4 -2
- package/dist/storage.d.ts +8 -3
- package/dist/types.d.ts +91 -7
- package/dist/user-manager.d.ts +2 -2
- package/dist/utils/globals.d.ts +42 -0
- package/dist/vtilt.d.ts +36 -0
- package/lib/config.js +2 -0
- package/lib/entrypoints/array.d.ts +1 -0
- package/lib/entrypoints/array.js +1 -0
- package/lib/entrypoints/external-scripts-loader.d.ts +24 -0
- package/lib/entrypoints/external-scripts-loader.js +107 -0
- package/lib/entrypoints/module.es.d.ts +1 -0
- package/lib/entrypoints/module.es.js +1 -0
- package/lib/entrypoints/recorder.d.ts +23 -0
- package/lib/entrypoints/recorder.js +42 -0
- package/lib/extensions/replay/index.d.ts +13 -0
- package/lib/extensions/replay/index.js +31 -0
- package/lib/extensions/replay/session-recording-utils.d.ts +92 -0
- package/lib/extensions/replay/session-recording-utils.js +212 -0
- package/lib/extensions/replay/session-recording-wrapper.d.ts +61 -0
- package/lib/extensions/replay/session-recording-wrapper.js +149 -0
- package/lib/extensions/replay/session-recording.d.ts +95 -0
- package/lib/extensions/replay/session-recording.js +700 -0
- package/lib/extensions/replay/types.d.ts +211 -0
- package/lib/extensions/replay/types.js +8 -0
- package/lib/session.d.ts +4 -2
- package/lib/session.js +7 -41
- package/lib/storage.d.ts +8 -3
- package/lib/storage.js +62 -9
- package/lib/types.d.ts +91 -7
- package/lib/user-manager.d.ts +2 -2
- package/lib/user-manager.js +4 -4
- package/lib/utils/globals.d.ts +42 -0
- package/lib/utils/globals.js +2 -0
- package/lib/vtilt.d.ts +36 -0
- package/lib/vtilt.js +110 -14
- package/package.json +4 -1
package/lib/utils/globals.d.ts
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
declare const win: (Window & typeof globalThis) | undefined;
|
|
2
|
+
/**
|
|
3
|
+
* Extension kinds that can be lazy loaded
|
|
4
|
+
*/
|
|
5
|
+
export type VTiltExtensionKind = "recorder" | "web-vitals";
|
|
6
|
+
/**
|
|
7
|
+
* Interface for lazy-loaded session recording (set by recorder.ts)
|
|
8
|
+
* Matches LazyLoadedSessionRecordingInterface in session-recording-wrapper.ts
|
|
9
|
+
*/
|
|
10
|
+
export interface LazyLoadedSessionRecordingInterface {
|
|
11
|
+
start: (startReason?: string) => void;
|
|
12
|
+
stop: () => void;
|
|
13
|
+
sessionId: string;
|
|
14
|
+
status: string;
|
|
15
|
+
isStarted: boolean;
|
|
16
|
+
onRemoteConfig?: (response: any) => void;
|
|
17
|
+
log: (message: string, level: "log" | "warn" | "error") => void;
|
|
18
|
+
updateConfig: (config: any) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* VTilt Extensions interface for dynamically loaded modules
|
|
22
|
+
* This is the contract between lazily loaded extensions and the SDK
|
|
23
|
+
*/
|
|
24
|
+
export interface VTiltExtensions {
|
|
25
|
+
/** Load an external dependency script */
|
|
26
|
+
loadExternalDependency?: (instance: any, // VTilt instance - using any to avoid circular imports
|
|
27
|
+
kind: VTiltExtensionKind, callback: (error?: string | Event, event?: Event) => void) => void;
|
|
28
|
+
/** rrweb record function (set by recorder.ts) */
|
|
29
|
+
rrweb?: {
|
|
30
|
+
record: any;
|
|
31
|
+
version?: string;
|
|
32
|
+
};
|
|
33
|
+
/** rrweb plugins (set by recorder.ts) */
|
|
34
|
+
rrwebPlugins?: {
|
|
35
|
+
getRecordConsolePlugin?: () => any;
|
|
36
|
+
getRecordNetworkPlugin?: (options: any) => any;
|
|
37
|
+
};
|
|
38
|
+
/** Factory to create LazyLoadedSessionRecording (set by recorder.ts) */
|
|
39
|
+
initSessionRecording?: (instance: any, config?: any) => LazyLoadedSessionRecordingInterface;
|
|
40
|
+
}
|
|
2
41
|
export type AssignableWindow = Window & typeof globalThis & {
|
|
42
|
+
/** Main VTilt instance */
|
|
3
43
|
vt: any;
|
|
44
|
+
/** VTilt Extensions for dynamically loaded modules */
|
|
45
|
+
__VTiltExtensions__?: VTiltExtensions;
|
|
4
46
|
};
|
|
5
47
|
export declare const ArrayProto: any[];
|
|
6
48
|
export declare const nativeForEach: (callbackfn: (value: any, index: number, array: any[]) => void, thisArg?: any) => void;
|
package/lib/utils/globals.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.window = exports.assignableWindow = exports.userAgent = exports.AbortController = exports.XMLHttpRequest = exports.fetch = exports.location = exports.document = exports.navigator = exports.nativeIndexOf = exports.nativeForEach = exports.ArrayProto = void 0;
|
|
13
|
+
// Note: We use 'any' for VTilt to avoid circular imports
|
|
14
|
+
// The actual type checking happens in the external-scripts-loader.ts
|
|
13
15
|
const win = typeof window !== "undefined" ? window : undefined;
|
|
14
16
|
exports.window = win;
|
|
15
17
|
const global = typeof globalThis !== "undefined" ? globalThis : win;
|
package/lib/vtilt.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { VTiltConfig, EventPayload } from "./types";
|
|
2
2
|
import { HistoryAutocapture } from "./extensions/history-autocapture";
|
|
3
|
+
import { SessionRecordingWrapper } from "./extensions/replay";
|
|
3
4
|
import { type QueuedRequest } from "./request-queue";
|
|
4
5
|
export declare class VTilt {
|
|
6
|
+
readonly version = "1.1.5";
|
|
5
7
|
private configManager;
|
|
6
8
|
private sessionManager;
|
|
7
9
|
private userManager;
|
|
@@ -10,6 +12,7 @@ export declare class VTilt {
|
|
|
10
12
|
private retryQueue;
|
|
11
13
|
private rateLimiter;
|
|
12
14
|
historyAutocapture?: HistoryAutocapture;
|
|
15
|
+
sessionRecording?: SessionRecordingWrapper;
|
|
13
16
|
__loaded: boolean;
|
|
14
17
|
private _initial_pageview_captured;
|
|
15
18
|
private _visibility_state_listener;
|
|
@@ -236,10 +239,43 @@ export declare class VTilt {
|
|
|
236
239
|
* Get current session ID
|
|
237
240
|
*/
|
|
238
241
|
getSessionId(): string | null;
|
|
242
|
+
/**
|
|
243
|
+
* Get current distinct ID
|
|
244
|
+
*/
|
|
245
|
+
getDistinctId(): string;
|
|
246
|
+
/**
|
|
247
|
+
* Get anonymous ID
|
|
248
|
+
*/
|
|
249
|
+
getAnonymousId(): string;
|
|
239
250
|
/**
|
|
240
251
|
* Update configuration
|
|
241
252
|
*/
|
|
242
253
|
updateConfig(config: Partial<VTiltConfig>): void;
|
|
254
|
+
/**
|
|
255
|
+
* Initialize session recording
|
|
256
|
+
*/
|
|
257
|
+
private _initSessionRecording;
|
|
258
|
+
/**
|
|
259
|
+
* Build session recording config from VTiltConfig
|
|
260
|
+
*/
|
|
261
|
+
private _buildSessionRecordingConfig;
|
|
262
|
+
/**
|
|
263
|
+
* Start session recording
|
|
264
|
+
* Call this to manually start recording if it wasn't enabled initially
|
|
265
|
+
*/
|
|
266
|
+
startSessionRecording(): void;
|
|
267
|
+
/**
|
|
268
|
+
* Stop session recording
|
|
269
|
+
*/
|
|
270
|
+
stopSessionRecording(): void;
|
|
271
|
+
/**
|
|
272
|
+
* Check if session recording is active
|
|
273
|
+
*/
|
|
274
|
+
isSessionRecordingActive(): boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Get session recording ID
|
|
277
|
+
*/
|
|
278
|
+
getSessionRecordingId(): string | null;
|
|
243
279
|
/**
|
|
244
280
|
* _execute_array() deals with processing any vTilt function
|
|
245
281
|
* calls that were called before the vTilt library was loaded
|
package/lib/vtilt.js
CHANGED
|
@@ -8,6 +8,7 @@ const session_1 = require("./session");
|
|
|
8
8
|
const user_manager_1 = require("./user-manager");
|
|
9
9
|
const web_vitals_1 = require("./web-vitals");
|
|
10
10
|
const history_autocapture_1 = require("./extensions/history-autocapture");
|
|
11
|
+
const replay_1 = require("./extensions/replay");
|
|
11
12
|
const request_1 = require("./request");
|
|
12
13
|
const request_queue_1 = require("./request-queue");
|
|
13
14
|
const retry_queue_1 = require("./retry-queue");
|
|
@@ -31,6 +32,8 @@ Use TypeScript accessibility modifiers (private/protected) for non-public member
|
|
|
31
32
|
const isArray = Array.isArray;
|
|
32
33
|
class VTilt {
|
|
33
34
|
constructor(config = {}) {
|
|
35
|
+
// SDK version - injected at build time or defaults to package version
|
|
36
|
+
this.version = "1.1.5";
|
|
34
37
|
this.__loaded = false; // Matches snippet's window.vt.__loaded check
|
|
35
38
|
this._initial_pageview_captured = false;
|
|
36
39
|
this._visibility_state_listener = null;
|
|
@@ -39,13 +42,8 @@ class VTilt {
|
|
|
39
42
|
this._set_once_properties_sent = false; // Track if $set_once with initial props has been sent (only send once per page load)
|
|
40
43
|
this.configManager = new config_1.ConfigManager(config);
|
|
41
44
|
const fullConfig = this.configManager.getConfig();
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!domain && globals_1.location) {
|
|
45
|
-
domain = this.getCurrentDomain();
|
|
46
|
-
}
|
|
47
|
-
this.sessionManager = new session_1.SessionManager(fullConfig.storage || "cookie", domain);
|
|
48
|
-
this.userManager = new user_manager_1.UserManager(fullConfig.persistence || "localStorage", domain);
|
|
45
|
+
this.sessionManager = new session_1.SessionManager(fullConfig.storage || "cookie", fullConfig.cross_subdomain_cookie);
|
|
46
|
+
this.userManager = new user_manager_1.UserManager(fullConfig.persistence || "localStorage", fullConfig.cross_subdomain_cookie);
|
|
49
47
|
this.webVitalsManager = new web_vitals_1.WebVitalsManager(fullConfig, this);
|
|
50
48
|
// Initialize rate limiter to prevent flooding
|
|
51
49
|
// Default: 10 events/second with burst of 100
|
|
@@ -137,6 +135,8 @@ class VTilt {
|
|
|
137
135
|
// Initialize history autocapture
|
|
138
136
|
this.historyAutocapture = new history_autocapture_1.HistoryAutocapture(this);
|
|
139
137
|
this.historyAutocapture.startIfEnabled();
|
|
138
|
+
// Initialize session recording if enabled
|
|
139
|
+
this._initSessionRecording();
|
|
140
140
|
// Set up page unload handler to flush queued events
|
|
141
141
|
this._setup_unload_handler();
|
|
142
142
|
// Enable the request queue for batched sending (PostHog pattern)
|
|
@@ -453,7 +453,6 @@ class VTilt {
|
|
|
453
453
|
timestamp: new Date().toISOString(),
|
|
454
454
|
event: name,
|
|
455
455
|
project_id: config.projectId || "",
|
|
456
|
-
domain: config.domain || this.getCurrentDomain(), // Use config domain or current domain
|
|
457
456
|
payload: processedPayload,
|
|
458
457
|
distinct_id: distinct_id,
|
|
459
458
|
// Always include anonymous_id in the event for identity linking
|
|
@@ -725,6 +724,18 @@ class VTilt {
|
|
|
725
724
|
getSessionId() {
|
|
726
725
|
return this.sessionManager.getSessionId();
|
|
727
726
|
}
|
|
727
|
+
/**
|
|
728
|
+
* Get current distinct ID
|
|
729
|
+
*/
|
|
730
|
+
getDistinctId() {
|
|
731
|
+
return (this.userManager.getDistinctId() || this.userManager.getAnonymousId());
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Get anonymous ID
|
|
735
|
+
*/
|
|
736
|
+
getAnonymousId() {
|
|
737
|
+
return this.userManager.getAnonymousId();
|
|
738
|
+
}
|
|
728
739
|
/**
|
|
729
740
|
* Update configuration
|
|
730
741
|
*/
|
|
@@ -732,13 +743,98 @@ class VTilt {
|
|
|
732
743
|
this.configManager.updateConfig(config);
|
|
733
744
|
const fullConfig = this.configManager.getConfig();
|
|
734
745
|
// Recreate managers with new config
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
domain = this.getCurrentDomain();
|
|
738
|
-
}
|
|
739
|
-
this.sessionManager = new session_1.SessionManager(fullConfig.storage || "cookie", domain);
|
|
740
|
-
this.userManager = new user_manager_1.UserManager(fullConfig.persistence || "localStorage", domain);
|
|
746
|
+
this.sessionManager = new session_1.SessionManager(fullConfig.storage || "cookie", fullConfig.cross_subdomain_cookie);
|
|
747
|
+
this.userManager = new user_manager_1.UserManager(fullConfig.persistence || "localStorage", fullConfig.cross_subdomain_cookie);
|
|
741
748
|
this.webVitalsManager = new web_vitals_1.WebVitalsManager(fullConfig, this);
|
|
749
|
+
// Update session recording config if it exists
|
|
750
|
+
if (this.sessionRecording && fullConfig.session_recording) {
|
|
751
|
+
this.sessionRecording.updateConfig(this._buildSessionRecordingConfig(fullConfig));
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
// ============================================================================
|
|
755
|
+
// Session Recording
|
|
756
|
+
// ============================================================================
|
|
757
|
+
/**
|
|
758
|
+
* Initialize session recording
|
|
759
|
+
*/
|
|
760
|
+
_initSessionRecording() {
|
|
761
|
+
const config = this.configManager.getConfig();
|
|
762
|
+
// Don't initialize if explicitly disabled
|
|
763
|
+
if (config.disable_session_recording) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
// Build session recording config
|
|
767
|
+
const sessionRecordingConfig = this._buildSessionRecordingConfig(config);
|
|
768
|
+
// Create session recording wrapper (lightweight - actual recorder is lazy-loaded)
|
|
769
|
+
this.sessionRecording = new replay_1.SessionRecordingWrapper(this, sessionRecordingConfig);
|
|
770
|
+
// Start recording if enabled (this will lazy-load the recorder script)
|
|
771
|
+
if (sessionRecordingConfig.enabled) {
|
|
772
|
+
this.sessionRecording.startIfEnabledOrStop("recording_initialized");
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Build session recording config from VTiltConfig
|
|
777
|
+
*/
|
|
778
|
+
_buildSessionRecordingConfig(config) {
|
|
779
|
+
var _a, _b, _c;
|
|
780
|
+
const sessionRecording = config.session_recording || {};
|
|
781
|
+
return {
|
|
782
|
+
enabled: (_a = sessionRecording.enabled) !== null && _a !== void 0 ? _a : false,
|
|
783
|
+
sampleRate: sessionRecording.sampleRate,
|
|
784
|
+
minimumDurationMs: sessionRecording.minimumDurationMs,
|
|
785
|
+
sessionIdleThresholdMs: sessionRecording.sessionIdleThresholdMs,
|
|
786
|
+
fullSnapshotIntervalMs: sessionRecording.fullSnapshotIntervalMs,
|
|
787
|
+
captureConsole: (_b = sessionRecording.captureConsole) !== null && _b !== void 0 ? _b : false,
|
|
788
|
+
captureNetwork: (_c = sessionRecording.captureNetwork) !== null && _c !== void 0 ? _c : false,
|
|
789
|
+
captureCanvas: sessionRecording.captureCanvas,
|
|
790
|
+
blockClass: sessionRecording.blockClass,
|
|
791
|
+
blockSelector: sessionRecording.blockSelector,
|
|
792
|
+
ignoreClass: sessionRecording.ignoreClass,
|
|
793
|
+
maskTextClass: sessionRecording.maskTextClass,
|
|
794
|
+
maskTextSelector: sessionRecording.maskTextSelector,
|
|
795
|
+
maskAllInputs: sessionRecording.maskAllInputs,
|
|
796
|
+
maskInputOptions: sessionRecording.maskInputOptions,
|
|
797
|
+
masking: sessionRecording.masking,
|
|
798
|
+
recordHeaders: sessionRecording.recordHeaders,
|
|
799
|
+
recordBody: sessionRecording.recordBody,
|
|
800
|
+
compressEvents: sessionRecording.compressEvents,
|
|
801
|
+
__mutationThrottlerRefillRate: sessionRecording.__mutationThrottlerRefillRate,
|
|
802
|
+
__mutationThrottlerBucketSize: sessionRecording.__mutationThrottlerBucketSize,
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Start session recording
|
|
807
|
+
* Call this to manually start recording if it wasn't enabled initially
|
|
808
|
+
*/
|
|
809
|
+
startSessionRecording() {
|
|
810
|
+
if (!this.sessionRecording) {
|
|
811
|
+
const config = this.configManager.getConfig();
|
|
812
|
+
const sessionRecordingConfig = this._buildSessionRecordingConfig(config);
|
|
813
|
+
sessionRecordingConfig.enabled = true;
|
|
814
|
+
this.sessionRecording = new replay_1.SessionRecordingWrapper(this, sessionRecordingConfig);
|
|
815
|
+
}
|
|
816
|
+
this.sessionRecording.startIfEnabledOrStop("recording_initialized");
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Stop session recording
|
|
820
|
+
*/
|
|
821
|
+
stopSessionRecording() {
|
|
822
|
+
var _a;
|
|
823
|
+
(_a = this.sessionRecording) === null || _a === void 0 ? void 0 : _a.stopRecording();
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Check if session recording is active
|
|
827
|
+
*/
|
|
828
|
+
isSessionRecordingActive() {
|
|
829
|
+
var _a;
|
|
830
|
+
return ((_a = this.sessionRecording) === null || _a === void 0 ? void 0 : _a.status) === "active";
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Get session recording ID
|
|
834
|
+
*/
|
|
835
|
+
getSessionRecordingId() {
|
|
836
|
+
var _a;
|
|
837
|
+
return ((_a = this.sessionRecording) === null || _a === void 0 ? void 0 : _a.sessionId) || null;
|
|
742
838
|
}
|
|
743
839
|
/**
|
|
744
840
|
* _execute_array() deals with processing any vTilt function
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@v-tilt/browser",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "vTilt browser tracking library",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"module": "dist/module.js",
|
|
@@ -48,6 +48,9 @@
|
|
|
48
48
|
"typescript": "^5.3.3"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
+
"@rrweb/record": "2.0.0-alpha.17",
|
|
52
|
+
"@rrweb/rrweb-plugin-console-record": "2.0.0-alpha.17",
|
|
53
|
+
"@rrweb/types": "2.0.0-alpha.17",
|
|
51
54
|
"fflate": "^0.8.2",
|
|
52
55
|
"web-vitals": "^3.5.0"
|
|
53
56
|
},
|