/**
 * Server Adapter Error Classes
 *
 * Typed error hierarchy for server adapters following NeuroLink error patterns.
 */
import { ErrorCategory, ErrorSeverity, ServerAdapterErrorCode, } from "../types/index.js";
/**
 * Base error class for server adapter errors
 */
export class ServerAdapterError extends Error {
    code;
    category;
    severity;
    retryable;
    retryAfterMs;
    requestId;
    path;
    method;
    details;
    cause;
    constructor(message, code, context = {}) {
        super(message);
        this.name = "ServerAdapterError";
        this.code = code;
        this.category = context.category ?? ErrorCategory.EXECUTION;
        this.severity = context.severity ?? ErrorSeverity.MEDIUM;
        this.retryable = context.retryable ?? false;
        this.retryAfterMs = context.retryAfterMs;
        this.requestId = context.requestId;
        this.path = context.path;
        this.method = context.method;
        this.details = context.details;
        this.cause = context.cause;
        // Maintain proper stack trace
        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, ServerAdapterError);
        }
    }
    /**
     * Convert to JSON for API responses
     */
    toJSON() {
        return {
            error: {
                code: this.code,
                message: this.message,
                category: this.category,
                requestId: this.requestId,
                details: this.details,
                retryAfter: this.retryAfterMs
                    ? Math.ceil(this.retryAfterMs / 1000)
                    : undefined,
            },
        };
    }
    /**
     * Get HTTP status code for this error
     */
    getHttpStatus() {
        switch (this.code) {
            case ServerAdapterErrorCode.VALIDATION_ERROR:
            case ServerAdapterErrorCode.SCHEMA_ERROR:
            case ServerAdapterErrorCode.INVALID_CONFIG:
            case ServerAdapterErrorCode.INVALID_ROUTE:
                return 400;
            case ServerAdapterErrorCode.AUTH_REQUIRED:
            case ServerAdapterErrorCode.AUTH_INVALID:
                return 401;
            case ServerAdapterErrorCode.FORBIDDEN:
                return 403;
            case ServerAdapterErrorCode.ROUTE_NOT_FOUND:
                return 404;
            case ServerAdapterErrorCode.RATE_LIMIT_EXCEEDED:
                return 429;
            case ServerAdapterErrorCode.TIMEOUT:
                return 408;
            case ServerAdapterErrorCode.STREAM_ABORTED:
                return 499;
            default:
                return 500;
        }
    }
}
/**
 * Configuration error
 */
export class ConfigurationError extends ServerAdapterError {
    constructor(message, details, cause) {
        super(message, ServerAdapterErrorCode.INVALID_CONFIG, {
            category: ErrorCategory.CONFIG,
            severity: ErrorSeverity.HIGH,
            retryable: false,
            details,
            cause,
        });
        this.name = "ConfigurationError";
    }
}
/**
 * Route conflict error
 */
export class RouteConflictError extends ServerAdapterError {
    constructor(path, method, existingRoute) {
        super(`Route conflict: ${method} ${path} conflicts with existing route${existingRoute ? `: ${existingRoute}` : ""}`, ServerAdapterErrorCode.ROUTE_CONFLICT, {
            category: ErrorCategory.CONFIG,
            severity: ErrorSeverity.HIGH,
            retryable: false,
            path,
            method,
            details: { existingRoute },
        });
        this.name = "RouteConflictError";
    }
}
/**
 * Route not found error
 */
export class RouteNotFoundError extends ServerAdapterError {
    constructor(path, method, requestId) {
        super(`Route not found: ${method} ${path}`, ServerAdapterErrorCode.ROUTE_NOT_FOUND, {
            category: ErrorCategory.VALIDATION,
            severity: ErrorSeverity.LOW,
            retryable: false,
            path,
            method,
            requestId,
        });
        this.name = "RouteNotFoundError";
    }
}
/**
 * Validation error
 */
export class ValidationError extends ServerAdapterError {
    errors;
    constructor(errors, requestId) {
        super(`Validation failed: ${errors.map((e) => e.message).join(", ")}`, ServerAdapterErrorCode.VALIDATION_ERROR, {
            category: ErrorCategory.VALIDATION,
            severity: ErrorSeverity.LOW,
            retryable: false,
            requestId,
            details: { errors },
        });
        this.name = "ValidationError";
        this.errors = errors;
    }
}
/**
 * Authentication error
 */
export class AuthenticationError extends ServerAdapterError {
    constructor(message = "Authentication required", requestId) {
        super(message, ServerAdapterErrorCode.AUTH_REQUIRED, {
            category: ErrorCategory.AUTHENTICATION,
            severity: ErrorSeverity.MEDIUM,
            retryable: false,
            requestId,
        });
        this.name = "AuthenticationError";
    }
}
/**
 * Invalid authentication error
 */
export class InvalidAuthenticationError extends ServerAdapterError {
    constructor(message = "Invalid authentication credentials", requestId) {
        super(message, ServerAdapterErrorCode.AUTH_INVALID, {
            category: ErrorCategory.AUTHENTICATION,
            severity: ErrorSeverity.MEDIUM,
            retryable: false,
            requestId,
        });
        this.name = "InvalidAuthenticationError";
    }
}
/**
 * Authorization error
 */
