openzeppelin_relayer/config/config_file/
plugin.rs1use std::collections::HashSet;
2
3use crate::config::ConfigFileError;
4use serde::{Deserialize, Serialize};
5
6const PLUGIN_FILE_TYPE: &str = ".ts";
10const PLUGIN_LANG: &str = "typescript";
11
12#[derive(Debug, Serialize, Deserialize, Clone)]
13pub struct PluginFileConfig {
14 pub id: String,
15 pub path: String,
16 pub timeout: Option<u64>,
17}
18
19pub struct PluginsFileConfig {
20 pub plugins: Vec<PluginFileConfig>,
21}
22
23impl PluginsFileConfig {
24 pub fn new(plugins: Vec<PluginFileConfig>) -> Self {
25 Self { plugins }
26 }
27
28 pub fn validate(&self) -> Result<(), ConfigFileError> {
29 let mut ids = HashSet::new();
30 for plugin in &self.plugins {
31 if !ids.insert(plugin.id.clone()) {
32 return Err(ConfigFileError::DuplicateId(plugin.id.clone()));
33 }
34
35 if plugin.id.is_empty() {
36 return Err(ConfigFileError::MissingField("id".into()));
37 }
38
39 if plugin.path.is_empty() {
40 return Err(ConfigFileError::MissingField("path".into()));
41 }
42
43 if let Some(timeout) = plugin.timeout {
45 if timeout == 0 {
46 return Err(ConfigFileError::InvalidTimeout(timeout));
47 }
48 }
49
50 if !plugin.path.ends_with(PLUGIN_FILE_TYPE) {
51 return Err(ConfigFileError::InvalidFormat(format!(
52 "Plugin path must be a {} file (ends with '{}')",
53 PLUGIN_LANG, PLUGIN_FILE_TYPE
54 )));
55 }
56 }
57
58 Ok(())
59 }
60}