plexus_substrate/activations/bash/
activation.rs1use super::executor::BashExecutor;
2use super::types::BashEvent;
3use futures::Stream;
4use plexus_macros::hub_methods;
5
6#[derive(Clone)]
8pub struct Bash {
9 executor: BashExecutor,
10}
11
12impl Bash {
13 pub fn new() -> Self {
14 Self {
15 executor: BashExecutor::new(),
16 }
17 }
18
19 pub async fn register_default_templates(
24 &self,
25 mustache: &crate::activations::mustache::Mustache,
26 ) -> Result<(), String> {
27 let plugin_id = Self::PLUGIN_ID;
28
29 mustache.register_templates(plugin_id, &[
30 ("execute", "default", "{{#stdout}}{{stdout}}{{/stdout}}{{#stderr}}\n[stderr] {{stderr}}{{/stderr}}{{#exit_code}}\n[exit: {{exit_code}}]{{/exit_code}}"),
32 ("execute", "compact", "{{stdout}}"),
33 ("execute", "verbose", "$ {{command}}\n{{stdout}}{{#stderr}}\n--- stderr ---\n{{stderr}}{{/stderr}}\n[exit code: {{exit_code}}]"),
34 ]).await
35 }
36}
37
38impl Default for Bash {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44#[hub_methods(
45 namespace = "bash",
46 version = "1.0.0",
47 description = "Execute bash commands and stream output"
48)]
49impl Bash {
50 #[plexus_macros::hub_method]
52 async fn execute(&self, command: String) -> impl Stream<Item = BashEvent> + Send + 'static {
53 self.executor.execute(&command).await
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::plexus::Activation;
61
62 #[test]
63 fn test_bash_activation_trait() {
64 let bash = Bash::new();
65 assert_eq!(bash.namespace(), "bash");
66 assert_eq!(bash.version(), "1.0.0");
67 assert!(bash.methods().contains(&"execute"));
68 }
69
70 #[test]
71 fn test_bash_method_help() {
72 let bash = Bash::new();
73 let help = bash.method_help("execute");
74 assert!(help.is_some());
75 assert!(help.unwrap().contains("Execute"));
76 }
77
78 #[test]
79 fn test_bash_namespace_constant() {
80 assert_eq!(Bash::NAMESPACE, "bash");
81 }
82
83 #[test]
84 fn test_generated_method_enum() {
85 let names = BashMethod::all_method_names();
86 assert!(names.contains(&"execute"));
87 }
88
89 #[test]
90 fn test_plugin_schema_with_return_types() {
91 use crate::plexus::Activation;
92 let bash = Bash::new();
93 let schema = bash.plugin_schema();
94
95 assert_eq!(schema.namespace, "bash");
96 assert_eq!(schema.version, "1.0.0");
97 assert_eq!(schema.methods.len(), 2);
99 assert!(schema.is_leaf(), "bash should be a leaf plugin");
100
101 let execute = schema.methods.iter().find(|m| m.name == "execute")
102 .expect("should have an 'execute' method");
103 assert!(execute.params.is_some(), "should have params schema");
104 assert!(execute.returns.is_some(), "should have returns schema");
105
106 let json = serde_json::to_string_pretty(&schema).unwrap();
108 println!("Bash plugin_schema():\n{}", json);
109
110 let returns_json = serde_json::to_string(&execute.returns).unwrap();
112 assert!(returns_json.contains("stdout") || returns_json.contains("Stdout"));
113 assert!(returns_json.contains("stderr") || returns_json.contains("Stderr"));
114 assert!(returns_json.contains("exit") || returns_json.contains("Exit"));
115 }
116}