defmodule GitHub.Error do
@moduledoc """
Exception struct used for communicating errors from the client
> #### Note {:.info}
>
> Functions in this module is unlikely to be used directly by applications. Instead, they are
> useful for plugins. See `GitHub.Plugin` for more information.
This error covers errors generated by the client (for example, HTTP connection errors) as well as
errors returned from the GitHub API (for example, Not Found errors).
## Fields
* `code` (integer): Status code of the API response, if a response was received.
* `message` (string): Human-readable message describing the error.
* `operation` (`t:Operation.t/0`): Operation at the time of the error.
* `source` (term): Cause of the error. This could be an operation, an API error response, or
something else.
* `stacktrace` (`t:Exception.stacktrace/0`): Stacktrace from the time of the error.
* `step` (plugin): Plugin active at the time of the error (expressed as a tuple containing the
module and function).
Users of the library can match on the information in the `code` and `source` fields to extract
additional information.
"""
alias GitHub.Operation
@typedoc "GitHub API client error"
@type t :: %__MODULE__{
code: integer | nil,
message: String.t(),
operation: Operation.t(),
source: term,
stacktrace: Exception.stacktrace(),
step: {module, atom}
}
@derive {Inspect, except: [:operation, :stacktrace]}
defexception [:code, :message, :operation, :source, :stacktrace, :step]
@doc """
Create a new error struct with the given fields
The current stacktrace is automatically filled in to the resulting error. Callers should specify
the status `code` (if available), a `message`, the original `operation`, the `source` of the
error, and which `step` or plugin is currently active.
"""
@spec new(keyword) :: t
def new(opts) do
{:current_stacktrace, stack} = Process.info(self(), :current_stacktrace)
# Drop `Process.info/2` and `new/1`.
stacktrace = Enum.drop(stack, 2)
struct!(%__MODULE__{stacktrace: stacktrace}, opts)
end
end