1use anyhow::{Context, Result};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4use std::fs;
5use std::path::{Path, PathBuf};
6
7#[derive(Serialize, Deserialize, Default, Debug)]
8pub struct Config {
9 #[serde(default)]
10 pub values: HashMap<String, String>,
11}
12
13impl Config {
14 pub fn load() -> Result<Self> {
17 let local_path = Path::new(".wasm4pm/config.json");
19 if local_path.exists() {
20 let content = fs::read_to_string(local_path)
21 .with_context(|| format!("Failed to read local config at {:?}", local_path))?;
22 return serde_json::from_str(&content)
23 .with_context(|| format!("Failed to parse local config at {:?}", local_path));
24 }
25
26 if let Some(global_path) = Self::global_config_path() {
28 if global_path.exists() {
29 let content = fs::read_to_string(&global_path).with_context(|| {
30 format!("Failed to read global config at {:?}", global_path)
31 })?;
32 return serde_json::from_str(&content).with_context(|| {
33 format!("Failed to parse global config at {:?}", global_path)
34 });
35 }
36 }
37
38 Ok(Config::default())
39 }
40
41 pub fn save(&self) -> Result<()> {
44 let content =
45 serde_json::to_string_pretty(self).context("Failed to serialize configuration")?;
46
47 let local_dir = Path::new(".wasm4pm");
49 if local_dir.exists() && local_dir.is_dir() {
50 let local_path = local_dir.join("config.json");
51 fs::write(&local_path, content)
52 .with_context(|| format!("Failed to write local config to {:?}", local_path))?;
53 return Ok(());
54 }
55
56 if let Some(global_path) = Self::global_config_path() {
58 if let Some(parent) = global_path.parent() {
59 fs::create_dir_all(parent)
60 .with_context(|| format!("Failed to create config directory {:?}", parent))?;
61 }
62 fs::write(&global_path, content)
63 .with_context(|| format!("Failed to write global config to {:?}", global_path))?;
64 return Ok(());
65 }
66
67 anyhow::bail!(
68 "Could not determine a valid path to save configuration. (Home directory not found)"
69 )
70 }
71
72 fn global_config_path() -> Option<PathBuf> {
74 let home = if cfg!(windows) {
75 std::env::var("USERPROFILE").ok()
76 } else {
77 std::env::var("HOME").ok()
78 };
79
80 home.map(|h| PathBuf::from(h).join(".wasm4pm").join("config.json"))
81 }
82
83 pub fn get(&self, key: &str) -> Option<&String> {
85 self.values.get(key)
86 }
87
88 pub fn set(&mut self, key: String, value: String) {
90 self.values.insert(key, value);
91 }
92}