Skip to main content

lib/triple/types/validation.ex

defmodule Triple.Types.Validation do
  @moduledoc false

  alias Triple.Error

  # Builds a `Triple.Error.t()` of type `:validation` from a list of
  # `{field, message}` pairs produced by `Triple.Types.Validators`. Note
  # `status: nil` here — that's how you can tell a *local* validation
  # failure (caught before any network call) apart from a `400` the
  # server itself returned (which has `status: 400`).
  @spec error([{atom(), String.t()}]) :: Error.t()
  def error(field_errors) do
    errors =
      Enum.group_by(
        field_errors,
        fn {field, _message} -> Atom.to_string(field) end,
        fn {_field, message} -> message end
      )

    %Error{
      type: :validation,
      message: "Invalid input: " <> format(errors),
      status: nil,
      errors: errors,
      retry_after: nil,
      raw_body: nil
    }
  end

  defp format(errors) do
    Enum.map_join(errors, "; ", fn {field, messages} ->
      "#{field}: #{Enum.join(messages, ", ")}"
    end)
  end
end