smbcloud_model/
runner.rs

1use {
2    crate::error_codes::{ErrorCode::UnsupportedRunner, ErrorResponse},
3    serde::{Deserialize, Serialize},
4    serde_repr::{Deserialize_repr, Serialize_repr},
5    std::{
6        fmt::{self, Display, Formatter},
7        fs,
8        path::PathBuf,
9    },
10};
11
12#[derive(Debug, Deserialize_repr, Serialize_repr, Clone, Copy)]
13#[repr(u8)]
14#[tsync::tsync]
15pub enum Runner {
16    NodeJs,
17    Ruby,
18    Swift,
19}
20
21impl Display for Runner {
22    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
23        write!(f, "{:?}", self)
24    }
25}
26
27#[derive(Debug, Serialize, Deserialize)]
28#[tsync::tsync]
29pub enum NodeJsFramework {
30    NextJs,
31    Astro,
32}
33
34#[derive(Debug, Serialize, Deserialize)]
35#[tsync::tsync]
36pub enum RubyFramework {
37    Rails,
38}
39
40#[derive(Debug, Serialize, Deserialize)]
41#[tsync::tsync]
42pub enum SwiftFramework {
43    Vapor,
44}
45
46impl Runner {
47    pub fn from(repo_path: &PathBuf) -> Result<Runner, ErrorResponse> {
48        if repo_path.join("package.json").exists()
49            && (next_config_exists(repo_path) || astro_config_exists(repo_path))
50        {
51            return Ok(Runner::NodeJs);
52        }
53
54        if repo_path.join("Gemfile").exists() {
55            return Ok(Runner::Ruby);
56        }
57        if repo_path.join("Package.swift").exists() {
58            return Ok(Runner::Swift);
59        }
60        Err(ErrorResponse::Error {
61            error_code: UnsupportedRunner,
62            message: UnsupportedRunner.message(None).to_string(),
63        })
64    }
65
66    pub fn git_host(&self) -> String {
67        format!("git@{}.smbcloud.xyz", self.api())
68    }
69
70    fn api(&self) -> &str {
71        match self {
72            Runner::NodeJs => "api",
73            Runner::Ruby | Runner::Swift => "api-1",
74        }
75    }
76}
77
78// Helper function to detect any next.config.* file
79fn next_config_exists(repo_path: &PathBuf) -> bool {
80    if let Ok(entries) = fs::read_dir(repo_path) {
81        for entry in entries.flatten() {
82            let filename = entry.file_name();
83            let filename_str = filename.to_string_lossy();
84            if filename_str.starts_with("next.config.") {
85                return true;
86            }
87        }
88    }
89    false
90}
91
92// Helper function to detect any astro.config.* file
93fn astro_config_exists(repo_path: &PathBuf) -> bool {
94    if let Ok(entries) = fs::read_dir(repo_path) {
95        for entry in entries.flatten() {
96            let filename = entry.file_name();
97            let filename_str = filename.to_string_lossy();
98            if filename_str.starts_with("astro.config.") {
99                return true;
100            }
101        }
102    }
103    false
104}