diff --git a/README.md b/README.md index 116cfdf..ce3384e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -**Code**: [![codecov](https://codecov.io/gh/zefiroproj/zefiro/graph/badge.svg?token=5DgmM1KzuQ)](https://codecov.io/gh/zefiroproj/zefiro) +[![codecov](https://codecov.io/gh/zefiroproj/zefiro/graph/badge.svg?token=5DgmM1KzuQ)](https://codecov.io/gh/zefiroproj/zefiro) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fzefiroproj%2Fzefiro.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fzefiroproj%2Fzefiro?ref=badge_shield) # Zefiro - fast, scalable and simple engine to manage workflows ⚠️ This project is a Work In Progress, and is very far from being suitable for use ⚠️ -## License +## License Compliance [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fzefiroproj%2Fzefiro.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fzefiroproj%2Fzefiro?ref=badge_large) \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl/Cargo.toml b/zefiro-core/zefiro-cwl/Cargo.toml index 4622bba..da6d86b 100644 --- a/zefiro-core/zefiro-cwl/Cargo.toml +++ b/zefiro-core/zefiro-cwl/Cargo.toml @@ -22,6 +22,7 @@ serde_json = "1.0.135" serde_with = "3.12.0" serde_yaml = "0.9.34" sha1 = "0.10.6" +tera = "1.20.0" [dev-dependencies] rstest = "0.24.0" diff --git a/zefiro-core/zefiro-cwl/src/exprs/mod.rs b/zefiro-core/zefiro-cwl/src/exprs/mod.rs deleted file mode 100644 index 4b318ea..0000000 --- a/zefiro-core/zefiro-cwl/src/exprs/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod exec; diff --git a/zefiro-core/zefiro-cwl/src/exprs/exec.rs b/zefiro-core/zefiro-cwl/src/js/execute.rs similarity index 100% rename from zefiro-core/zefiro-cwl/src/exprs/exec.rs rename to zefiro-core/zefiro-cwl/src/js/execute.rs diff --git a/zefiro-core/zefiro-cwl/src/js/mod.rs b/zefiro-core/zefiro-cwl/src/js/mod.rs new file mode 100644 index 0000000..2e8bddd --- /dev/null +++ b/zefiro-core/zefiro-cwl/src/js/mod.rs @@ -0,0 +1 @@ +pub mod execute; diff --git a/zefiro-core/zefiro-cwl/src/lib.rs b/zefiro-core/zefiro-cwl/src/lib.rs index 6b6e5ee..b6c5814 100644 --- a/zefiro-core/zefiro-cwl/src/lib.rs +++ b/zefiro-core/zefiro-cwl/src/lib.rs @@ -1,8 +1,10 @@ -pub mod exprs; +pub mod js; #[doc = include_str!("../README.md")] pub mod schema; +pub mod template; pub mod values; -pub use crate::exprs::exec::JsExecutor; +pub use crate::js::execute::JsExecutor; pub use crate::schema::document::CwlSchema; +pub use crate::template::render::TemplateRender; pub use crate::values::document::CwlValues; diff --git a/zefiro-core/zefiro-cwl/src/template/mod.rs b/zefiro-core/zefiro-cwl/src/template/mod.rs new file mode 100644 index 0000000..cf25e6c --- /dev/null +++ b/zefiro-core/zefiro-cwl/src/template/mod.rs @@ -0,0 +1 @@ +pub mod render; diff --git a/zefiro-core/zefiro-cwl/src/template/render.rs b/zefiro-core/zefiro-cwl/src/template/render.rs new file mode 100644 index 0000000..f7c3ece --- /dev/null +++ b/zefiro-core/zefiro-cwl/src/template/render.rs @@ -0,0 +1,82 @@ +use anyhow::Error; +use serde_json::Value; +use tera::{Context, Tera}; + +pub struct TemplateRender { + content: Value, + tera: Tera, +} + +impl TemplateRender { + pub fn new(content: Value, template: &str) -> Result { + let mut tera = Tera::default(); + tera.add_raw_template("template", template)?; + Ok(Self { content, tera }) + } + + pub fn render(&self) -> Result { + let mut context = Context::new(); + let object = self.content.as_object().ok_or_else(|| { + anyhow::anyhow!("Content must be a JSON object, got: {}", self.content) + })?; + for (key, value) in object { + context.insert(key, value); + } + let result = self.tera.render("template", &context)?; + + Ok(result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + use serde_json::json; + + #[rstest] + #[case( + json!({"inputLocation": "s3://bucket"}), + r#" + input_file: + class: location + location: {{ inputLocation }}/dir/input.txt + "#, + r#" + input_file: + class: location + location: s3://bucket/dir/input.txt + "#, + )] + #[case( + json!({ + "inputLocation": "s3://bucket", + "suffixes": [1, 2, 3] + }), + r#" + input_file: + {% for suffix in suffixes %} + - class: File + location: {{ inputLocation }}/dir/input-{{ suffix }}.txt + {% endfor %} + "#, + r#" + input_file: + + - class: File + location: s3://bucket/dir/input-1.txt + + - class: File + location: s3://bucket/dir/input-2.txt + + - class: File + location: s3://bucket/dir/input-3.txt + + "#, + )] + fn test_render(#[case] content: Value, #[case] template: &str, #[case] expected: &str) { + let template_render = TemplateRender::new(content.clone(), template).unwrap(); + let rendered = template_render.render().unwrap(); + assert_eq!(rendered, expected); + } +}