Skip to main content
Glama

1MCP Server

presetErrorHandler.ts5.7 kB
/** * Standardized error handling utilities for preset operations */ export interface PresetErrorOptions { context?: string; userMessage?: string; exit?: boolean; exitCode?: number; logLevel?: 'error' | 'warn' | 'info' | 'debug'; } /** * Standardized error class for preset operations */ export class PresetError extends Error { public readonly context?: string; public readonly userMessage?: string; public readonly exitCode?: number; public readonly logLevel: 'error' | 'warn' | 'info' | 'debug'; constructor(message: string, options: PresetErrorOptions = {}) { super(message); this.name = 'PresetError'; this.context = options.context; this.userMessage = options.userMessage; this.exitCode = options.exitCode; this.logLevel = options.logLevel || 'error'; } } /** * Error handler with consistent formatting and behavior */ export class PresetErrorHandler { /** * Create and throw a standardized preset error */ static throwError(message: string, options: PresetErrorOptions = {}): never { const error = new PresetError(message, options); throw error; } /** * Handle CLI error with proper exit codes and user-friendly messages */ static handleCliError(error: unknown, context?: string): never { if (error instanceof PresetError) { if (error.userMessage) { console.error(`❌ ${error.userMessage}`); } if (error.context || context) { console.error(`Context: ${error.context || context}`); } process.exit(error.exitCode || 1); } // Handle unknown errors const errorMessage = error instanceof Error ? error.message : 'Unknown error'; console.error(`❌ ${context ? `${context}: ` : ''}${errorMessage}`); process.exit(1); } /** * Create a validation error with consistent formatting */ static validationError(message: string, field?: string, options: PresetErrorOptions = {}): never { const userMessage = field ? `Invalid ${field}: ${message}` : message; this.throwError(message, { ...options, userMessage, context: options.context || 'validation', }); } /** * Create a file operation error */ static fileError(operation: 'read' | 'write' | 'delete', filePath: string, error: unknown): never { const operationPast = operation === 'read' ? 'reading' : operation === 'write' ? 'writing' : 'deleting'; const errorMessage = error instanceof Error ? error.message : 'Unknown error'; this.throwError(`Failed to ${operationPast} file: ${errorMessage}`, { context: `file ${operation}`, userMessage: `Could not ${operationPast} preset file: ${filePath}`, exitCode: 2, }); } /** * Create a parsing error for invalid filter expressions */ static parseError(expression: string, error: unknown, options: PresetErrorOptions = {}): never { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; this.throwError(`Failed to parse filter expression: ${errorMessage}`, { context: 'filter parsing', userMessage: `Invalid filter expression: "${expression}"`, exitCode: 1, ...options, }); } /** * Create a not found error */ static notFoundError(type: 'preset' | 'server' | 'config', name: string, options: PresetErrorOptions = {}): never { this.throwError(`${type} '${name}' not found`, { context: `${type} lookup`, userMessage: `No ${type} found with name: ${name}`, exitCode: 4, ...options, }); } /** * Wrap a function with standardized error handling */ static withErrorHandling<T>(fn: () => T, context?: string, options: PresetErrorOptions = {}): T { try { return fn(); } catch (error) { if (error instanceof PresetError) { throw error; } const errorMessage = error instanceof Error ? error.message : 'Unknown error'; this.throwError(`${context}: ${errorMessage}`, { ...options, context: context || options.context, }); } } /** * Create a user-friendly error message for filter examples */ static createFilterError(expression: string): never { console.error(`❌ Invalid filter expression: ${expression}`); console.error('Examples:'); console.error(' --filter "web,api,database" # OR logic (comma-separated)'); console.error(' --filter "web AND database" # AND logic'); console.error(' --filter "(web OR api) AND database" # Complex expressions'); this.parseError(expression, 'Invalid syntax', { userMessage: `Invalid filter expression: "${expression}"`, context: 'filter parsing', exitCode: 1, }); } /** * Log error with structured format */ static logError(error: unknown, context?: string): void { // Import logger dynamically to avoid circular dependencies import('@src/logger/logger.js') .then(({ default: logger }) => { if (error instanceof PresetError) { logger[error.logLevel](error.message, { context: error.context || context, userMessage: error.userMessage, exitCode: error.exitCode, stack: error.stack, }); } else { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; logger.error('Unexpected error', { context, error: errorMessage, stack: error instanceof Error ? error.stack : undefined, }); } }) .catch(() => { // Fallback to console if logger import fails console.error('Error logging failed:', error); }); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/1mcp-app/agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server