@bugspotter/sdk 2.0.5 → 2.1.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/CONTRIBUTING.md +3 -3
- package/README.md +112 -27
- package/dist/bugspotter.min.js +1 -1
- package/dist/bugspotter.min.js.map +1 -1
- package/dist/collectors/dom.d.ts +4 -0
- package/dist/collectors/dom.js +13 -14
- package/dist/core/capture-manager.d.ts +2 -0
- package/dist/core/capture-manager.js +3 -1
- package/dist/index.d.ts +26 -3
- package/dist/index.esm.js +87 -32
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +45 -6
- package/dist/utils/sanitize.js +25 -10
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/CDN.md +3 -3
- package/docs/FRAMEWORK_INTEGRATION.md +1 -1
- package/package.json +4 -4
- package/release_notes.md +1 -1
package/dist/collectors/dom.d.ts
CHANGED
|
@@ -20,6 +20,10 @@ export interface DOMCollectorConfig {
|
|
|
20
20
|
recordCanvas?: boolean;
|
|
21
21
|
/** Whether to record cross-origin iframes (default: false) */
|
|
22
22
|
recordCrossOriginIframes?: boolean;
|
|
23
|
+
/** CSS selectors for elements to block from recording */
|
|
24
|
+
blockSelectors?: string[];
|
|
25
|
+
/** CSS class name to block elements from recording */
|
|
26
|
+
blockClass?: string;
|
|
23
27
|
/** Sanitizer for PII protection */
|
|
24
28
|
sanitizer?: Sanitizer;
|
|
25
29
|
}
|
package/dist/collectors/dom.js
CHANGED
|
@@ -26,6 +26,8 @@ class DOMCollector {
|
|
|
26
26
|
collectFonts: (_h = config.collectFonts) !== null && _h !== void 0 ? _h : false,
|
|
27
27
|
recordCanvas: (_j = config.recordCanvas) !== null && _j !== void 0 ? _j : false,
|
|
28
28
|
recordCrossOriginIframes: (_k = config.recordCrossOriginIframes) !== null && _k !== void 0 ? _k : false,
|
|
29
|
+
blockSelectors: config.blockSelectors,
|
|
30
|
+
blockClass: config.blockClass,
|
|
29
31
|
sanitizer: config.sanitizer,
|
|
30
32
|
};
|
|
31
33
|
this.buffer = new buffer_1.CircularBuffer({
|
|
@@ -36,30 +38,26 @@ class DOMCollector {
|
|
|
36
38
|
* Start recording DOM events
|
|
37
39
|
*/
|
|
38
40
|
startRecording() {
|
|
39
|
-
var _a, _b, _c, _d;
|
|
41
|
+
var _a, _b, _c, _d, _e;
|
|
40
42
|
if (this.isRecording) {
|
|
41
43
|
(0, logger_1.getLogger)().warn('DOMCollector: Recording already in progress');
|
|
42
44
|
return;
|
|
43
45
|
}
|
|
44
46
|
try {
|
|
45
|
-
const recordConfig = {
|
|
46
|
-
emit: (event) => {
|
|
47
|
+
const recordConfig = Object.assign(Object.assign({ emit: (event) => {
|
|
47
48
|
this.buffer.add(event);
|
|
48
|
-
},
|
|
49
|
-
sampling: {
|
|
49
|
+
}, sampling: {
|
|
50
50
|
mousemove: (_b = (_a = this.config.sampling) === null || _a === void 0 ? void 0 : _a.mousemove) !== null && _b !== void 0 ? _b : 50,
|
|
51
51
|
scroll: (_d = (_c = this.config.sampling) === null || _c === void 0 ? void 0 : _c.scroll) !== null && _d !== void 0 ? _d : 100,
|
|
52
52
|
// Record all mouse interactions for replay visibility
|
|
53
53
|
mouseInteraction: true,
|
|
54
|
-
},
|
|
55
|
-
recordCanvas: this.config.recordCanvas,
|
|
56
|
-
recordCrossOriginIframes: this.config.recordCrossOriginIframes,
|
|
54
|
+
}, recordCanvas: this.config.recordCanvas, recordCrossOriginIframes: this.config.recordCrossOriginIframes,
|
|
57
55
|
// PII sanitization for text content
|
|
58
56
|
maskTextFn: this.sanitizer
|
|
59
57
|
? (text, element) => {
|
|
60
58
|
return this.sanitizer.sanitizeTextNode(text, element);
|
|
61
59
|
}
|
|
62
|
-
: undefined,
|
|
60
|
+
: undefined,
|
|
63
61
|
// Performance optimizations
|
|
64
62
|
slimDOMOptions: {
|
|
65
63
|
script: true, // Don't record script tags
|
|
@@ -71,12 +69,13 @@ class DOMCollector {
|
|
|
71
69
|
headMetaHttpEquiv: true, // Don't record http-equiv meta tags
|
|
72
70
|
headMetaAuthorship: true, // Don't record authorship meta tags
|
|
73
71
|
headMetaVerification: true, // Don't record verification meta tags
|
|
74
|
-
},
|
|
72
|
+
},
|
|
75
73
|
// Quality settings (controlled by backend or user config)
|
|
76
|
-
inlineStylesheet: this.config.inlineStylesheet,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
inlineStylesheet: this.config.inlineStylesheet, inlineImages: this.config.inlineImages, collectFonts: this.config.collectFonts }, (((_e = this.config.blockSelectors) === null || _e === void 0 ? void 0 : _e.length) && {
|
|
75
|
+
blockSelector: this.config.blockSelectors.join(','),
|
|
76
|
+
})), (this.config.blockClass && {
|
|
77
|
+
blockClass: this.config.blockClass,
|
|
78
|
+
}));
|
|
80
79
|
this.stopRecordingFn = (0, rrweb_1.record)(recordConfig);
|
|
81
80
|
this.isRecording = true;
|
|
82
81
|
(0, logger_1.getLogger)().debug('DOMCollector: Started recording');
|
|
@@ -17,7 +17,7 @@ const constants_1 = require("../constants");
|
|
|
17
17
|
*/
|
|
18
18
|
class CaptureManager {
|
|
19
19
|
constructor(config) {
|
|
20
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
20
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
21
21
|
// Initialize core capture modules
|
|
22
22
|
this.screenshot = new screenshot_1.ScreenshotCapture();
|
|
23
23
|
this.console = new console_1.ConsoleCapture({ sanitizer: config.sanitizer });
|
|
@@ -42,6 +42,8 @@ class CaptureManager {
|
|
|
42
42
|
collectFonts: (_h = config.replay) === null || _h === void 0 ? void 0 : _h.collectFonts,
|
|
43
43
|
recordCanvas: (_j = config.replay) === null || _j === void 0 ? void 0 : _j.recordCanvas,
|
|
44
44
|
recordCrossOriginIframes: (_k = config.replay) === null || _k === void 0 ? void 0 : _k.recordCrossOriginIframes,
|
|
45
|
+
blockSelectors: (_l = config.replay) === null || _l === void 0 ? void 0 : _l.blockSelectors,
|
|
46
|
+
blockClass: (_m = config.replay) === null || _m === void 0 ? void 0 : _m.blockClass,
|
|
45
47
|
sanitizer: config.sanitizer,
|
|
46
48
|
});
|
|
47
49
|
this.domCollector.startRecording();
|
package/dist/index.d.ts
CHANGED
|
@@ -12,9 +12,10 @@ export declare class BugSpotter {
|
|
|
12
12
|
private config;
|
|
13
13
|
private widget?;
|
|
14
14
|
private sanitizer?;
|
|
15
|
-
private captureManager
|
|
15
|
+
private captureManager?;
|
|
16
16
|
private bugReporter;
|
|
17
|
-
|
|
17
|
+
private _sampled;
|
|
18
|
+
constructor(config: BugSpotterConfig, sampled?: boolean);
|
|
18
19
|
static init(config: BugSpotterConfig): Promise<BugSpotter>;
|
|
19
20
|
/**
|
|
20
21
|
* Internal factory method to create a new BugSpotter instance
|
|
@@ -27,6 +28,8 @@ export declare class BugSpotter {
|
|
|
27
28
|
* Note: Screenshot is captured for modal preview only (_screenshotPreview)
|
|
28
29
|
* File uploads use presigned URLs returned from the backend
|
|
29
30
|
*/
|
|
31
|
+
/** Whether this session was sampled for capture */
|
|
32
|
+
get isSampled(): boolean;
|
|
30
33
|
capture(): Promise<BugReport>;
|
|
31
34
|
private handleBugReport;
|
|
32
35
|
/**
|
|
@@ -43,6 +46,13 @@ export interface BugSpotterConfig {
|
|
|
43
46
|
endpoint?: string;
|
|
44
47
|
/** API key for authentication (starts with 'bgs_'). Required. */
|
|
45
48
|
apiKey: string;
|
|
49
|
+
/**
|
|
50
|
+
* Session sampling rate (0 to 1). Controls what fraction of sessions activate capture.
|
|
51
|
+
* - 1 = capture all sessions (default)
|
|
52
|
+
* - 0.1 = capture 10% of sessions
|
|
53
|
+
* - 0 = capture nothing (SDK initializes but is inactive)
|
|
54
|
+
*/
|
|
55
|
+
sampleRate?: number;
|
|
46
56
|
showWidget?: boolean;
|
|
47
57
|
widgetOptions?: FloatingButtonOptions;
|
|
48
58
|
/** Retry configuration for failed requests */
|
|
@@ -74,6 +84,19 @@ export interface BugSpotterConfig {
|
|
|
74
84
|
recordCanvas?: boolean;
|
|
75
85
|
/** Whether to record cross-origin iframes (default: backend controlled) */
|
|
76
86
|
recordCrossOriginIframes?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* CSS selectors for DOM elements to exclude from session replay.
|
|
89
|
+
* Matched elements are replaced with a placeholder in the recording.
|
|
90
|
+
* Use for sensitive content that isn't PII (e.g., financial data, portfolios).
|
|
91
|
+
* Example: ['.portfolio-table', '#balance-widget', '[data-sensitive]']
|
|
92
|
+
*/
|
|
93
|
+
blockSelectors?: string[];
|
|
94
|
+
/**
|
|
95
|
+
* CSS class name to mark elements for blocking. Any element with this class
|
|
96
|
+
* will be excluded from replay. Alternative to blockSelectors.
|
|
97
|
+
* Example: 'bugspotter-block'
|
|
98
|
+
*/
|
|
99
|
+
blockClass?: string;
|
|
77
100
|
};
|
|
78
101
|
sanitize?: {
|
|
79
102
|
/** Enable PII sanitization (default: true) */
|
|
@@ -83,7 +106,7 @@ export interface BugSpotterConfig {
|
|
|
83
106
|
* - Can be a preset name: 'all', 'minimal', 'financial', 'contact', 'gdpr', 'pci', etc.
|
|
84
107
|
* - Or an array of pattern names: ['email', 'phone', 'ip']
|
|
85
108
|
*/
|
|
86
|
-
patterns?: 'all' | 'minimal' | 'financial' | 'contact' | 'identification' | 'kazakhstan' | 'gdpr' | 'pci' | Array<'email' | 'phone' | 'creditcard' | 'ssn' | 'iin' | 'ip' | 'custom'>;
|
|
109
|
+
patterns?: 'all' | 'minimal' | 'financial' | 'contact' | 'identification' | 'credentials' | 'kazakhstan' | 'gdpr' | 'pci' | Array<'email' | 'phone' | 'creditcard' | 'ssn' | 'iin' | 'ip' | 'apikey' | 'token' | 'password' | 'custom'>;
|
|
87
110
|
/** Custom regex patterns for PII detection */
|
|
88
111
|
customPatterns?: Array<{
|
|
89
112
|
name: string;
|
package/dist/index.esm.js
CHANGED
|
@@ -2344,6 +2344,7 @@ class StringSanitizer {
|
|
|
2344
2344
|
class ValueSanitizer {
|
|
2345
2345
|
constructor(stringSanitizer) {
|
|
2346
2346
|
this.stringSanitizer = stringSanitizer;
|
|
2347
|
+
this.seen = new WeakSet();
|
|
2347
2348
|
}
|
|
2348
2349
|
sanitize(value) {
|
|
2349
2350
|
// Handle null/undefined
|
|
@@ -2354,26 +2355,40 @@ class ValueSanitizer {
|
|
|
2354
2355
|
if (typeof value === 'string') {
|
|
2355
2356
|
return this.stringSanitizer.sanitize(value);
|
|
2356
2357
|
}
|
|
2357
|
-
// Handle arrays
|
|
2358
|
+
// Handle arrays (with circular reference protection)
|
|
2358
2359
|
if (Array.isArray(value)) {
|
|
2359
|
-
|
|
2360
|
-
return
|
|
2361
|
-
|
|
2360
|
+
if (this.seen.has(value))
|
|
2361
|
+
return '[Circular]';
|
|
2362
|
+
this.seen.add(value);
|
|
2363
|
+
try {
|
|
2364
|
+
return value.map((item) => this.sanitize(item));
|
|
2365
|
+
}
|
|
2366
|
+
finally {
|
|
2367
|
+
this.seen.delete(value);
|
|
2368
|
+
}
|
|
2362
2369
|
}
|
|
2363
|
-
// Handle objects
|
|
2370
|
+
// Handle objects (with circular reference protection)
|
|
2364
2371
|
if (typeof value === 'object') {
|
|
2372
|
+
if (this.seen.has(value))
|
|
2373
|
+
return '[Circular]';
|
|
2365
2374
|
return this.sanitizeObject(value);
|
|
2366
2375
|
}
|
|
2367
2376
|
// Return primitives as-is
|
|
2368
2377
|
return value;
|
|
2369
2378
|
}
|
|
2370
2379
|
sanitizeObject(obj) {
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
const
|
|
2374
|
-
|
|
2380
|
+
this.seen.add(obj);
|
|
2381
|
+
try {
|
|
2382
|
+
const sanitized = {};
|
|
2383
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
2384
|
+
const sanitizedKey = this.stringSanitizer.sanitize(key);
|
|
2385
|
+
sanitized[sanitizedKey] = this.sanitize(val);
|
|
2386
|
+
}
|
|
2387
|
+
return sanitized;
|
|
2388
|
+
}
|
|
2389
|
+
finally {
|
|
2390
|
+
this.seen.delete(obj);
|
|
2375
2391
|
}
|
|
2376
|
-
return sanitized;
|
|
2377
2392
|
}
|
|
2378
2393
|
}
|
|
2379
2394
|
/**
|
|
@@ -2944,7 +2959,7 @@ const MAX_RECOMMENDED_REPLAY_DURATION_SECONDS = 30;
|
|
|
2944
2959
|
* This file is automatically generated during the build process.
|
|
2945
2960
|
* To update the version, modify package.json
|
|
2946
2961
|
*/
|
|
2947
|
-
const VERSION = '2.0
|
|
2962
|
+
const VERSION = '2.1.0';
|
|
2948
2963
|
|
|
2949
2964
|
/**
|
|
2950
2965
|
* Configuration Validation Utilities
|
|
@@ -15451,6 +15466,8 @@ class DOMCollector {
|
|
|
15451
15466
|
collectFonts: (_h = config.collectFonts) !== null && _h !== void 0 ? _h : false,
|
|
15452
15467
|
recordCanvas: (_j = config.recordCanvas) !== null && _j !== void 0 ? _j : false,
|
|
15453
15468
|
recordCrossOriginIframes: (_k = config.recordCrossOriginIframes) !== null && _k !== void 0 ? _k : false,
|
|
15469
|
+
blockSelectors: config.blockSelectors,
|
|
15470
|
+
blockClass: config.blockClass,
|
|
15454
15471
|
sanitizer: config.sanitizer,
|
|
15455
15472
|
};
|
|
15456
15473
|
this.buffer = new CircularBuffer({
|
|
@@ -15461,30 +15478,26 @@ class DOMCollector {
|
|
|
15461
15478
|
* Start recording DOM events
|
|
15462
15479
|
*/
|
|
15463
15480
|
startRecording() {
|
|
15464
|
-
var _a, _b, _c, _d;
|
|
15481
|
+
var _a, _b, _c, _d, _e;
|
|
15465
15482
|
if (this.isRecording) {
|
|
15466
15483
|
getLogger().warn('DOMCollector: Recording already in progress');
|
|
15467
15484
|
return;
|
|
15468
15485
|
}
|
|
15469
15486
|
try {
|
|
15470
|
-
const recordConfig = {
|
|
15471
|
-
emit: (event) => {
|
|
15487
|
+
const recordConfig = Object.assign(Object.assign({ emit: (event) => {
|
|
15472
15488
|
this.buffer.add(event);
|
|
15473
|
-
},
|
|
15474
|
-
sampling: {
|
|
15489
|
+
}, sampling: {
|
|
15475
15490
|
mousemove: (_b = (_a = this.config.sampling) === null || _a === void 0 ? void 0 : _a.mousemove) !== null && _b !== void 0 ? _b : 50,
|
|
15476
15491
|
scroll: (_d = (_c = this.config.sampling) === null || _c === void 0 ? void 0 : _c.scroll) !== null && _d !== void 0 ? _d : 100,
|
|
15477
15492
|
// Record all mouse interactions for replay visibility
|
|
15478
15493
|
mouseInteraction: true,
|
|
15479
|
-
},
|
|
15480
|
-
recordCanvas: this.config.recordCanvas,
|
|
15481
|
-
recordCrossOriginIframes: this.config.recordCrossOriginIframes,
|
|
15494
|
+
}, recordCanvas: this.config.recordCanvas, recordCrossOriginIframes: this.config.recordCrossOriginIframes,
|
|
15482
15495
|
// PII sanitization for text content
|
|
15483
15496
|
maskTextFn: this.sanitizer
|
|
15484
15497
|
? (text, element) => {
|
|
15485
15498
|
return this.sanitizer.sanitizeTextNode(text, element);
|
|
15486
15499
|
}
|
|
15487
|
-
: undefined,
|
|
15500
|
+
: undefined,
|
|
15488
15501
|
// Performance optimizations
|
|
15489
15502
|
slimDOMOptions: {
|
|
15490
15503
|
script: true, // Don't record script tags
|
|
@@ -15496,12 +15509,13 @@ class DOMCollector {
|
|
|
15496
15509
|
headMetaHttpEquiv: true, // Don't record http-equiv meta tags
|
|
15497
15510
|
headMetaAuthorship: true, // Don't record authorship meta tags
|
|
15498
15511
|
headMetaVerification: true, // Don't record verification meta tags
|
|
15499
|
-
},
|
|
15512
|
+
},
|
|
15500
15513
|
// Quality settings (controlled by backend or user config)
|
|
15501
|
-
inlineStylesheet: this.config.inlineStylesheet,
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15514
|
+
inlineStylesheet: this.config.inlineStylesheet, inlineImages: this.config.inlineImages, collectFonts: this.config.collectFonts }, (((_e = this.config.blockSelectors) === null || _e === void 0 ? void 0 : _e.length) && {
|
|
15515
|
+
blockSelector: this.config.blockSelectors.join(','),
|
|
15516
|
+
})), (this.config.blockClass && {
|
|
15517
|
+
blockClass: this.config.blockClass,
|
|
15518
|
+
}));
|
|
15505
15519
|
this.stopRecordingFn = record(recordConfig);
|
|
15506
15520
|
this.isRecording = true;
|
|
15507
15521
|
getLogger().debug('DOMCollector: Started recording');
|
|
@@ -15591,7 +15605,7 @@ class DOMCollector {
|
|
|
15591
15605
|
*/
|
|
15592
15606
|
class CaptureManager {
|
|
15593
15607
|
constructor(config) {
|
|
15594
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
15608
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
15595
15609
|
// Initialize core capture modules
|
|
15596
15610
|
this.screenshot = new ScreenshotCapture();
|
|
15597
15611
|
this.console = new ConsoleCapture({ sanitizer: config.sanitizer });
|
|
@@ -15616,6 +15630,8 @@ class CaptureManager {
|
|
|
15616
15630
|
collectFonts: (_h = config.replay) === null || _h === void 0 ? void 0 : _h.collectFonts,
|
|
15617
15631
|
recordCanvas: (_j = config.replay) === null || _j === void 0 ? void 0 : _j.recordCanvas,
|
|
15618
15632
|
recordCrossOriginIframes: (_k = config.replay) === null || _k === void 0 ? void 0 : _k.recordCrossOriginIframes,
|
|
15633
|
+
blockSelectors: (_l = config.replay) === null || _l === void 0 ? void 0 : _l.blockSelectors,
|
|
15634
|
+
blockClass: (_m = config.replay) === null || _m === void 0 ? void 0 : _m.blockClass,
|
|
15619
15635
|
sanitizer: config.sanitizer,
|
|
15620
15636
|
});
|
|
15621
15637
|
this.domCollector.startRecording();
|
|
@@ -17220,13 +17236,20 @@ function fetchReplaySettings(endpoint, apiKey) {
|
|
|
17220
17236
|
});
|
|
17221
17237
|
}
|
|
17222
17238
|
class BugSpotter {
|
|
17223
|
-
constructor(config) {
|
|
17239
|
+
constructor(config, sampled = true) {
|
|
17224
17240
|
var _a, _b, _c, _d, _e, _f;
|
|
17225
17241
|
// Validate deduplication configuration if provided
|
|
17226
17242
|
if (config.deduplication) {
|
|
17227
17243
|
validateDeduplicationConfig(config.deduplication);
|
|
17228
17244
|
}
|
|
17229
17245
|
this.config = config;
|
|
17246
|
+
this._sampled = sampled;
|
|
17247
|
+
this.bugReporter = new BugReporter(config);
|
|
17248
|
+
// If not sampled, skip all capture initialization — true zero overhead
|
|
17249
|
+
// No console/network interception, no DOM recording, no widget
|
|
17250
|
+
if (!sampled) {
|
|
17251
|
+
return;
|
|
17252
|
+
}
|
|
17230
17253
|
// Initialize sanitizer (enabled by default)
|
|
17231
17254
|
const sanitizeEnabled = (_b = (_a = config.sanitize) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : true;
|
|
17232
17255
|
if (sanitizeEnabled) {
|
|
@@ -17239,8 +17262,6 @@ class BugSpotter {
|
|
|
17239
17262
|
}
|
|
17240
17263
|
// Initialize capture manager
|
|
17241
17264
|
this.captureManager = new CaptureManager(Object.assign(Object.assign({ sanitizer: this.sanitizer }, (config.endpoint && { apiEndpoint: getApiBaseUrl(config.endpoint) })), { replay: config.replay }));
|
|
17242
|
-
// Initialize bug reporter
|
|
17243
|
-
this.bugReporter = new BugReporter(config);
|
|
17244
17265
|
// Initialize widget (enabled by default)
|
|
17245
17266
|
const widgetEnabled = (_f = config.showWidget) !== null && _f !== void 0 ? _f : true;
|
|
17246
17267
|
if (widgetEnabled) {
|
|
@@ -17282,6 +17303,19 @@ class BugSpotter {
|
|
|
17282
17303
|
static createInstance(config) {
|
|
17283
17304
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
17284
17305
|
var _a, _b;
|
|
17306
|
+
// Check sampling rate — if this session is not sampled, disable all capture
|
|
17307
|
+
if (config.sampleRate !== undefined) {
|
|
17308
|
+
if (typeof config.sampleRate !== 'number' ||
|
|
17309
|
+
!Number.isFinite(config.sampleRate) ||
|
|
17310
|
+
config.sampleRate < 0 ||
|
|
17311
|
+
config.sampleRate > 1) {
|
|
17312
|
+
throw new Error('sampleRate must be a finite number between 0 and 1');
|
|
17313
|
+
}
|
|
17314
|
+
if (Math.random() >= config.sampleRate) {
|
|
17315
|
+
// Create a lightweight no-op instance — zero overhead (no console/network interception)
|
|
17316
|
+
return new BugSpotter(config, /* sampled */ false);
|
|
17317
|
+
}
|
|
17318
|
+
}
|
|
17285
17319
|
// Fetch replay quality settings from backend if replay is enabled
|
|
17286
17320
|
let backendSettings = null;
|
|
17287
17321
|
const replayEnabled = (_b = (_a = config.replay) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : true;
|
|
@@ -17310,8 +17344,29 @@ class BugSpotter {
|
|
|
17310
17344
|
* Note: Screenshot is captured for modal preview only (_screenshotPreview)
|
|
17311
17345
|
* File uploads use presigned URLs returned from the backend
|
|
17312
17346
|
*/
|
|
17347
|
+
/** Whether this session was sampled for capture */
|
|
17348
|
+
get isSampled() {
|
|
17349
|
+
return this._sampled;
|
|
17350
|
+
}
|
|
17313
17351
|
capture() {
|
|
17314
17352
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
17353
|
+
if (!this.captureManager) {
|
|
17354
|
+
// Unsampled session — return minimal valid report
|
|
17355
|
+
return {
|
|
17356
|
+
console: [],
|
|
17357
|
+
network: [],
|
|
17358
|
+
metadata: {
|
|
17359
|
+
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',
|
|
17360
|
+
url: typeof window !== 'undefined' ? window.location.href : '',
|
|
17361
|
+
timestamp: Date.now(),
|
|
17362
|
+
viewport: typeof window !== 'undefined'
|
|
17363
|
+
? { width: window.innerWidth, height: window.innerHeight }
|
|
17364
|
+
: { width: 0, height: 0 },
|
|
17365
|
+
browser: 'unknown',
|
|
17366
|
+
os: 'unknown',
|
|
17367
|
+
},
|
|
17368
|
+
};
|
|
17369
|
+
}
|
|
17315
17370
|
return yield this.captureManager.captureAll();
|
|
17316
17371
|
});
|
|
17317
17372
|
}
|
|
@@ -17355,9 +17410,9 @@ class BugSpotter {
|
|
|
17355
17410
|
return Object.assign({}, this.config);
|
|
17356
17411
|
}
|
|
17357
17412
|
destroy() {
|
|
17358
|
-
var _a;
|
|
17359
|
-
this.captureManager.destroy();
|
|
17360
|
-
(
|
|
17413
|
+
var _a, _b;
|
|
17414
|
+
(_a = this.captureManager) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
17415
|
+
(_b = this.widget) === null || _b === void 0 ? void 0 : _b.destroy();
|
|
17361
17416
|
this.bugReporter.destroy();
|
|
17362
17417
|
BugSpotter.instance = undefined;
|
|
17363
17418
|
BugSpotter.initPromise = undefined;
|