tools for building gleam projects with nix
1// SPDX-FileCopyrightText: 2025 Ruby Iris Juric <ruby@srxl.me>
2//
3// SPDX-License-Identifier: 0BSD
4
5use std::{fs, process::Command};
6
7use miette::{Context, IntoDiagnostic, Result, miette};
8
9use crate::gleam_toml;
10
11enum Target {
12 Erlang,
13 Javascript,
14}
15
16impl Target {
17 fn filename(&self) -> String {
18 match self {
19 Target::Erlang => "gleam_entrypoint.erl".to_string(),
20 Target::Javascript => "gleam_entrypoint.mjs".to_string(),
21 }
22 }
23}
24
25impl TryFrom<&str> for Target {
26 type Error = miette::Report;
27
28 fn try_from(target: &str) -> Result<Self, Self::Error> {
29 match target {
30 "erlang" => Ok(Self::Erlang),
31 "javascript" => Ok(Self::Javascript),
32 _ => Err(miette!("Unknown target {target}")),
33 }
34 }
35}
36
37fn generate_module_source(module_name: &str, target: &Target) -> String {
38 match target {
39 Target::Erlang => format!(
40 r#"-module('gleam_entrypoint').
41-export([run/0]).
42
43run() ->
44 {{ok, _}} = application:ensure_all_started('{module_name}'),
45 {module_name}:main(),
46 erlang:halt(0).
47"#
48 ),
49 Target::Javascript => format!(
50 r#"import {{ main }} from "./{module_name}/{module_name}.mjs";
51main();
52"#
53 ),
54 }
55}
56
57pub fn generate_module(target: &str) -> Result<()> {
58 let target: Target = target.try_into()?;
59 let gleam_toml = gleam_toml::parse("gleam.toml")?;
60 let source = generate_module_source(&gleam_toml.name, &target);
61
62 fs::write(target.filename(), source)
63 .into_diagnostic()
64 .wrap_err("While writing entrypoint module source:")?;
65
66 match target {
67 Target::Javascript => Ok(()),
68 Target::Erlang => {
69 let compile_result = Command::new("erlc")
70 .arg(target.filename())
71 .status()
72 .into_diagnostic()
73 .wrap_err("While running Erlang compiler:")?;
74
75 if compile_result.success() {
76 Ok(())
77 } else {
78 Err(miette!("Entrypoint compilation failed"))
79 }
80 }
81 }
82}