   Fetches the env atom for the config. Must be either `:dev` or `:prod`, or an
   exception will be thrown.
 
-      config :shippex, :env, :dev
-
-      Shippex.env #=> :dev
-  """
-  @spec env() :: atom
+      iex> Application.put_env(:shippex, :env, :dev)
+      iex> Shippex.env
+      :dev
+  """
+  @spec env() :: :dev | :prod | none()
   def env() do
     case Application.get_env(:shippex, :env, :dev) do
       e when e in [:dev, :prod] -> e

  end

  @doc """
  Fetches rates from `carriers` for a given `Shipment`.
  """
  @spec fetch_rates(Shipment.t(), [Carrier.t()] | nil) :: [{atom, Rate.t()}]
  def fetch_rates(%Shipment{} = shipment, carriers \\ nil) do
    # Convert the atom to a list if necessary.
    carriers =
      cond do
        is_nil(carriers) ->
          Shippex.carriers()

        is_atom(carriers) ->
          [carriers]

        is_list(carriers) ->
          carriers

        true ->
          raise """
          #{inspect(carriers)} is an invalid carrier or list of carriers.
          Try using an atom. For example:

              Shippex.fetch_rates(shipment, :ups)
          """
      end
      |> Enum.map(&Shippex.Carrier.module/1)

    rates = Enum.reduce(carriers, [], &(&1.fetch_rates(shipment) ++ &2))
    oks = Enum.filter(rates, &(elem(&1, 0) == :ok))
    errors = Enum.filter(rates, &(elem(&1, 0) == :error))


    defexception [:message]

    def exception(message) do
      %InvalidConfigError{message: message}
    end
  end

