lib/step_flow/models/workflow_definitions/external_loader.ex

defmodule StepFlow.WorkflowDefinitions.ExternalLoader do
  @moduledoc """
  Loader for referenced JSON schema implemented through Xema loader.
  """

  @behaviour Xema.Loader

  @spec fetch(binary) :: {:ok, map} | {:error, any}
  def fetch(uri) do
    with {:ok, response} <- get(uri), do: parse_body(response, uri)
  end

  defp get(uri) do
    specification_folder =
      Application.get_env(:step_flow, StepFlow.WorkflowDefinitions.ExternalLoader)[
        :specification_folder
      ]

    if specification_folder do
      File.read(specification_folder <> uri.path)
    else
      case HTTPoison.get(uri) do
        {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
          {:ok, body}

        {:ok, %HTTPoison.Response{status_code: 404}} ->
          {:error, "Remote schema '#{uri}' not found."}

        {:ok, %HTTPoison.Response{status_code: code}} ->
          {:error, "code: #{code}"}

        {:error, reason} ->
          {:error, reason}
      end
    end
  end

  defp parse_body(str, uri) do
    Jason.decode(str)
  rescue
    error -> {:error, %{error | file: URI.to_string(uri)}}
  end
end