defmodule Argos.Command.Error do @moduledoc """ Excepciones estructuradas para errores de comandos. Proporciona tipos de error estructurados en lugar de strings simples, facilitando el manejo y logging de errores. """ defexception [:message, :code, :reason, :command, :context] @type t :: %__MODULE__{ message: String.t(), code: non_neg_integer(), reason: atom() | String.t(), command: String.t() | nil, context: map() | nil } @doc """ Crea una excepción de error de comando. ## Ejemplos iex> Argos.Command.Error.exception(:timeout, "echo test") %Argos.Command.Error{ message: "Command execution timeout", code: 124, reason: :timeout, command: "echo test" } """ @spec exception(atom() | String.t(), String.t(), keyword()) :: t() def exception(reason, command \\ nil, opts \\ []) do {message, code} = error_info(reason) context = Keyword.get(opts, :context, %{}) %__MODULE__{ message: message, code: code, reason: reason, command: command, context: context } end defp error_info(:timeout), do: {"Command execution timeout", 124} defp error_info(:not_found), do: {"Command or process not found", 127} defp error_info(:permission_denied), do: {"Permission denied", 126} defp error_info(:invalid_input), do: {"Invalid input provided", 1} defp error_info(:execution_failed), do: {"Command execution failed", 1} defp error_info(:invalid_process_name), do: {"Invalid process name", 1} defp error_info(:pid_not_found), do: {"Process ID not found", 1} defp error_info(:circuit_open), do: {"Circuit breaker is open", 503} defp error_info(reason) when is_binary(reason), do: {reason, 1} defp error_info(reason), do: {"Command error: #{inspect(reason)}", 1} end