@bugspotter/sdk 0.3.1 → 1.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/.husky/pre-commit +1 -0
- package/CHANGELOG.md +15 -0
- package/CONTRIBUTING.md +200 -0
- package/README.md +18 -16
- package/SECURITY.md +65 -0
- package/dist/bugspotter.min.js +2 -1
- package/dist/bugspotter.min.js.map +1 -0
- package/dist/capture/console.js +2 -2
- package/dist/capture/network.js +2 -2
- package/dist/core/offline-queue.d.ts +13 -0
- package/dist/core/offline-queue.js +49 -4
- package/dist/core/transport.js +20 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +1460 -1178
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/utils/config-validator.js +6 -0
- package/dist/utils/sanitize-patterns.d.ts +3 -76
- package/dist/utils/sanitize-patterns.js +18 -216
- package/dist/utils/url-helpers.d.ts +2 -25
- package/dist/utils/url-helpers.js +10 -61
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/widget/button.d.ts +10 -0
- package/dist/widget/button.js +200 -3
- package/docs/CDN.md +5 -5
- package/eslint.config.js +10 -0
- package/package.json +15 -4
- package/release_notes.md +4 -0
- package/rollup.config.js +1 -1
- package/tsconfig.cjs.json +1 -1
- package/dist/core/circular-buffer.d.ts +0 -42
- package/dist/core/circular-buffer.js +0 -80
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.validateAuthConfig = validateAuthConfig;
|
|
8
8
|
exports.validateDeduplicationConfig = validateDeduplicationConfig;
|
|
9
|
+
const url_helpers_1 = require("./url-helpers");
|
|
9
10
|
/**
|
|
10
11
|
* Validate authentication configuration
|
|
11
12
|
* @throws Error if configuration is invalid
|
|
@@ -14,6 +15,11 @@ function validateAuthConfig(context) {
|
|
|
14
15
|
if (!context.endpoint) {
|
|
15
16
|
throw new Error('No endpoint configured for bug report submission');
|
|
16
17
|
}
|
|
18
|
+
// SECURITY: Ensure endpoint uses HTTPS
|
|
19
|
+
// This prevents credentials and sensitive data from being sent over plain HTTP
|
|
20
|
+
if (!(0, url_helpers_1.isSecureEndpoint)(context.endpoint)) {
|
|
21
|
+
throw new url_helpers_1.InsecureEndpointError(context.endpoint);
|
|
22
|
+
}
|
|
17
23
|
if (!context.auth) {
|
|
18
24
|
throw new Error('API key authentication is required');
|
|
19
25
|
}
|
|
@@ -1,42 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PII Pattern Definitions
|
|
3
|
-
*
|
|
3
|
+
* Re-exports from @bugspotter/common + SDK-specific extensions
|
|
4
4
|
*/
|
|
5
|
-
export type PIIPatternName
|
|
6
|
-
|
|
7
|
-
* Pattern definition with metadata
|
|
8
|
-
*/
|
|
9
|
-
export interface PatternDefinition {
|
|
10
|
-
/** Pattern name/identifier */
|
|
11
|
-
name: PIIPatternName;
|
|
12
|
-
/** Regular expression for detection */
|
|
13
|
-
regex: RegExp;
|
|
14
|
-
/** Human-readable description */
|
|
15
|
-
description: string;
|
|
16
|
-
/** Examples of data this pattern matches */
|
|
17
|
-
examples: string[];
|
|
18
|
-
/** Priority order (lower = higher priority, checked first) */
|
|
19
|
-
priority: number;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Default built-in patterns
|
|
23
|
-
*/
|
|
24
|
-
export declare const DEFAULT_PATTERNS: Record<PIIPatternName, PatternDefinition>;
|
|
25
|
-
/**
|
|
26
|
-
* Pattern categories for grouping
|
|
27
|
-
*/
|
|
28
|
-
export declare const PATTERN_CATEGORIES: {
|
|
29
|
-
readonly financial: PIIPatternName[];
|
|
30
|
-
readonly contact: PIIPatternName[];
|
|
31
|
-
readonly identification: PIIPatternName[];
|
|
32
|
-
readonly network: PIIPatternName[];
|
|
33
|
-
readonly credentials: PIIPatternName[];
|
|
34
|
-
readonly kazakhstan: PIIPatternName[];
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Get patterns sorted by priority
|
|
38
|
-
*/
|
|
39
|
-
export declare function getPatternsByPriority(patterns: PatternDefinition[]): PatternDefinition[];
|
|
5
|
+
export { type PIIPatternName, type PatternDefinition, type PatternPresetName, DEFAULT_PATTERNS, PATTERN_CATEGORIES, PATTERN_PRESETS, getAllPatternNames, getPatternsByPriority, getPatternsByPreset, createPatternConfig, validatePattern, } from '@bugspotter/common';
|
|
6
|
+
import { type PIIPatternName, type PatternDefinition, PATTERN_CATEGORIES } from '@bugspotter/common';
|
|
40
7
|
/**
|
|
41
8
|
* Get pattern by name
|
|
42
9
|
*/
|
|
@@ -45,10 +12,6 @@ export declare function getPattern(name: PIIPatternName): PatternDefinition;
|
|
|
45
12
|
* Get patterns by category
|
|
46
13
|
*/
|
|
47
14
|
export declare function getPatternsByCategory(category: keyof typeof PATTERN_CATEGORIES): PatternDefinition[];
|
|
48
|
-
/**
|
|
49
|
-
* Get all pattern names
|
|
50
|
-
*/
|
|
51
|
-
export declare function getAllPatternNames(): PIIPatternName[];
|
|
52
15
|
/**
|
|
53
16
|
* Custom pattern builder for advanced use cases
|
|
54
17
|
*/
|
|
@@ -61,42 +24,6 @@ export declare class PatternBuilder {
|
|
|
61
24
|
priority(priority: number): this;
|
|
62
25
|
build(): PatternDefinition;
|
|
63
26
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Pre-configured pattern sets for common use cases
|
|
66
|
-
*/
|
|
67
|
-
export declare const PATTERN_PRESETS: {
|
|
68
|
-
/** All patterns enabled (PII + credentials) - default */
|
|
69
|
-
readonly all: PIIPatternName[];
|
|
70
|
-
/** Minimal - only most critical PII */
|
|
71
|
-
readonly minimal: PIIPatternName[];
|
|
72
|
-
/** Financial data only */
|
|
73
|
-
readonly financial: PIIPatternName[];
|
|
74
|
-
/** Contact information only */
|
|
75
|
-
readonly contact: PIIPatternName[];
|
|
76
|
-
/** Identification numbers only */
|
|
77
|
-
readonly identification: PIIPatternName[];
|
|
78
|
-
/** Credentials and secrets only */
|
|
79
|
-
readonly credentials: PIIPatternName[];
|
|
80
|
-
/** Kazakhstan-specific patterns */
|
|
81
|
-
readonly kazakhstan: PIIPatternName[];
|
|
82
|
-
/** GDPR compliance recommended set */
|
|
83
|
-
readonly gdpr: PIIPatternName[];
|
|
84
|
-
/** PCI DSS compliance required */
|
|
85
|
-
readonly pci: PIIPatternName[];
|
|
86
|
-
/** Security-focused: PII + credentials */
|
|
87
|
-
readonly security: PIIPatternName[];
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Create custom pattern configuration
|
|
91
|
-
*/
|
|
92
|
-
export declare function createPatternConfig(preset: keyof typeof PATTERN_PRESETS | PIIPatternName[]): PatternDefinition[];
|
|
93
|
-
/**
|
|
94
|
-
* Validate pattern regex
|
|
95
|
-
*/
|
|
96
|
-
export declare function validatePattern(pattern: PatternDefinition): {
|
|
97
|
-
valid: boolean;
|
|
98
|
-
errors: string[];
|
|
99
|
-
};
|
|
100
27
|
/**
|
|
101
28
|
* Merge pattern configurations
|
|
102
29
|
*/
|
|
@@ -1,156 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* PII Pattern Definitions
|
|
4
|
-
*
|
|
4
|
+
* Re-exports from @bugspotter/common + SDK-specific extensions
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
8
|
-
exports.getPatternsByPriority = getPatternsByPriority;
|
|
7
|
+
exports.PatternBuilder = exports.validatePattern = exports.createPatternConfig = exports.getPatternsByPreset = exports.getPatternsByPriority = exports.getAllPatternNames = exports.PATTERN_PRESETS = exports.PATTERN_CATEGORIES = exports.DEFAULT_PATTERNS = void 0;
|
|
9
8
|
exports.getPattern = getPattern;
|
|
10
9
|
exports.getPatternsByCategory = getPatternsByCategory;
|
|
11
|
-
exports.getAllPatternNames = getAllPatternNames;
|
|
12
|
-
exports.createPatternConfig = createPatternConfig;
|
|
13
|
-
exports.validatePattern = validatePattern;
|
|
14
10
|
exports.mergePatternConfigs = mergePatternConfigs;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
exports.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
],
|
|
28
|
-
priority: 1, // Highest priority - most specific
|
|
29
|
-
},
|
|
30
|
-
creditcard: {
|
|
31
|
-
name: 'creditcard',
|
|
32
|
-
regex: /\b(?:\d{4}[-\s]){3}\d{4}\b|\b\d{4}[-\s]\d{6}[-\s]\d{5}\b|\b\d{13,19}\b/g,
|
|
33
|
-
description: 'Credit card numbers (Visa, MC, Amex, Discover, etc.)',
|
|
34
|
-
examples: [
|
|
35
|
-
'4532-1488-0343-6467',
|
|
36
|
-
'4532148803436467',
|
|
37
|
-
'5425 2334 3010 9903',
|
|
38
|
-
'3782 822463 10005',
|
|
39
|
-
],
|
|
40
|
-
priority: 2,
|
|
41
|
-
},
|
|
42
|
-
ssn: {
|
|
43
|
-
name: 'ssn',
|
|
44
|
-
regex: /\b\d{3}-\d{2}-\d{4}\b|\b(?<!\d)\d{9}(?!\d)\b/g,
|
|
45
|
-
description: 'US Social Security Numbers',
|
|
46
|
-
examples: ['123-45-6789', '987654321'],
|
|
47
|
-
priority: 3,
|
|
48
|
-
},
|
|
49
|
-
iin: {
|
|
50
|
-
name: 'iin',
|
|
51
|
-
regex: /\b[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])\d{6}\b/g,
|
|
52
|
-
description: 'Kazakhstan IIN/BIN (12 digits with date validation)',
|
|
53
|
-
examples: ['950315300123', '880612500456', '021225123456'],
|
|
54
|
-
priority: 4,
|
|
55
|
-
},
|
|
56
|
-
ip: {
|
|
57
|
-
name: 'ip',
|
|
58
|
-
regex: /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b|(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,
|
|
59
|
-
description: 'IPv4 and IPv6 addresses',
|
|
60
|
-
examples: [
|
|
61
|
-
'192.168.1.100',
|
|
62
|
-
'127.0.0.1',
|
|
63
|
-
'2001:0db8:85a3:0000:0000:8a2e:0370:7334',
|
|
64
|
-
],
|
|
65
|
-
priority: 5,
|
|
66
|
-
},
|
|
67
|
-
phone: {
|
|
68
|
-
name: 'phone',
|
|
69
|
-
regex: /\+\d{1,3}[-.\s]\d{3}[-.\s]\d{4}\b|\+\d{1,3}[-.\s]\d{3}[-.\s]\d{3}[-.\s]\d{4}\b|\(\d{3}\)\s*\d{3}[-.\s]\d{4}\b|\b\d{3}[-.\s]\d{3}[-.\s]\d{4}\b/g,
|
|
70
|
-
description: 'International phone numbers',
|
|
71
|
-
examples: [
|
|
72
|
-
'+1-555-1234',
|
|
73
|
-
'+1-555-123-4567',
|
|
74
|
-
'(555) 123-4567',
|
|
75
|
-
'555-123-4567',
|
|
76
|
-
'+7 777 123 4567',
|
|
77
|
-
],
|
|
78
|
-
priority: 6,
|
|
79
|
-
},
|
|
80
|
-
apikey: {
|
|
81
|
-
name: 'apikey',
|
|
82
|
-
regex: /\b(?:sk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}\b|AIza[a-zA-Z0-9_-]{35}|ya29\.[a-zA-Z0-9_-]+|AKIA[a-zA-Z0-9]{16}\b/g,
|
|
83
|
-
description: 'API keys (Stripe, Google, AWS, etc.)',
|
|
84
|
-
examples: [
|
|
85
|
-
'sk_live_abc123def456ghi789jkl',
|
|
86
|
-
'pk_test_xyz789abc123def456',
|
|
87
|
-
'AIzaSyD1234567890abcdefghijklmnopqrst',
|
|
88
|
-
'AKIAIOSFODNN7EXAMPLE',
|
|
89
|
-
],
|
|
90
|
-
priority: 7,
|
|
91
|
-
},
|
|
92
|
-
token: {
|
|
93
|
-
name: 'token',
|
|
94
|
-
regex: /\b(?:Bearer\s+)?[a-zA-Z0-9_-]{32,}\b|ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9_]{82}/g,
|
|
95
|
-
description: 'Authentication tokens (Bearer, GitHub, JWT-like)',
|
|
96
|
-
examples: [
|
|
97
|
-
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
98
|
-
'ghp_abc123def456ghi789jkl012mno345pqr',
|
|
99
|
-
'gho_xyz789abc123def456ghi789jkl012mno',
|
|
100
|
-
],
|
|
101
|
-
priority: 8,
|
|
102
|
-
},
|
|
103
|
-
password: {
|
|
104
|
-
name: 'password',
|
|
105
|
-
regex: /(?:password|passwd|pwd)[\s:=]+[^\s]{6,}|(?:password|passwd|pwd)["']?\s*[:=]\s*["']?[^\s"']{6,}/gi,
|
|
106
|
-
description: 'Password fields in text (password=..., pwd:...)',
|
|
107
|
-
examples: [
|
|
108
|
-
'password: MySecret123!',
|
|
109
|
-
'passwd=SecurePass456',
|
|
110
|
-
'pwd: "MyP@ssw0rd"',
|
|
111
|
-
],
|
|
112
|
-
priority: 9,
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
/**
|
|
116
|
-
* Pattern categories for grouping
|
|
117
|
-
*/
|
|
118
|
-
exports.PATTERN_CATEGORIES = {
|
|
119
|
-
financial: ['creditcard', 'ssn'],
|
|
120
|
-
contact: ['email', 'phone'],
|
|
121
|
-
identification: ['ssn', 'iin'],
|
|
122
|
-
network: ['ip', 'email'],
|
|
123
|
-
credentials: ['apikey', 'token', 'password'],
|
|
124
|
-
kazakhstan: ['iin'],
|
|
125
|
-
};
|
|
126
|
-
/**
|
|
127
|
-
* Get patterns sorted by priority
|
|
128
|
-
*/
|
|
129
|
-
function getPatternsByPriority(patterns) {
|
|
130
|
-
return [...patterns].sort((a, b) => {
|
|
131
|
-
return a.priority - b.priority;
|
|
132
|
-
});
|
|
133
|
-
}
|
|
11
|
+
// Re-export everything from @bugspotter/common
|
|
12
|
+
var common_1 = require("@bugspotter/common");
|
|
13
|
+
Object.defineProperty(exports, "DEFAULT_PATTERNS", { enumerable: true, get: function () { return common_1.DEFAULT_PATTERNS; } });
|
|
14
|
+
Object.defineProperty(exports, "PATTERN_CATEGORIES", { enumerable: true, get: function () { return common_1.PATTERN_CATEGORIES; } });
|
|
15
|
+
Object.defineProperty(exports, "PATTERN_PRESETS", { enumerable: true, get: function () { return common_1.PATTERN_PRESETS; } });
|
|
16
|
+
Object.defineProperty(exports, "getAllPatternNames", { enumerable: true, get: function () { return common_1.getAllPatternNames; } });
|
|
17
|
+
Object.defineProperty(exports, "getPatternsByPriority", { enumerable: true, get: function () { return common_1.getPatternsByPriority; } });
|
|
18
|
+
Object.defineProperty(exports, "getPatternsByPreset", { enumerable: true, get: function () { return common_1.getPatternsByPreset; } });
|
|
19
|
+
Object.defineProperty(exports, "createPatternConfig", { enumerable: true, get: function () { return common_1.createPatternConfig; } });
|
|
20
|
+
Object.defineProperty(exports, "validatePattern", { enumerable: true, get: function () { return common_1.validatePattern; } });
|
|
21
|
+
const common_2 = require("@bugspotter/common");
|
|
22
|
+
// SDK-specific extensions
|
|
134
23
|
/**
|
|
135
24
|
* Get pattern by name
|
|
136
25
|
*/
|
|
137
26
|
function getPattern(name) {
|
|
138
|
-
return
|
|
27
|
+
return common_2.DEFAULT_PATTERNS[name];
|
|
139
28
|
}
|
|
140
29
|
/**
|
|
141
30
|
* Get patterns by category
|
|
142
31
|
*/
|
|
143
32
|
function getPatternsByCategory(category) {
|
|
144
|
-
return
|
|
145
|
-
return
|
|
33
|
+
return common_2.PATTERN_CATEGORIES[category].map((name) => {
|
|
34
|
+
return common_2.DEFAULT_PATTERNS[name];
|
|
146
35
|
});
|
|
147
36
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Get all pattern names
|
|
150
|
-
*/
|
|
151
|
-
function getAllPatternNames() {
|
|
152
|
-
return Object.keys(exports.DEFAULT_PATTERNS);
|
|
153
|
-
}
|
|
154
37
|
/**
|
|
155
38
|
* Custom pattern builder for advanced use cases
|
|
156
39
|
*/
|
|
@@ -163,7 +46,6 @@ class PatternBuilder {
|
|
|
163
46
|
return this;
|
|
164
47
|
}
|
|
165
48
|
regex(regex) {
|
|
166
|
-
// Ensure global flag
|
|
167
49
|
if (!regex.global) {
|
|
168
50
|
const flags = regex.flags.includes('g') ? regex.flags : regex.flags + 'g';
|
|
169
51
|
this.pattern.regex = new RegExp(regex.source, flags);
|
|
@@ -200,85 +82,6 @@ class PatternBuilder {
|
|
|
200
82
|
}
|
|
201
83
|
}
|
|
202
84
|
exports.PatternBuilder = PatternBuilder;
|
|
203
|
-
/**
|
|
204
|
-
* Pre-configured pattern sets for common use cases
|
|
205
|
-
*/
|
|
206
|
-
exports.PATTERN_PRESETS = {
|
|
207
|
-
/** All patterns enabled (PII + credentials) - default */
|
|
208
|
-
all: getAllPatternNames(),
|
|
209
|
-
/** Minimal - only most critical PII */
|
|
210
|
-
minimal: ['email', 'creditcard', 'ssn'],
|
|
211
|
-
/** Financial data only */
|
|
212
|
-
financial: exports.PATTERN_CATEGORIES.financial,
|
|
213
|
-
/** Contact information only */
|
|
214
|
-
contact: exports.PATTERN_CATEGORIES.contact,
|
|
215
|
-
/** Identification numbers only */
|
|
216
|
-
identification: exports.PATTERN_CATEGORIES.identification,
|
|
217
|
-
/** Credentials and secrets only */
|
|
218
|
-
credentials: exports.PATTERN_CATEGORIES.credentials,
|
|
219
|
-
/** Kazakhstan-specific patterns */
|
|
220
|
-
kazakhstan: ['email', 'phone', 'iin'],
|
|
221
|
-
/** GDPR compliance recommended set */
|
|
222
|
-
gdpr: ['email', 'phone', 'ip'],
|
|
223
|
-
/** PCI DSS compliance required */
|
|
224
|
-
pci: ['creditcard'],
|
|
225
|
-
/** Security-focused: PII + credentials */
|
|
226
|
-
security: [
|
|
227
|
-
'email',
|
|
228
|
-
'phone',
|
|
229
|
-
'creditcard',
|
|
230
|
-
'ssn',
|
|
231
|
-
'apikey',
|
|
232
|
-
'token',
|
|
233
|
-
'password',
|
|
234
|
-
],
|
|
235
|
-
};
|
|
236
|
-
/**
|
|
237
|
-
* Create custom pattern configuration
|
|
238
|
-
*/
|
|
239
|
-
function createPatternConfig(preset) {
|
|
240
|
-
const names = typeof preset === 'string' ? exports.PATTERN_PRESETS[preset] : preset;
|
|
241
|
-
return names.map((name) => {
|
|
242
|
-
return exports.DEFAULT_PATTERNS[name];
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Validate pattern regex
|
|
247
|
-
*/
|
|
248
|
-
function validatePattern(pattern) {
|
|
249
|
-
const errors = [];
|
|
250
|
-
if (!pattern.name) {
|
|
251
|
-
errors.push('Pattern must have a name');
|
|
252
|
-
}
|
|
253
|
-
if (!pattern.regex) {
|
|
254
|
-
errors.push('Pattern must have a regex');
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
if (!pattern.regex.global) {
|
|
258
|
-
errors.push('Pattern regex must have global flag');
|
|
259
|
-
}
|
|
260
|
-
// Test regex doesn't cause catastrophic backtracking
|
|
261
|
-
try {
|
|
262
|
-
const testString = 'a'.repeat(1000);
|
|
263
|
-
const start = Date.now();
|
|
264
|
-
testString.match(pattern.regex);
|
|
265
|
-
const duration = Date.now() - start;
|
|
266
|
-
if (duration > 100) {
|
|
267
|
-
errors.push(`Pattern regex may cause performance issues (took ${duration}ms on test)`);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
catch (error) {
|
|
271
|
-
errors.push(`Pattern regex error: ${error.message}`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (pattern.priority < 0) {
|
|
275
|
-
errors.push('Pattern priority must be non-negative');
|
|
276
|
-
}
|
|
277
|
-
return {
|
|
278
|
-
valid: errors.length === 0,
|
|
279
|
-
errors,
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
85
|
/**
|
|
283
86
|
* Merge pattern configurations
|
|
284
87
|
*/
|
|
@@ -286,9 +89,8 @@ function mergePatternConfigs(...configs) {
|
|
|
286
89
|
const merged = new Map();
|
|
287
90
|
configs.forEach((config) => {
|
|
288
91
|
config.forEach((pattern) => {
|
|
289
|
-
// Later configs override earlier ones
|
|
290
92
|
merged.set(pattern.name, pattern);
|
|
291
93
|
});
|
|
292
94
|
});
|
|
293
|
-
return getPatternsByPriority([...merged.values()]);
|
|
95
|
+
return (0, common_2.getPatternsByPriority)([...merged.values()]);
|
|
294
96
|
}
|
|
@@ -1,28 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* URL Helper Utilities
|
|
3
|
-
*
|
|
3
|
+
* Re-exports from @bugspotter/common
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
* Custom error for invalid endpoint URLs
|
|
7
|
-
*/
|
|
8
|
-
export declare class InvalidEndpointError extends Error {
|
|
9
|
-
readonly endpoint: string;
|
|
10
|
-
readonly reason: string;
|
|
11
|
-
constructor(endpoint: string, reason: string);
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Strip known endpoint suffixes from path
|
|
15
|
-
* Removes /api/v1/reports path
|
|
16
|
-
*/
|
|
17
|
-
export declare function stripEndpointSuffix(path: string): string;
|
|
18
|
-
/**
|
|
19
|
-
* Extract base API URL from endpoint
|
|
20
|
-
* Returns scheme + host + base path (without /api/v1/reports suffix)
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* getApiBaseUrl('https://api.example.com/api/v1/reports')
|
|
24
|
-
* // Returns: 'https://api.example.com'
|
|
25
|
-
*
|
|
26
|
-
* @throws InvalidEndpointError if endpoint is not a valid absolute URL
|
|
27
|
-
*/
|
|
28
|
-
export declare function getApiBaseUrl(endpoint: string): string;
|
|
5
|
+
export { InvalidEndpointError, InsecureEndpointError, stripEndpointSuffix, getApiBaseUrl, isSecureEndpoint, } from '@bugspotter/common';
|
|
@@ -1,64 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* URL Helper Utilities
|
|
4
|
-
* Extract base API URL from endpoint configuration
|
|
5
|
-
*/
|
|
6
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.InvalidEndpointError = void 0;
|
|
8
|
-
exports.stripEndpointSuffix = stripEndpointSuffix;
|
|
9
|
-
exports.getApiBaseUrl = getApiBaseUrl;
|
|
10
|
-
const logger_1 = require("./logger");
|
|
11
|
-
const logger = (0, logger_1.getLogger)();
|
|
12
|
-
/**
|
|
13
|
-
* Custom error for invalid endpoint URLs
|
|
14
|
-
*/
|
|
15
|
-
class InvalidEndpointError extends Error {
|
|
16
|
-
constructor(endpoint, reason) {
|
|
17
|
-
super(`Invalid endpoint URL: ${endpoint}. ${reason}`);
|
|
18
|
-
this.endpoint = endpoint;
|
|
19
|
-
this.reason = reason;
|
|
20
|
-
this.name = 'InvalidEndpointError';
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.InvalidEndpointError = InvalidEndpointError;
|
|
3
|
+
exports.isSecureEndpoint = exports.getApiBaseUrl = exports.stripEndpointSuffix = exports.InsecureEndpointError = exports.InvalidEndpointError = void 0;
|
|
24
4
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// Remove trailing slash
|
|
35
|
-
return path.replace(/\/$/, '') || '';
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Extract base API URL from endpoint
|
|
39
|
-
* Returns scheme + host + base path (without /api/v1/reports suffix)
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* getApiBaseUrl('https://api.example.com/api/v1/reports')
|
|
43
|
-
* // Returns: 'https://api.example.com'
|
|
44
|
-
*
|
|
45
|
-
* @throws InvalidEndpointError if endpoint is not a valid absolute URL
|
|
46
|
-
*/
|
|
47
|
-
function getApiBaseUrl(endpoint) {
|
|
48
|
-
if (!endpoint) {
|
|
49
|
-
throw new InvalidEndpointError('', 'No endpoint configured');
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
const url = new URL(endpoint);
|
|
53
|
-
const basePath = stripEndpointSuffix(url.pathname);
|
|
54
|
-
return url.origin + basePath;
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
58
|
-
logger.error('Invalid endpoint URL - must be a valid absolute URL', {
|
|
59
|
-
endpoint,
|
|
60
|
-
error: errorMessage,
|
|
61
|
-
});
|
|
62
|
-
throw new InvalidEndpointError(endpoint, 'Must be a valid absolute URL (e.g., https://api.example.com/api/v1/reports)');
|
|
63
|
-
}
|
|
64
|
-
}
|
|
5
|
+
* URL Helper Utilities
|
|
6
|
+
* Re-exports from @bugspotter/common
|
|
7
|
+
*/
|
|
8
|
+
var common_1 = require("@bugspotter/common");
|
|
9
|
+
Object.defineProperty(exports, "InvalidEndpointError", { enumerable: true, get: function () { return common_1.InvalidEndpointError; } });
|
|
10
|
+
Object.defineProperty(exports, "InsecureEndpointError", { enumerable: true, get: function () { return common_1.InsecureEndpointError; } });
|
|
11
|
+
Object.defineProperty(exports, "stripEndpointSuffix", { enumerable: true, get: function () { return common_1.stripEndpointSuffix; } });
|
|
12
|
+
Object.defineProperty(exports, "getApiBaseUrl", { enumerable: true, get: function () { return common_1.getApiBaseUrl; } });
|
|
13
|
+
Object.defineProperty(exports, "isSecureEndpoint", { enumerable: true, get: function () { return common_1.isSecureEndpoint; } });
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/dist/widget/button.d.ts
CHANGED
|
@@ -21,6 +21,16 @@ export declare class FloatingButton {
|
|
|
21
21
|
private eventHandlers;
|
|
22
22
|
constructor(options?: FloatingButtonOptions);
|
|
23
23
|
private createButton;
|
|
24
|
+
/**
|
|
25
|
+
* Safely inject HTML content by parsing and validating SVG elements
|
|
26
|
+
* Prevents XSS attacks by only allowing safe SVG elements and attributes
|
|
27
|
+
*/
|
|
28
|
+
private setSafeHTMLContent;
|
|
29
|
+
/**
|
|
30
|
+
* Recursively sanitize SVG elements by removing dangerous tags and attributes
|
|
31
|
+
* Uses whitelists to ensure only safe SVG content is preserved
|
|
32
|
+
*/
|
|
33
|
+
private sanitizeSVGElement;
|
|
24
34
|
private getButtonStyles;
|
|
25
35
|
private getPositionStyles;
|
|
26
36
|
private handleMouseEnter;
|