kroki_rs/diagrams/
registry.rs1use crate::browser::BrowserManager;
2use crate::capabilities::Capabilities;
3use crate::diagrams::{
4 providers::{
5 bpmn::BpmnProvider,
6 cmd::CommandProvider,
7 d2::D2Provider,
8 ditaa::DitaaProvider,
9 excalidraw::ExcalidrawProvider,
10 mermaid::MermaidProvider,
11 vega::{VegaLiteProvider, VegaProvider},
12 wavedrom::WavedromProvider,
13 },
14 DiagramProvider,
15};
16use std::collections::HashMap;
17use std::sync::Arc;
18
19pub struct DiagramRegistry {
20 providers: HashMap<String, Arc<dyn DiagramProvider + Send + Sync>>,
21}
22
23impl DiagramRegistry {
24 pub fn new(
25 capabilities: &Capabilities,
26 config: &crate::config::Config,
27 browser_manager: Option<Arc<BrowserManager>>,
28 ) -> Self {
29 let mut providers: HashMap<String, Arc<dyn DiagramProvider + Send + Sync>> = HashMap::new();
30
31 if let Some(path) = &capabilities.graphviz {
32 let provider = Arc::new(CommandProvider::new(
33 path.clone(),
34 config.graphviz.timeout_ms,
35 )) as Arc<dyn DiagramProvider + Send + Sync>;
36 providers.insert("graphviz".to_string(), provider.clone());
37 providers.insert("dot".to_string(), provider);
38 }
39
40 if let (Some(_), Some(browser)) = (&capabilities.mermaid, &browser_manager) {
41 let provider = Arc::new(MermaidProvider::new(
42 browser.clone(),
43 config.mermaid.timeout_ms,
44 )) as Arc<dyn DiagramProvider + Send + Sync>;
45 providers.insert("mermaid".to_string(), provider);
46 }
47
48 if let Some(path) = &capabilities.vega {
49 let provider = Arc::new(VegaProvider::new(path.clone(), config.vega.timeout_ms))
50 as Arc<dyn DiagramProvider + Send + Sync>;
51 providers.insert("vega".to_string(), provider);
52 }
53
54 if let Some(vl_path) = &capabilities.vegalite {
55 if let Some(vg_path) = &capabilities.vega {
56 let provider = Arc::new(VegaLiteProvider::new(
57 vl_path.clone(),
58 vg_path.clone(),
59 config.vegalite.timeout_ms,
60 )) as Arc<dyn DiagramProvider + Send + Sync>;
61 providers.insert("vegalite".to_string(), provider);
62 }
63 }
64
65 if let Some(path) = &capabilities.wavedrom {
66 let provider = Arc::new(WavedromProvider::new(
67 path.clone(),
68 config.wavedrom.timeout_ms,
69 )) as Arc<dyn DiagramProvider + Send + Sync>;
70 providers.insert("wavedrom".to_string(), provider);
71 }
72
73 if let (Some(_), Some(browser)) = (&capabilities.bpmn, &browser_manager) {
74 let provider = Arc::new(BpmnProvider::new(browser.clone(), config.bpmn.timeout_ms))
75 as Arc<dyn DiagramProvider + Send + Sync>;
76 providers.insert("bpmn".to_string(), provider);
77 }
78
79 if let Some(path) = &capabilities.d2 {
80 let provider = Arc::new(D2Provider::new(path.clone(), config.d2.timeout_ms))
81 as Arc<dyn DiagramProvider + Send + Sync>;
82 providers.insert("d2".to_string(), provider);
83 }
84
85 if let Some(path) = &capabilities.ditaa {
86 let provider = Arc::new(DitaaProvider::new(path.clone(), config.ditaa.timeout_ms))
87 as Arc<dyn DiagramProvider + Send + Sync>;
88 providers.insert("ditaa".to_string(), provider);
89 }
90
91 if let Some(path) = &capabilities.excalidraw {
92 let provider = Arc::new(ExcalidrawProvider::new(
93 path.clone(),
94 config.excalidraw.timeout_ms,
95 )) as Arc<dyn DiagramProvider + Send + Sync>;
96 providers.insert("excalidraw".to_string(), provider);
97 }
98
99 for plugin_cfg in &config.plugins {
101 if providers.contains_key(&plugin_cfg.name) {
102 tracing::error!(
103 "Plugin collision: '{}' already exists as a built-in provider. Skipping.",
104 plugin_cfg.name
105 );
106 continue;
107 }
108
109 tracing::info!("Registering custom plugin: {}", plugin_cfg.name);
110 let provider = Arc::new(crate::diagrams::providers::plugin::PluginProvider::new(
111 plugin_cfg,
112 )) as Arc<dyn DiagramProvider + Send + Sync>;
113 providers.insert(plugin_cfg.name.clone(), provider);
114 }
115
116 Self { providers }
117 }
118
119 pub fn get(&self, name: &str) -> Option<Arc<dyn DiagramProvider + Send + Sync>> {
121 self.providers.get(name).cloned()
122 }
123
124 pub fn known_types(&self) -> Vec<String> {
126 let mut types: Vec<String> = self.providers.keys().cloned().collect();
127 types.sort();
128 types
129 }
130}