import { ErrorInfo, ErrorCategory, ErrorHandlingStrategy, ErrorReportingConfig } from '../Types'; import { Logger } from '../Logger'; // ErrorCategory, ErrorHandlingStrategy, ErrorReportingConfig class NetworkError extends Error { constructor(message: string) { super(message); this.name = 'NetworkError'; } } export class ErrorHandler { private static instance: ErrorHandler; private logger: Logger; private strategies: Map = new Map(); private reportingConfig: ErrorReportingConfig | null = null; private constructor() { this.logger = Logger.getInstance(); } /** * Get the singleton instance of ErrorHandler */ static getInstance(): ErrorHandler { if (!ErrorHandler.instance) { ErrorHandler.instance = new ErrorHandler(); } return ErrorHandler.instance; } /** * Handle an error with optional context * @param error The error object * @param context Optional context information */ handleError(error: Error, context?: string): void { const errorInfo: ErrorInfo = { code: error.name, message: error.message, stack: error.stack, context: context }; this.logger.error(`Error occurred: ${error.message}`, context, errorInfo); const category = this.categorizeError(error); const strategy = this.strategies.get(category); if (strategy) { strategy(error, errorInfo); } this.reportError(errorInfo); } /** * Handle an asynchronous error * @param promise The promise that might throw an error * @param context Optional context information */ async handleAsyncError(promise: Promise, context?: string): Promise { try { return await promise; } catch (error) { this.handleError(error as Error, context); throw error; } } /** * Register global error handlers */ registerGlobalErrorHandlers(): void { window.addEventListener('error', (event: ErrorEvent) => { this.handleError(event.error, 'Global Error'); }); window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => { this.handleError(event.reason, 'Unhandled Promise Rejection'); }); } /** * Set a handling strategy for a specific error category * @param category The error category * @param strategy The handling strategy function */ setStrategy(category: ErrorCategory, strategy: ErrorHandlingStrategy): void { this.strategies.set(category, strategy); } /** * Categorize an error * @param error The error to categorize */ private categorizeError(error: Error): ErrorCategory { // Implement your categorization logic here // This is a simple example; you might want to use more sophisticated logic if (error instanceof TypeError) { return 'TYPE_ERROR'; } else if (error instanceof ReferenceError) { return 'REFERENCE_ERROR'; } else if (error instanceof NetworkError) { return 'NETWORK_ERROR'; } return 'UNKNOWN_ERROR'; } /** * Configure error reporting * @param config The error reporting configuration */ configureErrorReporting(config: ErrorReportingConfig): void { this.reportingConfig = config; } /** * Report an error based on the current configuration * @param errorInfo The error information to report */ private reportError(errorInfo: ErrorInfo): void { if (this.reportingConfig && this.reportingConfig.endpoint) { // Implement the logic to send the error to the configured endpoint fetch(this.reportingConfig.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(errorInfo) }).catch(error => { this.logger.error('Failed to report error', 'ErrorReporting', error); }); } } /** * Attempt to recover from an error * @param error The error to recover from * @returns A boolean indicating whether recovery was successful */ attemptErrorRecovery(error: Error): boolean { // Implement your error recovery logic here // This is a placeholder implementation this.logger.info(`Attempting to recover from error: ${error.message}`, 'ErrorRecovery'); return false; } }