@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.
Files changed (67) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/LICENSE +21 -0
  3. package/README.md +639 -0
  4. package/dist/bugspotter.min.js +2 -0
  5. package/dist/bugspotter.min.js.LICENSE.txt +14 -0
  6. package/dist/capture/base-capture.d.ts +34 -0
  7. package/dist/capture/base-capture.js +23 -0
  8. package/dist/capture/capture-lifecycle.d.ts +24 -0
  9. package/dist/capture/capture-lifecycle.js +2 -0
  10. package/dist/capture/console.d.ts +29 -0
  11. package/dist/capture/console.js +107 -0
  12. package/dist/capture/metadata.d.ts +21 -0
  13. package/dist/capture/metadata.js +76 -0
  14. package/dist/capture/network.d.ts +32 -0
  15. package/dist/capture/network.js +135 -0
  16. package/dist/capture/screenshot.d.ts +19 -0
  17. package/dist/capture/screenshot.js +52 -0
  18. package/dist/collectors/dom.d.ts +67 -0
  19. package/dist/collectors/dom.js +164 -0
  20. package/dist/collectors/index.d.ts +2 -0
  21. package/dist/collectors/index.js +5 -0
  22. package/dist/core/buffer.d.ts +50 -0
  23. package/dist/core/buffer.js +88 -0
  24. package/dist/core/circular-buffer.d.ts +42 -0
  25. package/dist/core/circular-buffer.js +77 -0
  26. package/dist/core/compress.d.ts +49 -0
  27. package/dist/core/compress.js +245 -0
  28. package/dist/core/offline-queue.d.ts +76 -0
  29. package/dist/core/offline-queue.js +301 -0
  30. package/dist/core/transport.d.ts +73 -0
  31. package/dist/core/transport.js +352 -0
  32. package/dist/core/upload-helpers.d.ts +32 -0
  33. package/dist/core/upload-helpers.js +79 -0
  34. package/dist/core/uploader.d.ts +70 -0
  35. package/dist/core/uploader.js +185 -0
  36. package/dist/index.d.ts +140 -0
  37. package/dist/index.esm.js +205 -0
  38. package/dist/index.js +244 -0
  39. package/dist/utils/logger.d.ts +28 -0
  40. package/dist/utils/logger.js +84 -0
  41. package/dist/utils/sanitize-patterns.d.ts +103 -0
  42. package/dist/utils/sanitize-patterns.js +282 -0
  43. package/dist/utils/sanitize.d.ts +73 -0
  44. package/dist/utils/sanitize.js +254 -0
  45. package/dist/widget/button.d.ts +33 -0
  46. package/dist/widget/button.js +143 -0
  47. package/dist/widget/components/dom-element-cache.d.ts +62 -0
  48. package/dist/widget/components/dom-element-cache.js +105 -0
  49. package/dist/widget/components/form-validator.d.ts +66 -0
  50. package/dist/widget/components/form-validator.js +115 -0
  51. package/dist/widget/components/pii-detection-display.d.ts +64 -0
  52. package/dist/widget/components/pii-detection-display.js +142 -0
  53. package/dist/widget/components/redaction-canvas.d.ts +95 -0
  54. package/dist/widget/components/redaction-canvas.js +230 -0
  55. package/dist/widget/components/screenshot-processor.d.ts +44 -0
  56. package/dist/widget/components/screenshot-processor.js +191 -0
  57. package/dist/widget/components/style-manager.d.ts +37 -0
  58. package/dist/widget/components/style-manager.js +296 -0
  59. package/dist/widget/components/template-manager.d.ts +66 -0
  60. package/dist/widget/components/template-manager.js +198 -0
  61. package/dist/widget/modal.d.ts +62 -0
  62. package/dist/widget/modal.js +299 -0
  63. package/docs/CDN.md +213 -0
  64. package/docs/FRAMEWORK_INTEGRATION.md +1104 -0
  65. package/docs/PUBLISHING.md +550 -0
  66. package/docs/SESSION_REPLAY.md +381 -0
  67. 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 {};