Current section

Files

Jump to
drab lib mix tasks drab.install.ex
Raw

lib/mix/tasks/drab.install.ex

defmodule Mix.Tasks.Drab.Install do
use Mix.Task
@shortdoc "Installs Drab in the current Phoenix project"
@moduledoc """
Installs Drab in the current Phoenix application. It does inject lines of code to the existing
*.ex, *.exs and *.eex files, so it is wise to commit before continuing.
It assumes that the Phoenix application was generated by `mix phx.new`. In case you have a non
standard application, it is better to do it with manual install.
Usage:
mix drab.install
"""
@impl true
def run(_args) do
validate_phoenix_version()
app = Mix.Drab.app_name()
Mix.shell().info("Checking prerequisites for #{inspect(app)}")
app_html = find_file("lib", "app.html.eex")
user_socket = find_file("lib", "user_socket.ex")
config = find_file("config", "config.exs")
dev_config = find_file("config", "dev.exs")
if Mix.shell().yes?("The installer is going to modify those files. OK to proceed?") do
update("app.html.eex", app_html)
update("user_socket.ex", user_socket)
update("config.exs", config, app)
update("dev.exs", dev_config)
Mix.shell().info("""
Drab has been successfully installed in your Phoenix application.
Now it is time to create your first commander, for example, for PageController:
mix drab.gen.commander Page
""")
end
end
defp update(file, path, app \\ nil)
defp update("app.html.eex", file, _app) do
inject = "<%= Drab.Client.run(@conn) %>"
inject_to_file(file, " </body>", " #{inject}\n </body>")
end
defp update("user_socket.ex", file, _app) do
inject = "use Drab.Socket"
inject_to_file(file, " use Phoenix.Socket", " use Phoenix.Socket\n #{inject}")
end
defp update("dev.exs", file, _app) do
inject = "templates/.*(eex|drab)$"
inject_to_file(file, "templates/.*(eex)$", inject)
end
defp update("config.exs", file, app) do
phoenix = """
\n# Configures default Drab file extension
config :phoenix, :template_engines,
drab: Drab.Live.Engine\n
"""
drab = """
# Configures Drab
config :drab, #{inspect(Mix.Drab.find_endpoint_in_config_exs(app))},
otp_app: #{inspect(app)}
"""
unless inject_string_already_there(file, drab) do
# File.write!(file, phoenix <> drab, [:append])
logger = "# Configures Elixir's Logger\n"
inject_to_file(file, logger, drab <> phoenix <> logger)
end
end
defp inject_to_file(file, search_for, replace_with) do
unless inject_string_already_there(file, replace_with) do
f = File.read!(file)
replaced = String.replace(f, search_for, replace_with)
if replaced == f do
Mix.shell().error("Installer could not update #{file}. Please install Drab manually.")
else
File.write!(file, replaced, [:write])
end
end
end
defp inject_string_already_there(file, inject) do
f = File.read!(file)
contains = String.contains?(f, inject)
if contains do
Mix.shell().info(" Drab is already installed in #{file}, skipping.")
end
contains
end
defp find_file(dir, name) do
file =
case Path.wildcard("#{dir}/**/#{name}") do
[] -> ask_for_file_path(name)
[filename] -> filename
names -> choose_file(names, name)
end
Mix.shell().info(" #{file}")
file
end
defp ask_for_file_path(name) do
Mix.shell().error("Can't find #{name}. Please specify the full path.")
path = String.trim(Mix.shell().prompt(">"))
if File.exists?(path) do
path
else
ask_for_file_path(name)
end
end
defp choose_file(names, name) do
Mix.shell().error("Multiple #{name} found, please copy/paste the full path of correct one.")
# credo:disable-for-next-line
Mix.shell().info(Enum.join(names, "\n"))
path = String.trim(Mix.shell().prompt(">"))
if File.exists?(path) do
path
else
choose_file(names, name)
end
end
defp validate_phoenix_version do
unless phoenix13?() do
Mix.raise("""
Only Phoenix 1.3 is supported with the installer, please proceed with manual install.
""")
end
end
defp phoenix13?(), do: Regex.match?(~r/^1.3/, to_string(Application.spec(:phoenix, :vsn)))
end