lib/utils/maps.ex

defmodule Sorcery.Utils.Maps do

  @doc """
  Like `mkdir -p`, but for elixir maps.
  Safely does put_in, assuming nothing but maps all the way down.
  """
  def put_in_p(m, [hd], value) do
    Map.put(m, hd, value)
  end
  def put_in_p(m, [hd | tl], value) do
    submap = Map.get(m, hd, %{})
             |> put_in_p(tl, value)
    Map.put(m, hd, submap)
  end

  
  def delete_in(m, [hd]) do
    Map.delete(m, hd)
  end
  def delete_in(m, [hd | tl]) do
    submap = Map.get(m, hd, %{})
             |> delete_in(tl)
    Map.put(m, hd, submap)
  end

  
  def deep_merge(left, right) do
    Map.merge(left, right, &deep_resolve/3)
  end

 
  # Key exists in both maps, and both values are maps as well.
  # These can be merged recursively.
  defp deep_resolve(_key, left = %{}, right = %{}) do
    deep_merge(left, right)
  end
  

  # Key exists in both maps, but at least one of the values is
  # NOT a map. We fall back to standard merge behavior, preferring
  # the value on the right.
  defp deep_resolve(_key, _left, right) do
    right
  end

end