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