Current section
Files
Jump to
Current section
Files
lib/mix/tasks/ash_rpc.codegen.ex
defmodule Mix.Tasks.AshRpc.Codegen do
@moduledoc """
Generate a minimal TypeScript declaration for the Ash RPC router.
mix ash_rpc.codegen --output=./frontend/generated
Options:
--output - directory to write `trpc.d.ts` (required)
--domains - comma-separated domain modules (optional)
If --domains is not provided, tries to locate modules that expose `domains/0`
(i.e. modules using `AshRpc.Router`) and uses those.
"""
use Mix.Task
alias AshRpc.TypeScript.{Generator, ResourceUtils}
@shortdoc "Generate Ash RPC TS types"
@impl true
def run(args) do
Mix.Task.run("app.start")
{opts, _, _} =
OptionParser.parse(args, switches: [output: :string, domains: :string, zod: :boolean])
output_dir = opts[:output] || abort!("--output is required")
domains =
case opts[:domains] do
nil ->
case ResourceUtils.find_router_module() do
{:ok, domains} -> domains
{:error, msg} -> abort!(msg)
end
str ->
str |> String.split([",", " "], trim: true) |> Enum.map(&Module.concat([&1]))
end
unless File.dir?(output_dir) do
File.mkdir_p!(output_dir)
end
# Generate TypeScript types using the new modular system
v11_types = Generator.generate_types(domains)
out_file = Path.join(output_dir, "trpc.d.ts")
File.write!(out_file, v11_types)
Mix.shell().info([:green, "Wrote ", out_file])
if opts[:zod] do
zod_ts = Generator.generate_zod_schemas(domains)
zod_file = Path.join(output_dir, "trpc.zod.ts")
File.write!(zod_file, zod_ts)
Mix.shell().info([:green, "Wrote ", zod_file])
end
end
defp abort!(msg) do
Mix.raise("ash_rpc.codegen: #{msg}")
end
end