@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/dist/index.js CHANGED
@@ -91,13 +91,20 @@ async function fetchReplaySettings(endpoint, apiKey) {
91
91
  }
92
92
  }
93
93
  class BugSpotter {
94
- constructor(config) {
94
+ constructor(config, sampled = true) {
95
95
  var _a, _b, _c, _d, _e, _f;
96
96
  // Validate deduplication configuration if provided
97
97
  if (config.deduplication) {
98
98
  (0, config_validator_1.validateDeduplicationConfig)(config.deduplication);
99
99
  }
100
100
  this.config = config;
101
+ this._sampled = sampled;
102
+ this.bugReporter = new bug_reporter_1.BugReporter(config);
103
+ // If not sampled, skip all capture initialization — true zero overhead
104
+ // No console/network interception, no DOM recording, no widget
105
+ if (!sampled) {
106
+ return;
107
+ }
101
108
  // Initialize sanitizer (enabled by default)
102
109
  const sanitizeEnabled = (_b = (_a = config.sanitize) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : true;
103
110
  if (sanitizeEnabled) {
@@ -110,8 +117,6 @@ class BugSpotter {
110
117
  }
111
118
  // Initialize capture manager
112
119
  this.captureManager = new capture_manager_1.CaptureManager(Object.assign(Object.assign({ sanitizer: this.sanitizer }, (config.endpoint && { apiEndpoint: (0, url_helpers_1.getApiBaseUrl)(config.endpoint) })), { replay: config.replay }));
113
- // Initialize bug reporter
114
- this.bugReporter = new bug_reporter_1.BugReporter(config);
115
120
  // Initialize widget (enabled by default)
116
121
  const widgetEnabled = (_f = config.showWidget) !== null && _f !== void 0 ? _f : true;
117
122
  if (widgetEnabled) {
@@ -150,6 +155,19 @@ class BugSpotter {
150
155
  */
151
156
  static async createInstance(config) {
152
157
  var _a, _b;
158
+ // Check sampling rate — if this session is not sampled, disable all capture
159
+ if (config.sampleRate !== undefined) {
160
+ if (typeof config.sampleRate !== 'number' ||
161
+ !Number.isFinite(config.sampleRate) ||
162
+ config.sampleRate < 0 ||
163
+ config.sampleRate > 1) {
164
+ throw new Error('sampleRate must be a finite number between 0 and 1');
165
+ }
166
+ if (Math.random() >= config.sampleRate) {
167
+ // Create a lightweight no-op instance — zero overhead (no console/network interception)
168
+ return new BugSpotter(config, /* sampled */ false);
169
+ }
170
+ }
153
171
  // Fetch replay quality settings from backend if replay is enabled
154
172
  let backendSettings = null;
155
173
  const replayEnabled = (_b = (_a = config.replay) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : true;
@@ -177,7 +195,28 @@ class BugSpotter {
177
195
  * Note: Screenshot is captured for modal preview only (_screenshotPreview)
178
196
  * File uploads use presigned URLs returned from the backend
179
197
  */
198
+ /** Whether this session was sampled for capture */
199
+ get isSampled() {
200
+ return this._sampled;
201
+ }
180
202
  async capture() {
203
+ if (!this.captureManager) {
204
+ // Unsampled session — return minimal valid report
205
+ return {
206
+ console: [],
207
+ network: [],
208
+ metadata: {
209
+ userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',
210
+ url: typeof window !== 'undefined' ? window.location.href : '',
211
+ timestamp: Date.now(),
212
+ viewport: typeof window !== 'undefined'
213
+ ? { width: window.innerWidth, height: window.innerHeight }
214
+ : { width: 0, height: 0 },
215
+ browser: 'unknown',
216
+ os: 'unknown',
217
+ },
218
+ };
219
+ }
181
220
  return await this.captureManager.captureAll();
182
221
  }
183
222
  async handleBugReport() {
@@ -216,9 +255,9 @@ class BugSpotter {
216
255
  return Object.assign({}, this.config);
217
256
  }
218
257
  destroy() {
219
- var _a;
220
- this.captureManager.destroy();
221
- (_a = this.widget) === null || _a === void 0 ? void 0 : _a.destroy();
258
+ var _a, _b;
259
+ (_a = this.captureManager) === null || _a === void 0 ? void 0 : _a.destroy();
260
+ (_b = this.widget) === null || _b === void 0 ? void 0 : _b.destroy();
222
261
  this.bugReporter.destroy();
223
262
  BugSpotter.instance = undefined;
224
263
  BugSpotter.initPromise = undefined;
@@ -80,6 +80,7 @@ class StringSanitizer {
80
80
  class ValueSanitizer {
81
81
  constructor(stringSanitizer) {
82
82
  this.stringSanitizer = stringSanitizer;
83
+ this.seen = new WeakSet();
83
84
  }
84
85
  sanitize(value) {
85
86
  // Handle null/undefined
@@ -90,26 +91,40 @@ class ValueSanitizer {
90
91
  if (typeof value === 'string') {
91
92
  return this.stringSanitizer.sanitize(value);
92
93
  }
93
- // Handle arrays
94
+ // Handle arrays (with circular reference protection)
94
95
  if (Array.isArray(value)) {
95
- return value.map((item) => {
96
- return this.sanitize(item);
97
- });
96
+ if (this.seen.has(value))
97
+ return '[Circular]';
98
+ this.seen.add(value);
99
+ try {
100
+ return value.map((item) => this.sanitize(item));
101
+ }
102
+ finally {
103
+ this.seen.delete(value);
104
+ }
98
105
  }
99
- // Handle objects
106
+ // Handle objects (with circular reference protection)
100
107
  if (typeof value === 'object') {
108
+ if (this.seen.has(value))
109
+ return '[Circular]';
101
110
  return this.sanitizeObject(value);
102
111
  }
103
112
  // Return primitives as-is
104
113
  return value;
105
114
  }
106
115
  sanitizeObject(obj) {
107
- const sanitized = {};
108
- for (const [key, val] of Object.entries(obj)) {
109
- const sanitizedKey = this.stringSanitizer.sanitize(key);
110
- sanitized[sanitizedKey] = this.sanitize(val);
116
+ this.seen.add(obj);
117
+ try {
118
+ const sanitized = {};
119
+ for (const [key, val] of Object.entries(obj)) {
120
+ const sanitizedKey = this.stringSanitizer.sanitize(key);
121
+ sanitized[sanitizedKey] = this.sanitize(val);
122
+ }
123
+ return sanitized;
124
+ }
125
+ finally {
126
+ this.seen.delete(obj);
111
127
  }
112
- return sanitized;
113
128
  }
114
129
  }
115
130
  /**
package/dist/version.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * This file is automatically generated during the build process.
6
6
  * To update the version, modify package.json
7
7
  */
8
- export declare const VERSION = "2.0.5";
8
+ export declare const VERSION = "2.1.0";
package/dist/version.js CHANGED
@@ -8,4 +8,4 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.VERSION = void 0;
11
- exports.VERSION = '2.0.5';
11
+ exports.VERSION = '2.1.0';
package/docs/CDN.md CHANGED
@@ -140,7 +140,7 @@ If our primary CDN is unavailable, you can also use:
140
140
  Check available versions:
141
141
 
142
142
  - [npm package page](https://www.npmjs.com/package/@bugspotter/sdk?activeTab=versions)
143
- - [GitHub releases](https://github.com/apexbridge-tech/bugspotter/releases)
143
+ - [GitHub releases](https://github.com/apex-bridge/bugspotter-sdk/releases)
144
144
 
145
145
  ## ⚙️ Configuration
146
146
 
@@ -208,6 +208,6 @@ If updates aren't showing:
208
208
 
209
209
  ## 🆘 Support
210
210
 
211
- - **Issues:** [GitHub Issues](https://github.com/apexbridge-tech/bugspotter/issues)
212
- - **Discussions:** [GitHub Discussions](https://github.com/apexbridge-tech/bugspotter/discussions)
211
+ - **Issues:** [GitHub Issues](https://github.com/apex-bridge/bugspotter-sdk/issues)
212
+ - **Discussions:** [GitHub Discussions](https://github.com/apex-bridge/bugspotter-sdk/discussions)
213
213
  - **Security:** security@bugspotter.io
@@ -1101,4 +1101,4 @@ script-src 'self';
1101
1101
 
1102
1102
  ---
1103
1103
 
1104
- **Need Help?** Open an issue on [GitHub](https://github.com/apexbridge-tech/bugspotter) or contact support.
1104
+ **Need Help?** Open an issue on [GitHub](https://github.com/apex-bridge/bugspotter-sdk) or contact support.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bugspotter/sdk",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "description": "Professional bug reporting SDK with screenshots, session replay, and automatic error capture for web applications",
5
5
  "packageManager": "pnpm@9.15.0",
6
6
  "main": "dist/index.js",
@@ -56,12 +56,12 @@
56
56
  "license": "MIT",
57
57
  "repository": {
58
58
  "type": "git",
59
- "url": "https://github.com/apexbridge-tech/bugspotter-sdk.git"
59
+ "url": "https://github.com/apex-bridge/bugspotter-sdk.git"
60
60
  },
61
61
  "bugs": {
62
- "url": "https://github.com/apexbridge-tech/bugspotter-sdk/issues"
62
+ "url": "https://github.com/apex-bridge/bugspotter-sdk/issues"
63
63
  },
64
- "homepage": "https://github.com/apexbridge-tech/bugspotter-sdk#readme",
64
+ "homepage": "https://github.com/apex-bridge/bugspotter-sdk#readme",
65
65
  "engines": {
66
66
  "node": ">=16.0.0"
67
67
  },
package/release_notes.md CHANGED
@@ -1,4 +1,4 @@
1
- ## Release 2.0.5
1
+ ## Release 2.1.0
2
2
 
3
3
  ### Changes
4
4