spawn_db/commands/
init.rs1use crate::commands::{Outcome, TelemetryDescribe, TelemetryInfo};
2use crate::config::ConfigLoaderSaver;
3use crate::engine::{CommandSpec, DatabaseConfig, EngineType};
4use anyhow::{anyhow, Result};
5use opendal::Operator;
6use std::collections::HashMap;
7use uuid::Uuid;
8
9pub struct Init {
12 pub config_file: String,
13}
14
15impl TelemetryDescribe for Init {
16 fn telemetry(&self) -> TelemetryInfo {
17 TelemetryInfo::new("init")
18 }
19}
20
21impl Init {
22 pub async fn execute(&self, base_op: &Operator) -> Result<(Outcome, String)> {
25 if base_op.exists(&self.config_file).await? {
27 return Err(anyhow!(
28 "Config file '{}' already exists. Use a different path or remove the existing file.",
29 &self.config_file
30 ));
31 }
32
33 let project_id = Uuid::new_v4().to_string();
35
36 let mut databases = HashMap::new();
38 databases.insert(
39 "postgres_psql".to_string(),
40 DatabaseConfig {
41 engine: EngineType::PostgresPSQL,
42 spawn_database: "spawn".to_string(),
43 spawn_schema: "_spawn".to_string(),
44 environment: "dev".to_string(),
45 command: Some(CommandSpec::Direct {
46 direct: vec![
47 "docker".to_string(),
48 "exec".to_string(),
49 "-i".to_string(),
50 "spawn".to_string(),
51 "psql".to_string(),
52 "-U".to_string(),
53 "spawn".to_string(),
54 "spawn".to_string(),
55 ],
56 }),
57 },
58 );
59
60 let config = ConfigLoaderSaver {
62 spawn_folder: "spawn".to_string(),
63 database: Some("postgres_psql".to_string()),
64 environment: None,
65 databases: Some(databases),
66 project_id: Some(project_id.clone()),
67 telemetry: None,
68 };
69
70 config
72 .save(&self.config_file, base_op)
73 .await
74 .map_err(|e| e.context("Failed to write config file"))?;
75
76 let spawn_folder = &config.spawn_folder;
78 let subfolders = ["migrations", "components", "tests", "pinned"];
79 let mut created_folders = Vec::new();
80
81 for subfolder in &subfolders {
82 let path = format!("{}/{}/", spawn_folder, subfolder);
83 base_op
85 .write(&format!("{}.gitkeep", path), "")
86 .await
87 .map_err(|e| {
88 anyhow::Error::from(e).context(format!("Failed to create {} folder", subfolder))
89 })?;
90 created_folders.push(format!(" {}/{}/", spawn_folder, subfolder));
91 }
92
93 crate::show_telemetry_notice();
95
96 println!("Initialized spawn project with project_id: {}", project_id);
97 println!("Created directories:");
98 for folder in &created_folders {
99 println!("{}", folder);
100 }
101 println!(
102 "\nEdit {} to configure your database connection.",
103 &self.config_file
104 );
105
106 Ok((Outcome::Success, project_id))
107 }
108}