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, PartialEq)]
13#[repr(u8)]
14#[tsync::tsync]
15pub enum Runner {
16 NodeJs,
17 Ruby,
18 Swift,
19 Monorepo = 255,
20}
21
22impl Display for Runner {
23 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
24 write!(f, "{:?}", self)
25 }
26}
27
28#[derive(Debug, Serialize, Deserialize)]
29#[tsync::tsync]
30pub enum NodeJsFramework {
31 NextJs,
32 Astro,
33}
34
35#[derive(Debug, Serialize, Deserialize)]
36#[tsync::tsync]
37pub enum RubyFramework {
38 Rails,
39}
40
41#[derive(Debug, Serialize, Deserialize)]
42#[tsync::tsync]
43pub enum SwiftFramework {
44 Vapor,
45}
46
47impl Runner {
48 pub fn from(repo_path: &PathBuf) -> Result<Runner, ErrorResponse> {
49 if repo_path.join("package.json").exists()
51 && (next_config_exists(repo_path) || astro_config_exists(repo_path))
52 {
53 return Ok(Runner::NodeJs);
54 }
55
56 if repo_path.join("Gemfile").exists() {
57 return Ok(Runner::Ruby);
58 }
59 if repo_path.join("Package.swift").exists() {
60 return Ok(Runner::Swift);
61 }
62 non_framework_runner()
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::Monorepo => "monorepo",
73 Runner::NodeJs => "api",
74 Runner::Ruby | Runner::Swift => "api-1",
75 }
76 }
77}
78
79fn non_framework_runner() -> Result<Runner, ErrorResponse> {
80 Err(ErrorResponse::Error {
81 error_code: UnsupportedRunner,
82 message: UnsupportedRunner.message(None).to_string(),
83 })
84}
85
86fn next_config_exists(repo_path: &PathBuf) -> bool {
88 if let Ok(entries) = fs::read_dir(repo_path) {
89 for entry in entries.flatten() {
90 let filename = entry.file_name();
91 let filename_str = filename.to_string_lossy();
92 if filename_str.starts_with("next.config.") {
93 return true;
94 }
95 }
96 }
97 false
98}
99
100fn astro_config_exists(repo_path: &PathBuf) -> bool {
102 if let Ok(entries) = fs::read_dir(repo_path) {
103 for entry in entries.flatten() {
104 let filename = entry.file_name();
105 let filename_str = filename.to_string_lossy();
106 if filename_str.starts_with("astro.config.") {
107 return true;
108 }
109 }
110 }
111 false
112}