1use clap::{builder::Str, command, Arg, Command, Id};
2
3use crate::commands::{
4 build::build, init::init, login::login, migrate, password, publish::publish,
5 register::register, subscribe::subscribe, sync_servers, unsubscribe::unsubscribe,
6};
7
8pub async fn run() {
9 let matches = command!()
10 .subcommand(
11 Command::new(Subcommand::Register)
12 .about("Create a new account in Rocal platform")
13 )
14 .subcommand(
15 Command::new(Subcommand::Login)
16 .about("Login to Rocal platform")
17 )
18 .subcommand(
19 Command::new(Subcommand::Subscribe)
20 .about("Subscribe Rocal platform to publish a Rocal app")
21 )
22 .subcommand(
23 Command::new(Subcommand::Unsubscribe)
24 .about("Unsubscribe Rocal platform which leads to revoke tokens and shut your hosting app down")
25 )
26 .subcommand(
27 Command::new(Subcommand::New)
28 .about("Create a new Rocal app")
29 .arg(
30 Arg::new(InitCommandArg::Name)
31 .short('n')
32 .long("name")
33 .required(true)
34 .help("Set the resulting package name"),
35 ),
36 )
37 .subcommand(Command::new(Subcommand::Build).about("Build a Rocal app"))
38 .subcommand(
39 Command::new(Subcommand::Run)
40 .about("Run a Rocal app on your local")
41 .arg(
42 Arg::new(RunCommandArg::Port)
43 .short('p')
44 .long("port")
45 .required(false)
46 .help("Set port where you want to serve an app")
47 )
48 )
49 .subcommand(Command::new(Subcommand::Publish).about("Publish a Rocal app"))
50 .subcommand(
51 Command::new(Subcommand::Password)
52 .about("Password settings")
53 .arg_required_else_help(true)
54 .subcommand(Command::new(PasswordSubcommand::Reset).about("Reset your password"))
55 )
56 .subcommand(
57 Command::new(Subcommand::SyncServers)
58 .about("Manage sync servers")
59 .arg_required_else_help(true)
60 .subcommand(Command::new(SyncServersSubcommand::List).about("List available sync servers and show app_id"))
61 )
62 .subcommand(
63 Command::new(Subcommand::Migrate)
64 .about("Manage migrations")
65 .arg_required_else_help(true)
66 .subcommand(
67 Command::new(MigrateSubcommand::Add)
68 .about("Add a new migration file. e.g. db/migrations/<timestamp>-<name>.sql")
69 .arg(Arg::new("name").required(true))
70 )
71 )
72 .about("A tool to create and build a Rocal app.")
73 .arg_required_else_help(true)
74 .get_matches();
75
76 match matches.subcommand() {
77 Some((name, arg_matches)) => {
78 if name == Subcommand::New.as_str() {
79 if let Some(name) = arg_matches.get_one::<String>(InitCommandArg::Name.as_str()) {
80 init(name);
81 }
82 } else if name == Subcommand::Build.as_str() {
83 build();
84 } else if name == Subcommand::Publish.as_str() {
85 publish().await;
86 } else if name == Subcommand::Register.as_str() {
87 register().await;
88 } else if name == Subcommand::Login.as_str() {
89 login().await;
90 } else if name == Subcommand::Password.as_str() {
91 match arg_matches.subcommand() {
92 Some((name, _arg_matches)) => {
93 if name == PasswordSubcommand::Reset.as_str() {
94 password::reset().await;
95 }
96 }
97 None => (),
98 }
99 } else if name == Subcommand::Subscribe.as_str() {
100 if let Err(err) = subscribe().await {
101 println!("Error: {}", err.to_string());
102 }
103 } else if name == Subcommand::Unsubscribe.as_str() {
104 unsubscribe().await;
105 } else if name == Subcommand::Migrate.as_str() {
106 match arg_matches.subcommand() {
107 Some((name, arg_matches)) => {
108 if name == MigrateSubcommand::Add.as_str() {
109 let name = arg_matches
110 .get_one::<String>("name")
111 .expect("required argument");
112 migrate::add(&name);
113 }
114 }
115 None => (),
116 }
117 } else if name == Subcommand::SyncServers.as_str() {
118 match arg_matches.subcommand() {
119 Some((name, _arg_matches)) => {
120 if name == SyncServersSubcommand::List.as_str() {
121 sync_servers::list().await;
122 }
123 }
124 None => (),
125 }
126 } else if name == Subcommand::Run.as_str() {
127 build();
128 if let Some(port) = arg_matches.get_one::<String>(RunCommandArg::Port.as_str()) {
129 rocal_dev_server::run(Some(&port));
130 } else {
131 rocal_dev_server::run(None);
132 }
133 }
134 }
135 None => (),
136 }
137}
138
139enum Subcommand {
140 Register,
141 Login,
142 Subscribe,
143 Unsubscribe,
144 New,
145 Build,
146 Publish,
147 Password,
148 SyncServers,
149 Run,
150 Migrate,
151}
152
153enum PasswordSubcommand {
154 Reset,
155}
156
157enum InitCommandArg {
158 Name,
159}
160
161enum SyncServersSubcommand {
162 List,
163}
164
165enum RunCommandArg {
166 Port,
167}
168
169enum MigrateSubcommand {
170 Add,
171}
172
173impl Into<Str> for Subcommand {
174 fn into(self) -> Str {
175 self.as_str().into()
176 }
177}
178
179impl Subcommand {
180 pub fn as_str(self) -> &'static str {
181 match self {
182 Subcommand::Register => "register",
183 Subcommand::Login => "login",
184 Subcommand::Subscribe => "subscribe",
185 Subcommand::Unsubscribe => "unsubscribe",
186 Subcommand::New => "new",
187 Subcommand::Build => "build",
188 Subcommand::Publish => "publish",
189 Subcommand::Password => "password",
190 Subcommand::SyncServers => "sync-servers",
191 Subcommand::Run => "run",
192 Subcommand::Migrate => "migrate",
193 }
194 }
195}
196
197impl Into<Id> for InitCommandArg {
198 fn into(self) -> Id {
199 self.as_str().into()
200 }
201}
202
203impl InitCommandArg {
204 pub fn as_str(self) -> &'static str {
205 match self {
206 InitCommandArg::Name => "name",
207 }
208 }
209}
210
211impl Into<Str> for PasswordSubcommand {
212 fn into(self) -> Str {
213 self.as_str().into()
214 }
215}
216
217impl PasswordSubcommand {
218 pub fn as_str(self) -> &'static str {
219 match self {
220 PasswordSubcommand::Reset => "reset",
221 }
222 }
223}
224
225impl Into<Str> for SyncServersSubcommand {
226 fn into(self) -> Str {
227 self.as_str().into()
228 }
229}
230
231impl SyncServersSubcommand {
232 pub fn as_str(self) -> &'static str {
233 match self {
234 SyncServersSubcommand::List => "ls",
235 }
236 }
237}
238
239impl Into<Str> for MigrateSubcommand {
240 fn into(self) -> Str {
241 self.as_str().into()
242 }
243}
244
245impl MigrateSubcommand {
246 pub fn as_str(self) -> &'static str {
247 match self {
248 MigrateSubcommand::Add => "add",
249 }
250 }
251}
252
253impl Into<Id> for RunCommandArg {
254 fn into(self) -> Id {
255 self.as_str().into()
256 }
257}
258
259impl RunCommandArg {
260 pub fn as_str(self) -> &'static str {
261 match self {
262 RunCommandArg::Port => "port",
263 }
264 }
265}