@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/dist/session.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { PersistenceMethod } from "./types";
|
|
|
10
10
|
export declare class SessionManager {
|
|
11
11
|
private storage;
|
|
12
12
|
private _windowId;
|
|
13
|
-
constructor(storageMethod?: PersistenceMethod,
|
|
13
|
+
constructor(storageMethod?: PersistenceMethod, cross_subdomain?: boolean);
|
|
14
14
|
/**
|
|
15
15
|
* Get session ID (always returns a value, generates if needed)
|
|
16
16
|
*/
|
|
@@ -26,10 +26,12 @@ export declare class SessionManager {
|
|
|
26
26
|
resetSessionId(): void;
|
|
27
27
|
/**
|
|
28
28
|
* Get session ID from storage (raw, can return null)
|
|
29
|
+
* Cookie Max-Age handles expiration automatically
|
|
29
30
|
*/
|
|
30
31
|
private _getSessionIdRaw;
|
|
31
32
|
/**
|
|
32
33
|
* Store session ID
|
|
34
|
+
* Uses plain string format - cookie Max-Age handles expiration
|
|
33
35
|
*/
|
|
34
36
|
private _storeSessionId;
|
|
35
37
|
/**
|
|
@@ -60,5 +62,5 @@ export declare class SessionManager {
|
|
|
60
62
|
/**
|
|
61
63
|
* Update storage method at runtime
|
|
62
64
|
*/
|
|
63
|
-
updateStorageMethod(method: PersistenceMethod,
|
|
65
|
+
updateStorageMethod(method: PersistenceMethod, cross_subdomain?: boolean): void;
|
|
64
66
|
}
|
package/dist/storage.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare const SESSION_COOKIE_MAX_AGE = 1800;
|
|
|
16
16
|
export declare const USER_COOKIE_MAX_AGE = 31536000;
|
|
17
17
|
export interface StorageOptions {
|
|
18
18
|
method: PersistenceMethod;
|
|
19
|
-
|
|
19
|
+
cross_subdomain?: boolean;
|
|
20
20
|
secure?: boolean;
|
|
21
21
|
sameSite?: "Strict" | "Lax" | "None";
|
|
22
22
|
}
|
|
@@ -24,13 +24,18 @@ export interface StorageItem<T = string> {
|
|
|
24
24
|
value: T;
|
|
25
25
|
expiry?: number;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Auto-detect if cross-subdomain cookies should be enabled
|
|
29
|
+
* Returns false for platforms like herokuapp.com, vercel.app, netlify.app
|
|
30
|
+
*/
|
|
31
|
+
export declare function shouldUseCrossSubdomainCookie(): boolean;
|
|
27
32
|
/**
|
|
28
33
|
* Unified Storage Manager
|
|
29
34
|
* Provides consistent storage operations across all persistence methods
|
|
30
35
|
*/
|
|
31
36
|
export declare class StorageManager {
|
|
32
37
|
private method;
|
|
33
|
-
private
|
|
38
|
+
private cross_subdomain;
|
|
34
39
|
private secure;
|
|
35
40
|
private sameSite;
|
|
36
41
|
private memoryStorage;
|
|
@@ -92,4 +97,4 @@ export declare class StorageManager {
|
|
|
92
97
|
* Create a shared storage instance
|
|
93
98
|
* Use this for creating storage managers with consistent settings
|
|
94
99
|
*/
|
|
95
|
-
export declare function createStorageManager(method: PersistenceMethod,
|
|
100
|
+
export declare function createStorageManager(method: PersistenceMethod, cross_subdomain?: boolean): StorageManager;
|
package/dist/types.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export interface VTiltConfig {
|
|
|
12
12
|
api_host?: string;
|
|
13
13
|
/** UI host for dashboard links */
|
|
14
14
|
ui_host?: string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Host for loading extension scripts (recorder.js, etc.)
|
|
17
|
+
* Defaults to unpkg CDN: https://unpkg.com/@v-tilt/browser@{version}/dist
|
|
18
|
+
* Can also use jsdelivr: https://cdn.jsdelivr.net/npm/@v-tilt/browser@{version}/dist
|
|
19
|
+
* Or self-hosted: https://your-domain.com/static
|
|
20
|
+
*/
|
|
21
|
+
script_host?: string;
|
|
15
22
|
/** Proxy domain for tracking requests */
|
|
16
23
|
proxy?: string;
|
|
17
24
|
/** Full proxy URL for tracking requests */
|
|
@@ -20,7 +27,7 @@ export interface VTiltConfig {
|
|
|
20
27
|
name?: string;
|
|
21
28
|
/** Project ID (set via init() first argument) */
|
|
22
29
|
projectId?: string;
|
|
23
|
-
/** Domain to track (auto-detected if not provided) */
|
|
30
|
+
/** Domain to track (auto-detected if not provided) - used in event properties */
|
|
24
31
|
domain?: string;
|
|
25
32
|
/** Storage method for session data */
|
|
26
33
|
storage?: PersistenceMethod;
|
|
@@ -28,7 +35,12 @@ export interface VTiltConfig {
|
|
|
28
35
|
persistence?: PersistenceMethod;
|
|
29
36
|
/** Persistence name prefix */
|
|
30
37
|
persistence_name?: string;
|
|
31
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Enable cross-subdomain cookies.
|
|
40
|
+
* When true, cookies are shared across subdomains (e.g., app.example.com and www.example.com).
|
|
41
|
+
* Auto-detects false for platforms like herokuapp.com, vercel.app, netlify.app.
|
|
42
|
+
* @default true (except for excluded platforms)
|
|
43
|
+
*/
|
|
32
44
|
cross_subdomain_cookie?: boolean;
|
|
33
45
|
/**
|
|
34
46
|
* Person profiles mode:
|
|
@@ -59,6 +71,10 @@ export interface VTiltConfig {
|
|
|
59
71
|
respect_dnt?: boolean;
|
|
60
72
|
/** Opt users out by default */
|
|
61
73
|
opt_out_capturing_by_default?: boolean;
|
|
74
|
+
/** Session recording configuration */
|
|
75
|
+
session_recording?: SessionRecordingOptions;
|
|
76
|
+
/** Disable session recording (convenience flag) */
|
|
77
|
+
disable_session_recording?: boolean;
|
|
62
78
|
/** Global attributes added to all events */
|
|
63
79
|
globalAttributes?: Record<string, string>;
|
|
64
80
|
/** Bootstrap data for initialization */
|
|
@@ -97,7 +113,6 @@ export interface TrackingEvent {
|
|
|
97
113
|
timestamp: string;
|
|
98
114
|
event: string;
|
|
99
115
|
project_id: string;
|
|
100
|
-
domain: string;
|
|
101
116
|
distinct_id: string;
|
|
102
117
|
anonymous_id?: string;
|
|
103
118
|
payload: EventPayload;
|
|
@@ -172,14 +187,83 @@ export interface RequestOptions {
|
|
|
172
187
|
timeout?: number;
|
|
173
188
|
retry?: boolean;
|
|
174
189
|
}
|
|
190
|
+
/** Mask options for input elements in session recording */
|
|
191
|
+
export interface SessionRecordingMaskInputOptions {
|
|
192
|
+
color?: boolean;
|
|
193
|
+
date?: boolean;
|
|
194
|
+
"datetime-local"?: boolean;
|
|
195
|
+
email?: boolean;
|
|
196
|
+
month?: boolean;
|
|
197
|
+
number?: boolean;
|
|
198
|
+
range?: boolean;
|
|
199
|
+
search?: boolean;
|
|
200
|
+
tel?: boolean;
|
|
201
|
+
text?: boolean;
|
|
202
|
+
time?: boolean;
|
|
203
|
+
url?: boolean;
|
|
204
|
+
week?: boolean;
|
|
205
|
+
textarea?: boolean;
|
|
206
|
+
select?: boolean;
|
|
207
|
+
password?: boolean;
|
|
208
|
+
}
|
|
209
|
+
/** Session recording configuration */
|
|
210
|
+
export interface SessionRecordingOptions {
|
|
211
|
+
/** Enable session recording */
|
|
212
|
+
enabled?: boolean;
|
|
213
|
+
/** Sample rate (0-1, where 1 = 100%) */
|
|
214
|
+
sampleRate?: number;
|
|
215
|
+
/** Minimum session duration in ms before sending */
|
|
216
|
+
minimumDurationMs?: number;
|
|
217
|
+
/** Session idle threshold in ms (default: 5 minutes) */
|
|
218
|
+
sessionIdleThresholdMs?: number;
|
|
219
|
+
/** Full snapshot interval in ms (default: 5 minutes) */
|
|
220
|
+
fullSnapshotIntervalMs?: number;
|
|
221
|
+
/** Enable console log capture */
|
|
222
|
+
captureConsole?: boolean;
|
|
223
|
+
/** Enable network request capture */
|
|
224
|
+
captureNetwork?: boolean;
|
|
225
|
+
/** Canvas recording settings */
|
|
226
|
+
captureCanvas?: {
|
|
227
|
+
recordCanvas?: boolean;
|
|
228
|
+
canvasFps?: number;
|
|
229
|
+
canvasQuality?: number;
|
|
230
|
+
};
|
|
231
|
+
/** Block class for elements to hide (default: 'vt-no-capture') */
|
|
232
|
+
blockClass?: string;
|
|
233
|
+
/** Block selector for elements to hide */
|
|
234
|
+
blockSelector?: string;
|
|
235
|
+
/** Ignore class for input masking (default: 'vt-ignore-input') */
|
|
236
|
+
ignoreClass?: string;
|
|
237
|
+
/** Mask text class (default: 'vt-mask') */
|
|
238
|
+
maskTextClass?: string;
|
|
239
|
+
/** Mask text selector */
|
|
240
|
+
maskTextSelector?: string;
|
|
241
|
+
/** Mask all inputs (default: true) */
|
|
242
|
+
maskAllInputs?: boolean;
|
|
243
|
+
/** Mask input options */
|
|
244
|
+
maskInputOptions?: SessionRecordingMaskInputOptions;
|
|
245
|
+
/** Masking configuration */
|
|
246
|
+
masking?: {
|
|
247
|
+
maskAllInputs?: boolean;
|
|
248
|
+
maskTextSelector?: string;
|
|
249
|
+
blockSelector?: string;
|
|
250
|
+
};
|
|
251
|
+
/** Record headers in network requests */
|
|
252
|
+
recordHeaders?: boolean;
|
|
253
|
+
/** Record body in network requests */
|
|
254
|
+
recordBody?: boolean;
|
|
255
|
+
/** Compress events before sending (default: true) */
|
|
256
|
+
compressEvents?: boolean;
|
|
257
|
+
/** Internal: Mutation throttler refill rate */
|
|
258
|
+
__mutationThrottlerRefillRate?: number;
|
|
259
|
+
/** Internal: Mutation throttler bucket size */
|
|
260
|
+
__mutationThrottlerBucketSize?: number;
|
|
261
|
+
}
|
|
175
262
|
export interface RemoteConfig {
|
|
176
263
|
/** Default to identified_only mode */
|
|
177
264
|
defaultIdentifiedOnly?: boolean;
|
|
178
265
|
/** Feature flags */
|
|
179
266
|
featureFlags?: FeatureFlagsConfig;
|
|
180
267
|
/** Session recording config */
|
|
181
|
-
sessionRecording?:
|
|
182
|
-
enabled?: boolean;
|
|
183
|
-
sampleRate?: number;
|
|
184
|
-
};
|
|
268
|
+
sessionRecording?: SessionRecordingOptions;
|
|
185
269
|
}
|
package/dist/user-manager.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare class UserManager {
|
|
|
15
15
|
private storage;
|
|
16
16
|
private userIdentity;
|
|
17
17
|
private _cachedPersonProperties;
|
|
18
|
-
constructor(storageMethod?: PersistenceMethod,
|
|
18
|
+
constructor(storageMethod?: PersistenceMethod, cross_subdomain?: boolean);
|
|
19
19
|
/**
|
|
20
20
|
* Get current user identity
|
|
21
21
|
*/
|
|
@@ -136,5 +136,5 @@ export declare class UserManager {
|
|
|
136
136
|
/**
|
|
137
137
|
* Update storage method at runtime
|
|
138
138
|
*/
|
|
139
|
-
updateStorageMethod(method: PersistenceMethod,
|
|
139
|
+
updateStorageMethod(method: PersistenceMethod, cross_subdomain?: boolean): void;
|
|
140
140
|
}
|
package/dist/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/dist/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/config.js
CHANGED
|
@@ -25,6 +25,8 @@ class ConfigManager {
|
|
|
25
25
|
script.getAttribute("data-api-host") ||
|
|
26
26
|
script.getAttribute("data-host") ||
|
|
27
27
|
initialConfig.api_host;
|
|
28
|
+
config.script_host =
|
|
29
|
+
script.getAttribute("data-script-host") || initialConfig.script_host;
|
|
28
30
|
config.proxy = script.getAttribute("data-proxy") || initialConfig.proxy;
|
|
29
31
|
config.proxyUrl =
|
|
30
32
|
script.getAttribute("data-proxy-url") || initialConfig.proxyUrl;
|
package/lib/entrypoints/array.js
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External Scripts Loader
|
|
3
|
+
*
|
|
4
|
+
* Dynamically loads external scripts (like rrweb) from CDN.
|
|
5
|
+
* Based on PostHog's implementation.
|
|
6
|
+
*/
|
|
7
|
+
import type { VTilt } from "../vtilt";
|
|
8
|
+
import { VTiltExtensionKind } from "../utils/globals";
|
|
9
|
+
/**
|
|
10
|
+
* Load a script dynamically
|
|
11
|
+
*/
|
|
12
|
+
declare const loadScript: (vtilt: VTilt, url: string, callback: (error?: string | Event, event?: Event) => void) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Get the URL for an extension script
|
|
15
|
+
*
|
|
16
|
+
* Priority:
|
|
17
|
+
* 1. script_host config (if set) - loads from {script_host}/dist/{kind}.js
|
|
18
|
+
* 2. Default to unpkg CDN for npm package
|
|
19
|
+
*
|
|
20
|
+
* Note: script_host should be the base URL (e.g., "https://cdn.example.com")
|
|
21
|
+
* The /dist/ path is automatically appended to match the npm package structure
|
|
22
|
+
*/
|
|
23
|
+
declare const getExtensionUrl: (vtilt: VTilt, kind: VTiltExtensionKind) => string;
|
|
24
|
+
export { loadScript, getExtensionUrl };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* External Scripts Loader
|
|
4
|
+
*
|
|
5
|
+
* Dynamically loads external scripts (like rrweb) from CDN.
|
|
6
|
+
* Based on PostHog's implementation.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getExtensionUrl = exports.loadScript = void 0;
|
|
10
|
+
const globals_1 = require("../utils/globals");
|
|
11
|
+
const LOGGER_PREFIX = "[ExternalScriptsLoader]";
|
|
12
|
+
/**
|
|
13
|
+
* Load a script dynamically
|
|
14
|
+
*/
|
|
15
|
+
const loadScript = (vtilt, url, callback) => {
|
|
16
|
+
const config = vtilt.getConfig();
|
|
17
|
+
// Check if external script loading is disabled
|
|
18
|
+
if (config.disable_external_dependency_loading) {
|
|
19
|
+
console.warn(`${LOGGER_PREFIX} ${url} was requested but loading of external scripts is disabled.`);
|
|
20
|
+
return callback("Loading of external scripts is disabled");
|
|
21
|
+
}
|
|
22
|
+
// Check if script is already loaded
|
|
23
|
+
const existingScripts = globals_1.document === null || globals_1.document === void 0 ? void 0 : globals_1.document.querySelectorAll("script");
|
|
24
|
+
if (existingScripts) {
|
|
25
|
+
for (let i = 0; i < existingScripts.length; i++) {
|
|
26
|
+
if (existingScripts[i].src === url) {
|
|
27
|
+
const alreadyExistingScriptTag = existingScripts[i];
|
|
28
|
+
if (alreadyExistingScriptTag.__vtilt_loading_callback_fired) {
|
|
29
|
+
// Script already exists and fired its load event
|
|
30
|
+
return callback();
|
|
31
|
+
}
|
|
32
|
+
// Script exists but hasn't loaded yet - attach callback
|
|
33
|
+
alreadyExistingScriptTag.addEventListener("load", (event) => {
|
|
34
|
+
alreadyExistingScriptTag.__vtilt_loading_callback_fired = true;
|
|
35
|
+
callback(undefined, event);
|
|
36
|
+
});
|
|
37
|
+
alreadyExistingScriptTag.onerror = (error) => callback(error);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const addScript = () => {
|
|
43
|
+
var _a;
|
|
44
|
+
if (!globals_1.document) {
|
|
45
|
+
return callback("document not found");
|
|
46
|
+
}
|
|
47
|
+
const scriptTag = globals_1.document.createElement("script");
|
|
48
|
+
scriptTag.type = "text/javascript";
|
|
49
|
+
scriptTag.crossOrigin = "anonymous";
|
|
50
|
+
scriptTag.src = url;
|
|
51
|
+
scriptTag.onload = (event) => {
|
|
52
|
+
scriptTag.__vtilt_loading_callback_fired = true;
|
|
53
|
+
callback(undefined, event);
|
|
54
|
+
};
|
|
55
|
+
scriptTag.onerror = (error) => callback(error);
|
|
56
|
+
const scripts = globals_1.document.querySelectorAll("body > script");
|
|
57
|
+
if (scripts.length > 0) {
|
|
58
|
+
(_a = scripts[0].parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(scriptTag, scripts[0]);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
globals_1.document.body.appendChild(scriptTag);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
if (globals_1.document === null || globals_1.document === void 0 ? void 0 : globals_1.document.body) {
|
|
65
|
+
addScript();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
globals_1.document === null || globals_1.document === void 0 ? void 0 : globals_1.document.addEventListener("DOMContentLoaded", addScript);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
exports.loadScript = loadScript;
|
|
72
|
+
/**
|
|
73
|
+
* SDK version - used for loading correct script version from CDN
|
|
74
|
+
*/
|
|
75
|
+
const SDK_VERSION = "1.1.5";
|
|
76
|
+
/**
|
|
77
|
+
* Get the URL for an extension script
|
|
78
|
+
*
|
|
79
|
+
* Priority:
|
|
80
|
+
* 1. script_host config (if set) - loads from {script_host}/dist/{kind}.js
|
|
81
|
+
* 2. Default to unpkg CDN for npm package
|
|
82
|
+
*
|
|
83
|
+
* Note: script_host should be the base URL (e.g., "https://cdn.example.com")
|
|
84
|
+
* The /dist/ path is automatically appended to match the npm package structure
|
|
85
|
+
*/
|
|
86
|
+
const getExtensionUrl = (vtilt, kind) => {
|
|
87
|
+
const config = vtilt.getConfig();
|
|
88
|
+
// Use script_host if configured (matches snippet behavior: script_host+"/dist/array.js")
|
|
89
|
+
if (config.script_host) {
|
|
90
|
+
const cleanHost = config.script_host.replace(/\/+$/gm, "");
|
|
91
|
+
return `${cleanHost}/dist/${kind}.js`;
|
|
92
|
+
}
|
|
93
|
+
// Default: load from unpkg (npm CDN)
|
|
94
|
+
// This serves the file directly from the published @v-tilt/browser package
|
|
95
|
+
return `https://unpkg.com/@v-tilt/browser@${SDK_VERSION}/dist/${kind}.js`;
|
|
96
|
+
};
|
|
97
|
+
exports.getExtensionUrl = getExtensionUrl;
|
|
98
|
+
// Initialize extensions object
|
|
99
|
+
globals_1.assignableWindow.__VTiltExtensions__ =
|
|
100
|
+
globals_1.assignableWindow.__VTiltExtensions__ || {};
|
|
101
|
+
/**
|
|
102
|
+
* Load an external dependency
|
|
103
|
+
*/
|
|
104
|
+
globals_1.assignableWindow.__VTiltExtensions__.loadExternalDependency = (vtilt, kind, callback) => {
|
|
105
|
+
const url = getExtensionUrl(vtilt, kind);
|
|
106
|
+
loadScript(vtilt, url, callback);
|
|
107
|
+
};
|
|
@@ -17,6 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
require("./external-scripts-loader");
|
|
20
21
|
const module_no_external_es_1 = __importDefault(require("./module.no-external.es"));
|
|
21
22
|
__exportStar(require("./module.no-external.es"), exports);
|
|
22
23
|
exports.default = module_no_external_es_1.default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recorder Entrypoint
|
|
3
|
+
*
|
|
4
|
+
* This file is built as a separate bundle (recorder.js) that can be
|
|
5
|
+
* lazy-loaded when session recording is enabled.
|
|
6
|
+
*
|
|
7
|
+
* It exports:
|
|
8
|
+
* - rrweb.record: The rrweb record function
|
|
9
|
+
* - rrwebPlugins: Plugins for console recording
|
|
10
|
+
* - initSessionRecording: Factory function to create LazyLoadedSessionRecording
|
|
11
|
+
*/
|
|
12
|
+
import { record as rrwebRecord } from "@rrweb/record";
|
|
13
|
+
import { LazyLoadedSessionRecordingInterface } from "../utils/globals";
|
|
14
|
+
import type { SessionRecordingConfig } from "../extensions/replay/types";
|
|
15
|
+
import type { VTilt } from "../vtilt";
|
|
16
|
+
/**
|
|
17
|
+
* Factory function to create a LazyLoadedSessionRecording instance
|
|
18
|
+
*
|
|
19
|
+
* Called by SessionRecordingWrapper after the recorder script is loaded
|
|
20
|
+
*/
|
|
21
|
+
declare function initSessionRecording(instance: VTilt, config?: SessionRecordingConfig): LazyLoadedSessionRecordingInterface;
|
|
22
|
+
export { initSessionRecording };
|
|
23
|
+
export default rrwebRecord;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Recorder Entrypoint
|
|
4
|
+
*
|
|
5
|
+
* This file is built as a separate bundle (recorder.js) that can be
|
|
6
|
+
* lazy-loaded when session recording is enabled.
|
|
7
|
+
*
|
|
8
|
+
* It exports:
|
|
9
|
+
* - rrweb.record: The rrweb record function
|
|
10
|
+
* - rrwebPlugins: Plugins for console recording
|
|
11
|
+
* - initSessionRecording: Factory function to create LazyLoadedSessionRecording
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.initSessionRecording = initSessionRecording;
|
|
15
|
+
const record_1 = require("@rrweb/record");
|
|
16
|
+
const rrweb_plugin_console_record_1 = require("@rrweb/rrweb-plugin-console-record");
|
|
17
|
+
const globals_1 = require("../utils/globals");
|
|
18
|
+
const session_recording_1 = require("../extensions/replay/session-recording");
|
|
19
|
+
// Initialize extensions object
|
|
20
|
+
globals_1.assignableWindow.__VTiltExtensions__ =
|
|
21
|
+
globals_1.assignableWindow.__VTiltExtensions__ || {};
|
|
22
|
+
// Register rrweb record function
|
|
23
|
+
globals_1.assignableWindow.__VTiltExtensions__.rrweb = {
|
|
24
|
+
record: record_1.record,
|
|
25
|
+
version: "v2",
|
|
26
|
+
};
|
|
27
|
+
// Register rrweb plugins
|
|
28
|
+
globals_1.assignableWindow.__VTiltExtensions__.rrwebPlugins = {
|
|
29
|
+
getRecordConsolePlugin: rrweb_plugin_console_record_1.getRecordConsolePlugin,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Factory function to create a LazyLoadedSessionRecording instance
|
|
33
|
+
*
|
|
34
|
+
* Called by SessionRecordingWrapper after the recorder script is loaded
|
|
35
|
+
*/
|
|
36
|
+
function initSessionRecording(instance, config) {
|
|
37
|
+
return new session_recording_1.LazyLoadedSessionRecording(instance, config);
|
|
38
|
+
}
|
|
39
|
+
// Register the factory function
|
|
40
|
+
globals_1.assignableWindow.__VTiltExtensions__.initSessionRecording =
|
|
41
|
+
initSessionRecording;
|
|
42
|
+
exports.default = record_1.record;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Recording Extension
|
|
3
|
+
*
|
|
4
|
+
* Exports for rrweb session recording functionality.
|
|
5
|
+
*
|
|
6
|
+
* Architecture:
|
|
7
|
+
* - SessionRecordingWrapper: Lightweight wrapper in main bundle, handles lazy loading
|
|
8
|
+
* - LazyLoadedSessionRecording: Actual recording logic, loaded on demand via recorder.js
|
|
9
|
+
*/
|
|
10
|
+
export { SessionRecordingWrapper, LAZY_LOADING, type SessionRecordingStatus, type LazyLoadedSessionRecordingInterface, } from "./session-recording-wrapper";
|
|
11
|
+
export { LazyLoadedSessionRecording } from "./session-recording";
|
|
12
|
+
export type { SessionRecordingConfig, SessionStartReason, RecordOptions, RRWebRecord, SnapshotBuffer, CanvasRecordingConfig, NetworkPayloadCaptureConfig, MaskingConfig, TriggerType, } from "./types";
|
|
13
|
+
export { compressEvent, estimateSize, truncateLargeConsoleLogs, splitBuffer, isSessionIdleEvent, isRecordingPausedEvent, isInteractiveEvent, RECORDING_MAX_EVENT_SIZE, RECORDING_BUFFER_TIMEOUT, RECORDING_IDLE_THRESHOLD_MS, } from "./session-recording-utils";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session Recording Extension
|
|
4
|
+
*
|
|
5
|
+
* Exports for rrweb session recording functionality.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - SessionRecordingWrapper: Lightweight wrapper in main bundle, handles lazy loading
|
|
9
|
+
* - LazyLoadedSessionRecording: Actual recording logic, loaded on demand via recorder.js
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RECORDING_IDLE_THRESHOLD_MS = exports.RECORDING_BUFFER_TIMEOUT = exports.RECORDING_MAX_EVENT_SIZE = exports.isInteractiveEvent = exports.isRecordingPausedEvent = exports.isSessionIdleEvent = exports.splitBuffer = exports.truncateLargeConsoleLogs = exports.estimateSize = exports.compressEvent = exports.LazyLoadedSessionRecording = exports.LAZY_LOADING = exports.SessionRecordingWrapper = void 0;
|
|
13
|
+
// Main export - the wrapper that lives in the main bundle
|
|
14
|
+
var session_recording_wrapper_1 = require("./session-recording-wrapper");
|
|
15
|
+
Object.defineProperty(exports, "SessionRecordingWrapper", { enumerable: true, get: function () { return session_recording_wrapper_1.SessionRecordingWrapper; } });
|
|
16
|
+
Object.defineProperty(exports, "LAZY_LOADING", { enumerable: true, get: function () { return session_recording_wrapper_1.LAZY_LOADING; } });
|
|
17
|
+
// Lazy-loaded implementation (only used in recorder.js bundle)
|
|
18
|
+
var session_recording_1 = require("./session-recording");
|
|
19
|
+
Object.defineProperty(exports, "LazyLoadedSessionRecording", { enumerable: true, get: function () { return session_recording_1.LazyLoadedSessionRecording; } });
|
|
20
|
+
// Utilities
|
|
21
|
+
var session_recording_utils_1 = require("./session-recording-utils");
|
|
22
|
+
Object.defineProperty(exports, "compressEvent", { enumerable: true, get: function () { return session_recording_utils_1.compressEvent; } });
|
|
23
|
+
Object.defineProperty(exports, "estimateSize", { enumerable: true, get: function () { return session_recording_utils_1.estimateSize; } });
|
|
24
|
+
Object.defineProperty(exports, "truncateLargeConsoleLogs", { enumerable: true, get: function () { return session_recording_utils_1.truncateLargeConsoleLogs; } });
|
|
25
|
+
Object.defineProperty(exports, "splitBuffer", { enumerable: true, get: function () { return session_recording_utils_1.splitBuffer; } });
|
|
26
|
+
Object.defineProperty(exports, "isSessionIdleEvent", { enumerable: true, get: function () { return session_recording_utils_1.isSessionIdleEvent; } });
|
|
27
|
+
Object.defineProperty(exports, "isRecordingPausedEvent", { enumerable: true, get: function () { return session_recording_utils_1.isRecordingPausedEvent; } });
|
|
28
|
+
Object.defineProperty(exports, "isInteractiveEvent", { enumerable: true, get: function () { return session_recording_utils_1.isInteractiveEvent; } });
|
|
29
|
+
Object.defineProperty(exports, "RECORDING_MAX_EVENT_SIZE", { enumerable: true, get: function () { return session_recording_utils_1.RECORDING_MAX_EVENT_SIZE; } });
|
|
30
|
+
Object.defineProperty(exports, "RECORDING_BUFFER_TIMEOUT", { enumerable: true, get: function () { return session_recording_utils_1.RECORDING_BUFFER_TIMEOUT; } });
|
|
31
|
+
Object.defineProperty(exports, "RECORDING_IDLE_THRESHOLD_MS", { enumerable: true, get: function () { return session_recording_utils_1.RECORDING_IDLE_THRESHOLD_MS; } });
|