export class AuthorizationError extends ServerAdapterError {
    constructor(message = "Access forbidden", requestId, requiredPermissions) {
        super(message, ServerAdapterErrorCode.FORBIDDEN, {
            category: ErrorCategory.AUTHORIZATION,
            severity: ErrorSeverity.MEDIUM,
            retryable: false,
            requestId,
            details: { requiredPermissions },
        });
        this.name = "AuthorizationError";
    }
}
/**
 * Rate limit error
 */
export class RateLimitError extends ServerAdapterError {
    constructor(retryAfterMs, message, requestId) {
        super(message ?? "Too many requests, please try again later", ServerAdapterErrorCode.RATE_LIMIT_EXCEEDED, {
            category: ErrorCategory.RATE_LIMIT,
            severity: ErrorSeverity.MEDIUM,
            retryable: true,
            retryAfterMs,
            requestId,
        });
        this.name = "RateLimitError";
    }
}
/**
 * Timeout error
 */
export class TimeoutError extends ServerAdapterError {
    constructor(timeoutMs, operation, requestId) {
        super(`Operation timed out after ${timeoutMs}ms${operation ? `: ${operation}` : ""}`, ServerAdapterErrorCode.TIMEOUT, {
            category: ErrorCategory.EXECUTION,
            severity: ErrorSeverity.MEDIUM,
            retryable: true,
            requestId,
            details: { timeoutMs, operation },
        });
        this.name = "TimeoutError";
    }
}
/**
 * Handler error
 */
export class HandlerError extends ServerAdapterError {
    constructor(message, cause, requestId, path, method) {
        super(message, ServerAdapterErrorCode.HANDLER_ERROR, {
            category: ErrorCategory.EXECUTION,
            severity: ErrorSeverity.HIGH,
            retryable: false,
            cause,
            requestId,
            path,
            method,
        });
        this.name = "HandlerError";
    }
}
/**
 * Streaming error
 */
export class StreamingError extends ServerAdapterError {
    constructor(message, cause, requestId) {
        super(message, ServerAdapterErrorCode.STREAM_ERROR, {
            category: ErrorCategory.STREAMING,
            severity: ErrorSeverity.MEDIUM,
            retryable: false,
            cause,
            requestId,
        });
        this.name = "StreamingError";
    }
}
/**
 * Stream aborted error
 */
export class StreamAbortedError extends ServerAdapterError {
    constructor(reason, requestId) {
        super(`Stream aborted${reason ? `: ${reason}` : ""}`, ServerAdapterErrorCode.STREAM_ABORTED, {
            category: ErrorCategory.STREAMING,
            severity: ErrorSeverity.LOW,
            retryable: false,
            requestId,
            details: { reason },
        });
        this.name = "StreamAbortedError";
    }
}
/**
 * WebSocket error
 */
export class WebSocketError extends ServerAdapterError {
    constructor(message, cause, connectionId) {
        super(message, ServerAdapterErrorCode.WEBSOCKET_ERROR, {
            category: ErrorCategory.WEBSOCKET,
            severity: ErrorSeverity.MEDIUM,
            retryable: true,
            cause,
            details: { connectionId },
        });
        this.name = "WebSocketError";
    }
}
/**
 * WebSocket connection failed error
 */
export class WebSocketConnectionError extends ServerAdapterError {
    constructor(message = "WebSocket connection failed", cause) {
        super(message, ServerAdapterErrorCode.WEBSOCKET_CONNECTION_FAILED, {
            category: ErrorCategory.WEBSOCKET,
            severity: ErrorSeverity.HIGH,
            retryable: true,
            cause,
        });
        this.name = "WebSocketConnectionError";
    }
}
/**
 * Server start error
 */
export class ServerStartError extends ServerAdapterError {
    constructor(message, cause, port, host) {
        super(message, ServerAdapterErrorCode.START_FAILED, {
            category: ErrorCategory.CONFIG,
            severity: ErrorSeverity.CRITICAL,
            retryable: true,
            cause,
            details: { port, host },
        });
        this.name = "ServerStartError";
    }
}
/**
 * Server stop error
 */
export class ServerStopError extends ServerAdapterError {
    constructor(message, cause) {
        super(message, ServerAdapterErrorCode.STOP_FAILED, {
            category: ErrorCategory.EXECUTION,
            severity: ErrorSeverity.HIGH,
            retryable: false,
            cause,
        });
        this.name = "ServerStopError";
    }
}
/**
 * Already running error
 */
export class AlreadyRunningError extends ServerAdapterError {
    constructor(port, host) {
        super(`Server is already running${port && host ? ` on ${host}:${port}` : ""}`, ServerAdapterErrorCode.ALREADY_RUNNING, {
            category: ErrorCategory.CONFIG,
            severity: ErrorSeverity.LOW,
            retryable: false,
            details: { port, host },
        });
        this.name = "AlreadyRunningError";
    }
}
/**
 * Not running error
 */
