Packages

Run WebAssembly from Elixir. Load WASM modules in Rust, Go, C β€” call them like native functions.

Current section

Files

Jump to
firebird lib mix tasks firebird.doctor.ex
Raw

lib/mix/tasks/firebird.doctor.ex

defmodule Mix.Tasks.Firebird.Doctor do
@moduledoc """
Diagnose common Firebird setup issues.
Runs a series of checks to verify your Firebird installation is working correctly.
## Usage
mix firebird.doctor
## Checks
1. Wasmex dependency is available
2. WASM runtime loads correctly
3. Function calls work
4. wat2wasm is available (optional, for WAT compilation)
5. Sample WASM file exists
6. priv/wasm directory setup
"""
use Mix.Task
@shortdoc "Diagnose Firebird setup issues"
@impl Mix.Task
def run(_args) do
Mix.Task.run("app.start", ["--no-start"])
Application.ensure_all_started(:wasmex)
Mix.shell().info("πŸ”₯ Firebird Doctor β€” Checking your setup...\n")
checks = [
{"Wasmex dependency", &check_wasmex/0},
{"WASM runtime", &check_runtime/0},
{"Function calls", &check_calls/0},
{"Sample WASM file", &check_sample/0},
{"wat2wasm (WAT compiler)", &check_wat2wasm/0},
{"priv/wasm directory", &check_priv_wasm/0}
]
results =
Enum.map(checks, fn {name, check_fn} ->
result = check_fn.()
status =
case result do
:ok -> "βœ…"
{:warn, _} -> "⚠️ "
{:error, _} -> "❌"
end
message =
case result do
:ok -> ""
{:warn, msg} -> " β€” #{msg}"
{:error, msg} -> " β€” #{msg}"
end
Mix.shell().info(" #{status} #{name}#{message}")
result
end)
errors = Enum.count(results, fn r -> match?({:error, _}, r) end)
warnings = Enum.count(results, fn r -> match?({:warn, _}, r) end)
ok = Enum.count(results, fn r -> r == :ok end)
Mix.shell().info("")
cond do
errors > 0 ->
Mix.shell().info(
"❌ #{errors} issue(s) found. Fix the errors above to get Firebird working."
)
Mix.shell().info("")
Mix.shell().info("Common fixes:")
Mix.shell().info(" β€’ mix deps.get")
Mix.shell().info(" β€’ mix deps.compile wasmex --force")
Mix.shell().info(" β€’ mix firebird.init")
warnings > 0 ->
Mix.shell().info(
"⚠️ #{ok} checks passed, #{warnings} warning(s). Firebird is functional but some features may be limited."
)
true ->
Mix.shell().info("βœ… All #{ok} checks passed! Firebird is ready to use.")
Mix.shell().info("")
Mix.shell().info("Try it:")
Mix.shell().info(" iex -S mix")
Mix.shell().info(" iex> Firebird.demo()")
end
end
defp check_wasmex do
case Code.ensure_loaded(Wasmex) do
{:module, _} -> :ok
_ -> {:error, "Wasmex not loaded. Run: mix deps.get && mix deps.compile"}
end
end
defp check_runtime do
sample = Firebird.sample_wasm_path()
if File.exists?(sample) do
case Firebird.load(sample) do
{:ok, pid} ->
Firebird.stop(pid)
:ok
{:error, reason} ->
{:error, "Failed to load WASM: #{inspect(reason)}"}
end
else
{:error, "Sample WASM not found at #{sample}"}
end
end
defp check_calls do
case Firebird.run(Firebird.sample_wasm_path(), :add, [2, 3]) do
{:ok, [5]} -> :ok
{:ok, other} -> {:error, "Expected [5], got #{inspect(other)}"}
{:error, reason} -> {:error, "Call failed: #{inspect(reason)}"}
end
end
defp check_sample do
path = Firebird.sample_wasm_path()
if File.exists?(path) do
:ok
else
{:error, "Not found at #{path}. Run: mix deps.compile firebird --force"}
end
end
defp check_wat2wasm do
case System.find_executable("wat2wasm") do
nil ->
{:warn,
"Not installed. Install wabt for WAT support: brew install wabt (macOS) or apt install wabt (Ubuntu)"}
path ->
case System.cmd(path, ["--version"], stderr_to_stdout: true) do
{version, 0} ->
Mix.shell().info(" (#{String.trim(version)})")
:ok
_ ->
:ok
end
end
end
defp check_priv_wasm do
cond do
File.dir?("priv/wasm") ->
:ok
File.dir?("wasm") ->
{:warn, "Using wasm/ instead of priv/wasm/ (OK for dev, use priv/ for releases)"}
true ->
{:warn, "No wasm directory found. Create priv/wasm/ or run: mix firebird.init"}
end
end
end