Skip to main content

acts_package_javascript/
code.rs

1use crate::env::Environment;
2use acts::{ActPackage, ActPackageCatalog, ActPackageDefinition, ActRunAs, Context, Result, Vars};
3use serde_json::json;
4
5#[derive(Debug, Clone)]
6pub struct CodePackage {
7    env: Environment,
8}
9
10#[async_trait::async_trait]
11impl ActPackage for CodePackage {
12    fn definition() -> ActPackageDefinition {
13        ActPackageDefinition {
14            id: "acts.app.javascript",
15            name: "Code",
16            desc: "run javascript code",
17            version: "0.1.0",
18            icon: r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-braces-icon lucide-braces"><path d="M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1"/><path d="M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1"/></svg>"#,
19            doc: "",
20            schema: json!({
21                "type": "string",
22                "description": "The JavaScript code to execute",
23                "default": "",
24            }),
25            options: Some(json!({
26                "ui:widget": "textarea",
27                "ui:options": {
28                    "placeholder": "Type your JavaScript code here..."
29                }
30            })),
31            run_as: ActRunAs::Func,
32            resources: vec![],
33            catalog: ActPackageCatalog::Transform,
34        }
35    }
36
37    fn new(_: &acts::Config) -> Result<Self>
38    where
39        Self: Sized,
40    {
41        Ok(Self {
42            env: Environment::new(),
43        })
44    }
45
46    async fn execute(&self, _ctx: &Context, params: &serde_json::Value) -> Result<Option<Vars>> {
47        let Some(code) = params.as_str() else {
48            return Err(acts::ActError::Package(
49                "Code package requires a string parameter".to_string(),
50            ));
51        };
52
53        // wrap the code into a function to support return syntax
54        let code_fn = format!(r#"(()=>{{ {} }})()"#, code);
55        let outputs = self.env.eval::<serde_json::Value>(&code_fn)?;
56        let mut ret = None;
57        if let serde_json::Value::Object(map) = outputs {
58            ret = Some(Vars::from(map));
59        }
60        Ok(ret)
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use crate::CodePackage;
67    use acts::ActPackage;
68
69    #[test]
70    fn pack_code_parse() {
71        let params = r#"
72            console.log("Hello, World!");
73        "#;
74
75        let value = serde_yaml::from_str::<serde_json::Value>(params).unwrap();
76        let meta = CodePackage::definition();
77        jsonschema::validate(&meta.schema, &value).unwrap()
78    }
79}