export class NotRunningError extends ServerAdapterError {
    constructor() {
        super("Server is not running", ServerAdapterErrorCode.NOT_RUNNING, {
            category: ErrorCategory.CONFIG,
            severity: ErrorSeverity.LOW,
            retryable: false,
        });
        this.name = "NotRunningError";
    }
}
/**
 * Shutdown timeout error
 * Thrown when graceful shutdown exceeds the configured timeout
 */
export class ShutdownTimeoutError extends ServerAdapterError {
    timeoutMs;
    remainingConnections;
    constructor(timeoutMs, remainingConnections) {
        super(`Shutdown timed out after ${timeoutMs}ms with ${remainingConnections} active connection(s)`, ServerAdapterErrorCode.STOP_FAILED, {
            category: ErrorCategory.EXECUTION,
            severity: ErrorSeverity.HIGH,
            retryable: false,
            details: { timeoutMs, remainingConnections },
        });
        this.name = "ShutdownTimeoutError";
        this.timeoutMs = timeoutMs;
        this.remainingConnections = remainingConnections;
    }
}
/**
 * Drain timeout error
 * Thrown when connection draining exceeds the configured timeout
 */
export class DrainTimeoutError extends ServerAdapterError {
    timeoutMs;
    remainingConnections;
    constructor(timeoutMs, remainingConnections) {
        super(`Connection drain timed out after ${timeoutMs}ms with ${remainingConnections} active connection(s)`, ServerAdapterErrorCode.STOP_FAILED, {
            category: ErrorCategory.EXECUTION,
            severity: ErrorSeverity.MEDIUM,
            retryable: false,
            details: { timeoutMs, remainingConnections },
        });
        this.name = "DrainTimeoutError";
        this.timeoutMs = timeoutMs;
        this.remainingConnections = remainingConnections;
    }
}
/**
 * Invalid lifecycle state error
 * Thrown when attempting an operation in an invalid lifecycle state
 */
export class InvalidLifecycleStateError extends ServerAdapterError {
    currentState;
    expectedStates;
    operation;
    constructor(operation, currentState, expectedStates) {
        super(`Cannot ${operation}: server is in '${currentState}' state, expected one of [${expectedStates.join(", ")}]`, ServerAdapterErrorCode.STOP_FAILED, {
            category: ErrorCategory.CONFIG,
            severity: ErrorSeverity.MEDIUM,
            retryable: false,
            details: { operation, currentState, expectedStates },
        });
        this.name = "InvalidLifecycleStateError";
        this.currentState = currentState;
        this.expectedStates = expectedStates;
        this.operation = operation;
    }
}
/**
 * Missing dependency error
 */
export class MissingDependencyError extends ServerAdapterError {
    constructor(dependency, framework, installCommand) {
        super(`Missing dependency '${dependency}' for ${framework} adapter. ${installCommand ? `Install with: ${installCommand}` : ""}`, ServerAdapterErrorCode.MISSING_DEPENDENCY, {
            category: ErrorCategory.CONFIG,
            severity: ErrorSeverity.CRITICAL,
            retryable: false,
            details: { dependency, framework, installCommand },
        });
        this.name = "MissingDependencyError";
    }
}
/**
 * Error recovery strategies
 */
export const ErrorRecoveryStrategies = {
    [ErrorCategory.CONFIG]: {
        strategy: "fail",
        maxRetries: 0,
        baseDelayMs: 0,
    },
    [ErrorCategory.VALIDATION]: {
        strategy: "fail",
        maxRetries: 0,
        baseDelayMs: 0,
    },
    [ErrorCategory.EXECUTION]: {
        strategy: "retry",
        maxRetries: 3,
        baseDelayMs: 1000,
    },
    [ErrorCategory.EXTERNAL]: {
        strategy: "exponentialBackoff",
        maxRetries: 5,
        baseDelayMs: 1000,
    },
    [ErrorCategory.RATE_LIMIT]: {
        strategy: "exponentialBackoff",
        maxRetries: 3,
        baseDelayMs: 5000,
    },
    [ErrorCategory.AUTHENTICATION]: {
        strategy: "fail",
        maxRetries: 0,
        baseDelayMs: 0,
    },
    [ErrorCategory.AUTHORIZATION]: {
        strategy: "fail",
        maxRetries: 0,
        baseDelayMs: 0,
    },
    [ErrorCategory.STREAMING]: {
        strategy: "retry",
        maxRetries: 2,
        baseDelayMs: 500,
    },
    [ErrorCategory.WEBSOCKET]: {
        strategy: "exponentialBackoff",
        maxRetries: 5,
        baseDelayMs: 1000,
    },
};
/**
 * Helper to wrap errors as ServerAdapterError
 */
export function wrapError(error, requestId, path, method) {
    if (error instanceof ServerAdapterError) {
        return error;
    }
    const message = error instanceof Error ? error.message : String(error);
    const cause = error instanceof Error ? error : undefined;
    return new HandlerError(message, cause, requestId, path, method);
}
//# sourceMappingURL=errors.js.map