@casoon/auditmysite
Version:
Professional website analysis suite with robust accessibility testing, Core Web Vitals performance monitoring, SEO analysis, and content optimization insights. Features isolated browser contexts, retry mechanisms, and comprehensive API endpoints for profe
237 lines • 8.89 kB
JavaScript
;
/**
* 🚨 Standardized Error Handling
*
* Common error types and handling utilities for the audit system.
* Provides consistent error categorization and recovery strategies.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorHandler = exports.ConfigurationError = exports.PermissionError = exports.TimeoutError = exports.ResourceError = exports.ValidationError = exports.ParsingError = exports.BrowserError = exports.NetworkError = exports.ErrorCategory = exports.AuditError = void 0;
exports.withErrorHandling = withErrorHandling;
/**
* Base class for all audit-related errors
*/
class AuditError extends Error {
constructor(message, code, category, recoverable = false, context) {
super(message);
this.name = this.constructor.name;
this.code = code;
this.category = category;
this.recoverable = recoverable;
this.context = context;
// Maintains proper stack trace for where error was thrown
Error.captureStackTrace(this, this.constructor);
}
}
exports.AuditError = AuditError;
/**
* Error categories for better error handling
*/
var ErrorCategory;
(function (ErrorCategory) {
ErrorCategory["NETWORK"] = "NETWORK";
ErrorCategory["BROWSER"] = "BROWSER";
ErrorCategory["PARSING"] = "PARSING";
ErrorCategory["VALIDATION"] = "VALIDATION";
ErrorCategory["RESOURCE"] = "RESOURCE";
ErrorCategory["TIMEOUT"] = "TIMEOUT";
ErrorCategory["PERMISSION"] = "PERMISSION";
ErrorCategory["CONFIGURATION"] = "CONFIGURATION";
ErrorCategory["UNKNOWN"] = "UNKNOWN";
})(ErrorCategory || (exports.ErrorCategory = ErrorCategory = {}));
/**
* Network-related errors (connection, DNS, HTTP)
*/
class NetworkError extends AuditError {
constructor(message, url, statusCode) {
super(message, 'ERR_NETWORK', ErrorCategory.NETWORK, true, // Retryable
{ url, statusCode });
}
}
exports.NetworkError = NetworkError;
/**
* Browser/Playwright-related errors
*/
class BrowserError extends AuditError {
constructor(message, browserType, recoverable = false) {
super(message, 'ERR_BROWSER', ErrorCategory.BROWSER, recoverable, { browserType });
}
}
exports.BrowserError = BrowserError;
/**
* Sitemap/XML parsing errors
*/
class ParsingError extends AuditError {
constructor(message, source) {
super(message, 'ERR_PARSING', ErrorCategory.PARSING, false, { source });
}
}
exports.ParsingError = ParsingError;
/**
* Data validation errors
*/
class ValidationError extends AuditError {
constructor(message, field, value) {
super(message, 'ERR_VALIDATION', ErrorCategory.VALIDATION, false, { field, value });
}
}
exports.ValidationError = ValidationError;
/**
* System resource errors (memory, CPU, disk)
*/
class ResourceError extends AuditError {
constructor(message, resourceType, limit) {
super(message, 'ERR_RESOURCE', ErrorCategory.RESOURCE, false, { resourceType, limit });
}
}
exports.ResourceError = ResourceError;
/**
* Timeout errors
*/
class TimeoutError extends AuditError {
constructor(message, operation, timeoutMs) {
super(message, 'ERR_TIMEOUT', ErrorCategory.TIMEOUT, true, // Retryable
{ operation, timeoutMs });
}
}
exports.TimeoutError = TimeoutError;
/**
* Permission/access errors
*/
class PermissionError extends AuditError {
constructor(message, resource) {
super(message, 'ERR_PERMISSION', ErrorCategory.PERMISSION, false, { resource });
}
}
exports.PermissionError = PermissionError;
/**
* Configuration errors
*/
class ConfigurationError extends AuditError {
constructor(message, configKey, providedValue) {
super(message, 'ERR_CONFIGURATION', ErrorCategory.CONFIGURATION, false, { configKey, providedValue });
}
}
exports.ConfigurationError = ConfigurationError;
/**
* Error handler utility
*/
class ErrorHandler {
/**
* Categorize unknown errors into known types
*/
static categorize(error) {
if (error instanceof AuditError) {
return error;
}
const errorMessage = error instanceof Error ? error.message : String(error);
const lowerMessage = errorMessage.toLowerCase();
// Network errors
if (lowerMessage.includes('network') ||
lowerMessage.includes('econnrefused') ||
lowerMessage.includes('enotfound') ||
lowerMessage.includes('timeout') ||
lowerMessage.includes('fetch failed')) {
return new NetworkError(errorMessage);
}
// Browser errors
if (lowerMessage.includes('browser') ||
lowerMessage.includes('playwright') ||
lowerMessage.includes('page closed') ||
lowerMessage.includes('context') ||
lowerMessage.includes('target closed')) {
return new BrowserError(errorMessage);
}
// Parsing errors
if (lowerMessage.includes('parse') ||
lowerMessage.includes('xml') ||
lowerMessage.includes('json') ||
lowerMessage.includes('sitemap')) {
return new ParsingError(errorMessage);
}
// Validation errors
if (lowerMessage.includes('invalid') ||
lowerMessage.includes('validation') ||
lowerMessage.includes('required')) {
return new ValidationError(errorMessage);
}
// Resource errors
if (lowerMessage.includes('memory') ||
lowerMessage.includes('heap') ||
lowerMessage.includes('out of') ||
lowerMessage.includes('resource')) {
return new ResourceError(errorMessage);
}
// Timeout errors
if (lowerMessage.includes('timeout')) {
return new TimeoutError(errorMessage);
}
// Permission errors
if (lowerMessage.includes('permission') ||
lowerMessage.includes('eacces') ||
lowerMessage.includes('forbidden')) {
return new PermissionError(errorMessage);
}
// Unknown error
return new AuditError(errorMessage, 'ERR_UNKNOWN', ErrorCategory.UNKNOWN, false);
}
/**
* Get user-friendly error message with recovery suggestions
*/
static getUserMessage(error) {
const messages = {
[ErrorCategory.NETWORK]: `Network error: ${error.message}. Please check your internet connection and try again.`,
[ErrorCategory.BROWSER]: `Browser error: ${error.message}. The browser may have crashed or closed unexpectedly.`,
[ErrorCategory.PARSING]: `Parsing error: ${error.message}. The sitemap or data format may be invalid.`,
[ErrorCategory.VALIDATION]: `Validation error: ${error.message}. Please check your input parameters.`,
[ErrorCategory.RESOURCE]: `Resource error: ${error.message}. The system may be running out of memory or resources.`,
[ErrorCategory.TIMEOUT]: `Timeout error: ${error.message}. The operation took too long. Try increasing timeout or reducing load.`,
[ErrorCategory.PERMISSION]: `Permission error: ${error.message}. Check file/folder permissions.`,
[ErrorCategory.CONFIGURATION]: `Configuration error: ${error.message}. Please review your configuration settings.`,
[ErrorCategory.UNKNOWN]: `Unexpected error: ${error.message}`
};
return messages[error.category] || error.message;
}
/**
* Determine if error should be retried
*/
static shouldRetry(error, attemptNumber, maxRetries) {
if (attemptNumber >= maxRetries) {
return false;
}
return error.recoverable;
}
/**
* Calculate backoff delay for retries
*/
static getRetryDelay(attemptNumber, baseDelay = 1000) {
// Exponential backoff: 1s, 2s, 4s, 8s, ...
return Math.min(baseDelay * Math.pow(2, attemptNumber - 1), 30000); // Max 30s
}
}
exports.ErrorHandler = ErrorHandler;
/**
* Async wrapper with automatic error categorization and retry logic
*/
async function withErrorHandling(operation, options = {}) {
const { maxRetries = 3, baseDelay = 1000, onRetry } = options;
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
}
catch (error) {
lastError = ErrorHandler.categorize(error);
if (!ErrorHandler.shouldRetry(lastError, attempt, maxRetries)) {
throw lastError;
}
if (onRetry) {
onRetry(lastError, attempt);
}
const delay = ErrorHandler.getRetryDelay(attempt, baseDelay);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
//# sourceMappingURL=audit-errors.js.map