mongo_embedded/
lib.rs

1pub mod downloader;
2pub mod extractor;
3pub mod process;
4
5use anyhow::Result;
6use std::path::PathBuf;
7use directories::ProjectDirs;
8
9use crate::downloader::{get_download_url, download_file_with_callback, get_os};
10use crate::extractor::extract;
11use crate::process::MongoProcess;
12
13pub use crate::downloader::DownloadProgress;
14
15pub enum InitStatus {
16    CheckingDB,
17    ValidatingInstallation,
18    Downloading,
19    DownloadProgress(DownloadProgress),
20    DBInitialized,
21}
22
23pub struct MongoEmbedded {
24    pub version: String,
25    pub download_path: PathBuf,
26    pub extract_path: PathBuf,
27    pub db_path: PathBuf,
28    pub port: u16,
29    pub bind_ip: String,
30}
31
32
33impl MongoEmbedded {
34    pub fn new(version: &str) -> Result<Self> {
35        let proj_dirs = ProjectDirs::from("com", "mongo", "embedded")
36            .ok_or_else(|| anyhow::anyhow!("Could not determine project directories"))?;
37        
38        let cache_dir = proj_dirs.cache_dir();
39        let data_dir = proj_dirs.data_dir();
40
41        Ok(Self {
42            version: version.to_string(),
43            download_path: cache_dir.join("downloads"),
44            extract_path: cache_dir.join("extracted"),
45            db_path: data_dir.join("db"),
46            port: 27017,
47            bind_ip: "127.0.0.1".to_string(),
48        })
49    }
50
51    pub fn set_port(mut self, port: u16) -> Self {
52        self.port = port;
53        self
54    }
55
56    pub fn set_bind_ip(mut self, bind_ip: &str) -> Self {
57        self.bind_ip = bind_ip.to_string();
58        self
59    }
60
61    pub fn set_db_path(mut self, path: PathBuf) -> Self {
62        self.db_path = path;
63        self
64    }
65
66    pub fn is_installed(&self) -> bool {
67        let extract_target = self.extract_path.join(self.version.as_str());
68        extract_target.exists()
69    }
70
71    pub async fn start(&self) -> Result<MongoProcess> {
72        self.start_with_progress(|_| {}).await
73    }
74
75    pub async fn start_with_progress<F>(&self, mut callback: F) -> Result<MongoProcess>
76    where
77        F: FnMut(InitStatus),
78    {
79        callback(InitStatus::CheckingDB);
80        let mongo_url = get_download_url(&self.version)?;
81        let download_target = self.download_path.join(&mongo_url.filename);
82
83        callback(InitStatus::ValidatingInstallation);
84        if !download_target.exists() {
85            if !self.download_path.exists() {
86                std::fs::create_dir_all(&self.download_path)?;
87            }
88            callback(InitStatus::Downloading);
89            download_file_with_callback(&mongo_url.url, &download_target, |progress| {
90                callback(InitStatus::DownloadProgress(progress));
91            }).await?;
92        }
93
94        let extract_target = self.extract_path.join(self.version.as_str());
95        if !extract_target.exists() {
96            extract(&download_target, &extract_target)?;
97        }
98
99        let os = get_os()?;
100        
101        let process = MongoProcess::start(&extract_target, self.port, &self.db_path, &os, &self.bind_ip)?;
102        callback(InitStatus::DBInitialized);
103        Ok(process)
104    }
105}
106