#pragma once #include #include #include #include #include namespace smartbotic::common { // Error codes enum class ErrorCode { // General errors (1xxx) Unknown = 1000, InvalidArgument = 1001, NotFound = 1002, AlreadyExists = 1003, PermissionDenied = 1004, Unauthenticated = 1005, ResourceExhausted = 1006, FailedPrecondition = 1007, Aborted = 1008, Internal = 1009, Unavailable = 1010, Timeout = 1011, // Database errors (2xxx) DatabaseError = 2000, DocumentNotFound = 2001, CollectionNotFound = 2002, VersionConflict = 2003, ValidationError = 2004, QueryError = 2005, // Auth errors (3xxx) AuthError = 3000, InvalidCredentials = 3001, TokenExpired = 3002, TokenInvalid = 3003, SessionExpired = 3004, InsufficientPermissions = 3005, // Workflow errors (4xxx) WorkflowError = 4000, WorkflowNotFound = 4001, WorkflowInactive = 4002, NodeNotFound = 4003, NodeExecutionFailed = 4004, ExecutionTimeout = 4005, ExecutionCancelled = 4006, CircuitBreakerOpen = 4007, // Runner errors (5xxx) RunnerError = 5000, RunnerUnavailable = 5001, NoRunnersAvailable = 5002, ScriptError = 5003, ScriptTimeout = 5004, }; // Convert error code to HTTP status int errorCodeToHttpStatus(ErrorCode code); // Error class with detailed information class Error { public: Error(ErrorCode code, std::string message); Error(ErrorCode code, std::string message, nlohmann::json details); ErrorCode code() const { return code_; } const std::string& message() const { return message_; } const nlohmann::json& details() const { return details_; } nlohmann::json toJson() const; std::string toString() const; static Error fromException(const std::exception& e); private: ErrorCode code_; std::string message_; nlohmann::json details_; }; // Exception class that wraps Error class SmartBoticException : public std::runtime_error { public: explicit SmartBoticException(Error error); const Error& error() const { return error_; } ErrorCode code() const { return error_.code(); } private: Error error_; }; // Result type for operations that can fail template class Result { public: Result(T value) : data_(std::move(value)) {} Result(Error error) : data_(std::move(error)) {} bool ok() const { return std::holds_alternative(data_); } bool failed() const { return !ok(); } const T& value() const { return std::get(data_); } T& value() { return std::get(data_); } const Error& error() const { return std::get(data_); } // Throw if error const T& valueOrThrow() const { if (failed()) { throw SmartBoticException(error()); } return value(); } T& valueOrThrow() { if (failed()) { throw SmartBoticException(error()); } return value(); } private: std::variant data_; }; // Void result specialization template<> class Result { public: Result() : error_(std::nullopt) {} Result(Error error) : error_(std::move(error)) {} bool ok() const { return !error_.has_value(); } bool failed() const { return error_.has_value(); } const Error& error() const { return *error_; } void throwIfFailed() const { if (failed()) { throw SmartBoticException(*error_); } } private: std::optional error_; }; } // namespace smartbotic::common