Skip to main content

pipedash_plugin_api/
config.rs

1use std::collections::HashMap;
2
3use reqwest::Url;
4
5use crate::error::{
6    PluginError,
7    PluginResult,
8};
9use crate::http::parse_http_url;
10
11pub const PIPELINE_ID_SEPARATOR: &str = "__";
12
13pub fn value<'a>(config: &'a HashMap<String, String>, key: &str) -> Option<&'a str> {
14    config.get(key).map(|v| v.trim()).filter(|v| !v.is_empty())
15}
16
17pub fn required_value<'a>(
18    config: &'a HashMap<String, String>, key: &str, missing_message: &str,
19) -> PluginResult<&'a str> {
20    value(config, key).ok_or_else(|| PluginError::InvalidConfig(missing_message.to_string()))
21}
22
23pub fn credential(config: &HashMap<String, String>, key: &str) -> PluginResult<String> {
24    required_value(config, key, &format!("Missing {key} in config")).map(str::to_string)
25}
26
27pub fn comma_separated(value: &str) -> impl Iterator<Item = &str> + '_ {
28    value
29        .split(',')
30        .map(str::trim)
31        .filter(|item| !item.is_empty())
32}
33
34pub fn csv_list(config: &HashMap<String, String>, key: &str) -> Option<Vec<String>> {
35    config
36        .get(key)
37        .map(|items| comma_separated(items).map(str::to_string).collect())
38}
39
40pub fn selected_items(config: &HashMap<String, String>) -> Option<Vec<String>> {
41    csv_list(config, "selected_items")
42}
43
44pub fn bool_value(config: &HashMap<String, String>, key: &str) -> bool {
45    config
46        .get(key)
47        .and_then(|v| v.parse::<bool>().ok())
48        .unwrap_or(false)
49}
50
51pub fn insecure(config: &HashMap<String, String>) -> bool {
52    bool_value(config, "insecure")
53}
54
55pub fn base_url<'a>(config: &'a HashMap<String, String>, key: &str) -> Option<&'a str> {
56    value(config, key)
57        .map(|url| url.trim_end_matches('/'))
58        .filter(|url| !url.is_empty())
59}
60
61pub fn required_base_url<'a>(
62    config: &'a HashMap<String, String>, key: &str, missing_message: &str,
63) -> PluginResult<&'a str> {
64    base_url(config, key).ok_or_else(|| PluginError::InvalidConfig(missing_message.to_string()))
65}
66
67pub fn http_base_url<'a>(
68    config: &'a HashMap<String, String>, key: &str, missing_message: &str, label: &str,
69) -> PluginResult<(&'a str, Url)> {
70    let raw = required_base_url(config, key, missing_message)?;
71    let parsed = parse_http_url(raw, label)?;
72    if parsed.query().is_some() || parsed.fragment().is_some() {
73        return Err(PluginError::InvalidConfig(format!(
74            "Invalid {label} URL: remove the query or fragment"
75        )));
76    }
77    Ok((raw, parsed))
78}
79
80pub fn invalid_pipeline_id(id: &str) -> PluginError {
81    PluginError::InvalidConfig(format!("Invalid pipeline ID format: {id}"))
82}
83
84#[cfg(test)]
85mod tests;