Skip to main content

fizzy_sdk/
config.rs

1//! What a client is configured with, and where it reads that from.
2
3use std::env;
4use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7
8/// Where a client sends when nothing says otherwise.
9pub const DEFAULT_BASE_URL: &str = "https://fizzy.do";
10
11/// What a client needs to know before it can talk to Fizzy.
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(default)]
14#[non_exhaustive]
15pub struct Config {
16    /// The API origin: `https://fizzy.do`, or a Fizzy running on this machine.
17    pub base_url: String,
18    /// The account most calls are scoped to, when there is a usual one.
19    pub account: Option<String>,
20    /// Where the response cache keeps its files.
21    pub cache_dir: PathBuf,
22    /// Whether reads are cached by `ETag`.
23    pub cache_enabled: bool,
24}
25
26impl Default for Config {
27    fn default() -> Config {
28        Config {
29            base_url: DEFAULT_BASE_URL.to_string(),
30            account: None,
31            cache_dir: default_cache_dir(),
32            cache_enabled: false,
33        }
34    }
35}
36
37impl Config {
38    /// The defaults.
39    pub fn new() -> Config {
40        Config::default()
41    }
42
43    /// Lets `FIZZY_API_URL`, `FIZZY_ACCOUNT`, `FIZZY_CACHE_DIR` and `FIZZY_CACHE_ENABLED`
44    /// override whatever is set, the same variables the Go SDK reads. An empty variable
45    /// counts as unset.
46    pub fn with_env(mut self) -> Config {
47        if let Some(value) = env_value("FIZZY_API_URL") {
48            self.base_url = value;
49        }
50        if let Some(value) = env_value("FIZZY_ACCOUNT") {
51            self.account = Some(value);
52        }
53        if let Some(value) = env_value("FIZZY_CACHE_DIR") {
54            self.cache_dir = PathBuf::from(value);
55        }
56        if let Some(value) = env_value("FIZZY_CACHE_ENABLED") {
57            self.cache_enabled = value.eq_ignore_ascii_case("true") || value == "1";
58        }
59        self
60    }
61
62    /// Points the client somewhere other than `https://fizzy.do`.
63    pub fn with_base_url(mut self, base_url: impl Into<String>) -> Config {
64        self.base_url = base_url.into();
65        self
66    }
67
68    /// Names the usual account.
69    pub fn with_account(mut self, account: impl Into<String>) -> Config {
70        self.account = Some(account.into());
71        self
72    }
73
74    /// Turns the `ETag` cache on or off.
75    pub fn with_cache_enabled(mut self, enabled: bool) -> Config {
76        self.cache_enabled = enabled;
77        self
78    }
79
80    /// Moves the cache directory.
81    pub fn with_cache_dir(mut self, cache_dir: impl Into<PathBuf>) -> Config {
82        self.cache_dir = cache_dir.into();
83        self
84    }
85
86    /// The base URL without a trailing slash.
87    pub fn origin(&self) -> &str {
88        self.base_url.trim_end_matches('/')
89    }
90}
91
92fn env_value(name: &str) -> Option<String> {
93    env::var(name).ok().filter(|value| !value.is_empty())
94}
95
96/// Where the response cache goes when nothing says otherwise: `$XDG_CACHE_HOME/fizzy`,
97/// falling back to `~/.cache/fizzy`.
98pub fn default_cache_dir() -> PathBuf {
99    xdg_dir("XDG_CACHE_HOME", ".cache").join("fizzy")
100}
101
102/// Where credentials and settings go when nothing says otherwise: `$XDG_CONFIG_HOME/fizzy`,
103/// falling back to `~/.config/fizzy`. Shared with the Fizzy CLI.
104pub fn default_config_dir() -> PathBuf {
105    xdg_dir("XDG_CONFIG_HOME", ".config").join("fizzy")
106}
107
108fn xdg_dir(variable: &str, fallback: &str) -> PathBuf {
109    match env_value(variable) {
110        Some(value) => PathBuf::from(value),
111        None => env::home_dir()
112            .unwrap_or_else(|| PathBuf::from("."))
113            .join(fallback),
114    }
115}