camel_cli/template/
bean.rs1use super::{TemplateFile, cargo_toml, gitignore, plugin_toml, readme_md, to_pascal_case};
2
3pub fn bean_files(plugin_name: &str) -> Vec<TemplateFile> {
4 vec![
5 TemplateFile {
6 path: "Cargo.toml".to_string(),
7 content: cargo_toml(plugin_name),
8 },
9 TemplateFile {
10 path: "src/lib.rs".to_string(),
11 content: lib_rs(plugin_name),
12 },
13 TemplateFile {
14 path: "Camel.plugin.toml".to_string(),
15 content: plugin_toml(plugin_name, "bean"),
16 },
17 TemplateFile {
18 path: "README.md".to_string(),
19 content: readme_md(plugin_name, "bean"),
20 },
21 TemplateFile {
22 path: ".gitignore".to_string(),
23 content: gitignore().to_string(),
24 },
25 TemplateFile {
26 path: "wit/camel-bean.wit".to_string(),
27 content: camel_bean_wit().to_string(),
28 },
29 TemplateFile {
30 path: "wit/camel-plugin.wit".to_string(),
31 content: camel_plugin_wit().to_string(),
32 },
33 ]
34}
35
36fn lib_rs(plugin_name: &str) -> String {
37 let plugin_type = to_pascal_case(plugin_name);
38 format!(
39 "use bindings::camel::plugin::types::{{WasmBody, WasmError, WasmExchange}};\nuse bindings::Guest;\n\nmod bindings {{\n wit_bindgen::generate!({{\n world: \"bean\",\n path: \"../wit\",\n }});\n}}\n\nstruct {plugin_type};\n\nimpl Guest for {plugin_type} {{\n fn init() -> Result<(), String> {{\n Ok(())\n }}\n\n fn methods() -> Vec<String> {{\n vec![\"hello\".into()]\n }}\n\n fn invoke(method: String, mut exchange: WasmExchange) -> Result<WasmExchange, WasmError> {{\n match method.as_str() {{\n \"hello\" => {{\n let text = match &exchange.input.body {{\n WasmBody::Text(s) => s.clone(),\n _ => String::new(),\n }};\n exchange.input.body = WasmBody::Text(format!(\"Hello from {plugin_name}: {{text}}\"));\n Ok(exchange)\n }}\n _ => Err(WasmError::ProcessorError(format!(\"unknown method: {{method}}\"))),\n }}\n }}\n}}\n\nbindings::export!({plugin_type} with_types_in bindings);\n"
40 )
41}
42
43fn camel_bean_wit() -> &'static str {
44 camel_wit::BEAN_WIT
45}
46
47fn camel_plugin_wit() -> &'static str {
48 camel_wit::PLUGIN_WIT
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn bean_files_contains_expected_paths() {
57 let files = bean_files("acme-bean");
58 let paths: Vec<&str> = files.iter().map(|f| f.path.as_str()).collect();
59
60 assert_eq!(files.len(), 7);
61 assert!(paths.contains(&"Cargo.toml"));
62 assert!(paths.contains(&"src/lib.rs"));
63 assert!(paths.contains(&"Camel.plugin.toml"));
64 assert!(paths.contains(&"README.md"));
65 assert!(paths.contains(&".gitignore"));
66 assert!(paths.contains(&"wit/camel-bean.wit"));
67 assert!(paths.contains(&"wit/camel-plugin.wit"));
68 }
69
70 #[test]
71 fn cargo_template_contains_workspace_and_wit_bindgen() {
72 let cargo = cargo_toml("acme-bean");
73
74 assert!(cargo.contains("name = \"acme-bean\""));
75 assert!(cargo.contains("crate-type = [\"cdylib\"]"));
76 assert!(cargo.contains("[workspace]"));
77 assert!(cargo.contains("wit-bindgen = \"0.57\""));
78 assert!(!cargo.contains("camel-wasm-sdk"));
79 }
80
81 #[test]
82 fn lib_template_uses_wit_bindgen_and_bean_world() {
83 let lib = lib_rs("acme-bean");
84
85 assert!(lib.contains("wit_bindgen::generate!"));
86 assert!(lib.contains("world: \"bean\""));
87 assert!(lib.contains("path: \"../wit\""));
88 assert!(lib.contains("impl Guest for AcmeBean"));
89 assert!(lib.contains("fn methods() -> Vec<String>"));
90 assert!(lib.contains("fn invoke("));
91 assert!(lib.contains("Hello from acme-bean: {text}"));
92 assert!(lib.contains("bindings::export!(AcmeBean with_types_in bindings);"));
93 assert!(!lib.contains("camel_wasm_sdk"));
94 }
95
96 #[test]
97 fn plugin_toml_contains_expected_keys() {
98 let plugin = plugin_toml("acme-bean", "bean");
99
100 assert!(plugin.contains("type = \"bean\""));
101 assert!(plugin.contains("entry = \"acme-bean.wasm\""));
102 }
103
104 #[test]
105 fn wit_templates_include_expected_worlds() {
106 let bean_wit = camel_bean_wit();
107 let plugin_wit = camel_plugin_wit();
108
109 assert!(bean_wit.contains("world bean"));
110 assert!(bean_wit.contains("import host;"));
111 assert!(plugin_wit.contains("interface types"));
112 assert!(plugin_wit.contains("interface host"));
113 }
114
115 #[test]
116 fn gitignore_contains_target_and_plugins() {
117 let files = bean_files("acme-bean");
118 let gitignore = files
119 .iter()
120 .find(|f| f.path == ".gitignore")
121 .expect("gitignore");
122 assert!(gitignore.content.contains("target"));
123 assert!(gitignore.content.contains("plugins/"));
124 }
125}