content-security-toolkit 1.0.1 → 1.0.2
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 +22 -0
- package/dist/core/mediator/handlers/baseEventHandler.d.ts +65 -0
- package/dist/core/mediator/handlers/baseEventHandler.js +99 -0
- package/dist/core/mediator/handlers/index.d.ts +9 -0
- package/dist/core/mediator/handlers/index.js +34 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/otel.d.ts +24 -0
- package/dist/otel.js +87 -0
- package/dist/strategies/AbstractStrategy.mediator.d.ts +162 -0
- package/dist/strategies/AbstractStrategy.mediator.js +349 -0
- package/dist/strategies/DevToolsStrategy copy.d.ts +85 -0
- package/dist/strategies/DevToolsStrategy copy.js +362 -0
- package/dist/strategies/DevToolsStrategy-detectorManager.d.ts +70 -0
- package/dist/strategies/DevToolsStrategy-detectorManager.js +309 -0
- package/dist/strategies/DevToolsStrategy-simple.d.ts +75 -0
- package/dist/strategies/DevToolsStrategy-simple.js +366 -0
- package/dist/strategies/StrategyRegistry.d.ts +133 -0
- package/dist/strategies/StrategyRegistry.js +379 -0
- package/dist/utils/base/LoggableComponent.d.ts +62 -0
- package/dist/utils/base/LoggableComponent.js +95 -0
- package/dist/utils/debuggerDetector/debuggerDetectionWorker.d.ts +6 -0
- package/dist/utils/debuggerDetector/debuggerDetectionWorker.js +24 -0
- package/dist/utils/debuggerDetector/debuggerDetector.d.ts +55 -0
- package/dist/utils/debuggerDetector/debuggerDetector.js +158 -0
- package/dist/utils/debuggerDetector/firefoxDetector.d.ts +8 -0
- package/dist/utils/debuggerDetector/firefoxDetector.js +64 -0
- package/dist/utils/detection.d.ts +29 -0
- package/dist/utils/detection.js +267 -0
- package/dist/utils/detectors/debuggerDetectionWorker.d.ts +6 -0
- package/dist/utils/detectors/debuggerDetectionWorker.js +24 -0
- package/dist/utils/detectors/firefoxDetector.d.ts +8 -0
- package/dist/utils/detectors/firefoxDetector.js +64 -0
- package/dist/utils/logging/LogLevel.d.ts +21 -0
- package/dist/utils/logging/LogLevel.js +46 -0
- package/dist/utils/logging/LoggingConfig.d.ts +68 -0
- package/dist/utils/logging/LoggingConfig.js +64 -0
- package/dist/utils/logging/LoggingFactory.d.ts +22 -0
- package/dist/utils/logging/LoggingFactory.js +61 -0
- package/dist/utils/logging/LoggingService.d.ts +235 -0
- package/dist/utils/logging/LoggingService.js +385 -0
- package/dist/utils/logging/SimpleLoggingService.d.ts +39 -0
- package/dist/utils/logging/SimpleLoggingService.js +58 -0
- package/dist/utils/logging/advanced/LogLevel.d.ts +21 -0
- package/dist/utils/logging/advanced/LogLevel.js +46 -0
- package/dist/utils/logging/advanced/LoggingConfig.d.ts +68 -0
- package/dist/utils/logging/advanced/LoggingConfig.js +64 -0
- package/dist/utils/logging/advanced/LoggingFactory.d.ts +22 -0
- package/dist/utils/logging/advanced/LoggingFactory.js +61 -0
- package/dist/utils/logging/advanced/LoggingService.d.ts +235 -0
- package/dist/utils/logging/advanced/LoggingService.js +385 -0
- package/dist/utils/protectedContentManager-simple.d.ts +86 -0
- package/dist/utils/protectedContentManager-simple.js +180 -0
- package/dist/utils/securityOverlayManager-observer-pause.d.ts +283 -0
- package/dist/utils/securityOverlayManager-observer-pause.js +878 -0
- package/dist/utils/securityOverlayManager-simple.d.ts +197 -0
- package/dist/utils/securityOverlayManager-simple.js +552 -0
- package/package.json +1 -1
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { SimpleLoggingService } from "../utils/logging/simple/SimpleLoggingService";
|
|
2
|
+
import { ProtectionEventType } from "../core/mediator/protection-event";
|
|
3
|
+
/**
|
|
4
|
+
* Error types for strategy operations
|
|
5
|
+
*/
|
|
6
|
+
export var StrategyErrorType;
|
|
7
|
+
(function (StrategyErrorType) {
|
|
8
|
+
StrategyErrorType["REGISTRATION_ERROR"] = "registration_error";
|
|
9
|
+
StrategyErrorType["UNREGISTRATION_ERROR"] = "unregistration_error";
|
|
10
|
+
StrategyErrorType["APPLICATION_ERROR"] = "application_error";
|
|
11
|
+
StrategyErrorType["REMOVAL_ERROR"] = "removal_error";
|
|
12
|
+
StrategyErrorType["INVALID_STRATEGY"] = "invalid_strategy";
|
|
13
|
+
StrategyErrorType["STRATEGY_NOT_FOUND"] = "strategy_not_found";
|
|
14
|
+
StrategyErrorType["STRATEGY_ALREADY_REGISTERED"] = "strategy_already_registered";
|
|
15
|
+
})(StrategyErrorType || (StrategyErrorType = {}));
|
|
16
|
+
/**
|
|
17
|
+
* Custom error class for strategy registry operations
|
|
18
|
+
*/
|
|
19
|
+
export class StrategyRegistryError extends Error {
|
|
20
|
+
constructor(errorType, message, strategyId, originalError) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.errorType = errorType;
|
|
23
|
+
this.strategyId = strategyId;
|
|
24
|
+
this.originalError = originalError;
|
|
25
|
+
this.name = "StrategyRegistryError";
|
|
26
|
+
// Maintain the stack trace
|
|
27
|
+
if (Error.captureStackTrace) {
|
|
28
|
+
Error.captureStackTrace(this, StrategyRegistryError);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Registry for managing protection strategies
|
|
34
|
+
* Provides centralized access and lifecycle management
|
|
35
|
+
*/
|
|
36
|
+
export class StrategyRegistry {
|
|
37
|
+
constructor(options = {}) {
|
|
38
|
+
this.COMPONENT_NAME = "StrategyRegistry";
|
|
39
|
+
this.strategies = new Map();
|
|
40
|
+
this.mediator = null;
|
|
41
|
+
this.logger = new SimpleLoggingService(this.COMPONENT_NAME, !!options.debugMode);
|
|
42
|
+
this.logger.log("Initialized");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Set the mediator to communicate with other components
|
|
46
|
+
* @param mediator The protection mediator
|
|
47
|
+
*/
|
|
48
|
+
setMediator(mediator) {
|
|
49
|
+
this.mediator = mediator;
|
|
50
|
+
this.logger.log("Mediator set");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Register a strategy with the registry
|
|
54
|
+
* @param id Unique identifier for the strategy
|
|
55
|
+
* @param strategy Strategy instance
|
|
56
|
+
* @returns True if registration was successful
|
|
57
|
+
* @throws StrategyRegistryError if registration fails
|
|
58
|
+
*/
|
|
59
|
+
register(id, strategy) {
|
|
60
|
+
try {
|
|
61
|
+
// Validate inputs
|
|
62
|
+
if (!id) {
|
|
63
|
+
throw new StrategyRegistryError(StrategyErrorType.INVALID_STRATEGY, "Strategy ID cannot be empty");
|
|
64
|
+
}
|
|
65
|
+
if (!strategy) {
|
|
66
|
+
throw new StrategyRegistryError(StrategyErrorType.INVALID_STRATEGY, `Strategy instance for "${id}" is invalid`, id);
|
|
67
|
+
}
|
|
68
|
+
if (this.strategies.has(id)) {
|
|
69
|
+
throw new StrategyRegistryError(StrategyErrorType.STRATEGY_ALREADY_REGISTERED, `Strategy with ID "${id}" is already registered`, id);
|
|
70
|
+
}
|
|
71
|
+
// Set mediator on the strategy if it's mediator-aware
|
|
72
|
+
if (this.mediator && 'setMediator' in strategy) {
|
|
73
|
+
strategy.setMediator(this.mediator);
|
|
74
|
+
}
|
|
75
|
+
// Register the strategy
|
|
76
|
+
this.strategies.set(id, strategy);
|
|
77
|
+
this.logger.log(`Registered strategy "${id}"`);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
// Handle errors
|
|
82
|
+
if (error instanceof StrategyRegistryError) {
|
|
83
|
+
this.logger.warn(error.message);
|
|
84
|
+
// Publish error event through mediator
|
|
85
|
+
this.publishErrorEvent(id, error);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const registryError = new StrategyRegistryError(StrategyErrorType.REGISTRATION_ERROR, `Failed to register strategy "${id}": ${error instanceof Error ? error.message : String(error)}`, id, error instanceof Error ? error : undefined);
|
|
90
|
+
this.logger.error(registryError.message);
|
|
91
|
+
// Publish error event through mediator
|
|
92
|
+
this.publishErrorEvent(id, registryError);
|
|
93
|
+
throw registryError;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Unregister a strategy from the registry
|
|
99
|
+
* @param id Strategy ID to unregister
|
|
100
|
+
* @returns True if unregistration was successful
|
|
101
|
+
* @throws StrategyRegistryError if unregistration fails
|
|
102
|
+
*/
|
|
103
|
+
unregister(id) {
|
|
104
|
+
try {
|
|
105
|
+
if (!id) {
|
|
106
|
+
throw new StrategyRegistryError(StrategyErrorType.INVALID_STRATEGY, "Strategy ID cannot be empty");
|
|
107
|
+
}
|
|
108
|
+
if (!this.strategies.has(id)) {
|
|
109
|
+
throw new StrategyRegistryError(StrategyErrorType.STRATEGY_NOT_FOUND, `Strategy with ID "${id}" is not registered`, id);
|
|
110
|
+
}
|
|
111
|
+
// Get the strategy and remove it if it's applied
|
|
112
|
+
const strategy = this.strategies.get(id);
|
|
113
|
+
if (strategy.isApplied()) {
|
|
114
|
+
try {
|
|
115
|
+
strategy.remove();
|
|
116
|
+
// Publish removal event through mediator
|
|
117
|
+
this.publishStrategyRemovedEvent(id);
|
|
118
|
+
}
|
|
119
|
+
catch (removeError) {
|
|
120
|
+
this.logger.error(`Error removing strategy "${id}" during unregistration:`, removeError);
|
|
121
|
+
// Publish error event through mediator
|
|
122
|
+
this.publishErrorEvent(id, removeError instanceof Error ? removeError : new Error(String(removeError)));
|
|
123
|
+
// Continue with unregistration despite removal error
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Remove from map
|
|
127
|
+
this.strategies.delete(id);
|
|
128
|
+
this.logger.log(`Unregistered strategy "${id}"`);
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
// Handle errors
|
|
133
|
+
if (error instanceof StrategyRegistryError) {
|
|
134
|
+
this.logger.warn(error.message);
|
|
135
|
+
// Publish error event through mediator
|
|
136
|
+
this.publishErrorEvent(id, error);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const registryError = new StrategyRegistryError(StrategyErrorType.UNREGISTRATION_ERROR, `Failed to unregister strategy "${id}": ${error instanceof Error ? error.message : String(error)}`, id, error instanceof Error ? error : undefined);
|
|
141
|
+
this.logger.error(registryError.message);
|
|
142
|
+
// Publish error event through mediator
|
|
143
|
+
this.publishErrorEvent(id, registryError);
|
|
144
|
+
throw registryError;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get a strategy by ID
|
|
150
|
+
* @param id Strategy ID
|
|
151
|
+
* @returns The strategy instance or undefined if not found
|
|
152
|
+
*/
|
|
153
|
+
getStrategy(id) {
|
|
154
|
+
return this.strategies.get(id);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Check if a strategy is registered
|
|
158
|
+
* @param id Strategy ID
|
|
159
|
+
* @returns True if the strategy is registered
|
|
160
|
+
*/
|
|
161
|
+
hasStrategy(id) {
|
|
162
|
+
return this.strategies.has(id);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Apply a specific strategy
|
|
166
|
+
* @param id Strategy ID to apply
|
|
167
|
+
* @returns True if the strategy was applied successfully
|
|
168
|
+
* @throws StrategyRegistryError if application fails
|
|
169
|
+
*/
|
|
170
|
+
applyStrategy(id) {
|
|
171
|
+
try {
|
|
172
|
+
if (!id) {
|
|
173
|
+
throw new StrategyRegistryError(StrategyErrorType.INVALID_STRATEGY, "Strategy ID cannot be empty");
|
|
174
|
+
}
|
|
175
|
+
if (!this.strategies.has(id)) {
|
|
176
|
+
throw new StrategyRegistryError(StrategyErrorType.STRATEGY_NOT_FOUND, `Cannot apply strategy "${id}" because it is not registered`, id);
|
|
177
|
+
}
|
|
178
|
+
const strategy = this.strategies.get(id);
|
|
179
|
+
// Only apply if not already applied
|
|
180
|
+
if (!strategy.isApplied()) {
|
|
181
|
+
strategy.apply();
|
|
182
|
+
this.logger.log(`Applied strategy "${id}"`);
|
|
183
|
+
// Publish event through mediator
|
|
184
|
+
this.publishStrategyAppliedEvent(id);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
this.logger.log(`Strategy "${id}" is already applied`);
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
// Handle errors
|
|
193
|
+
const registryError = new StrategyRegistryError(StrategyErrorType.APPLICATION_ERROR, `Error applying strategy "${id}": ${error instanceof Error ? error.message : String(error)}`, id, error instanceof Error ? error : undefined);
|
|
194
|
+
this.logger.error(registryError.message);
|
|
195
|
+
// Publish error event through mediator
|
|
196
|
+
this.publishErrorEvent(id, registryError);
|
|
197
|
+
throw registryError;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Apply all registered strategies
|
|
202
|
+
* @returns Array of strategy IDs that failed to apply
|
|
203
|
+
*/
|
|
204
|
+
applyAllStrategies() {
|
|
205
|
+
const failed = [];
|
|
206
|
+
for (const id of this.strategies.keys()) {
|
|
207
|
+
try {
|
|
208
|
+
this.applyStrategy(id);
|
|
209
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
failed.push(id);
|
|
213
|
+
// Error already logged and event published in applyStrategy
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return failed;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Remove a specific strategy
|
|
220
|
+
* @param id Strategy ID to remove
|
|
221
|
+
* @returns True if removal was successful
|
|
222
|
+
* @throws StrategyRegistryError if removal fails
|
|
223
|
+
*/
|
|
224
|
+
removeStrategy(id) {
|
|
225
|
+
try {
|
|
226
|
+
if (!id) {
|
|
227
|
+
throw new StrategyRegistryError(StrategyErrorType.INVALID_STRATEGY, "Strategy ID cannot be empty");
|
|
228
|
+
}
|
|
229
|
+
if (!this.strategies.has(id)) {
|
|
230
|
+
throw new StrategyRegistryError(StrategyErrorType.STRATEGY_NOT_FOUND, `Cannot remove strategy "${id}" because it is not registered`, id);
|
|
231
|
+
}
|
|
232
|
+
const strategy = this.strategies.get(id);
|
|
233
|
+
// Only remove if applied
|
|
234
|
+
if (strategy.isApplied()) {
|
|
235
|
+
strategy.remove();
|
|
236
|
+
this.logger.log(`Removed strategy "${id}"`);
|
|
237
|
+
// Publish event through mediator
|
|
238
|
+
this.publishStrategyRemovedEvent(id);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
this.logger.log(`Strategy "${id}" is not applied, nothing to remove`);
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
// Handle errors
|
|
247
|
+
const registryError = new StrategyRegistryError(StrategyErrorType.REMOVAL_ERROR, `Error removing strategy "${id}": ${error instanceof Error ? error.message : String(error)}`, id, error instanceof Error ? error : undefined);
|
|
248
|
+
this.logger.error(registryError.message);
|
|
249
|
+
// Publish error event through mediator
|
|
250
|
+
this.publishErrorEvent(id, registryError);
|
|
251
|
+
throw registryError;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Remove all registered strategies
|
|
256
|
+
* @returns Array of strategy IDs that failed to remove
|
|
257
|
+
*/
|
|
258
|
+
removeAllStrategies() {
|
|
259
|
+
const failed = [];
|
|
260
|
+
for (const id of this.strategies.keys()) {
|
|
261
|
+
try {
|
|
262
|
+
this.removeStrategy(id);
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
failed.push(id);
|
|
267
|
+
// Error already logged and event published in removeStrategy
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return failed;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Get all registered strategy IDs
|
|
274
|
+
* @returns Array of strategy IDs
|
|
275
|
+
*/
|
|
276
|
+
getStrategyIds() {
|
|
277
|
+
return Array.from(this.strategies.keys());
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Get all registered strategies
|
|
281
|
+
* @returns Map of strategy IDs to strategy instances
|
|
282
|
+
*/
|
|
283
|
+
getAllStrategies() {
|
|
284
|
+
return new Map(this.strategies);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Get all applied strategies
|
|
288
|
+
* @returns Array of strategy IDs that are currently applied
|
|
289
|
+
*/
|
|
290
|
+
getAppliedStrategies() {
|
|
291
|
+
const applied = [];
|
|
292
|
+
for (const [id, strategy] of this.strategies.entries()) {
|
|
293
|
+
if (strategy.isApplied()) {
|
|
294
|
+
applied.push(id);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return applied;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Set debug mode for all strategies that support it
|
|
301
|
+
* @param enabled Whether debug mode should be enabled
|
|
302
|
+
*/
|
|
303
|
+
setDebugMode(enabled) {
|
|
304
|
+
this.logger.setDebugMode(enabled);
|
|
305
|
+
for (const [id, strategy] of this.strategies.entries()) {
|
|
306
|
+
try {
|
|
307
|
+
strategy.setDebugMode(enabled);
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
this.logger.error(`Error setting debug mode for strategy "${id}":`, error);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
this.logger.log(`Set debug mode to ${enabled} for all strategies`);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Clear the registry (remove all strategies first)
|
|
317
|
+
*/
|
|
318
|
+
clear() {
|
|
319
|
+
// Remove all strategies first
|
|
320
|
+
this.removeAllStrategies();
|
|
321
|
+
// Clear the map
|
|
322
|
+
this.strategies.clear();
|
|
323
|
+
this.logger.log("Cleared registry");
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Publish a strategy applied event through the mediator
|
|
327
|
+
* @param strategyId ID of the strategy that was applied
|
|
328
|
+
*/
|
|
329
|
+
publishStrategyAppliedEvent(strategyId) {
|
|
330
|
+
if (!this.mediator)
|
|
331
|
+
return;
|
|
332
|
+
this.mediator.publish({
|
|
333
|
+
type: ProtectionEventType.STRATEGY_APPLIED,
|
|
334
|
+
source: this.COMPONENT_NAME,
|
|
335
|
+
timestamp: Date.now(),
|
|
336
|
+
data: {
|
|
337
|
+
strategyName: strategyId,
|
|
338
|
+
options: {}
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Publish a strategy removed event through the mediator
|
|
344
|
+
* @param strategyId ID of the strategy that was removed
|
|
345
|
+
*/
|
|
346
|
+
publishStrategyRemovedEvent(strategyId) {
|
|
347
|
+
if (!this.mediator)
|
|
348
|
+
return;
|
|
349
|
+
this.mediator.publish({
|
|
350
|
+
type: ProtectionEventType.STRATEGY_REMOVED,
|
|
351
|
+
source: this.COMPONENT_NAME,
|
|
352
|
+
timestamp: Date.now(),
|
|
353
|
+
data: {
|
|
354
|
+
strategyName: strategyId,
|
|
355
|
+
reason: "registry_operation"
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Publish an error event through the mediator
|
|
361
|
+
* @param strategyId ID of the strategy that had an error
|
|
362
|
+
* @param error The error that occurred
|
|
363
|
+
*/
|
|
364
|
+
publishErrorEvent(strategyId, error) {
|
|
365
|
+
if (!this.mediator)
|
|
366
|
+
return;
|
|
367
|
+
this.mediator.publish({
|
|
368
|
+
type: ProtectionEventType.ERROR_OCCURRED,
|
|
369
|
+
source: this.COMPONENT_NAME,
|
|
370
|
+
timestamp: Date.now(),
|
|
371
|
+
data: {
|
|
372
|
+
strategyName: strategyId,
|
|
373
|
+
errorType: error instanceof StrategyRegistryError ? error.errorType : "unknown",
|
|
374
|
+
message: error.message,
|
|
375
|
+
stack: error.stack
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { SimpleLoggingService } from "../logging/simple/SimpleLoggingService";
|
|
2
|
+
/**
|
|
3
|
+
* Base class providing common logging and error handling functionality.
|
|
4
|
+
* Extract shared functionality from AbstractStrategy, AbstractDevToolsDetector, and AbstractEventHandler.
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class LoggableComponent {
|
|
7
|
+
readonly COMPONENT_NAME: string;
|
|
8
|
+
protected debugMode: boolean;
|
|
9
|
+
protected logger: SimpleLoggingService;
|
|
10
|
+
/**
|
|
11
|
+
* Create a new LoggableComponent
|
|
12
|
+
* @param componentName Unique name for the component (used in logging)
|
|
13
|
+
* @param debugMode Enable debug mode for troubleshooting
|
|
14
|
+
*/
|
|
15
|
+
constructor(componentName: string, debugMode?: boolean);
|
|
16
|
+
/**
|
|
17
|
+
* Get the debug mode status
|
|
18
|
+
* @returns True if debug mode is enabled
|
|
19
|
+
*/
|
|
20
|
+
isDebugEnabled(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Set debug mode
|
|
23
|
+
* @param enabled Whether debug mode should be enabled
|
|
24
|
+
*/
|
|
25
|
+
setDebugMode(enabled: boolean): void;
|
|
26
|
+
/**
|
|
27
|
+
* Log a debug message if debug mode is enabled
|
|
28
|
+
* @param message Message to log
|
|
29
|
+
* @param args Additional arguments to log
|
|
30
|
+
*/
|
|
31
|
+
protected log(message: string, ...args: unknown[]): void;
|
|
32
|
+
/**
|
|
33
|
+
* Log a warning message
|
|
34
|
+
* @param message Warning message
|
|
35
|
+
* @param args Additional arguments to log
|
|
36
|
+
*/
|
|
37
|
+
protected warn(message: string, ...args: unknown[]): void;
|
|
38
|
+
/**
|
|
39
|
+
* Log an error message
|
|
40
|
+
* @param message Error message
|
|
41
|
+
* @param args Additional arguments to log
|
|
42
|
+
*/
|
|
43
|
+
protected error(message: string, ...args: unknown[]): void;
|
|
44
|
+
/**
|
|
45
|
+
* Execute a function with error handling
|
|
46
|
+
* This method can be overridden in subclasses to add type-specific error handling.
|
|
47
|
+
* @param operation Name of the operation for error reporting
|
|
48
|
+
* @param errorTypeOrFn Either an error type (for subclasses) or the function to execute
|
|
49
|
+
* @param fn Function to execute (only if errorTypeOrFn is an error type)
|
|
50
|
+
* @returns The result of the function or undefined if an error occurred
|
|
51
|
+
*/
|
|
52
|
+
protected safeExecute<T>(operation: string, errorTypeOrFn: unknown, fn?: () => T): T | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Execute an async function with error handling
|
|
55
|
+
* This method can be overridden in subclasses to add type-specific error handling.
|
|
56
|
+
* @param operation Name of the operation for error reporting
|
|
57
|
+
* @param errorTypeOrFn Either an error type (for subclasses) or the async function to execute
|
|
58
|
+
* @param fn Async function to execute (only if errorTypeOrFn is an error type)
|
|
59
|
+
* @returns Promise resolving to the result of the function or undefined if an error occurred
|
|
60
|
+
*/
|
|
61
|
+
protected safeExecuteAsync<T>(operation: string, errorTypeOrFn: unknown, fn?: () => Promise<T>): Promise<T | undefined>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { SimpleLoggingService } from "../logging/simple/SimpleLoggingService";
|
|
2
|
+
/**
|
|
3
|
+
* Base class providing common logging and error handling functionality.
|
|
4
|
+
* Extract shared functionality from AbstractStrategy, AbstractDevToolsDetector, and AbstractEventHandler.
|
|
5
|
+
*/
|
|
6
|
+
export class LoggableComponent {
|
|
7
|
+
/**
|
|
8
|
+
* Create a new LoggableComponent
|
|
9
|
+
* @param componentName Unique name for the component (used in logging)
|
|
10
|
+
* @param debugMode Enable debug mode for troubleshooting
|
|
11
|
+
*/
|
|
12
|
+
constructor(componentName, debugMode = false) {
|
|
13
|
+
this.COMPONENT_NAME = componentName;
|
|
14
|
+
this.debugMode = debugMode;
|
|
15
|
+
this.logger = new SimpleLoggingService(componentName, debugMode);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get the debug mode status
|
|
19
|
+
* @returns True if debug mode is enabled
|
|
20
|
+
*/
|
|
21
|
+
isDebugEnabled() {
|
|
22
|
+
return this.debugMode;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Set debug mode
|
|
26
|
+
* @param enabled Whether debug mode should be enabled
|
|
27
|
+
*/
|
|
28
|
+
setDebugMode(enabled) {
|
|
29
|
+
this.debugMode = enabled;
|
|
30
|
+
this.logger.setDebugMode(enabled);
|
|
31
|
+
this.logger.log(`Debug mode ${enabled ? "enabled" : "disabled"}`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Log a debug message if debug mode is enabled
|
|
35
|
+
* @param message Message to log
|
|
36
|
+
* @param args Additional arguments to log
|
|
37
|
+
*/
|
|
38
|
+
log(message, ...args) {
|
|
39
|
+
this.logger.log(message, ...args);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Log a warning message
|
|
43
|
+
* @param message Warning message
|
|
44
|
+
* @param args Additional arguments to log
|
|
45
|
+
*/
|
|
46
|
+
warn(message, ...args) {
|
|
47
|
+
this.logger.warn(message, ...args);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Log an error message
|
|
51
|
+
* @param message Error message
|
|
52
|
+
* @param args Additional arguments to log
|
|
53
|
+
*/
|
|
54
|
+
error(message, ...args) {
|
|
55
|
+
this.logger.error(message, ...args);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Execute a function with error handling
|
|
59
|
+
* This method can be overridden in subclasses to add type-specific error handling.
|
|
60
|
+
* @param operation Name of the operation for error reporting
|
|
61
|
+
* @param errorTypeOrFn Either an error type (for subclasses) or the function to execute
|
|
62
|
+
* @param fn Function to execute (only if errorTypeOrFn is an error type)
|
|
63
|
+
* @returns The result of the function or undefined if an error occurred
|
|
64
|
+
*/
|
|
65
|
+
safeExecute(operation, errorTypeOrFn, fn) {
|
|
66
|
+
// If only two args were provided (operation, fn), fn is actually in errorTypeOrFn
|
|
67
|
+
const actualFn = fn || errorTypeOrFn;
|
|
68
|
+
try {
|
|
69
|
+
return actualFn();
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
this.logger.error(`Error during ${operation}:`, error);
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Execute an async function with error handling
|
|
78
|
+
* This method can be overridden in subclasses to add type-specific error handling.
|
|
79
|
+
* @param operation Name of the operation for error reporting
|
|
80
|
+
* @param errorTypeOrFn Either an error type (for subclasses) or the async function to execute
|
|
81
|
+
* @param fn Async function to execute (only if errorTypeOrFn is an error type)
|
|
82
|
+
* @returns Promise resolving to the result of the function or undefined if an error occurred
|
|
83
|
+
*/
|
|
84
|
+
async safeExecuteAsync(operation, errorTypeOrFn, fn) {
|
|
85
|
+
// If only two args were provided (operation, fn), fn is actually in errorTypeOrFn
|
|
86
|
+
const actualFn = fn || errorTypeOrFn;
|
|
87
|
+
try {
|
|
88
|
+
return await actualFn();
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
this.logger.error(`Error during ${operation}:`, error);
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker script for DevTools detection
|
|
3
|
+
* This worker helps detect DevTools by using the debugger statement
|
|
4
|
+
* in a separate thread, which won't block the main UI thread
|
|
5
|
+
*/
|
|
6
|
+
// Set up message handler
|
|
7
|
+
self.onmessage = (e) => {
|
|
8
|
+
if (e.data === "checkDevTools") {
|
|
9
|
+
// Send immediate response (opening heartbeat)
|
|
10
|
+
console.log("DebuggerDetectionWorker: Received checkDevTools message");
|
|
11
|
+
self.postMessage("heartbeatStart");
|
|
12
|
+
// This will pause execution if DevTools is open
|
|
13
|
+
// We use a function to make it harder to bypass
|
|
14
|
+
function triggerDebugger() {
|
|
15
|
+
// eslint-disable-next-line no-debugger
|
|
16
|
+
debugger;
|
|
17
|
+
}
|
|
18
|
+
// Call the function to trigger the debugger
|
|
19
|
+
triggerDebugger();
|
|
20
|
+
// If we reach here without significant delay, DevTools is closed
|
|
21
|
+
self.postMessage("heartbeatEnd");
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility class for detecting DevTools using a Web Worker
|
|
3
|
+
* This approach works across browsers and provides immediate feedback
|
|
4
|
+
*/
|
|
5
|
+
export interface DebuggerDetectorOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Timeout duration in milliseconds
|
|
8
|
+
* If the worker doesn't respond within this time, DevTools is considered open
|
|
9
|
+
*/
|
|
10
|
+
timeoutDuration?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Callback function when DevTools state changes
|
|
13
|
+
*/
|
|
14
|
+
onDevToolsChange?: (isOpen: boolean) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Enable debug mode for troubleshooting
|
|
17
|
+
*/
|
|
18
|
+
debugMode?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class DebuggerDetector {
|
|
21
|
+
private worker;
|
|
22
|
+
private firefoxDetector;
|
|
23
|
+
private isChecking;
|
|
24
|
+
private timeoutId;
|
|
25
|
+
private timeoutDuration;
|
|
26
|
+
private onDevToolsChange;
|
|
27
|
+
private debugMode;
|
|
28
|
+
private isDevToolsOpen;
|
|
29
|
+
/**
|
|
30
|
+
* Create a new DebuggerDetector
|
|
31
|
+
* @param options Configuration options
|
|
32
|
+
*/
|
|
33
|
+
constructor(options?: DebuggerDetectorOptions);
|
|
34
|
+
private initWorker;
|
|
35
|
+
/**
|
|
36
|
+
* Check if DevTools is open
|
|
37
|
+
* @returns Promise that resolves to true if DevTools is open
|
|
38
|
+
*/
|
|
39
|
+
checkDevTools(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Get the current DevTools state
|
|
42
|
+
* @returns True if DevTools is open
|
|
43
|
+
*/
|
|
44
|
+
isOpen(): boolean;
|
|
45
|
+
private terminateWorker;
|
|
46
|
+
/**
|
|
47
|
+
* Clean up resources
|
|
48
|
+
*/
|
|
49
|
+
dispose(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Set debug mode
|
|
52
|
+
* @param enabled Whether debug mode should be enabled
|
|
53
|
+
*/
|
|
54
|
+
setDebugMode(enabled: boolean): void;
|
|
55
|
+
}
|