Skip to main content

folk_builder/
codegen.rs

1use crate::config::{BuildConfig, PluginEntry};
2
3/// Generate the content of the output `Cargo.toml`.
4pub fn generate_cargo_toml(cfg: &BuildConfig) -> String {
5    let mut deps = String::new();
6
7    // Core dependencies
8    deps.push_str(
9        r#"folk-core = { git = "https://github.com/Folk-Project/folk-core", version = "0.1" }
10folk-api = { git = "https://github.com/Folk-Project/folk-api", version = "0.1" }
11folk-runtime-pipe = { git = "https://github.com/Folk-Project/folk-core", version = "0.1" }
12tokio = { version = "1", features = ["full"] }
13anyhow = "1"
14tracing-subscriber = { version = "0.3", features = ["env-filter"] }
15"#,
16    );
17
18    for plugin in &cfg.plugin {
19        deps.push_str(&generate_plugin_dep(plugin));
20    }
21
22    format!(
23        r#"[package]
24name = "{output}"
25version = "0.1.0"
26edition = "2024"
27
28[[bin]]
29name = "{output}"
30path = "src/main.rs"
31
32[dependencies]
33{deps}
34"#,
35        output = cfg.build.output,
36        deps = deps
37    )
38}
39
40fn generate_plugin_dep(p: &PluginEntry) -> String {
41    if let Some(path) = &p.path {
42        format!(
43            r#"{} = {{ path = "{}" }}
44"#,
45            p.crate_name, path
46        )
47    } else if let Some(git) = &p.git {
48        let ver = p.version.as_deref().unwrap_or("0.1");
49        format!(
50            r#"{} = {{ git = "{}", version = "{}" }}
51"#,
52            p.crate_name, git, ver
53        )
54    } else {
55        let ver = p.version.as_deref().unwrap_or("0.1");
56        format!(
57            r#"{} = "{}"
58"#,
59            p.crate_name, ver
60        )
61    }
62}
63
64/// Generate the content of the output `main.rs`.
65pub fn generate_main_rs(cfg: &BuildConfig) -> String {
66    let imports: Vec<String> = cfg
67        .plugin
68        .iter()
69        .map(|p| {
70            format!(
71                "use {}::folk_plugin_factory as {}_factory;",
72                p.crate_name, p.crate_name
73            )
74        })
75        .collect();
76
77    let registrations: Vec<String> = cfg
78        .plugin
79        .iter()
80        .map(|p| {
81            let key = if p.config_key.is_empty() {
82                &p.crate_name
83            } else {
84                &p.config_key
85            };
86            format!(
87                r#"    let cfg_{name} = cfg.get_table("{key}").cloned().unwrap_or_default();
88    let cfg_{name}_json = serde_json::to_value(cfg_{name}).unwrap_or_default();
89    server.register_plugin({name}_factory().create(cfg_{name}_json)?);
90"#,
91                name = p.crate_name,
92                key = key
93            )
94        })
95        .collect();
96
97    format!(
98        r#"//! Generated by folk-builder. Do not edit.
99
100{imports}
101
102#[tokio::main]
103async fn main() -> anyhow::Result<()> {{
104    tracing_subscriber::fmt::init();
105
106    let cfg = folk_core::config::FolkConfig::load()?;
107    let runtime = folk_runtime_pipe::runtime::PipeRuntime::new(
108        folk_runtime_pipe::runtime::PipeConfig {{
109            php:    cfg.workers.php.clone(),
110            script: cfg.workers.script.clone(),
111        }}
112    );
113
114    let mut server = folk_core::server::FolkServer::new(cfg, std::sync::Arc::new(runtime));
115
116{registrations}
117
118    server.run().await
119}}
120"#,
121        imports = imports.join("\n"),
122        registrations = registrations.join("")
123    )
124}