Current section
Files
Jump to
Current section
Files
lib/serum/dev_server.ex
defmodule Serum.DevServer do
@moduledoc """
The Serum development server.
"""
alias Serum.DevServer.Logger
alias Serum.DevServer.Service
alias Serum.Project
alias Serum.Project.Loader, as: ProjectLoader
alias Serum.Result
@doc """
Starts the Serum development server.
This function returns `{:ok, pid}` on success where `pid` is a process ID of
a supervision tree for the Serum development server.
"""
@spec run(binary, pos_integer) :: Result.t(pid())
def run(dir, port) do
uniq = Base.url_encode64(:crypto.strong_rand_bytes(6))
site = Path.expand("serum_" <> uniq, System.tmp_dir!())
with {:ok, %Project{} = proj} <- ProjectLoader.load(dir, site),
{:ok, pid} when is_pid(pid) <- do_run(dir, site, port, proj) do
{:ok, pid}
else
{:error, {:shutdown, {:failed_to_start_child, _, :eaddrinuse}}} ->
msg =
"could not start the Serum development server. " <>
"Make sure the port #{port} is not used by other applications"
{:error, msg}
{:error, {:shutdown, reason}} when not is_list(reason) ->
msg = "could not start the Serum development server: #{inspect(reason)}"
{:error, msg}
{:error, _} = error ->
error
end
end
@spec do_run(binary(), binary(), integer(), Project.t()) :: Supervisor.on_start()
defp do_run(dir, site, port, proj) do
trap_exit = Process.flag(:trap_exit, true)
base = proj.base_url
ms_options = [
port: port,
base: base,
callbacks: [Logger],
index: true,
route_overrides: [
{"/serum_live_reloader", Serum.DevServer.LiveReloadHandler, nil}
]
]
children = [
{Service.GenServer, {dir, site, port}},
%{
id: Microscope,
start: {Microscope, :start_link, [site, ms_options]}
}
]
sup_opts = [strategy: :one_for_one, name: Serum.DevServer.Supervisor]
start_result = Supervisor.start_link(children, sup_opts)
Process.flag(:trap_exit, trap_exit)
start_result
end
end