prompt-plus-plus-mcp
Version:
Advanced MCP server with 44+ metaprompt strategies including AI Core Principles, Vibe Coding Rules, and metadata-driven intelligent selection
115 lines • 4.03 kB
JavaScript
import { BaseError, ErrorCode, ErrorSeverity, isPromptPlusError } from './errors.js';
import { logger } from './logger.js';
export class ErrorHandler {
metrics = {
total: 0,
byCode: {},
bySeverity: {}
};
recoveryStrategies = new Map();
suppressInProduction = false;
customLogger;
constructor(customLogger) {
this.customLogger = customLogger || logger;
}
setSuppressInProduction(suppress) {
this.suppressInProduction = suppress;
}
registerRecovery(code, strategy) {
this.recoveryStrategies.set(code, strategy);
}
async handle(error) {
const promptPlusError = this.normalizeError(error);
// Update metrics
this.updateMetrics(promptPlusError);
// Log error based on severity
this.logError(promptPlusError);
// Attempt recovery if available
const recovery = this.recoveryStrategies.get(promptPlusError.code);
if (recovery) {
try {
return await recovery(promptPlusError);
}
catch (recoveryError) {
this.customLogger.error('Recovery strategy failed', {
originalError: promptPlusError.code,
recoveryError: recoveryError instanceof Error ? recoveryError.message : String(recoveryError)
});
}
}
// In production, suppress errors if configured
if (this.suppressInProduction && process.env.NODE_ENV === 'production') {
this.customLogger.info('Error suppressed in production', {
code: promptPlusError.code
});
return undefined;
}
// Re-throw for upstream handling
throw promptPlusError;
}
normalizeError(error) {
if (isPromptPlusError(error)) {
return error;
}
if (error instanceof Error) {
return new BaseError(error.message, ErrorCode.UNKNOWN_ERROR, {
originalError: error.name,
stack: error.stack
}, error);
}
return new BaseError(String(error), ErrorCode.UNKNOWN_ERROR, { originalValue: error });
}
updateMetrics(error) {
this.metrics.total++;
this.metrics.byCode[error.code] = (this.metrics.byCode[error.code] || 0) + 1;
this.metrics.bySeverity[error.severity] = (this.metrics.bySeverity[error.severity] || 0) + 1;
this.metrics.lastError = error;
}
logError(error) {
const logData = {
code: error.code,
severity: error.severity,
context: error.context,
timestamp: error.timestamp.toISOString()
};
switch (error.severity) {
case ErrorSeverity.CRITICAL:
this.customLogger.error(`CRITICAL: ${error.message}`, logData);
break;
case ErrorSeverity.HIGH:
this.customLogger.error(error.message, logData);
break;
case ErrorSeverity.MEDIUM:
this.customLogger.warn(error.message, logData);
break;
case ErrorSeverity.LOW:
this.customLogger.info(error.message, logData);
break;
}
}
getMetrics() {
return { ...this.metrics };
}
resetMetrics() {
this.metrics = {
total: 0,
byCode: {},
bySeverity: {}
};
}
}
// Global error handler instance
export const errorHandler = new ErrorHandler();
// Convenience method for handling errors in routes
export async function handleError(operation, context) {
try {
return await operation();
}
catch (error) {
const baseError = isPromptPlusError(error)
? error
: new BaseError(error instanceof Error ? error.message : String(error), ErrorCode.UNKNOWN_ERROR, context);
return errorHandler.handle(baseError);
}
}
//# sourceMappingURL=error-handler.js.map