232 lines
8.7 KiB
Rust
232 lines
8.7 KiB
Rust
|
|
//! Build script template demonstrating configuration traits usage
|
||
|
|
//!
|
||
|
|
//! This build script shows how to use Rustelo's configuration traits
|
||
|
|
//! to generate compile-time constants and build artifacts.
|
||
|
|
|
||
|
|
use rustelo_core_types::traits_config::*;
|
||
|
|
use std::env;
|
||
|
|
use std::path::{Path, PathBuf};
|
||
|
|
use std::error::Error;
|
||
|
|
|
||
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
||
|
|
// Get build environment
|
||
|
|
let out_dir = env::var("OUT_DIR")?;
|
||
|
|
let manifest_dir = env::var("CARGO_MANIFEST_DIR")?;
|
||
|
|
let project_root = Path::new(&manifest_dir);
|
||
|
|
|
||
|
|
println!("cargo:rerun-if-changed=config");
|
||
|
|
println!("cargo:rerun-if-changed=config.toml");
|
||
|
|
println!("cargo:rerun-if-changed=.env");
|
||
|
|
|
||
|
|
// Example 1: Using a custom configuration resolver
|
||
|
|
generate_config_with_custom_resolver(&project_root, &out_dir)?;
|
||
|
|
|
||
|
|
// Example 2: Generate environment-specific constants
|
||
|
|
generate_environment_constants(&project_root, &out_dir)?;
|
||
|
|
|
||
|
|
// Example 3: Feature-based configuration
|
||
|
|
generate_feature_constants(&project_root, &out_dir)?;
|
||
|
|
|
||
|
|
println!("cargo:warning=Configuration build completed successfully");
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Example of using a custom configuration resolver with traits
|
||
|
|
fn generate_config_with_custom_resolver(
|
||
|
|
project_root: &Path,
|
||
|
|
out_dir: &str
|
||
|
|
) -> Result<(), Box<dyn Error>> {
|
||
|
|
// This would use your custom resolver implementation
|
||
|
|
// For this example, we'll create a simple resolver
|
||
|
|
|
||
|
|
let config = ExampleConfig {
|
||
|
|
server_host: env::var("SERVER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()),
|
||
|
|
server_port: env::var("SERVER_PORT")
|
||
|
|
.unwrap_or_else(|_| "3030".to_string())
|
||
|
|
.parse()
|
||
|
|
.unwrap_or(3030),
|
||
|
|
content_path: env::var("SITE_CONTENT_PATH")
|
||
|
|
.map(PathBuf::from)
|
||
|
|
.unwrap_or_else(|_| PathBuf::from("content")),
|
||
|
|
debug_mode: env::var("DEBUG")
|
||
|
|
.unwrap_or_else(|_| "true".to_string())
|
||
|
|
.parse()
|
||
|
|
.unwrap_or(true),
|
||
|
|
};
|
||
|
|
|
||
|
|
// Generate WASM constants using trait
|
||
|
|
let resolver = ExampleResolver;
|
||
|
|
let constants = resolver.generate_constants(&config);
|
||
|
|
|
||
|
|
let out_path = Path::new(out_dir).join("server_config_constants.rs");
|
||
|
|
resolver.write_constants_file(&constants, &out_path)?;
|
||
|
|
|
||
|
|
println!("cargo:warning=Generated server config constants at: {}", out_path.display());
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Generate environment-specific constants
|
||
|
|
fn generate_environment_constants(
|
||
|
|
project_root: &Path,
|
||
|
|
out_dir: &str
|
||
|
|
) -> Result<(), Box<dyn Error>> {
|
||
|
|
let environment = env::var("RUSTELO_ENV").unwrap_or_else(|_| "development".to_string());
|
||
|
|
|
||
|
|
let mut constants = WasmConstants::new();
|
||
|
|
constants.add_string("BUILD_ENVIRONMENT", environment.clone());
|
||
|
|
constants.add_string("BUILD_TIMESTAMP", chrono::Utc::now().to_rfc3339());
|
||
|
|
constants.add_boolean("IS_PRODUCTION", environment == "production");
|
||
|
|
constants.add_boolean("IS_DEVELOPMENT", environment == "development");
|
||
|
|
|
||
|
|
// Add environment-specific settings
|
||
|
|
match environment.as_str() {
|
||
|
|
"production" => {
|
||
|
|
constants.add_boolean("ENABLE_DEBUG_LOGS", false);
|
||
|
|
constants.add_boolean("ENABLE_PERFORMANCE_METRICS", true);
|
||
|
|
constants.add_numeric("LOG_LEVEL", 2); // WARN
|
||
|
|
}
|
||
|
|
"development" => {
|
||
|
|
constants.add_boolean("ENABLE_DEBUG_LOGS", true);
|
||
|
|
constants.add_boolean("ENABLE_PERFORMANCE_METRICS", false);
|
||
|
|
constants.add_numeric("LOG_LEVEL", 0); // DEBUG
|
||
|
|
}
|
||
|
|
"staging" => {
|
||
|
|
constants.add_boolean("ENABLE_DEBUG_LOGS", true);
|
||
|
|
constants.add_boolean("ENABLE_PERFORMANCE_METRICS", true);
|
||
|
|
constants.add_numeric("LOG_LEVEL", 1); // INFO
|
||
|
|
}
|
||
|
|
_ => {
|
||
|
|
constants.add_boolean("ENABLE_DEBUG_LOGS", true);
|
||
|
|
constants.add_boolean("ENABLE_PERFORMANCE_METRICS", false);
|
||
|
|
constants.add_numeric("LOG_LEVEL", 0); // DEBUG
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let code = constants.generate_rust_code();
|
||
|
|
let out_path = Path::new(out_dir).join("environment_constants.rs");
|
||
|
|
std::fs::write(&out_path, code)?;
|
||
|
|
|
||
|
|
println!("cargo:warning=Generated environment constants for '{}' at: {}", environment, out_path.display());
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Generate feature-based constants
|
||
|
|
fn generate_feature_constants(
|
||
|
|
project_root: &Path,
|
||
|
|
out_dir: &str
|
||
|
|
) -> Result<(), Box<dyn Error>> {
|
||
|
|
let mut constants = WasmConstants::new();
|
||
|
|
|
||
|
|
// Check which Cargo features are enabled and generate corresponding constants
|
||
|
|
constants.add_boolean("FEATURE_AUTH", cfg!(feature = "auth"));
|
||
|
|
constants.add_boolean("FEATURE_CONTENT_DB", cfg!(feature = "content-db"));
|
||
|
|
constants.add_boolean("FEATURE_EMAIL", cfg!(feature = "email"));
|
||
|
|
constants.add_boolean("FEATURE_TLS", cfg!(feature = "tls"));
|
||
|
|
constants.add_boolean("FEATURE_METRICS", cfg!(feature = "metrics"));
|
||
|
|
constants.add_boolean("FEATURE_CRYPTO", cfg!(feature = "crypto"));
|
||
|
|
|
||
|
|
// Add feature-specific configuration
|
||
|
|
if cfg!(feature = "auth") {
|
||
|
|
constants.add_string("AUTH_JWT_ALGORITHM", "HS256");
|
||
|
|
constants.add_numeric("AUTH_TOKEN_EXPIRY_HOURS", 24);
|
||
|
|
}
|
||
|
|
|
||
|
|
if cfg!(feature = "content-db") {
|
||
|
|
constants.add_string("CONTENT_STORAGE_TYPE", "database");
|
||
|
|
} else {
|
||
|
|
constants.add_string("CONTENT_STORAGE_TYPE", "filesystem");
|
||
|
|
}
|
||
|
|
|
||
|
|
if cfg!(feature = "metrics") {
|
||
|
|
constants.add_string("METRICS_ENDPOINT", "/metrics");
|
||
|
|
constants.add_boolean("METRICS_ENABLED", true);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add build-time feature detection functions
|
||
|
|
let mut feature_code = constants.generate_rust_code();
|
||
|
|
feature_code.push_str("\n// Feature detection functions\n");
|
||
|
|
feature_code.push_str("pub fn has_auth_feature() -> bool { FEATURE_AUTH }\n");
|
||
|
|
feature_code.push_str("pub fn has_database_content() -> bool { FEATURE_CONTENT_DB }\n");
|
||
|
|
feature_code.push_str("pub fn has_email_feature() -> bool { FEATURE_EMAIL }\n");
|
||
|
|
feature_code.push_str("pub fn has_tls_feature() -> bool { FEATURE_TLS }\n");
|
||
|
|
feature_code.push_str("pub fn has_metrics_feature() -> bool { FEATURE_METRICS }\n");
|
||
|
|
feature_code.push_str("pub fn has_crypto_feature() -> bool { FEATURE_CRYPTO }\n");
|
||
|
|
|
||
|
|
feature_code.push_str("\n// Runtime feature configuration\n");
|
||
|
|
feature_code.push_str("pub fn get_enabled_features() -> Vec<&'static str> {\n");
|
||
|
|
feature_code.push_str(" let mut features = Vec::new();\n");
|
||
|
|
feature_code.push_str(" if FEATURE_AUTH { features.push(\"auth\"); }\n");
|
||
|
|
feature_code.push_str(" if FEATURE_CONTENT_DB { features.push(\"content-db\"); }\n");
|
||
|
|
feature_code.push_str(" if FEATURE_EMAIL { features.push(\"email\"); }\n");
|
||
|
|
feature_code.push_str(" if FEATURE_TLS { features.push(\"tls\"); }\n");
|
||
|
|
feature_code.push_str(" if FEATURE_METRICS { features.push(\"metrics\"); }\n");
|
||
|
|
feature_code.push_str(" if FEATURE_CRYPTO { features.push(\"crypto\"); }\n");
|
||
|
|
feature_code.push_str(" features\n");
|
||
|
|
feature_code.push_str("}\n");
|
||
|
|
|
||
|
|
let out_path = Path::new(out_dir).join("feature_constants.rs");
|
||
|
|
std::fs::write(&out_path, feature_code)?;
|
||
|
|
|
||
|
|
println!("cargo:warning=Generated feature constants at: {}", out_path.display());
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Example configuration structure
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
struct ExampleConfig {
|
||
|
|
server_host: String,
|
||
|
|
server_port: u16,
|
||
|
|
content_path: PathBuf,
|
||
|
|
debug_mode: bool,
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Example resolver implementation
|
||
|
|
struct ExampleResolver;
|
||
|
|
|
||
|
|
impl WasmConstantGenerator for ExampleResolver {
|
||
|
|
type Config = ExampleConfig;
|
||
|
|
|
||
|
|
fn generate_constants(&self, config: &Self::Config) -> WasmConstants {
|
||
|
|
let mut constants = WasmConstants::new();
|
||
|
|
|
||
|
|
constants.add_string("SERVER_HOST", &config.server_host);
|
||
|
|
constants.add_numeric("SERVER_PORT", config.server_port as i64);
|
||
|
|
constants.add_path("CONTENT_PATH", config.content_path.clone());
|
||
|
|
constants.add_boolean("DEBUG_MODE", config.debug_mode);
|
||
|
|
|
||
|
|
// Add derived constants
|
||
|
|
constants.add_string("SERVER_URL",
|
||
|
|
format!("http://{}:{}", config.server_host, config.server_port));
|
||
|
|
|
||
|
|
constants
|
||
|
|
}
|
||
|
|
|
||
|
|
fn write_constants_file(
|
||
|
|
&self,
|
||
|
|
constants: &WasmConstants,
|
||
|
|
out_path: &Path,
|
||
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||
|
|
let mut code = constants.generate_rust_code();
|
||
|
|
|
||
|
|
// Add convenience functions
|
||
|
|
code.push_str("\n// Convenience functions\n");
|
||
|
|
code.push_str("pub fn get_server_url() -> String {\n");
|
||
|
|
code.push_str(" format!(\"http://{}:{}\", SERVER_HOST, SERVER_PORT)\n");
|
||
|
|
code.push_str("}\n\n");
|
||
|
|
|
||
|
|
code.push_str("pub fn is_debug_build() -> bool {\n");
|
||
|
|
code.push_str(" DEBUG_MODE\n");
|
||
|
|
code.push_str("}\n\n");
|
||
|
|
|
||
|
|
code.push_str("pub fn get_content_path() -> &'static str {\n");
|
||
|
|
code.push_str(" CONTENT_PATH\n");
|
||
|
|
code.push_str("}\n");
|
||
|
|
|
||
|
|
std::fs::write(out_path, code)?;
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
}
|