1use serde::{Deserialize, Serialize};
4use std::path::{Path, PathBuf};
5
6use crate::error::CliResult;
7
8pub const CONFIG_FILE_NAME: &str = "prax.toml";
10
11pub const PRAX_DIR: &str = "prax";
13
14pub const SCHEMA_FILE_NAME: &str = "schema.prax";
16
17pub const SCHEMA_FILE_PATH: &str = "prax/schema.prax";
19
20pub const MIGRATIONS_DIR: &str = "prax/migrations";
22
23pub const SEEDS_DIR: &str = "prax/seeds";
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28#[serde(default)]
29pub struct Config {
30 pub database: DatabaseConfig,
32
33 pub generator: GeneratorConfig,
35
36 pub migrations: MigrationConfig,
38
39 pub seed: SeedConfig,
41}
42
43impl Default for Config {
44 fn default() -> Self {
45 Self {
46 database: DatabaseConfig::default(),
47 generator: GeneratorConfig::default(),
48 migrations: MigrationConfig::default(),
49 seed: SeedConfig::default(),
50 }
51 }
52}
53
54impl Config {
55 pub fn load(path: &Path) -> CliResult<Self> {
57 let content = std::fs::read_to_string(path)?;
58 let config: Config = toml::from_str(&content)?;
59 Ok(config)
60 }
61
62 pub fn save(&self, path: &Path) -> CliResult<()> {
64 let content = toml::to_string_pretty(self)?;
65 std::fs::write(path, content)?;
66 Ok(())
67 }
68
69 pub fn default_for_provider(provider: &str) -> Self {
71 let mut config = Self::default();
72 config.database.provider = provider.to_string();
73 config
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79#[serde(default)]
80pub struct DatabaseConfig {
81 pub provider: String,
83
84 pub url: Option<String>,
86
87 pub shadow_url: Option<String>,
89
90 pub direct_url: Option<String>,
92
93 pub seed_path: Option<PathBuf>,
95}
96
97impl Default for DatabaseConfig {
98 fn default() -> Self {
99 Self {
100 provider: "postgresql".to_string(),
101 url: None,
102 shadow_url: None,
103 direct_url: None,
104 seed_path: None,
105 }
106 }
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111#[serde(default)]
112pub struct GeneratorConfig {
113 pub output: String,
115
116 pub features: Option<Vec<String>>,
118
119 pub prelude: Option<Vec<String>>,
121}
122
123impl Default for GeneratorConfig {
124 fn default() -> Self {
125 Self {
126 output: "./src/generated".to_string(),
127 features: None,
128 prelude: None,
129 }
130 }
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
135#[serde(default)]
136pub struct MigrationConfig {
137 pub directory: String,
139
140 pub table_name: String,
142
143 pub schema: Option<String>,
145}
146
147impl Default for MigrationConfig {
148 fn default() -> Self {
149 Self {
150 directory: MIGRATIONS_DIR.to_string(),
151 table_name: "_prax_migrations".to_string(),
152 schema: None,
153 }
154 }
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
159#[serde(default)]
160pub struct SeedConfig {
161 pub directory: String,
163
164 pub script: Option<PathBuf>,
166
167 pub auto_seed: bool,
169
170 pub environments: std::collections::HashMap<String, bool>,
173}
174
175impl Default for SeedConfig {
176 fn default() -> Self {
177 let mut environments = std::collections::HashMap::new();
178 environments.insert("development".to_string(), true);
179 environments.insert("test".to_string(), true);
180 environments.insert("staging".to_string(), false);
181 environments.insert("production".to_string(), false);
182
183 Self {
184 directory: SEEDS_DIR.to_string(),
185 script: None,
186 auto_seed: false,
187 environments,
188 }
189 }
190}
191
192impl SeedConfig {
193 pub fn should_seed(&self, environment: &str) -> bool {
195 self.environments.get(environment).copied().unwrap_or(false)
196 }
197}