diff --git a/crates/server/src/config.rs b/crates/server/src/config.rs new file mode 100644 index 0000000..a1bb6ea --- /dev/null +++ b/crates/server/src/config.rs @@ -0,0 +1,21 @@ +use clap::Parser; + +/// Runtime configuration, sourced from CLI arguments and environment variables. +#[derive(Debug, Clone, Parser)] +#[command(version, about = "Collection management system server")] +pub struct Config { + /// PostgreSQL connection string. + #[arg(long, env = "DATABASE_URL")] + pub database_url: String, + + /// Address to bind the HTTP server to. + #[arg(long, env = "BIND_ADDR", default_value = "0.0.0.0:8080")] + pub bind_addr: String, + + /// User-facing application name (OpenAPI title, page title, …). + /// + /// Defaults to a neutral name; set this to the real product name at deploy + /// time. The product name must never be hardcoded in source. + #[arg(long, env = "APP_NAME", default_value = "Collection Management System")] + pub app_name: String, +} diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs index 9c7c8dc..30138bc 100644 --- a/crates/server/src/lib.rs +++ b/crates/server/src/lib.rs @@ -1 +1,5 @@ //! Server wiring: configuration and startup. + +mod config; + +pub use config::Config; diff --git a/crates/server/tests/config.rs b/crates/server/tests/config.rs new file mode 100644 index 0000000..d921ff5 --- /dev/null +++ b/crates/server/tests/config.rs @@ -0,0 +1,17 @@ +use clap::Parser; +use server::Config; + +#[test] +fn parses_from_args_with_defaults() { + let cfg = Config::try_parse_from(["server", "--database-url", "postgres://localhost/test"]) + .expect("should parse"); + + assert_eq!(cfg.database_url, "postgres://localhost/test"); + assert_eq!(cfg.bind_addr, "0.0.0.0:8080"); + assert_eq!(cfg.app_name, "Collection Management System"); +} + +#[test] +fn database_url_is_required() { + assert!(Config::try_parse_from(["server"]).is_err()); +}