GitRoot

craft your forge, build your project, grow your community freely
 1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
 2//
 3// SPDX-License-Identifier: MIT
 4
 5use crate::{Plugin, PluginReporter, PluginRun, Server, imports};
 6use std::sync::{Arc, OnceLock};
 7
 8type DynServer = Arc<Server>;
 9type DynPlugin = Arc<dyn Plugin + Send + Sync>;
10type DynPluginReporter = Arc<dyn PluginReporter + Send + Sync>;
11
12static INSTANCE: OnceLock<DynServer> = OnceLock::new();
13static PLUGIN: OnceLock<DynPlugin> = OnceLock::new();
14static PLUGIN_REPORTER: OnceLock<DynPluginReporter> = OnceLock::new();
15
16pub fn register<T, F>(run: Vec<PluginRun>, plugin_factory: F)
17where
18    T: Plugin + Send + Sync,
19    F: FnOnce(DynServer) -> T,
20{
21    let _ = INSTANCE.set(Arc::new(Server::new(run)));
22    let static_server = INSTANCE.get().unwrap();
23    let _ = PLUGIN.set(Arc::new(plugin_factory(static_server.clone())));
24}
25
26pub fn register_reporter<T, F>(run: Vec<PluginRun>, plugin_factory: F)
27where
28    T: PluginReporter + Send + Sync,
29    F: FnOnce(DynServer) -> T,
30{
31    let _ = INSTANCE.set(Arc::new(Server::new(run)));
32    let static_server = INSTANCE.get().unwrap();
33    let _ = PLUGIN_REPORTER.set(Arc::new(plugin_factory(static_server.clone())));
34}
35
36pub fn get() -> DynServer {
37    INSTANCE
38        .get()
39        .expect("Server has not been initialized. Call Server::init() first.")
40        .clone()
41}
42
43pub fn with_plugin<F>(f: F)
44where
45    F: FnOnce(DynPlugin) -> Result<(), String>,
46{
47    if let Some(plugin) = PLUGIN.get() {
48        let _ = f(plugin.clone()).map_err(|err| imports::log_error("unknown error", err.as_ref()));
49    } else if let Some(plugin) = PLUGIN_REPORTER.get() {
50        let _ = f(plugin.clone()).map_err(|err| imports::log_error("unknown error", err.as_ref()));
51    } else {
52        imports::log_error(
53            "Plugin not initialized after server was created",
54            "Fatal error",
55        );
56    }
57}
58
59pub fn with_plugin_reporter<F>(f: F)
60where
61    F: FnOnce(DynPluginReporter) -> Result<(), String>,
62{
63    if let Some(plugin) = PLUGIN_REPORTER.get() {
64        let _ = f(plugin.clone()).map_err(|err| imports::log_error("unknown error", err.as_ref()));
65    } //no else the plugin is not a reporter
66}