1use anyhow::Result;
2use std::path::PathBuf;
3
4#[derive(Debug, Default)]
5pub struct ProjectOptions {
6 pub name: String,
7 pub path: PathBuf,
8
9 pub init_git: bool,
10
11 pub web_server: WebServer,
12 pub websocket_server: Option<WebsocketServer>,
13 pub database: Option<Database>,
14
15 pub docker: bool,
16}
17
18impl ProjectOptions {
19 pub fn prompt() -> Result<Self> {
20 let mut options = ProjectOptions::default();
21
22 let project_name = inquire::Text::new("Project name: ")
23 .with_initial_value("my-awesome-project")
24 .prompt()?;
25 options.name = project_name;
26 options.path = PathBuf::from("./").join(&options.name);
27
28 let init_git = inquire::Confirm::new("Initialize git repository?").prompt()?;
29 options.init_git = init_git;
30
31 let web_server =
32 inquire::Select::new("Select web server:", WebServer::variants()).prompt()?;
33 options.web_server = WebServer::from_str(web_server).unwrap();
34
35 let websocket_server = inquire::Select::new(
36 "Select websocket server:",
37 WebsocketServer::variants(&options),
38 )
39 .prompt()?;
40 options.websocket_server = WebsocketServer::from_str(websocket_server);
41
42 let database =
43 inquire::Select::new("Select database:", Database::variants(&options)).prompt()?;
44 options.database = Database::from_str(database);
45
46 if options.web_server != WebServer::Cloudflare {
47 let use_docker = inquire::Confirm::new("Use docker?").prompt()?;
48 options.docker = use_docker;
49 }
50
51 Ok(options)
52 }
53}
54
55#[derive(Debug, Default, PartialEq, Eq)]
56pub enum WebServer {
57 #[default]
58 Actix,
59 Axum,
60 Cloudflare,
61}
62
63impl<'a> WebServer {
64 pub fn variants() -> Vec<&'a str> {
65 vec!["Actix", "Axum", "Cloudflare (Workers)"]
66 }
67
68 pub fn from_str(s: &str) -> Option<Self> {
69 match s {
70 "Actix" => Some(WebServer::Actix),
71 "Axum" => Some(WebServer::Axum),
72 "Cloudflare (Workers)" => Some(WebServer::Cloudflare),
73 _ => None,
74 }
75 }
76
77 pub fn to_str(&self) -> &'a str {
78 match self {
79 WebServer::Actix => "Actix",
80 WebServer::Axum => "Axum",
81 WebServer::Cloudflare => "Cloudflare",
82 }
83 }
84}
85
86#[derive(Debug, Default, PartialEq, Eq)]
87pub enum WebsocketServer {
88 #[default]
89 Actix,
90 Tungstenite,
91 On,
92 Off,
93}
94
95impl<'a> WebsocketServer {
96 pub fn variants(options: &ProjectOptions) -> Vec<&'a str> {
97 match options.web_server {
98 WebServer::Actix => vec!["Tungstenite", "Off"],
99 WebServer::Axum => vec!["Tungstenite", "Off"],
100 WebServer::Cloudflare => vec!["On", "Off"],
101 }
102 }
103
104 pub fn from_str(s: &str) -> Option<Self> {
105 match s {
106 "Actix" => Some(WebsocketServer::Actix),
107 "Tungstenite" => Some(WebsocketServer::Tungstenite),
108 "On" => Some(WebsocketServer::On),
109 _ => None,
110 }
111 }
112}
113
114#[derive(Debug, Default, PartialEq, Eq)]
115pub enum Database {
116 #[default]
117 Postgres,
118 Off,
119}
120
121impl<'a> Database {
122 pub fn variants(options: &ProjectOptions) -> Vec<&'a str> {
123 match options.web_server {
124 WebServer::Actix => vec!["Postgres(SQLX)", "Off"],
125 WebServer::Axum => vec!["Postgres(SQLX)", "Off"],
126 WebServer::Cloudflare => vec!["TODO: Cloudflare", "Off"],
127 }
128 }
129
130 pub fn from_str(s: &str) -> Option<Self> {
131 match s {
132 "Postgres(SQLX)" => Some(Database::Postgres),
133 _ => None,
134 }
135 }
136}