1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::{api::config::PluginConfig, App, Invoke, PageLoadPayload, Params, Window};
use serde_json::Value as JsonValue;
use std::collections::HashMap;
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
pub trait Plugin<P: Params>: Send {
fn name(&self) -> &'static str;
#[allow(unused_variables)]
fn initialize(&mut self, app: &App<P>, config: JsonValue) -> Result<()> {
Ok(())
}
fn initialization_script(&self) -> Option<String> {
None
}
#[allow(unused_variables)]
fn created(&mut self, window: Window<P>) {}
#[allow(unused_variables)]
fn on_page_load(&mut self, window: Window<P>, payload: PageLoadPayload) {}
#[allow(unused_variables)]
fn extend_api(&mut self, invoke: Invoke<P>) {}
}
crate::manager::default_args! {
pub(crate) struct PluginStore<P: Params> {
store: HashMap<&'static str, Box<dyn Plugin<P>>>,
}
}
impl<P: Params> Default for PluginStore<P> {
fn default() -> Self {
Self {
store: HashMap::new(),
}
}
}
impl<P: Params> PluginStore<P> {
pub fn register<Plug: Plugin<P> + 'static>(&mut self, plugin: Plug) -> bool {
self.store.insert(plugin.name(), Box::new(plugin)).is_some()
}
pub(crate) fn initialize(&mut self, app: &App<P>, config: &PluginConfig) -> crate::Result<()> {
self.store.values_mut().try_for_each(|plugin| {
plugin
.initialize(
app,
config.0.get(plugin.name()).cloned().unwrap_or_default(),
)
.map_err(|e| crate::Error::PluginInitialization(plugin.name().to_string(), e.to_string()))
})
}
pub(crate) fn initialization_script(&self) -> String {
self
.store
.values()
.filter_map(|p| p.initialization_script())
.fold(String::new(), |acc, script| {
format!("{}\n(function () {{ {} }})();", acc, script)
})
}
pub(crate) fn created(&mut self, window: Window<P>) {
self
.store
.values_mut()
.for_each(|plugin| plugin.created(window.clone()))
}
pub(crate) fn on_page_load(&mut self, window: Window<P>, payload: PageLoadPayload) {
self
.store
.values_mut()
.for_each(|plugin| plugin.on_page_load(window.clone(), payload.clone()))
}
pub(crate) fn extend_api(&mut self, mut invoke: Invoke<P>) {
let command = invoke.message.command.replace("plugin:", "");
let mut tokens = command.split('|');
let target = tokens.next().unwrap();
if let Some(plugin) = self.store.get_mut(target) {
invoke.message.command = tokens
.next()
.map(|c| c.to_string())
.unwrap_or_else(String::new);
plugin.extend_api(invoke);
} else {
invoke
.resolver
.reject(format!("plugin {} not found", target));
}
}
}