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 struct MongoEmbedded {
16 pub version: String,
17 pub download_path: PathBuf,
18 pub extract_path: PathBuf,
19 pub db_path: PathBuf,
20 pub port: u16,
21}
22
23impl MongoEmbedded {
24 pub fn new(version: &str) -> Result<Self> {
25 let proj_dirs = ProjectDirs::from("com", "mongo", "embedded")
26 .ok_or_else(|| anyhow::anyhow!("Could not determine project directories"))?;
27
28 let cache_dir = proj_dirs.cache_dir();
29 let data_dir = proj_dirs.data_dir();
30
31 Ok(Self {
32 version: version.to_string(),
33 download_path: cache_dir.join("downloads"),
34 extract_path: cache_dir.join("extracted"),
35 db_path: data_dir.join("db"),
36 port: 27017,
37 })
38 }
39
40 pub fn set_port(mut self, port: u16) -> Self {
41 self.port = port;
42 self
43 }
44
45 pub fn set_db_path(mut self, path: PathBuf) -> Self {
46 self.db_path = path;
47 self
48 }
49
50 pub fn is_installed(&self) -> bool {
51 let extract_target = self.extract_path.join(self.version.as_str());
52 extract_target.exists()
53 }
54
55 pub async fn start(&self) -> Result<MongoProcess> {
56 self.start_with_progress(|_| {}).await
57 }
58
59 pub async fn start_with_progress<F>(&self, callback: F) -> Result<MongoProcess>
60 where
61 F: FnMut(DownloadProgress),
62 {
63 let mongo_url = get_download_url(&self.version)?;
64 let download_target = self.download_path.join(&mongo_url.filename);
65
66 if !download_target.exists() {
67 if !self.download_path.exists() {
68 std::fs::create_dir_all(&self.download_path)?;
69 }
70 download_file_with_callback(&mongo_url.url, &download_target, callback).await?;
71 }
72
73 let extract_target = self.extract_path.join(self.version.as_str());
74 if !extract_target.exists() {
75 extract(&download_target, &extract_target)?;
76 }
77
78 let os = get_os()?;
79
80 MongoProcess::start(&extract_target, self.port, &self.db_path, &os)
81 }
82}
83