@bugspotter/sdk 2.0.0 → 2.0.5
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 +15 -45
- package/dist/bugspotter.min.js +1 -1
- package/dist/bugspotter.min.js.map +1 -1
- package/dist/core/bug-reporter.js +6 -4
- package/dist/index.d.ts +5 -7
- package/dist/index.esm.js +17 -16
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +7 -4
- package/dist/utils/config-validator.d.ts +2 -3
- package/dist/utils/config-validator.js +3 -7
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/eslint.config.js +7 -0
- package/package.json +1 -1
- package/release_notes.md +1 -1
|
@@ -137,7 +137,7 @@ class BugReporter {
|
|
|
137
137
|
var _a;
|
|
138
138
|
(0, config_validator_1.validateAuthConfig)({
|
|
139
139
|
endpoint: this.config.endpoint,
|
|
140
|
-
|
|
140
|
+
apiKey: this.config.apiKey,
|
|
141
141
|
});
|
|
142
142
|
const dedupContext = createDeduplicationContext(payload);
|
|
143
143
|
if (this.deduplicator.isDuplicate(dedupContext.title, dedupContext.description, dedupContext.errorStacks)) {
|
|
@@ -165,8 +165,10 @@ class BugReporter {
|
|
|
165
165
|
network: report.network,
|
|
166
166
|
metadata: report.metadata,
|
|
167
167
|
}, hasScreenshot: fileAnalysis.hasScreenshot, hasReplay: fileAnalysis.hasReplay });
|
|
168
|
-
const
|
|
169
|
-
|
|
168
|
+
const apiBaseUrl = (0, url_helpers_1.getApiBaseUrl)(this.config.endpoint);
|
|
169
|
+
const submitUrl = `${apiBaseUrl}/api/v1/reports`;
|
|
170
|
+
const response = await (0, transport_1.submitWithAuth)(submitUrl, JSON.stringify(createPayload), { 'Content-Type': 'application/json' }, {
|
|
171
|
+
auth: { apiKey: this.config.apiKey },
|
|
170
172
|
retry: this.config.retry,
|
|
171
173
|
offline: this.config.offline,
|
|
172
174
|
});
|
|
@@ -218,7 +220,7 @@ class BugReporter {
|
|
|
218
220
|
throw new Error('Server did not provide presigned URLs for file uploads. Check backend configuration.');
|
|
219
221
|
}
|
|
220
222
|
const apiEndpoint = (0, url_helpers_1.getApiBaseUrl)(this.config.endpoint);
|
|
221
|
-
const uploadHandler = new file_upload_handler_1.FileUploadHandler(apiEndpoint, this.config.
|
|
223
|
+
const uploadHandler = new file_upload_handler_1.FileUploadHandler(apiEndpoint, this.config.apiKey);
|
|
222
224
|
try {
|
|
223
225
|
await uploadHandler.uploadFiles(bugId, report, bugReportData.presignedUrls);
|
|
224
226
|
logger.debug('File uploads completed successfully', { bugId });
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BrowserMetadata } from './capture/metadata';
|
|
2
2
|
import { type FloatingButtonOptions } from './widget/button';
|
|
3
3
|
import type { eventWithTime } from '@rrweb/types';
|
|
4
|
-
import type {
|
|
4
|
+
import type { RetryConfig } from './core/transport';
|
|
5
5
|
import type { OfflineConfig } from './core/offline-queue';
|
|
6
6
|
import { VERSION } from './version';
|
|
7
7
|
import { type DeduplicationConfig } from './utils/deduplicator';
|
|
@@ -39,14 +39,12 @@ export declare class BugSpotter {
|
|
|
39
39
|
destroy(): void;
|
|
40
40
|
}
|
|
41
41
|
export interface BugSpotterConfig {
|
|
42
|
+
/** Base URL of BugSpotter API (e.g., https://api.example.com). SDK appends paths internally. */
|
|
42
43
|
endpoint?: string;
|
|
44
|
+
/** API key for authentication (starts with 'bgs_'). Required. */
|
|
45
|
+
apiKey: string;
|
|
43
46
|
showWidget?: boolean;
|
|
44
47
|
widgetOptions?: FloatingButtonOptions;
|
|
45
|
-
/**
|
|
46
|
-
* Authentication configuration (required)
|
|
47
|
-
* API key authentication with project ID
|
|
48
|
-
*/
|
|
49
|
-
auth: AuthConfig;
|
|
50
48
|
/** Retry configuration for failed requests */
|
|
51
49
|
retry?: RetryConfig;
|
|
52
50
|
/** Offline queue configuration */
|
|
@@ -133,7 +131,7 @@ export { CircularBuffer } from './core/buffer';
|
|
|
133
131
|
export type { CircularBufferConfig } from './core/buffer';
|
|
134
132
|
export { compressData, decompressData, compressImage, estimateSize, getCompressionRatio, } from './core/compress';
|
|
135
133
|
export { submitWithAuth, getAuthHeaders, clearOfflineQueue, } from './core/transport';
|
|
136
|
-
export type {
|
|
134
|
+
export type { TransportOptions, RetryConfig } from './core/transport';
|
|
137
135
|
export type { OfflineConfig } from './core/offline-queue';
|
|
138
136
|
export type { Logger, LogLevel, LoggerConfig } from './utils/logger';
|
|
139
137
|
export { getLogger, configureLogger, createLogger } from './utils/logger';
|
package/dist/index.esm.js
CHANGED
|
@@ -2944,14 +2944,14 @@ const MAX_RECOMMENDED_REPLAY_DURATION_SECONDS = 30;
|
|
|
2944
2944
|
* This file is automatically generated during the build process.
|
|
2945
2945
|
* To update the version, modify package.json
|
|
2946
2946
|
*/
|
|
2947
|
-
const VERSION = '2.0.
|
|
2947
|
+
const VERSION = '2.0.5';
|
|
2948
2948
|
|
|
2949
2949
|
/**
|
|
2950
2950
|
* Configuration Validation Utilities
|
|
2951
2951
|
* Validates BugSpotter configuration before use
|
|
2952
2952
|
*/
|
|
2953
2953
|
/**
|
|
2954
|
-
* Validate
|
|
2954
|
+
* Validate configuration before submitting a bug report
|
|
2955
2955
|
* @throws Error if configuration is invalid
|
|
2956
2956
|
*/
|
|
2957
2957
|
function validateAuthConfig(context) {
|
|
@@ -2959,15 +2959,11 @@ function validateAuthConfig(context) {
|
|
|
2959
2959
|
throw new Error('No endpoint configured for bug report submission');
|
|
2960
2960
|
}
|
|
2961
2961
|
// SECURITY: Ensure endpoint uses HTTPS
|
|
2962
|
-
// This prevents credentials and sensitive data from being sent over plain HTTP
|
|
2963
2962
|
if (!isSecureEndpoint(context.endpoint)) {
|
|
2964
2963
|
throw new InsecureEndpointError(context.endpoint);
|
|
2965
2964
|
}
|
|
2966
|
-
if (!context.
|
|
2967
|
-
throw new Error('API key
|
|
2968
|
-
}
|
|
2969
|
-
if (!context.auth.apiKey) {
|
|
2970
|
-
throw new Error('API key is required in auth configuration');
|
|
2965
|
+
if (!context.apiKey) {
|
|
2966
|
+
throw new Error('API key is required');
|
|
2971
2967
|
}
|
|
2972
2968
|
}
|
|
2973
2969
|
/**
|
|
@@ -16742,7 +16738,7 @@ class BugReporter {
|
|
|
16742
16738
|
var _a;
|
|
16743
16739
|
validateAuthConfig({
|
|
16744
16740
|
endpoint: this.config.endpoint,
|
|
16745
|
-
|
|
16741
|
+
apiKey: this.config.apiKey,
|
|
16746
16742
|
});
|
|
16747
16743
|
const dedupContext = createDeduplicationContext(payload);
|
|
16748
16744
|
if (this.deduplicator.isDuplicate(dedupContext.title, dedupContext.description, dedupContext.errorStacks)) {
|
|
@@ -16771,8 +16767,10 @@ class BugReporter {
|
|
|
16771
16767
|
network: report.network,
|
|
16772
16768
|
metadata: report.metadata,
|
|
16773
16769
|
}, hasScreenshot: fileAnalysis.hasScreenshot, hasReplay: fileAnalysis.hasReplay });
|
|
16774
|
-
const
|
|
16775
|
-
|
|
16770
|
+
const apiBaseUrl = getApiBaseUrl(this.config.endpoint);
|
|
16771
|
+
const submitUrl = `${apiBaseUrl}/api/v1/reports`;
|
|
16772
|
+
const response = yield submitWithAuth(submitUrl, JSON.stringify(createPayload), { 'Content-Type': 'application/json' }, {
|
|
16773
|
+
auth: { apiKey: this.config.apiKey },
|
|
16776
16774
|
retry: this.config.retry,
|
|
16777
16775
|
offline: this.config.offline,
|
|
16778
16776
|
});
|
|
@@ -16826,7 +16824,7 @@ class BugReporter {
|
|
|
16826
16824
|
throw new Error('Server did not provide presigned URLs for file uploads. Check backend configuration.');
|
|
16827
16825
|
}
|
|
16828
16826
|
const apiEndpoint = getApiBaseUrl(this.config.endpoint);
|
|
16829
|
-
const uploadHandler = new FileUploadHandler(apiEndpoint, this.config.
|
|
16827
|
+
const uploadHandler = new FileUploadHandler(apiEndpoint, this.config.apiKey);
|
|
16830
16828
|
try {
|
|
16831
16829
|
yield uploadHandler.uploadFiles(bugId, report, bugReportData.presignedUrls);
|
|
16832
16830
|
logger$1.debug('File uploads completed successfully', { bugId });
|
|
@@ -17283,17 +17281,20 @@ class BugSpotter {
|
|
|
17283
17281
|
*/
|
|
17284
17282
|
static createInstance(config) {
|
|
17285
17283
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
17286
|
-
var _a, _b
|
|
17284
|
+
var _a, _b;
|
|
17287
17285
|
// Fetch replay quality settings from backend if replay is enabled
|
|
17288
17286
|
let backendSettings = null;
|
|
17289
17287
|
const replayEnabled = (_b = (_a = config.replay) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : true;
|
|
17290
17288
|
if (replayEnabled && config.endpoint) {
|
|
17291
|
-
//
|
|
17292
|
-
if (!(
|
|
17289
|
+
// SECURITY: Don't send API key over insecure connection
|
|
17290
|
+
if (!isSecureEndpoint(config.endpoint)) {
|
|
17291
|
+
logger.warn('Insecure endpoint — skipping backend settings fetch to protect API key.');
|
|
17292
|
+
}
|
|
17293
|
+
else if (!config.apiKey) {
|
|
17293
17294
|
logger.warn('Endpoint provided but no API key configured. Skipping backend settings fetch.');
|
|
17294
17295
|
}
|
|
17295
17296
|
else {
|
|
17296
|
-
backendSettings = yield fetchReplaySettings(config.endpoint, config.
|
|
17297
|
+
backendSettings = yield fetchReplaySettings(config.endpoint, config.apiKey);
|
|
17297
17298
|
}
|
|
17298
17299
|
}
|
|
17299
17300
|
// Merge backend settings with user config (user config takes precedence)
|