use std::collections::HashMap;
use std::env;
use prax_schema::ModelStyle;
pub const PLUGIN_PREFIX: &str = "PRAX_PLUGIN_";
pub const PLUGINS_ALL: &str = "PRAX_PLUGINS_ALL";
pub const PLUGINS_ENABLED: &str = "PRAX_PLUGINS";
#[derive(Debug, Clone)]
pub struct PluginConfig {
all_enabled: bool,
overrides: HashMap<String, bool>,
enabled_list: Vec<String>,
model_style: ModelStyle,
}
impl Default for PluginConfig {
fn default() -> Self {
Self::from_env()
}
}
#[allow(dead_code)]
impl PluginConfig {
pub fn new() -> Self {
Self {
all_enabled: false,
overrides: HashMap::new(),
enabled_list: Vec::new(),
model_style: ModelStyle::default(),
}
}
pub fn all_enabled() -> Self {
Self {
all_enabled: true,
overrides: HashMap::new(),
enabled_list: Vec::new(),
model_style: ModelStyle::default(),
}
}
pub fn from_env() -> Self {
let mut config = Self::new();
if let Ok(val) = env::var(PLUGINS_ALL) {
config.all_enabled = is_truthy(&val);
}
if let Ok(val) = env::var(PLUGINS_ENABLED) {
config.enabled_list = val
.split(',')
.map(|s| s.trim().to_lowercase())
.filter(|s| !s.is_empty())
.collect();
}
for (key, value) in env::vars() {
if let Some(plugin_name) = key.strip_prefix(PLUGIN_PREFIX) {
let plugin_name = plugin_name.to_lowercase();
if plugin_name == "all" || plugin_name == "s" {
continue;
}
config.overrides.insert(key, is_truthy(&value));
}
}
config
}
pub fn is_enabled(&self, env_var: &str) -> bool {
if let Some(&enabled) = self.overrides.get(env_var) {
return enabled;
}
if !self.enabled_list.is_empty() {
if let Some(name) = env_var.strip_prefix(PLUGIN_PREFIX) {
let name_lower = name.to_lowercase();
if self.enabled_list.contains(&name_lower) {
return true;
}
}
}
self.all_enabled
}
pub fn is_enabled_by_name(&self, name: &str) -> bool {
let env_var = format!("{}{}", PLUGIN_PREFIX, name.to_uppercase());
self.is_enabled(&env_var)
}
pub fn enable(&mut self, env_var: &str) {
self.overrides.insert(env_var.to_string(), true);
}
pub fn disable(&mut self, env_var: &str) {
self.overrides.insert(env_var.to_string(), false);
}
pub fn enable_by_name(&mut self, name: &str) {
let env_var = format!("{}{}", PLUGIN_PREFIX, name.to_uppercase());
self.enable(&env_var);
}
pub fn disable_by_name(&mut self, name: &str) {
let env_var = format!("{}{}", PLUGIN_PREFIX, name.to_uppercase());
self.disable(&env_var);
}
pub fn overrides(&self) -> &HashMap<String, bool> {
&self.overrides
}
pub fn all_plugins_enabled(&self) -> bool {
self.all_enabled
}
pub fn model_style(&self) -> ModelStyle {
self.model_style
}
pub fn set_model_style(&mut self, style: ModelStyle) {
self.model_style = style;
if style.is_graphql() {
self.enable_by_name("graphql");
self.enable_by_name("graphql_async");
}
}
pub fn with_model_style(style: ModelStyle) -> Self {
let mut config = Self::from_env();
config.set_model_style(style);
config
}
}
fn is_truthy(value: &str) -> bool {
matches!(
value.to_lowercase().as_str(),
"1" | "true" | "yes" | "on" | "enabled"
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_truthy() {
assert!(is_truthy("1"));
assert!(is_truthy("true"));
assert!(is_truthy("TRUE"));
assert!(is_truthy("yes"));
assert!(is_truthy("on"));
assert!(is_truthy("enabled"));
assert!(!is_truthy("0"));
assert!(!is_truthy("false"));
assert!(!is_truthy("no"));
assert!(!is_truthy("off"));
assert!(!is_truthy(""));
}
#[test]
fn test_plugin_config_new() {
let config = PluginConfig::new();
assert!(!config.all_plugins_enabled());
assert!(!config.is_enabled("PRAX_PLUGIN_DEBUG"));
}
#[test]
fn test_plugin_config_all_enabled() {
let config = PluginConfig::all_enabled();
assert!(config.all_plugins_enabled());
assert!(config.is_enabled("PRAX_PLUGIN_DEBUG"));
assert!(config.is_enabled("PRAX_PLUGIN_ANYTHING"));
}
#[test]
fn test_plugin_config_override() {
let mut config = PluginConfig::all_enabled();
config.disable("PRAX_PLUGIN_DEBUG");
assert!(config.is_enabled("PRAX_PLUGIN_JSON_SCHEMA"));
assert!(!config.is_enabled("PRAX_PLUGIN_DEBUG"));
}
#[test]
fn test_plugin_config_enable_by_name() {
let mut config = PluginConfig::new();
config.enable_by_name("debug");
assert!(config.is_enabled("PRAX_PLUGIN_DEBUG"));
assert!(!config.is_enabled("PRAX_PLUGIN_OTHER"));
}
#[test]
fn test_plugin_config_is_enabled_by_name() {
let mut config = PluginConfig::new();
config.enable_by_name("json_schema");
assert!(config.is_enabled_by_name("json_schema"));
assert!(!config.is_enabled_by_name("debug"));
}
}