Packages

Provides `mix needle.new.*` tasks to bootstrap new Phoenix projects.

Current section

Files

Jump to
needle_new lib needle_new.ex
Raw

lib/needle_new.ex

defmodule Needle.New do
@moduledoc false
alias Needle.New.Project
@app Mix.Project.config()[:app]
@version Mix.Project.config()[:version]
@elixir_requirement Mix.Project.config()[:elixir]
@switches [
umbrella: :boolean,
app: :string,
module: :string,
# ctx
database: :string,
binary_id: :boolean,
ecto: :boolean,
mailer: :boolean,
# web
http_server: :string,
dashboard: :boolean,
assets: :boolean,
html: :boolean,
live: :boolean,
# other
gettext: :boolean
]
def run(_mix_task_module, [option] = _agrv, _generator) when option in ~w(-v --version) do
Mix.shell().info("#{@app} v#{@version}")
end
def run(mix_task_module, argv, generator) do
elixir_version_check!()
case OptionParser.parse!(argv, strict: @switches) do
{opts, [base_path | _]} ->
generate(base_path, generator, opts)
_ ->
task_name =
mix_task_module
|> inspect()
|> to_mix_task_name()
Mix.Tasks.Help.run([task_name])
end
end
def to_mix_task_name("Mix.Tasks." <> module) do
String.downcase(module)
end
defdelegate phoenix_version(), to: Needle.New.Project
defdelegate in_umbrella?(path), to: Needle.New.Generator
defp elixir_version_check!() do
unless Version.match?(System.version(), @elixir_requirement) do
Mix.raise(
"#{@app} v#{@version} requires Elixir #{@elixir_requirement}. " <>
"But, you have Elixir #{System.version()}. \n" <> "Please update accordingly."
)
end
end
defp generate(base_path, generator, opts) do
base_path
|> Project.new(opts)
|> generator.prepare_project()
|> Project.put_binding()
|> Project.validate!()
|> generator.generate()
|> print_next_steps(generator)
end
defp print_next_steps(%Project{} = project, generator) do
print_missing_steps(project)
print_ecto_info(project, generator)
print_pubsub_info(project, generator)
print_mix_info(project, generator)
end
defp print_missing_steps(project) do
steps =
Enum.reject(
[
"$ cd #{relative_app_path(project.root_app_path)}",
"$ mix deps.get",
if(Project.assets?(project), do: "$ mix assets.setup")
],
&(&1 == nil)
)
Mix.shell().info("""
We are almost there! The following steps are missing:
#{Enum.join(steps, "\n ")}
""")
end
defp relative_app_path(path) do
case Path.relative_to_cwd(path) do
^path -> Path.basename(path)
rel -> rel
end
end
defp print_ecto_info(_project, Web), do: :ok
defp print_ecto_info(project, _generator) do
if Project.ecto?(project) do
Mix.shell().info("""
Then configure your database in config/dev.exs and run:
$ mix ecto.create
""")
else
:ok
end
end
defp print_pubsub_info(project, Web) do
Mix.shell().info("""
Your web app requires a PubSub server to be running.
The PubSub server is typically defined in a `mix phx.new.ecto` app.
If you don't plan to define an Ecto app, you must explicitly start
the PubSub in your supervision tree as:
{Phoenix.PubSub, name: #{inspect(project.ctx_module)}.PubSub}
""")
end
defp print_pubsub_info(_project, _generator), do: :ok
defp print_mix_info(_project, Ecto) do
Mix.shell().info("""
You can run your app inside IEx (Interactive Elixir) as:
$ iex -S mix
""")
end
defp print_mix_info(_project, _generator) do
Mix.shell().info("""
Start your Phoenix app with:
$ mix phx.server
You can also run your app inside IEx (Interactive Elixir) as:
$ iex -S mix phx.server
""")
end
end