From bd69bba05c56eed9e454d85e356a87970cc5f1e5 Mon Sep 17 00:00:00 2001 From: itowlson Date: Thu, 1 May 2025 09:41:07 +1200 Subject: [PATCH] More comprehensive templates Signed-off-by: itowlson --- crates/templates/src/manager.rs | 1 + crates/templates/src/renderer.rs | 4 ++-- crates/templates/src/run.rs | 28 +++++++++++++++++----- crates/templates/src/test_built_ins/mod.rs | 3 +++ src/commands/new.rs | 7 ++++++ templates/http-rust/content/spin.toml | 15 ++++++++++++ 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/crates/templates/src/manager.rs b/crates/templates/src/manager.rs index d073088dc7..369b711018 100644 --- a/crates/templates/src/manager.rs +++ b/crates/templates/src/manager.rs @@ -539,6 +539,7 @@ mod tests { accept_defaults: false, no_vcs: false, allow_overwrite: false, + explain: false, }; rest(&mut options); options diff --git a/crates/templates/src/renderer.rs b/crates/templates/src/renderer.rs index faf0233ca3..35b431c6d4 100644 --- a/crates/templates/src/renderer.rs +++ b/crates/templates/src/renderer.rs @@ -8,7 +8,7 @@ use crate::writer::{TemplateOutput, TemplateOutputs}; // it needs to render. pub(crate) struct TemplateRenderer { pub render_operations: Vec, - pub parameter_values: HashMap, + pub parameter_values: HashMap, } pub(crate) enum TemplateContent { @@ -50,7 +50,7 @@ impl TemplateRenderer { for (k, v) in &self.parameter_values { object.insert( k.to_owned().into(), - liquid_core::Value::Scalar(v.to_owned().into()), + liquid_core::Value::Scalar(v.to_owned()), ); } diff --git a/crates/templates/src/run.rs b/crates/templates/src/run.rs index 9b9cb215df..b1881ec83c 100644 --- a/crates/templates/src/run.rs +++ b/crates/templates/src/run.rs @@ -46,6 +46,8 @@ pub struct RunOptions { /// Skip the overwrite prompt if the output directory already contains files /// (or, if silent, allow overwrite instead of erroring). pub allow_overwrite: bool, + /// The user has asked for additional explanatory information + pub explain: bool, } impl Run { @@ -144,7 +146,7 @@ impl Run { .special_values() .await .into_iter() - .chain(parameter_values) + .chain(liquefy_values(parameter_values)) .collect(); let prepared_template = TemplateRenderer { render_operations, @@ -184,16 +186,23 @@ impl Run { Ok(file_ops) } - async fn special_values(&self) -> HashMap { + async fn special_values(&self) -> HashMap { let mut values = HashMap::new(); let authors = crate::environment::get_authors().await.unwrap_or_default(); - values.insert("authors".into(), authors.author); - values.insert("username".into(), authors.username); - values.insert("project-name".into(), self.options.name.clone()); + values.insert("authors".into(), liquid_core::scalar!(authors.author)); + values.insert("username".into(), liquid_core::scalar!(authors.username)); + values.insert( + "project-name".into(), + liquid_core::scalar!(self.options.name.clone()), + ); values.insert( "output-path".into(), - self.relative_target_dir().to_string_lossy().to_string(), + liquid_core::scalar!(self.relative_target_dir().to_string_lossy().to_string()), + ); + values.insert( + "explain".to_owned(), + liquid_core::scalar!(self.options.explain), ); values @@ -455,6 +464,13 @@ impl Run { } } +fn liquefy_values( + map: HashMap, +) -> impl Iterator { + map.into_iter() + .map(|(k, v)| (k, liquid_core::scalar!(v.to_owned()))) +} + #[cfg(test)] mod test { use super::*; diff --git a/crates/templates/src/test_built_ins/mod.rs b/crates/templates/src/test_built_ins/mod.rs index aeb335b8a4..65263a8eb7 100644 --- a/crates/templates/src/test_built_ins/mod.rs +++ b/crates/templates/src/test_built_ins/mod.rs @@ -40,6 +40,7 @@ async fn new_fileserver_creates_assets_dir() -> anyhow::Result<()> { accept_defaults: true, no_vcs: false, allow_overwrite: false, + explain: false, }; manager .get("static-fileserver")? @@ -87,6 +88,7 @@ async fn add_fileserver_creates_assets_dir_next_to_manifest() -> anyhow::Result< accept_defaults: true, no_vcs: false, allow_overwrite: false, + explain: false, }; manager .get("http-empty")? @@ -107,6 +109,7 @@ async fn add_fileserver_creates_assets_dir_next_to_manifest() -> anyhow::Result< accept_defaults: true, no_vcs: false, allow_overwrite: false, + explain: false, }; manager .get("static-fileserver")? diff --git a/src/commands/new.rs b/src/commands/new.rs index 59b9c52e16..3cf487b2cf 100644 --- a/src/commands/new.rs +++ b/src/commands/new.rs @@ -76,6 +76,12 @@ pub struct TemplateNewCommandCore { takes_value = false )] pub allow_overwrite: bool, + + /// Include additional explanatory information, where available, in the generated code. + /// This can be useful for learning about available options, but some users will find + /// the extra output burdensome. + #[clap(long = "explain", takes_value = false)] + explain: bool, } /// Scaffold a new application based on a template. @@ -195,6 +201,7 @@ impl TemplateNewCommandCore { accept_defaults: self.accept_defaults, no_vcs: self.no_vcs, allow_overwrite: self.allow_overwrite, + explain: self.explain, }; let run = template.run(options); diff --git a/templates/http-rust/content/spin.toml b/templates/http-rust/content/spin.toml index de01ce2605..012ade19f7 100644 --- a/templates/http-rust/content/spin.toml +++ b/templates/http-rust/content/spin.toml @@ -12,7 +12,22 @@ component = "{{project-name | kebab_case}}" [component.{{project-name | kebab_case}}] source = "target/wasm32-wasip1/release/{{project-name | snake_case}}.wasm" +{% if explain %}# The network hosts to which the component may make requests to. E.g. ["https://example.com", "postgres://data.example.com:4004"] +# Learn more: https://spinframework.dev/v3/http-outbound#granting-http-permissions-to-components, https://spinframework.dev/v3/mqtt-outbound#granting-network-permissions-to-components, https://spinframework.dev/v3/rdbms-storage#granting-network-permissions-to-components allowed_outbound_hosts = [] +# The files from your host system that should be included in the application and available to the component. E.g. [{ source = "assets", destination = "/"}] +# Learn more: https://spinframework.dev/v3/writing-apps#including-files-with-components +files = [] +# The key-value stores the component should have access to. E.g. ["default", "cache"]. Learn more: https://spinframework.dev/v3/kv-store-api-guide#granting-key-value-store-permissions-to-components +# Non-default stores must be mapped in a runtime config file. Learn more: https://spinframework.dev/v3/dynamic-configuration#key-value-store-runtime-configuration +key_value_stores = [] +# The SQLite databases the component should have access to. E.g. ["default", "accounts"]. Learn more: https://spinframework.dev/v3/sqlite-api-guide#granting-sqlite-database-permissions-to-components +# Non-default databases must be mapped in a runtime config file. Learn more: hhttps://spinframework.dev/v3/dynamic-configuration#sqlite-storage-runtime-configuration +sqlite_databases = [] + +[component.{{project-name | kebab_case}}.dependencies] +# Wasm components on which your Wasm binary depends. Learn more: https://spinframework.dev/v3/writing-apps#using-component-dependencies +{% else %}allowed_outbound_hosts = []{% endif %} [component.{{project-name | kebab_case}}.build] command = "cargo build --target wasm32-wasip1 --release" watch = ["src/**/*.rs", "Cargo.toml"]