1#[cfg(feature = "config")]
2pub mod config;
3pub mod constants;
4#[cfg(feature = "models")]
5pub mod models;
6pub mod secrets;
7#[cfg(feature = "tables")]
8pub mod tables;
9pub mod templates;
10
11use serde::{Deserialize, Serialize};
12
13#[derive(Clone, Deserialize, Serialize, Default)]
17pub struct DbInput {
18 pub local_uri: Option<String>,
19 pub db_name: Option<String>,
21}
22
23#[derive(Deserialize, Serialize)]
25#[serde(untagged)]
26pub enum DatabaseResource {
27 ConnectionString(String),
28 Info(DatabaseInfo),
29}
30
31#[derive(Clone, Serialize, Deserialize)]
33#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
34#[typeshare::typeshare]
35pub struct DatabaseInfo {
36 engine: String,
37 role_name: String,
38 role_password: String,
39 database_name: String,
40 port: String,
41 hostname: String,
42 instance_name: Option<String>,
45}
46
47impl DatabaseInfo {
48 pub fn new(
49 engine: String,
50 role_name: String,
51 role_password: String,
52 database_name: String,
53 port: String,
54 hostname: String,
55 instance_name: Option<String>,
56 ) -> Self {
57 Self {
58 engine,
59 role_name,
60 role_password,
61 database_name,
62 port,
63 hostname,
64 instance_name,
65 }
66 }
67
68 pub fn connection_string(&self, show_password: bool) -> String {
70 format!(
71 "{}://{}:{}@{}:{}/{}",
72 self.engine,
73 self.role_name,
74 if show_password {
75 &self.role_password
76 } else {
77 "********"
78 },
79 self.hostname,
80 self.port,
81 self.database_name,
82 )
83 }
84
85 pub fn role_name(&self) -> String {
86 self.role_name.to_string()
87 }
88
89 pub fn database_name(&self) -> String {
90 self.database_name.to_string()
91 }
92
93 pub fn instance_name(&self) -> Option<String> {
94 self.instance_name.clone()
95 }
96}
97
98impl std::fmt::Debug for DatabaseInfo {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 write!(f, "DatabaseInfo {{ {:?} }}", self.connection_string(false))
102 }
103}
104
105#[derive(Serialize, Deserialize)]
107pub struct ContainerRequest {
108 pub project_name: String,
109 pub container_name: String,
111 pub image: String,
113 pub port: String,
115 pub env: Vec<String>,
117}
118
119#[derive(Serialize, Deserialize)]
121pub struct ContainerResponse {
122 pub host_port: String,
125}
126
127pub fn semvers_are_compatible(a: &semver::Version, b: &semver::Version) -> bool {
130 if a.major != 0 || b.major != 0 {
131 a.major == b.major
132 } else if a.minor != 0 || b.minor != 0 {
133 a.minor == b.minor
134 } else {
135 a.patch == b.patch
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use std::str::FromStr;
142
143 #[test]
144 fn semver_compatibility_check_works() {
145 let semver_tests = &[
146 ("1.0.0", "1.0.0", true),
147 ("1.8.0", "1.0.0", true),
148 ("0.1.0", "0.2.1", false),
149 ("0.9.0", "0.2.0", false),
150 ];
151 for (version_a, version_b, are_compatible) in semver_tests {
152 let version_a = semver::Version::from_str(version_a).unwrap();
153 let version_b = semver::Version::from_str(version_b).unwrap();
154 assert_eq!(
155 super::semvers_are_compatible(&version_a, &version_b),
156 *are_compatible
157 );
158 }
159 }
160}