Packages

SpacetimeDB client library for Elixir

Current section

Files

Jump to
spacetimedbex lib mix tasks spacetimedb.gen.ex
Raw

lib/mix/tasks/spacetimedb.gen.ex

defmodule Mix.Tasks.Spacetimedb.Gen do
@moduledoc """
Generates Elixir modules from a SpacetimeDB schema.
mix spacetimedb.gen --host localhost:3000 --database mydb --module MyApp.SpacetimeDB
## Options
- `--host` — SpacetimeDB host (required)
- `--database` — database name (required)
- `--module` — base module name for generated code (required)
- `--output` — output directory (default: "lib")
"""
use Mix.Task
@shortdoc "Generate Elixir modules from SpacetimeDB schema"
@switches [host: :string, database: :string, module: :string, output: :string]
@impl Mix.Task
def run(args) do
{opts, _, _} = OptionParser.parse(args, strict: @switches)
host = opts[:host] || Mix.raise("--host is required")
database = opts[:database] || Mix.raise("--database is required")
base_module = opts[:module] || Mix.raise("--module is required")
output_dir = opts[:output] || "lib"
# Ensure HTTP client is started
Mix.Task.run("app.start", ["--no-start"])
Application.ensure_all_started(:req)
Mix.shell().info("Fetching schema from #{host}/#{database}...")
case Spacetimedbex.Schema.fetch(host, database) do
{:ok, schema} ->
files = Spacetimedbex.Codegen.generate(schema, base_module, database: database)
Enum.each(files, fn {relative_path, content} ->
full_path = Path.join(output_dir, relative_path)
File.mkdir_p!(Path.dirname(full_path))
File.write!(full_path, content)
Mix.shell().info(" * creating #{full_path}")
end)
Mix.shell().info(
"Generated #{length(files)} file(s) for #{map_size(schema.tables)} table(s) and #{map_size(schema.reducers)} reducer(s)."
)
{:error, reason} ->
Mix.raise("Failed to fetch schema: #{inspect(reason)}")
end
end
end