use crate::backends::gleam::naming::gleam_app_name;
use crate::core::backend::GeneratedFile;
use crate::core::config::ResolvedCrateConfig;
use crate::core::ir::ApiSurface;
use crate::core::template_versions::hex;
use crate::scaffold::scaffold_meta;
use std::path::PathBuf;
pub(crate) fn scaffold_gleam(api: &ApiSurface, config: &ResolvedCrateConfig) -> anyhow::Result<Vec<GeneratedFile>> {
let meta = scaffold_meta(config);
let version = &api.version;
let gleam_app = gleam_app_name(config);
let gleam_toml = format!(
r#"name = "{app_name}"
version = "{version}"
description = "{description}"
licences = ["{license}"]
target = "erlang"
[dependencies]
gleam_stdlib = "{stdlib}"
[dev-dependencies]
gleeunit = "{gleeunit}"
"#,
app_name = gleam_app,
version = version,
description = meta.description,
license = meta.license,
stdlib = hex::GLEAM_STDLIB_VERSION_RANGE,
gleeunit = hex::GLEEUNIT_VERSION_RANGE,
);
let manifest_toml =
"# This file is generated by gleam build\n# Do not manually edit\n\npackages = []\n\n[requirements]\n";
let gitignore = "build/\n";
let smoke_test = r#"import gleeunit
import gleeunit/should
pub fn main() {
gleeunit.main()
}
/// Smoke test: confirms the test runner is wired up. Replace with real tests
/// that import the generated module and exercise its functions.
pub fn smoke_test() {
should.equal(1, 1)
}
"#
.to_string();
let editorconfig = "[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\n\n[*.gleam]\nindent_style = space\nindent_size = 2\n";
let readme = format!(
r#"# {gleam_app}
{description}
## Building
Install Gleam (see [gleam.run](https://gleam.run)):
```sh
gleam build
gleam test
```
## Usage
Add to your `gleam.toml`:
```toml
[dependencies]
{gleam_app} = {dependency_ref}
```
## License
{license}
"#,
gleam_app = gleam_app,
description = meta.description,
dependency_ref = gleam_dependency_ref(&meta),
license = meta.license,
);
let example_gleam = format!(
r#"import {gleam_app}
pub fn main() {{
// Example: load and use the generated {gleam_app} module
// Replace with your actual API calls after code generation
Nil
}}
"#,
gleam_app = gleam_app,
);
Ok(vec![
GeneratedFile {
path: PathBuf::from("packages/gleam/gleam.toml"),
content: gleam_toml,
generated_header: false,
},
GeneratedFile {
path: PathBuf::from("packages/gleam/manifest.toml"),
content: manifest_toml.to_string(),
generated_header: false,
},
GeneratedFile {
path: PathBuf::from("packages/gleam/.gitignore"),
content: gitignore.to_string(),
generated_header: false,
},
GeneratedFile {
path: PathBuf::from(format!("packages/gleam/test/{gleam_app}_test.gleam")),
content: smoke_test,
generated_header: false,
},
GeneratedFile {
path: PathBuf::from("packages/gleam/.editorconfig"),
content: editorconfig.to_string(),
generated_header: false,
},
GeneratedFile {
path: PathBuf::from("packages/gleam/README.md"),
content: readme,
generated_header: false,
},
GeneratedFile {
path: PathBuf::from(format!("packages/gleam/src/{gleam_app}_example.gleam")),
content: example_gleam,
generated_header: false,
},
])
}
fn gleam_dependency_ref(meta: &crate::scaffold::ScaffoldMeta) -> String {
let Some(repository) = meta.configured_repository.as_deref() else {
return "{path = \"../packages/gleam\"}".to_string();
};
let github_path = repository
.strip_prefix("https://github.com/")
.or_else(|| repository.strip_prefix("http://github.com/"))
.map(|path| path.trim_end_matches('/').trim_end_matches(".git"));
if let Some(path) = github_path
&& !path.is_empty()
{
return format!("{{github = \"{path}\"}}");
}
format!("{{git = \"{}\"}}", repository.trim_end_matches(".git"))
}