@bugspotter/sdk 0.1.0-alpha.1
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/CHANGELOG.md +69 -0
- package/LICENSE +21 -0
- package/README.md +639 -0
- package/dist/bugspotter.min.js +2 -0
- package/dist/bugspotter.min.js.LICENSE.txt +14 -0
- package/dist/capture/base-capture.d.ts +34 -0
- package/dist/capture/base-capture.js +23 -0
- package/dist/capture/capture-lifecycle.d.ts +24 -0
- package/dist/capture/capture-lifecycle.js +2 -0
- package/dist/capture/console.d.ts +29 -0
- package/dist/capture/console.js +107 -0
- package/dist/capture/metadata.d.ts +21 -0
- package/dist/capture/metadata.js +76 -0
- package/dist/capture/network.d.ts +32 -0
- package/dist/capture/network.js +135 -0
- package/dist/capture/screenshot.d.ts +19 -0
- package/dist/capture/screenshot.js +52 -0
- package/dist/collectors/dom.d.ts +67 -0
- package/dist/collectors/dom.js +164 -0
- package/dist/collectors/index.d.ts +2 -0
- package/dist/collectors/index.js +5 -0
- package/dist/core/buffer.d.ts +50 -0
- package/dist/core/buffer.js +88 -0
- package/dist/core/circular-buffer.d.ts +42 -0
- package/dist/core/circular-buffer.js +77 -0
- package/dist/core/compress.d.ts +49 -0
- package/dist/core/compress.js +245 -0
- package/dist/core/offline-queue.d.ts +76 -0
- package/dist/core/offline-queue.js +301 -0
- package/dist/core/transport.d.ts +73 -0
- package/dist/core/transport.js +352 -0
- package/dist/core/upload-helpers.d.ts +32 -0
- package/dist/core/upload-helpers.js +79 -0
- package/dist/core/uploader.d.ts +70 -0
- package/dist/core/uploader.js +185 -0
- package/dist/index.d.ts +140 -0
- package/dist/index.esm.js +205 -0
- package/dist/index.js +244 -0
- package/dist/utils/logger.d.ts +28 -0
- package/dist/utils/logger.js +84 -0
- package/dist/utils/sanitize-patterns.d.ts +103 -0
- package/dist/utils/sanitize-patterns.js +282 -0
- package/dist/utils/sanitize.d.ts +73 -0
- package/dist/utils/sanitize.js +254 -0
- package/dist/widget/button.d.ts +33 -0
- package/dist/widget/button.js +143 -0
- package/dist/widget/components/dom-element-cache.d.ts +62 -0
- package/dist/widget/components/dom-element-cache.js +105 -0
- package/dist/widget/components/form-validator.d.ts +66 -0
- package/dist/widget/components/form-validator.js +115 -0
- package/dist/widget/components/pii-detection-display.d.ts +64 -0
- package/dist/widget/components/pii-detection-display.js +142 -0
- package/dist/widget/components/redaction-canvas.d.ts +95 -0
- package/dist/widget/components/redaction-canvas.js +230 -0
- package/dist/widget/components/screenshot-processor.d.ts +44 -0
- package/dist/widget/components/screenshot-processor.js +191 -0
- package/dist/widget/components/style-manager.d.ts +37 -0
- package/dist/widget/components/style-manager.js +296 -0
- package/dist/widget/components/template-manager.d.ts +66 -0
- package/dist/widget/components/template-manager.js +198 -0
- package/dist/widget/modal.d.ts +62 -0
- package/dist/widget/modal.js +299 -0
- package/docs/CDN.md +213 -0
- package/docs/FRAMEWORK_INTEGRATION.md +1104 -0
- package/docs/PUBLISHING.md +550 -0
- package/docs/SESSION_REPLAY.md +381 -0
- package/package.json +90 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PII Pattern Definitions
|
|
4
|
+
* Configurable regex patterns for detecting sensitive data (PII + credentials)
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.PATTERN_PRESETS = exports.PatternBuilder = exports.PATTERN_CATEGORIES = exports.DEFAULT_PATTERNS = void 0;
|
|
8
|
+
exports.getPatternsByPriority = getPatternsByPriority;
|
|
9
|
+
exports.getPattern = getPattern;
|
|
10
|
+
exports.getPatternsByCategory = getPatternsByCategory;
|
|
11
|
+
exports.getAllPatternNames = getAllPatternNames;
|
|
12
|
+
exports.createPatternConfig = createPatternConfig;
|
|
13
|
+
exports.validatePattern = validatePattern;
|
|
14
|
+
exports.mergePatternConfigs = mergePatternConfigs;
|
|
15
|
+
/**
|
|
16
|
+
* Default built-in patterns
|
|
17
|
+
*/
|
|
18
|
+
exports.DEFAULT_PATTERNS = {
|
|
19
|
+
email: {
|
|
20
|
+
name: 'email',
|
|
21
|
+
regex: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
|
|
22
|
+
description: 'Email addresses',
|
|
23
|
+
examples: ['user@example.com', 'john.doe+tag@company.co.uk', 'test_user@sub.domain.com'],
|
|
24
|
+
priority: 1, // Highest priority - most specific
|
|
25
|
+
},
|
|
26
|
+
creditcard: {
|
|
27
|
+
name: 'creditcard',
|
|
28
|
+
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,
|
|
29
|
+
description: 'Credit card numbers (Visa, MC, Amex, Discover, etc.)',
|
|
30
|
+
examples: [
|
|
31
|
+
'4532-1488-0343-6467',
|
|
32
|
+
'4532148803436467',
|
|
33
|
+
'5425 2334 3010 9903',
|
|
34
|
+
'3782 822463 10005',
|
|
35
|
+
],
|
|
36
|
+
priority: 2,
|
|
37
|
+
},
|
|
38
|
+
ssn: {
|
|
39
|
+
name: 'ssn',
|
|
40
|
+
regex: /\b\d{3}-\d{2}-\d{4}\b|\b(?<!\d)\d{9}(?!\d)\b/g,
|
|
41
|
+
description: 'US Social Security Numbers',
|
|
42
|
+
examples: ['123-45-6789', '987654321'],
|
|
43
|
+
priority: 3,
|
|
44
|
+
},
|
|
45
|
+
iin: {
|
|
46
|
+
name: 'iin',
|
|
47
|
+
regex: /\b[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])\d{6}\b/g,
|
|
48
|
+
description: 'Kazakhstan IIN/BIN (12 digits with date validation)',
|
|
49
|
+
examples: ['950315300123', '880612500456', '021225123456'],
|
|
50
|
+
priority: 4,
|
|
51
|
+
},
|
|
52
|
+
ip: {
|
|
53
|
+
name: 'ip',
|
|
54
|
+
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,
|
|
55
|
+
description: 'IPv4 and IPv6 addresses',
|
|
56
|
+
examples: ['192.168.1.100', '127.0.0.1', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'],
|
|
57
|
+
priority: 5,
|
|
58
|
+
},
|
|
59
|
+
phone: {
|
|
60
|
+
name: 'phone',
|
|
61
|
+
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,
|
|
62
|
+
description: 'International phone numbers',
|
|
63
|
+
examples: [
|
|
64
|
+
'+1-555-1234',
|
|
65
|
+
'+1-555-123-4567',
|
|
66
|
+
'(555) 123-4567',
|
|
67
|
+
'555-123-4567',
|
|
68
|
+
'+7 777 123 4567',
|
|
69
|
+
],
|
|
70
|
+
priority: 6,
|
|
71
|
+
},
|
|
72
|
+
apikey: {
|
|
73
|
+
name: 'apikey',
|
|
74
|
+
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,
|
|
75
|
+
description: 'API keys (Stripe, Google, AWS, etc.)',
|
|
76
|
+
examples: [
|
|
77
|
+
'sk_live_abc123def456ghi789jkl',
|
|
78
|
+
'pk_test_xyz789abc123def456',
|
|
79
|
+
'AIzaSyD1234567890abcdefghijklmnopqrst',
|
|
80
|
+
'AKIAIOSFODNN7EXAMPLE',
|
|
81
|
+
],
|
|
82
|
+
priority: 7,
|
|
83
|
+
},
|
|
84
|
+
token: {
|
|
85
|
+
name: 'token',
|
|
86
|
+
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,
|
|
87
|
+
description: 'Authentication tokens (Bearer, GitHub, JWT-like)',
|
|
88
|
+
examples: [
|
|
89
|
+
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
90
|
+
'ghp_abc123def456ghi789jkl012mno345pqr',
|
|
91
|
+
'gho_xyz789abc123def456ghi789jkl012mno',
|
|
92
|
+
],
|
|
93
|
+
priority: 8,
|
|
94
|
+
},
|
|
95
|
+
password: {
|
|
96
|
+
name: 'password',
|
|
97
|
+
regex: /(?:password|passwd|pwd)[\s:=]+[^\s]{6,}|(?:password|passwd|pwd)["']?\s*[:=]\s*["']?[^\s"']{6,}/gi,
|
|
98
|
+
description: 'Password fields in text (password=..., pwd:...)',
|
|
99
|
+
examples: ['password: MySecret123!', 'passwd=SecurePass456', 'pwd: "MyP@ssw0rd"'],
|
|
100
|
+
priority: 9,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Pattern categories for grouping
|
|
105
|
+
*/
|
|
106
|
+
exports.PATTERN_CATEGORIES = {
|
|
107
|
+
financial: ['creditcard', 'ssn'],
|
|
108
|
+
contact: ['email', 'phone'],
|
|
109
|
+
identification: ['ssn', 'iin'],
|
|
110
|
+
network: ['ip', 'email'],
|
|
111
|
+
credentials: ['apikey', 'token', 'password'],
|
|
112
|
+
kazakhstan: ['iin'],
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Get patterns sorted by priority
|
|
116
|
+
*/
|
|
117
|
+
function getPatternsByPriority(patterns) {
|
|
118
|
+
return [...patterns].sort((a, b) => {
|
|
119
|
+
return a.priority - b.priority;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get pattern by name
|
|
124
|
+
*/
|
|
125
|
+
function getPattern(name) {
|
|
126
|
+
return exports.DEFAULT_PATTERNS[name];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get patterns by category
|
|
130
|
+
*/
|
|
131
|
+
function getPatternsByCategory(category) {
|
|
132
|
+
return exports.PATTERN_CATEGORIES[category].map((name) => {
|
|
133
|
+
return exports.DEFAULT_PATTERNS[name];
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get all pattern names
|
|
138
|
+
*/
|
|
139
|
+
function getAllPatternNames() {
|
|
140
|
+
return Object.keys(exports.DEFAULT_PATTERNS);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Custom pattern builder for advanced use cases
|
|
144
|
+
*/
|
|
145
|
+
class PatternBuilder {
|
|
146
|
+
constructor() {
|
|
147
|
+
this.pattern = {};
|
|
148
|
+
}
|
|
149
|
+
name(name) {
|
|
150
|
+
this.pattern.name = name;
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
regex(regex) {
|
|
154
|
+
// Ensure global flag
|
|
155
|
+
if (!regex.global) {
|
|
156
|
+
const flags = regex.flags.includes('g') ? regex.flags : regex.flags + 'g';
|
|
157
|
+
this.pattern.regex = new RegExp(regex.source, flags);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
this.pattern.regex = regex;
|
|
161
|
+
}
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
description(description) {
|
|
165
|
+
this.pattern.description = description;
|
|
166
|
+
return this;
|
|
167
|
+
}
|
|
168
|
+
examples(examples) {
|
|
169
|
+
this.pattern.examples = examples;
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
priority(priority) {
|
|
173
|
+
this.pattern.priority = priority;
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
build() {
|
|
177
|
+
var _a;
|
|
178
|
+
if (!this.pattern.name || !this.pattern.regex) {
|
|
179
|
+
throw new Error('Pattern must have at least name and regex');
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
name: this.pattern.name,
|
|
183
|
+
regex: this.pattern.regex,
|
|
184
|
+
description: this.pattern.description || this.pattern.name,
|
|
185
|
+
examples: this.pattern.examples || [],
|
|
186
|
+
priority: (_a = this.pattern.priority) !== null && _a !== void 0 ? _a : 99,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.PatternBuilder = PatternBuilder;
|
|
191
|
+
/**
|
|
192
|
+
* Pre-configured pattern sets for common use cases
|
|
193
|
+
*/
|
|
194
|
+
exports.PATTERN_PRESETS = {
|
|
195
|
+
/** All patterns enabled (PII + credentials) - default */
|
|
196
|
+
all: getAllPatternNames(),
|
|
197
|
+
/** Minimal - only most critical PII */
|
|
198
|
+
minimal: ['email', 'creditcard', 'ssn'],
|
|
199
|
+
/** Financial data only */
|
|
200
|
+
financial: exports.PATTERN_CATEGORIES.financial,
|
|
201
|
+
/** Contact information only */
|
|
202
|
+
contact: exports.PATTERN_CATEGORIES.contact,
|
|
203
|
+
/** Identification numbers only */
|
|
204
|
+
identification: exports.PATTERN_CATEGORIES.identification,
|
|
205
|
+
/** Credentials and secrets only */
|
|
206
|
+
credentials: exports.PATTERN_CATEGORIES.credentials,
|
|
207
|
+
/** Kazakhstan-specific patterns */
|
|
208
|
+
kazakhstan: ['email', 'phone', 'iin'],
|
|
209
|
+
/** GDPR compliance recommended set */
|
|
210
|
+
gdpr: ['email', 'phone', 'ip'],
|
|
211
|
+
/** PCI DSS compliance required */
|
|
212
|
+
pci: ['creditcard'],
|
|
213
|
+
/** Security-focused: PII + credentials */
|
|
214
|
+
security: [
|
|
215
|
+
'email',
|
|
216
|
+
'phone',
|
|
217
|
+
'creditcard',
|
|
218
|
+
'ssn',
|
|
219
|
+
'apikey',
|
|
220
|
+
'token',
|
|
221
|
+
'password',
|
|
222
|
+
],
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Create custom pattern configuration
|
|
226
|
+
*/
|
|
227
|
+
function createPatternConfig(preset) {
|
|
228
|
+
const names = typeof preset === 'string' ? exports.PATTERN_PRESETS[preset] : preset;
|
|
229
|
+
return names.map((name) => {
|
|
230
|
+
return exports.DEFAULT_PATTERNS[name];
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Validate pattern regex
|
|
235
|
+
*/
|
|
236
|
+
function validatePattern(pattern) {
|
|
237
|
+
const errors = [];
|
|
238
|
+
if (!pattern.name) {
|
|
239
|
+
errors.push('Pattern must have a name');
|
|
240
|
+
}
|
|
241
|
+
if (!pattern.regex) {
|
|
242
|
+
errors.push('Pattern must have a regex');
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
if (!pattern.regex.global) {
|
|
246
|
+
errors.push('Pattern regex must have global flag');
|
|
247
|
+
}
|
|
248
|
+
// Test regex doesn't cause catastrophic backtracking
|
|
249
|
+
try {
|
|
250
|
+
const testString = 'a'.repeat(1000);
|
|
251
|
+
const start = Date.now();
|
|
252
|
+
testString.match(pattern.regex);
|
|
253
|
+
const duration = Date.now() - start;
|
|
254
|
+
if (duration > 100) {
|
|
255
|
+
errors.push(`Pattern regex may cause performance issues (took ${duration}ms on test)`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
errors.push(`Pattern regex error: ${error.message}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (pattern.priority < 0) {
|
|
263
|
+
errors.push('Pattern priority must be non-negative');
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
valid: errors.length === 0,
|
|
267
|
+
errors,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Merge pattern configurations
|
|
272
|
+
*/
|
|
273
|
+
function mergePatternConfigs(...configs) {
|
|
274
|
+
const merged = new Map();
|
|
275
|
+
configs.forEach((config) => {
|
|
276
|
+
config.forEach((pattern) => {
|
|
277
|
+
// Later configs override earlier ones
|
|
278
|
+
merged.set(pattern.name, pattern);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
return getPatternsByPriority([...merged.values()]);
|
|
282
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PII Detection and Sanitization Utility - REFACTORED
|
|
3
|
+
* Follows SOLID, DRY, and KISS principles
|
|
4
|
+
*/
|
|
5
|
+
import { PIIPatternName, PATTERN_PRESETS } from './sanitize-patterns';
|
|
6
|
+
export type PIIPattern = PIIPatternName | 'custom';
|
|
7
|
+
export interface CustomPattern {
|
|
8
|
+
name: string;
|
|
9
|
+
regex: RegExp;
|
|
10
|
+
description?: string;
|
|
11
|
+
examples?: string[];
|
|
12
|
+
priority?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface SanitizeConfig {
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
patterns?: PIIPattern[] | keyof typeof PATTERN_PRESETS;
|
|
17
|
+
customPatterns?: CustomPattern[];
|
|
18
|
+
excludeSelectors?: string[];
|
|
19
|
+
}
|
|
20
|
+
export type { PIIPatternName, PatternDefinition } from './sanitize-patterns';
|
|
21
|
+
export { DEFAULT_PATTERNS, PATTERN_PRESETS, PATTERN_CATEGORIES, PatternBuilder, createPatternConfig, getPattern, getPatternsByCategory, validatePattern, } from './sanitize-patterns';
|
|
22
|
+
/**
|
|
23
|
+
* Main Sanitizer - Facade pattern: Coordinates all sanitization operations
|
|
24
|
+
* SOLID: Open/Closed - easily extensible without modification
|
|
25
|
+
*/
|
|
26
|
+
export declare class Sanitizer {
|
|
27
|
+
private enabled;
|
|
28
|
+
private stringSanitizer;
|
|
29
|
+
private valueSanitizer;
|
|
30
|
+
private elementMatcher;
|
|
31
|
+
constructor(config: SanitizeConfig);
|
|
32
|
+
/**
|
|
33
|
+
* Guard clause helper - DRY principle
|
|
34
|
+
*/
|
|
35
|
+
private guardDisabled;
|
|
36
|
+
/**
|
|
37
|
+
* Sanitize any value (string, object, array, etc.)
|
|
38
|
+
*/
|
|
39
|
+
sanitize(value: unknown): unknown;
|
|
40
|
+
/**
|
|
41
|
+
* Sanitize console arguments - KISS: delegates to generic sanitize
|
|
42
|
+
*/
|
|
43
|
+
sanitizeConsoleArgs(args: unknown[]): unknown[];
|
|
44
|
+
/**
|
|
45
|
+
* Sanitize network data - KISS: uses generic sanitize with type safety
|
|
46
|
+
*/
|
|
47
|
+
sanitizeNetworkData<T extends Record<string, unknown>>(data: T): T;
|
|
48
|
+
/**
|
|
49
|
+
* Sanitize error - KISS: uses generic sanitize with type safety
|
|
50
|
+
*/
|
|
51
|
+
sanitizeError<T extends {
|
|
52
|
+
message?: string;
|
|
53
|
+
stack?: string;
|
|
54
|
+
[key: string]: unknown;
|
|
55
|
+
}>(error: T): T;
|
|
56
|
+
/**
|
|
57
|
+
* Check if element should be excluded
|
|
58
|
+
*/
|
|
59
|
+
shouldExclude(element: Element): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Sanitize DOM text node
|
|
62
|
+
*/
|
|
63
|
+
sanitizeTextNode(text: string, element?: Element): string;
|
|
64
|
+
/**
|
|
65
|
+
* Detect PII patterns in text without sanitizing
|
|
66
|
+
* Returns a map of pattern names to match counts
|
|
67
|
+
*/
|
|
68
|
+
detectPII(text: string): Map<string, number>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Factory function to create a Sanitizer instance
|
|
72
|
+
*/
|
|
73
|
+
export declare function createSanitizer(config: SanitizeConfig): Sanitizer;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PII Detection and Sanitization Utility - REFACTORED
|
|
4
|
+
* Follows SOLID, DRY, and KISS principles
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.Sanitizer = exports.validatePattern = exports.getPatternsByCategory = exports.getPattern = exports.createPatternConfig = exports.PatternBuilder = exports.PATTERN_CATEGORIES = exports.PATTERN_PRESETS = exports.DEFAULT_PATTERNS = void 0;
|
|
8
|
+
exports.createSanitizer = createSanitizer;
|
|
9
|
+
const sanitize_patterns_1 = require("./sanitize-patterns");
|
|
10
|
+
var sanitize_patterns_2 = require("./sanitize-patterns");
|
|
11
|
+
Object.defineProperty(exports, "DEFAULT_PATTERNS", { enumerable: true, get: function () { return sanitize_patterns_2.DEFAULT_PATTERNS; } });
|
|
12
|
+
Object.defineProperty(exports, "PATTERN_PRESETS", { enumerable: true, get: function () { return sanitize_patterns_2.PATTERN_PRESETS; } });
|
|
13
|
+
Object.defineProperty(exports, "PATTERN_CATEGORIES", { enumerable: true, get: function () { return sanitize_patterns_2.PATTERN_CATEGORIES; } });
|
|
14
|
+
Object.defineProperty(exports, "PatternBuilder", { enumerable: true, get: function () { return sanitize_patterns_2.PatternBuilder; } });
|
|
15
|
+
Object.defineProperty(exports, "createPatternConfig", { enumerable: true, get: function () { return sanitize_patterns_2.createPatternConfig; } });
|
|
16
|
+
Object.defineProperty(exports, "getPattern", { enumerable: true, get: function () { return sanitize_patterns_2.getPattern; } });
|
|
17
|
+
Object.defineProperty(exports, "getPatternsByCategory", { enumerable: true, get: function () { return sanitize_patterns_2.getPatternsByCategory; } });
|
|
18
|
+
Object.defineProperty(exports, "validatePattern", { enumerable: true, get: function () { return sanitize_patterns_2.validatePattern; } });
|
|
19
|
+
/**
|
|
20
|
+
* Pattern Manager - SRP: Handles pattern initialization and storage
|
|
21
|
+
*/
|
|
22
|
+
class PatternManager {
|
|
23
|
+
constructor(selectedPatterns, customPatterns) {
|
|
24
|
+
this.patterns = new Map();
|
|
25
|
+
this.initializePatterns(selectedPatterns, customPatterns);
|
|
26
|
+
}
|
|
27
|
+
initializePatterns(selectedPatterns, customPatterns) {
|
|
28
|
+
// Resolve preset to pattern names
|
|
29
|
+
let patternNames;
|
|
30
|
+
if (typeof selectedPatterns === 'string') {
|
|
31
|
+
// It's a preset name like 'all', 'minimal', etc.
|
|
32
|
+
patternNames = sanitize_patterns_1.PATTERN_PRESETS[selectedPatterns];
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// It's an array of pattern names
|
|
36
|
+
patternNames = selectedPatterns.filter((p) => {
|
|
37
|
+
return p !== 'custom';
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Get pattern definitions and sort by priority
|
|
41
|
+
const patternDefs = patternNames.map((name) => {
|
|
42
|
+
return sanitize_patterns_1.DEFAULT_PATTERNS[name];
|
|
43
|
+
});
|
|
44
|
+
const sortedPatterns = (0, sanitize_patterns_1.getPatternsByPriority)(patternDefs);
|
|
45
|
+
// Add built-in patterns in priority order
|
|
46
|
+
sortedPatterns.forEach((patternDef) => {
|
|
47
|
+
this.patterns.set(patternDef.name, patternDef.regex);
|
|
48
|
+
});
|
|
49
|
+
// Add custom patterns (convert to PatternDefinition format)
|
|
50
|
+
customPatterns.forEach((custom) => {
|
|
51
|
+
this.patterns.set(custom.name, custom.regex);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
getPatterns() {
|
|
55
|
+
return this.patterns;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* String Sanitizer - SRP: Handles string-level PII detection and replacement
|
|
60
|
+
*/
|
|
61
|
+
class StringSanitizer {
|
|
62
|
+
constructor(patterns) {
|
|
63
|
+
this.patterns = patterns;
|
|
64
|
+
}
|
|
65
|
+
sanitize(value) {
|
|
66
|
+
if (typeof value !== 'string') {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
let sanitized = value;
|
|
70
|
+
this.patterns.forEach((regex, name) => {
|
|
71
|
+
const patternType = name.toUpperCase();
|
|
72
|
+
sanitized = sanitized.replace(regex, `[REDACTED-${patternType}]`);
|
|
73
|
+
});
|
|
74
|
+
return sanitized;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Value Sanitizer - SRP: Handles recursive object/array traversal
|
|
79
|
+
*/
|
|
80
|
+
class ValueSanitizer {
|
|
81
|
+
constructor(stringSanitizer) {
|
|
82
|
+
this.stringSanitizer = stringSanitizer;
|
|
83
|
+
}
|
|
84
|
+
sanitize(value) {
|
|
85
|
+
// Handle null/undefined
|
|
86
|
+
if (value == null) {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
// Handle strings
|
|
90
|
+
if (typeof value === 'string') {
|
|
91
|
+
return this.stringSanitizer.sanitize(value);
|
|
92
|
+
}
|
|
93
|
+
// Handle arrays
|
|
94
|
+
if (Array.isArray(value)) {
|
|
95
|
+
return value.map((item) => {
|
|
96
|
+
return this.sanitize(item);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// Handle objects
|
|
100
|
+
if (typeof value === 'object') {
|
|
101
|
+
return this.sanitizeObject(value);
|
|
102
|
+
}
|
|
103
|
+
// Return primitives as-is
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
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);
|
|
111
|
+
}
|
|
112
|
+
return sanitized;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Element Matcher - SRP: Handles DOM element exclusion logic
|
|
117
|
+
*/
|
|
118
|
+
class ElementMatcher {
|
|
119
|
+
constructor(excludeSelectors) {
|
|
120
|
+
this.excludeSelectors = excludeSelectors;
|
|
121
|
+
}
|
|
122
|
+
shouldExclude(element) {
|
|
123
|
+
if (!element || !this.excludeSelectors.length) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return this.excludeSelectors.some((selector) => {
|
|
127
|
+
try {
|
|
128
|
+
return element.matches(selector);
|
|
129
|
+
}
|
|
130
|
+
catch (_a) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Main Sanitizer - Facade pattern: Coordinates all sanitization operations
|
|
138
|
+
* SOLID: Open/Closed - easily extensible without modification
|
|
139
|
+
*/
|
|
140
|
+
class Sanitizer {
|
|
141
|
+
constructor(config) {
|
|
142
|
+
var _a, _b, _c, _d;
|
|
143
|
+
this.enabled = (_a = config.enabled) !== null && _a !== void 0 ? _a : true;
|
|
144
|
+
if (!this.enabled) {
|
|
145
|
+
// Create no-op implementations when disabled
|
|
146
|
+
this.stringSanitizer = new StringSanitizer(new Map());
|
|
147
|
+
this.valueSanitizer = new ValueSanitizer(this.stringSanitizer);
|
|
148
|
+
this.elementMatcher = new ElementMatcher([]);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Default to 'all' preset if no patterns specified
|
|
152
|
+
const selectedPatterns = (_b = config.patterns) !== null && _b !== void 0 ? _b : 'all';
|
|
153
|
+
const customPatterns = (_c = config.customPatterns) !== null && _c !== void 0 ? _c : [];
|
|
154
|
+
const excludeSelectors = (_d = config.excludeSelectors) !== null && _d !== void 0 ? _d : [];
|
|
155
|
+
const patternManager = new PatternManager(selectedPatterns, customPatterns);
|
|
156
|
+
this.stringSanitizer = new StringSanitizer(patternManager.getPatterns());
|
|
157
|
+
this.valueSanitizer = new ValueSanitizer(this.stringSanitizer);
|
|
158
|
+
this.elementMatcher = new ElementMatcher(excludeSelectors);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Guard clause helper - DRY principle
|
|
162
|
+
*/
|
|
163
|
+
guardDisabled(value) {
|
|
164
|
+
return this.enabled ? undefined : value;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Sanitize any value (string, object, array, etc.)
|
|
168
|
+
*/
|
|
169
|
+
sanitize(value) {
|
|
170
|
+
const guarded = this.guardDisabled(value);
|
|
171
|
+
if (guarded !== undefined) {
|
|
172
|
+
return guarded;
|
|
173
|
+
}
|
|
174
|
+
return this.valueSanitizer.sanitize(value);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Sanitize console arguments - KISS: delegates to generic sanitize
|
|
178
|
+
*/
|
|
179
|
+
sanitizeConsoleArgs(args) {
|
|
180
|
+
const guarded = this.guardDisabled(args);
|
|
181
|
+
if (guarded !== undefined) {
|
|
182
|
+
return guarded;
|
|
183
|
+
}
|
|
184
|
+
return args.map((arg) => {
|
|
185
|
+
return this.sanitize(arg);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Sanitize network data - KISS: uses generic sanitize with type safety
|
|
190
|
+
*/
|
|
191
|
+
sanitizeNetworkData(data) {
|
|
192
|
+
const guarded = this.guardDisabled(data);
|
|
193
|
+
if (guarded !== undefined) {
|
|
194
|
+
return guarded;
|
|
195
|
+
}
|
|
196
|
+
return this.sanitize(data);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Sanitize error - KISS: uses generic sanitize with type safety
|
|
200
|
+
*/
|
|
201
|
+
sanitizeError(error) {
|
|
202
|
+
const guarded = this.guardDisabled(error);
|
|
203
|
+
if (guarded !== undefined) {
|
|
204
|
+
return guarded;
|
|
205
|
+
}
|
|
206
|
+
return this.sanitize(error);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Check if element should be excluded
|
|
210
|
+
*/
|
|
211
|
+
shouldExclude(element) {
|
|
212
|
+
if (!this.enabled) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
return this.elementMatcher.shouldExclude(element);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Sanitize DOM text node
|
|
219
|
+
*/
|
|
220
|
+
sanitizeTextNode(text, element) {
|
|
221
|
+
const guarded = this.guardDisabled(text);
|
|
222
|
+
if (guarded !== undefined) {
|
|
223
|
+
return guarded;
|
|
224
|
+
}
|
|
225
|
+
if (this.elementMatcher.shouldExclude(element)) {
|
|
226
|
+
return text;
|
|
227
|
+
}
|
|
228
|
+
return this.stringSanitizer.sanitize(text);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Detect PII patterns in text without sanitizing
|
|
232
|
+
* Returns a map of pattern names to match counts
|
|
233
|
+
*/
|
|
234
|
+
detectPII(text) {
|
|
235
|
+
const detections = new Map();
|
|
236
|
+
if (!this.enabled || !text) {
|
|
237
|
+
return detections;
|
|
238
|
+
}
|
|
239
|
+
for (const [name, regex] of this.stringSanitizer['patterns']) {
|
|
240
|
+
const matches = text.match(new RegExp(regex, 'g'));
|
|
241
|
+
if (matches && matches.length > 0) {
|
|
242
|
+
detections.set(name, matches.length);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return detections;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
exports.Sanitizer = Sanitizer;
|
|
249
|
+
/**
|
|
250
|
+
* Factory function to create a Sanitizer instance
|
|
251
|
+
*/
|
|
252
|
+
function createSanitizer(config) {
|
|
253
|
+
return new Sanitizer(config);
|
|
254
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
type ButtonPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
2
|
+
export interface FloatingButtonOptions {
|
|
3
|
+
position?: ButtonPosition;
|
|
4
|
+
icon?: string;
|
|
5
|
+
backgroundColor?: string;
|
|
6
|
+
size?: number;
|
|
7
|
+
offset?: {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
11
|
+
zIndex?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class FloatingButton {
|
|
14
|
+
private button;
|
|
15
|
+
private options;
|
|
16
|
+
private eventHandlers;
|
|
17
|
+
constructor(options?: FloatingButtonOptions);
|
|
18
|
+
private createButton;
|
|
19
|
+
private getButtonStyles;
|
|
20
|
+
private getPositionStyles;
|
|
21
|
+
private handleMouseEnter;
|
|
22
|
+
private handleMouseLeave;
|
|
23
|
+
private handleMouseDown;
|
|
24
|
+
private handleMouseUp;
|
|
25
|
+
private addHoverEffects;
|
|
26
|
+
onClick(handler: () => void): void;
|
|
27
|
+
show(): void;
|
|
28
|
+
hide(): void;
|
|
29
|
+
setIcon(icon: string): void;
|
|
30
|
+
setBackgroundColor(color: string): void;
|
|
31
|
+
destroy(): void;
|
|
32
|
+
}
|
|
33
|
+
export {};
|