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
78fn 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
92fn 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}