use std::collections::HashMap;
use std::sync::Arc;
use crate::domain::error::{ConfigError, Result, StygianError};
use crate::ports::graphql_plugin::GraphQlTargetPlugin;
pub struct GraphQlPluginRegistry {
plugins: HashMap<String, Arc<dyn GraphQlTargetPlugin>>,
}
impl GraphQlPluginRegistry {
pub fn new() -> Self {
Self {
plugins: HashMap::new(),
}
}
pub fn register(&mut self, plugin: Arc<dyn GraphQlTargetPlugin>) {
self.plugins.insert(plugin.name().to_owned(), plugin);
}
pub fn get(&self, name: &str) -> Result<Arc<dyn GraphQlTargetPlugin>> {
self.plugins.get(name).cloned().ok_or_else(|| {
StygianError::Config(ConfigError::MissingConfig(format!(
"no GraphQL plugin registered for target '{name}'"
)))
})
}
pub fn list(&self) -> Vec<&str> {
self.plugins.keys().map(String::as_str).collect()
}
}
impl Default for GraphQlPluginRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
use crate::ports::graphql_plugin::GraphQlTargetPlugin;
struct Plugin(&'static str, &'static str);
impl GraphQlTargetPlugin for Plugin {
fn name(&self) -> &str {
self.0
}
fn endpoint(&self) -> &str {
self.1
}
}
#[test]
fn register_and_get_plugin() {
let mut registry = GraphQlPluginRegistry::new();
registry.register(Arc::new(Plugin(
"jobber",
"https://api.getjobber.com/api/graphql",
)));
let plugin = registry.get("jobber").unwrap();
assert_eq!(plugin.endpoint(), "https://api.getjobber.com/api/graphql");
}
#[test]
fn get_unknown_plugin_returns_error() {
let registry = GraphQlPluginRegistry::new();
assert!(
matches!(registry.get("unknown"), Err(StygianError::Config(_))),
"expected Config error for unregistered plugin"
);
}
#[test]
fn register_overwrites_previous() {
let mut registry = GraphQlPluginRegistry::new();
registry.register(Arc::new(Plugin("api", "https://v1.example.com/graphql")));
registry.register(Arc::new(Plugin("api", "https://v2.example.com/graphql")));
let plugin = registry.get("api").unwrap();
assert_eq!(plugin.endpoint(), "https://v2.example.com/graphql");
}
#[test]
fn list_returns_all_names() {
let mut registry = GraphQlPluginRegistry::new();
registry.register(Arc::new(Plugin("alpha", "https://a.example.com/graphql")));
registry.register(Arc::new(Plugin("beta", "https://b.example.com/graphql")));
let mut names = registry.list();
names.sort_unstable();
assert_eq!(names, vec!["alpha", "beta"]);
}
}