use tron::{TronTemplate, TronRef, TronAssembler, TronTemplateBuilder, TronRefBuilder, Result};
use tron::validation::TemplateValidator;
use std::collections::HashMap;
fn main() -> Result<()> {
println!("=== Tron Advanced Features Example ===\n");
example_rest_api_generation()?;
example_database_models()?;
example_configuration_driven()?;
example_build_integration()?;
Ok(())
}
fn example_rest_api_generation() -> Result<()> {
println!("1. REST API Code Generation:");
struct ApiEndpoint {
name: String,
method: String,
path: String,
request_type: Option<String>,
response_type: String,
description: String,
}
let endpoints = vec![
ApiEndpoint {
name: "get_users".to_string(),
method: "GET".to_string(),
path: "/api/users".to_string(),
request_type: None,
response_type: "Vec<User>".to_string(),
description: "Retrieve all users".to_string(),
},
ApiEndpoint {
name: "create_user".to_string(),
method: "POST".to_string(),
path: "/api/users".to_string(),
request_type: Some("CreateUserRequest".to_string()),
response_type: "User".to_string(),
description: "Create a new user".to_string(),
},
ApiEndpoint {
name: "get_user".to_string(),
method: "GET".to_string(),
path: "/api/users/{id}".to_string(),
request_type: None,
response_type: "User".to_string(),
description: "Retrieve a specific user".to_string(),
},
];
let mut assembler = TronAssembler::new();
let header = TronTemplate::new(r#"//! Auto-generated REST API handlers
//!
//! This module contains handlers for all REST API endpoints.
//! Generated by Tron Template Engine.
use axum::{
extract::{Path, Json},
response::Json as ResponseJson,
http::StatusCode,
};
use serde::{Deserialize, Serialize};
"#)?;
assembler.add_template(TronRef::new(header));
for endpoint in endpoints {
let handler_template = if endpoint.request_type.is_some() {
TronTemplate::new(r#"/// @[description]@
pub async fn @[handler_name]@(Json(payload): Json<@[request_type]@>) -> Result<ResponseJson<@[response_type]@>, StatusCode> {
// TODO: Implement @[method]@ @[path]@
todo!("Implement handler for @[handler_name]@")
}
"#)?
} else {
TronTemplate::new(r#"/// @[description]@
pub async fn @[handler_name]@() -> Result<ResponseJson<@[response_type]@>, StatusCode> {
// TODO: Implement @[method]@ @[path]@
todo!("Implement handler for @[handler_name]@")
}
"#)?
};
let mut handler_ref = TronRef::new(handler_template);
handler_ref.set("description", &endpoint.description)?;
handler_ref.set("handler_name", &endpoint.name)?;
handler_ref.set("method", &endpoint.method)?;
handler_ref.set("path", &endpoint.path)?;
handler_ref.set("response_type", &endpoint.response_type)?;
if let Some(ref req_type) = endpoint.request_type {
handler_ref.set("request_type", req_type)?;
}
assembler.add_template(handler_ref);
}
let router_template = TronTemplate::new(r#"/// Setup API routes
pub fn create_router() -> axum::Router {
axum::Router::new()
.route("/api/users", axum::routing::get(get_users).post(create_user))
.route("/api/users/:id", axum::routing::get(get_user))
}
"#)?;
assembler.add_template(TronRef::new(router_template));
let result = assembler.render_all()?;
println!("{}", result);
Ok(())
}
fn example_database_models() -> Result<()> {
println!("2. Database Model Generation:");
struct Column {
name: String,
rust_type: String,
sql_type: String,
nullable: bool,
primary_key: bool,
}
struct Table {
name: String,
columns: Vec<Column>,
}
let table = Table {
name: "users".to_string(),
columns: vec![
Column {
name: "id".to_string(),
rust_type: "i32".to_string(),
sql_type: "INTEGER".to_string(),
nullable: false,
primary_key: true,
},
Column {
name: "email".to_string(),
rust_type: "String".to_string(),
sql_type: "VARCHAR(255)".to_string(),
nullable: false,
primary_key: false,
},
Column {
name: "name".to_string(),
rust_type: "String".to_string(),
sql_type: "VARCHAR(100)".to_string(),
nullable: false,
primary_key: false,
},
Column {
name: "created_at".to_string(),
rust_type: "chrono::DateTime<chrono::Utc>".to_string(),
sql_type: "TIMESTAMP".to_string(),
nullable: false,
primary_key: false,
},
],
};
let struct_fields = table.columns
.iter()
.map(|col| {
let field_type = if col.nullable && !col.primary_key {
format!("Option<{}>", col.rust_type)
} else {
col.rust_type.clone()
};
format!(" pub {}: {},", col.name, field_type)
})
.collect::<Vec<_>>()
.join("\n");
let model = TronRefBuilder::new()
.content(r#"use serde::{Deserialize, Serialize};
use sqlx::FromRow;
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct @[struct_name]@ {
@[fields]@
}
impl @[struct_name]@ {
pub async fn find_by_id(pool: &sqlx::PgPool, id: i32) -> Result<Option<Self>, sqlx::Error> {
sqlx::query_as!(
Self,
"SELECT * FROM @[table_name]@ WHERE id = $1",
id
)
.fetch_optional(pool)
.await
}
pub async fn create(pool: &sqlx::PgPool, @[create_params]@) -> Result<Self, sqlx::Error> {
sqlx::query_as!(
Self,
"@[insert_query]@",
@[insert_params]@
)
.fetch_one(pool)
.await
}
}
"#)
.dependencies(&[
"serde = { version = \"1.0\", features = [\"derive\"] }",
"sqlx = { version = \"0.7\", features = [\"postgres\", \"chrono\", \"uuid\"] }",
"chrono = { version = \"0.4\", features = [\"serde\"] }"
])
.set("struct_name", "User")
.set("table_name", &table.name)
.set("fields", &struct_fields)
.set("create_params", "email: String, name: String")
.set("insert_query", "INSERT INTO users (email, name, created_at) VALUES ($1, $2, NOW()) RETURNING *")
.set("insert_params", "email, name")
.build()?;
let result = model.render()?;
println!("{}", result);
println!("Dependencies: {:?}", model.dependencies());
Ok(())
}
fn example_configuration_driven() -> Result<()> {
println!("3. Configuration-Driven Generation:");
let config = HashMap::from([
("project_name", "MyAwesomeApp"),
("version", "1.0.0"),
("author", "Tron User"),
("description", "An awesome application built with Tron templates"),
("license", "MIT"),
("rust_version", "1.70"),
]);
let cargo_toml = TronTemplateBuilder::new()
.content(r#"[package]
name = "@[project_name]@"
version = "@[version]@"
edition = "2021"
rust-version = "@[rust_version]@"
authors = ["@[author]@"]
description = "@[description]@"
license = "@[license]@"
repository = "https://github.com/@[author]@/@[project_name]@"
[dependencies]
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
clap = { version = "4.0", features = ["derive"] }
[dev-dependencies]
tokio-test = "0.4"
"#)
.set_many(config.clone())
.build()?;
println!("Generated Cargo.toml:");
println!("{}", cargo_toml.render()?);
let readme = TronTemplateBuilder::new()
.content(r#"# @[project_name]@
@[description]@
## Installation
```bash
cargo install @[project_name]@
```
## Usage
```rust
use @[project_name]@::*;
fn main() {
println!("Hello from @[project_name]@ v@[version]@!");
}
```
## License
This project is licensed under the @[license]@ License - see the [LICENSE](LICENSE) file for details.
## Author
@[author]@
"#)
.set_many(config)
.build()?;
println!("Generated README.md:");
println!("{}", readme.render()?);
Ok(())
}
fn example_build_integration() -> Result<()> {
println!("4. Template Validation in Build Process:");
let templates = vec![
("config.tpl", "const @[constant_name]@: &str = \"@[value]@\";"),
("api.tpl", "fn @[function_name]@(@[params]@) -> @[return_type]@ { @[body]@ }"),
("bad.tpl", "fn @[x]@() { @[a]@; }"), ];
let validator = TemplateValidator::new();
let mut all_valid = true;
for (name, content) in templates {
match TronTemplate::new(content) {
Ok(template) => {
let report = validator.validate(&template)?;
if report.has_errors() {
println!("❌ {} failed validation:", name);
for issue in report.issues() {
println!(" - {}", issue);
}
all_valid = false;
} else if report.has_issues() {
println!("⚠️ {} has warnings:", name);
for issue in report.issues() {
println!(" - {}", issue);
}
} else {
println!("✅ {} passed validation", name);
}
}
Err(e) => {
println!("❌ {} failed to parse: {}", name, e);
all_valid = false;
}
}
}
if all_valid {
println!("\n🎉 All critical validations passed! Build can continue.");
} else {
println!("\n💥 Some templates failed validation. Build should fail.");
}
println!("\n📦 Template Caching Simulation:");
let cache_key = "user_struct_v1";
println!(" Cache key: {}", cache_key);
let template = TronTemplate::new(r#"#[derive(Debug)]
pub struct User {
pub id: @[id_type]@,
pub name: String,
}
"#)?;
println!(" Template cached: {} bytes", template.content().len());
println!(" Placeholders: {:?}", template.placeholder_names());
Ok(())
}