defmodule Mix.Tasks.Scoria.Assets.Build do
@shortdoc "Builds the self-contained Scoria dashboard asset bundle (CSS + JS)"
@moduledoc """
Assembles the precompiled, self-contained dashboard assets into `priv/static/scoria/`.
The library ships these compiled artifacts so the dashboard renders fully styled and
interactive in any host app — with no dependency on the host's Tailwind/esbuild pipeline
(the Phoenix LiveDashboard / Oban Web model).
$ mix scoria.assets.build
CSS: concatenates `assets/css/*.css` (numeric order) under one cascade `@layer` declaration.
JS: concatenates the prebuilt Phoenix + LiveView + phoenix_html UMD bundles with
`assets/js/scoria.js` (Scoria's own LiveSocket + hooks). No bundler binary required.
Run before `mix hex.publish`; the output is committed and shipped via `package.files`.
"""
use Mix.Task
@layer_order "@layer scoria.reset, scoria.tokens, scoria.base, scoria.components, scoria.utilities, scoria.compat;\n"
@impl Mix.Task
def run(_args) do
root = File.cwd!()
out_dir = Path.join([root, "priv", "static", "scoria"])
File.mkdir_p!(out_dir)
build_css(root, out_dir)
build_js(root, out_dir)
Mix.shell().info([:green, "* scoria assets built -> priv/static/scoria/{app.css,app.js}"])
end
defp build_css(root, out_dir) do
css_dir = Path.join([root, "assets", "css"])
css =
css_dir
|> Path.join("*.css")
|> Path.wildcard()
|> Enum.sort()
|> Enum.map_join("\n", &File.read!/1)
header =
"/* Scoria dashboard styles — generated by `mix scoria.assets.build`. Do not edit by hand. */\n"
File.write!(Path.join(out_dir, "app.css"), header <> @layer_order <> css)
end
defp build_js(root, out_dir) do
deps = Mix.Project.deps_path()
sources = [
Path.join([deps, "phoenix", "priv", "static", "phoenix.min.js"]),
Path.join([deps, "phoenix_live_view", "priv", "static", "phoenix_live_view.min.js"]),
Path.join([deps, "phoenix_html", "priv", "static", "phoenix_html.js"]),
Path.join([root, "assets", "js", "scoria.js"])
]
Enum.each(sources, fn path ->
unless File.exists?(path), do: Mix.raise("scoria.assets.build: missing source #{path}")
end)
header =
"/* Scoria dashboard client — generated by `mix scoria.assets.build`. Do not edit by hand. */\n"
js = Enum.map_join(sources, "\n;\n", &File.read!/1)
File.write!(Path.join(out_dir, "app.js"), header <> js)
end
end