vtcode_core/pods/
store.rs1use crate::pods::catalog::PodCatalog;
2use crate::pods::state::PodsState;
3use anyhow::{Context, Result, anyhow};
4use std::path::{Path, PathBuf};
5use vtcode_commons::fs::{ensure_dir_exists, read_json_file, write_json_file};
6
7#[derive(Debug, Clone)]
9pub struct PodsStore {
10 base_dir: PathBuf,
11}
12
13impl PodsStore {
14 pub fn new(base_dir: impl Into<PathBuf>) -> Self {
15 Self {
16 base_dir: base_dir.into(),
17 }
18 }
19
20 pub fn default_store() -> Result<Self> {
21 let home = dirs::home_dir().ok_or_else(|| anyhow!("failed to resolve home directory"))?;
22 Ok(Self::new(home.join(".vtcode").join("pods")))
23 }
24
25 pub fn base_dir(&self) -> &Path {
26 &self.base_dir
27 }
28
29 pub fn state_path(&self) -> PathBuf {
30 self.base_dir.join("state.json")
31 }
32
33 pub fn catalog_path(&self) -> PathBuf {
34 self.base_dir.join("catalog.json")
35 }
36
37 pub async fn ensure_initialized(&self) -> Result<()> {
38 ensure_dir_exists(&self.base_dir).await?;
39
40 if !tokio::fs::try_exists(&self.catalog_path())
41 .await
42 .unwrap_or(false)
43 {
44 self.save_catalog(&PodCatalog::embedded_default()).await?;
45 }
46
47 if !tokio::fs::try_exists(&self.state_path())
48 .await
49 .unwrap_or(false)
50 {
51 self.save_state(&PodsState::default()).await?;
52 }
53
54 Ok(())
55 }
56
57 pub async fn load_state(&self) -> Result<PodsState> {
58 self.ensure_initialized().await?;
59 read_json_file(&self.state_path()).await.with_context(|| {
60 format!(
61 "failed to read pod state at {}",
62 self.state_path().display()
63 )
64 })
65 }
66
67 pub async fn save_state(&self, state: &PodsState) -> Result<()> {
68 ensure_dir_exists(&self.base_dir).await?;
69 write_json_file(&self.state_path(), state)
70 .await
71 .with_context(|| {
72 format!(
73 "failed to write pod state at {}",
74 self.state_path().display()
75 )
76 })
77 }
78
79 pub async fn load_catalog(&self) -> Result<PodCatalog> {
80 self.ensure_initialized().await?;
81 read_json_file(&self.catalog_path()).await.with_context(|| {
82 format!(
83 "failed to read pod catalog at {}",
84 self.catalog_path().display()
85 )
86 })
87 }
88
89 pub async fn save_catalog(&self, catalog: &PodCatalog) -> Result<()> {
90 ensure_dir_exists(&self.base_dir).await?;
91 write_json_file(&self.catalog_path(), catalog)
92 .await
93 .with_context(|| {
94 format!(
95 "failed to write pod catalog at {}",
96 self.catalog_path().display()
97 )
98 })
99 }
100}