Skip to main content

lib/host_kit/loader.ex

defmodule HostKit.Loader do
  @moduledoc "Loads HostKit `.exs` project declarations."

  alias HostKit.Project

  @spec load(Path.t(), keyword()) :: {:ok, Project.t()} | {:error, term()}
  def load(path, opts \\ []) do
    path = Path.expand(path)

    try do
      require_files(path, Keyword.get(opts, :require, []))
      {project, _binding} = Code.eval_file(path)

      case project do
        %Project{} -> {:ok, project}
        other -> {:error, {:expected_project, other}}
      end
    rescue
      exception in [ArgumentError, Code.LoadError, CompileError, RuntimeError, SyntaxError] ->
        {:error, {exception, __STACKTRACE__}}
    end
  end

  defp require_files(path, files) do
    base = Path.dirname(path)

    files
    |> List.wrap()
    |> Enum.map(&Path.expand(&1, base))
    |> Enum.each(&Code.require_file/1)
  end
end