sova_notifications/
plugin.rs1use crate::channel::Channel;
4use crate::http::mount_routes;
5use crate::notify::NotificationService;
6use sova_core::extend::{IntoMwEntry, MwEntry};
7use sova_core::{App, Plugin, Router};
8use std::collections::HashMap;
9use std::sync::Arc;
10
11pub struct Notifications {
13 channels: HashMap<String, Channel>,
14 mount: Option<String>,
15 guard: Option<MwEntry>,
16 #[cfg(feature = "ws")]
17 ws_path: Option<String>,
18 #[cfg(feature = "templates")]
19 template_helpers: bool,
20}
21
22impl Notifications {
23 pub fn new() -> Self {
24 let mut channels = HashMap::new();
25 channels.insert("default".into(), Channel::new("default"));
26 Self {
27 channels,
28 mount: None,
29 guard: None,
30 #[cfg(feature = "ws")]
31 ws_path: None,
32 #[cfg(feature = "templates")]
33 template_helpers: false,
34 }
35 }
36
37 pub fn channel(mut self, ch: Channel) -> Self {
38 self.channels.insert(ch.slug.clone(), ch);
39 self
40 }
41
42 pub fn mount(mut self, path: impl Into<String>) -> Self {
44 self.mount = Some(path.into());
45 self
46 }
47
48 pub fn guard(mut self, mw: impl IntoMwEntry) -> Self {
49 self.guard = Some(mw.into_mw_entry());
50 self
51 }
52
53 #[cfg(feature = "ws")]
55 pub fn ws_path(mut self, path: impl Into<String>) -> Self {
56 self.ws_path = Some(path.into());
57 self
58 }
59
60 #[cfg(feature = "templates")]
62 pub fn with_template_helpers(mut self) -> Self {
63 self.template_helpers = true;
64 self
65 }
66}
67
68impl Default for Notifications {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74impl Plugin for Notifications {
75 fn id(&self) -> &'static str {
76 "notifications"
77 }
78
79 fn requires(&self) -> &'static [&'static str] {
80 #[cfg(all(feature = "ws", feature = "templates"))]
81 if self.ws_path.is_some() && self.template_helpers {
82 return &["db", "ws", "templates"];
83 }
84 #[cfg(feature = "ws")]
85 if self.ws_path.is_some() {
86 return &["db", "ws"];
87 }
88 #[cfg(feature = "templates")]
89 if self.template_helpers {
90 return &["db", "templates"];
91 }
92 &["db"]
93 }
94
95 fn meta(&self) -> sova_core::PluginMeta {
96 sova_core::PluginMeta::new("Notifications")
97 .description("DB inbox, channels with ACL, optional WS/mail")
98 .version(env!("CARGO_PKG_VERSION"))
99 }
100
101 fn install(self, app: &mut App) {
102 app.state(NotificationService {
103 channels: Arc::new(self.channels),
104 });
105
106 let guard = self.guard;
107
108 if let Some(path) = self.mount {
109 let mut r = Router::new();
110 if let Some(ref g) = guard {
111 r.use_middleware(g.clone());
112 }
113 #[cfg(feature = "templates")]
114 if self.template_helpers {
115 r.use_middleware(crate::templates::preload_middleware());
116 }
117 mount_routes(&mut r);
118 app.mount(&path, r);
119 }
120
121 #[cfg(feature = "ws")]
122 if let Some(path) = self.ws_path {
123 crate::ws::install_ws(app, &path, guard);
124 }
125
126 #[cfg(feature = "templates")]
127 if self.template_helpers {
128 crate::templates::register(app);
129 }
130 }
131}