UNPKG

@tryloop/oats

Version:

🌾 OATS - OpenAPI TypeScript Sync. The missing link between your OpenAPI specs and TypeScript applications. Automatically watch, generate, and sync TypeScript clients from your API definitions.

306 lines • 8.33 kB
/** * Custom Error Classes for OATS * * This module defines a hierarchy of error classes for better error handling * and user-friendly error messages throughout the application. * * @module @oatsjs/errors */ /** * Base error class for all OATS errors */ export class OatsError extends Error { /** * Error code for programmatic handling */ code; /** * Additional context about the error */ context; /** * Whether this error is recoverable */ recoverable; /** * Timestamp when the error occurred */ timestamp; constructor(message, code, recoverable = false, context) { super(message); this.name = this.constructor.name; this.code = code; this.recoverable = recoverable; this.context = context; this.timestamp = new Date(); // Maintains proper stack trace for where our error was thrown if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } } /** * Returns a user-friendly error message */ getUserMessage() { return this.message; } /** * Returns error details for logging */ getDetails() { return { name: this.name, code: this.code, message: this.message, recoverable: this.recoverable, context: this.context, timestamp: this.timestamp, stack: this.stack, }; } } /** * Configuration-related errors */ export class ConfigError extends OatsError { constructor(message, context) { super(message, 'CONFIG_ERROR', false, context); } } /** * Configuration validation error */ export class ConfigValidationError extends ConfigError { validationErrors; constructor(message, validationErrors, context) { super(message, context); this.code = 'CONFIG_VALIDATION_ERROR'; this.validationErrors = validationErrors; } getUserMessage() { const errors = this.validationErrors .map((err) => ` - ${err.path}: ${err.message}`) .join('\n'); return `${this.message}\n${errors}`; } } /** * Service-related errors */ export class ServiceError extends OatsError { service; constructor(message, service, code = 'SERVICE_ERROR', recoverable = true, context) { super(message, code, recoverable, context); this.service = service; } } /** * Service start error */ export class ServiceStartError extends ServiceError { exitCode; stderr; constructor(service, message, exitCode, stderr, context) { super(message, service, 'SERVICE_START_ERROR', true, context); this.exitCode = exitCode; this.stderr = stderr; } getUserMessage() { let message = `Failed to start ${this.service}: ${this.message}`; if (this.stderr) { message += `\nError output: ${this.stderr}`; } return message; } } /** * File system errors */ export class FileSystemError extends OatsError { path; operation; constructor(message, path, operation, recoverable = false, context) { super(message, 'FILESYSTEM_ERROR', recoverable, context); this.path = path; this.operation = operation; } getUserMessage() { return `File system error during ${this.operation} on ${this.path}: ${this.message}`; } } /** * API specification errors */ export class ApiSpecError extends OatsError { specPath; constructor(message, specPath, recoverable = true, context) { super(message, 'API_SPEC_ERROR', recoverable, context); this.specPath = specPath; } } /** * Generator errors */ export class GeneratorError extends OatsError { generator; phase; constructor(message, generator, phase, recoverable = true, context) { super(message, 'GENERATOR_ERROR', recoverable, context); this.generator = generator; this.phase = phase; } getUserMessage() { return `Generator error during ${this.phase} phase (${this.generator}): ${this.message}`; } } /** * Network-related errors */ export class NetworkError extends OatsError { url; statusCode; constructor(message, url, statusCode, context) { super(message, 'NETWORK_ERROR', true, context); this.url = url; this.statusCode = statusCode; } } /** * Dependency errors */ export class DependencyError extends OatsError { dependency; requiredVersion; installedVersion; constructor(message, dependency, requiredVersion, installedVersion, context) { super(message, 'DEPENDENCY_ERROR', false, context); this.dependency = dependency; this.requiredVersion = requiredVersion; this.installedVersion = installedVersion; } getUserMessage() { let message = `Dependency error: ${this.dependency} - ${this.message}`; if (this.requiredVersion) { message += `\nRequired: ${this.requiredVersion}`; } if (this.installedVersion) { message += `\nInstalled: ${this.installedVersion}`; } return message; } } /** * Command execution errors */ export class CommandError extends OatsError { command; exitCode; stdout; stderr; constructor(message, command, exitCode, stdout, stderr, context) { super(message, 'COMMAND_ERROR', true, context); this.command = command; this.exitCode = exitCode; this.stdout = stdout; this.stderr = stderr; } getUserMessage() { let message = `Command failed: ${this.command}\n`; message += `Exit code: ${this.exitCode}\n`; if (this.stderr) { message += `Error: ${this.stderr}`; } return message; } } /** * Timeout errors */ export class TimeoutError extends OatsError { operation; timeoutMs; constructor(operation, timeoutMs, context) { super(`Operation '${operation}' timed out after ${timeoutMs}ms`, 'TIMEOUT_ERROR', true, context); this.operation = operation; this.timeoutMs = timeoutMs; } } /** * User cancellation error */ export class UserCancelledError extends OatsError { constructor(operation, context) { super(`User cancelled: ${operation}`, 'USER_CANCELLED', false, context); } } /** * Creates an error with a suggestion for fixing it */ export class ErrorWithSuggestion extends OatsError { suggestion; constructor(message, code, suggestion, recoverable = false, context) { super(message, code, recoverable, context); this.suggestion = suggestion; } getUserMessage() { return `${this.message}\n\nšŸ’” Suggestion: ${this.suggestion}`; } } /** * Error handler utility */ export class ErrorHandler { /** * Handles an error and returns a user-friendly message */ static handle(error) { if (error instanceof OatsError) { return error.getUserMessage(); } if (error instanceof Error) { return `Unexpected error: ${error.message}`; } return 'An unknown error occurred'; } /** * Logs error details for debugging */ static log(error, logger) { const log = logger || console.error; if (error instanceof OatsError) { log(JSON.stringify(error.getDetails(), null, 2)); } else if (error instanceof Error) { log(error.stack || error.message); } else { log(String(error)); } } /** * Determines if an error is recoverable */ static isRecoverable(error) { if (error instanceof OatsError) { return error.recoverable; } return false; } /** * Wraps an async function with error handling */ static async wrap(fn, context) { try { return await fn(); } catch (error) { const message = this.handle(error); console.error(`Error in ${context}: ${message}`); if (!this.isRecoverable(error)) { throw error; } return undefined; } } } //# sourceMappingURL=index.js.map