Packages
drab
0.10.3
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.6.0-pre.1
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
Remote controlled frontend framework for Phoenix.
Current section
Files
Jump to
Current section
Files
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")
app_js = if webpack?(), do: find_file("assets/js", "app.js")
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)
update("app.js", app_js)
if webpack?(), do: update("config.exs - webpack", config, app)
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("app.js", file, _app) do
inject = "window.__socket = require(\"phoenix\").Socket;"
add_to_file(file, 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 update("config.exs - webpack", file, app) do
drab = """
# Configures Drab for webpack
config :drab, #{inspect(Mix.Drab.find_endpoint_in_config_exs(app))},
js_socket_constructor: "window.__socket"
"""
unless inject_string_already_there(file, drab) do
logger = "# Configures Elixir's Logger\n"
inject_to_file(file, logger, drab <> "\n" <> 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 add_to_file(file, string) do
unless inject_string_already_there(file, string) do
f = File.read!(file)
added = "#{f}\n#{string}"
File.write!(file, added, [:write])
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
Application.load(:phoenix)
unless supported_phoenix?() do
Mix.raise("""
Only Phoenix 1.3 and 1.4 are supported with the installer, please proceed with manual install.
""")
end
end
defp supported_phoenix?() do
v = to_string(Application.spec(:phoenix, :vsn))
Regex.match?(~r/^1.[34]/, v)
end
defp webpack?() do
File.exists?(Path.join("assets", "webpack.config.js"))
end
end