1use colored::Colorize;
4
5struct CommandEntry {
6 command: &'static str, summary: &'static str, description: &'static str, usage: &'static str, requires_auth: bool, requires_admin: bool, params: &'static [(&'static str, &'static str)], }
14
15const COMMANDS: &[CommandEntry] = &[
16 CommandEntry {
18 command: "help",
19 summary: "Lists all available commands.",
20 description: "Prints a summary of every available command, grouped by namespace.",
21 usage: "help",
22 requires_auth: false,
23 requires_admin: false,
24 params: &[],
25 },
26 CommandEntry {
27 command: "help <command>",
28 summary: "Shows detailed help for a specific command.",
29 description: "Prints the full description, usage, parameters, and auth requirement for the given command.",
30 usage: "help server:status",
31 requires_auth: false,
32 requires_admin: false,
33 params: &[("command", "The command to look up, e.g. server:status")],
34 },
35 CommandEntry {
37 command: "server:status",
38 summary: "Shows uptime and basic server info.",
39 description: "Prints how long the server has been running, what address it is listening on, and whether testing mode is active.",
40 usage: "server:status",
41 requires_auth: false,
42 requires_admin: false,
43 params: &[],
44 },
45 CommandEntry {
46 command: "server:logout",
47 summary: "Ends the current operator session.",
48 description: "Clears the authenticated session immediately. Any subsequent write commands will require logging in again.",
49 usage: "server:logout",
50 requires_auth: true,
51 requires_admin: false,
52 params: &[],
53 },
54 CommandEntry {
55 command: "server:shutdown",
56 summary: "Gracefully shuts the server down.",
57 description: "Signals the server to stop accepting new requests, waits for in-flight requests to complete, flushes logs, and exits cleanly.",
58 usage: "server:shutdown",
59 requires_auth: true,
60 requires_admin: true,
61 params: &[],
62 },
63 CommandEntry {
64 command: "server:logs",
65 summary: "Displays recent server logs.",
66 description: "Prints logs in order from most recent to oldest, allowing for optional filter for last X days.",
67 usage: "server:logs [days]",
68 requires_auth: false,
69 requires_admin: false,
70 params: &[("days", "Optional number of days to display logs for")],
71 },
72 CommandEntry {
73 command: "server:audit",
74 summary: "Displays recent audit logs.",
75 description: "Prints audit logs in order from most recent to oldest, allowing for optional filter for last X days.",
76 usage: "server:audit [days]",
77 requires_auth: false,
78 requires_admin: false,
79 params: &[("days", "Optional number of days to display audit logs for")],
80 },
81 CommandEntry {
83 command: "db:stats",
84 summary: "Displays database statistics.",
85 description: "Prints the number of rows in each table, total row count, and estimated size of each table and database.",
86 usage: "db:stats",
87 requires_auth: false,
88 requires_admin: false,
89 params: &[],
90 },
91 CommandEntry {
92 command: "db:table",
93 summary: "Displays records from a specific table.",
94 description: "Prints the records from the specified table, with an option to view a specific page of results.",
95 usage: "db:table <name>, <page>",
96 requires_auth: false,
97 requires_admin: false,
98 params: &[
99 ("name", "The name of the table to display"),
100 ("page", "The page of results to display"),
101 ],
102 },
103 CommandEntry {
105 command: "user:delete",
106 summary: "Deletes a user account.",
107 description: "Removes a user account from the database. This action is irreversible.",
108 usage: "user:delete <id>",
109 requires_auth: true,
110 requires_admin: true,
111 params: &[("id", "The ID of the user to delete")],
112 },
113 CommandEntry {
115 command: "test:run",
116 summary: "Runs functional tests on the server.",
117 description: "Executes a suite of functional tests to verify that the server is operating correctly. This is only available if testing mode is enabled.",
118 usage: "test:run",
119 requires_auth: false,
120 requires_admin: false,
121 params: &[],
122 },
123];
124
125pub fn print_all() {
129 println!();
130 println!("{}", " Available Commands".cyan().bold());
131 println!(
132 "{}",
133 " ─────────────────────────────────────────────────────".dimmed()
134 );
135
136 let namespaces = ["help", "server", "db", "user", "test"];
137
138 for ns in namespaces {
139 println!();
140 println!(" {}", ns.white().bold());
141
142 for entry in COMMANDS {
143 let ns_prefix = format!("{}:", ns);
144 let belongs = entry.command == ns
145 || entry.command.starts_with(&ns_prefix)
146 || (ns == "help" && entry.command.starts_with("help "));
147
148 if belongs {
149 let auth_marker = if entry.requires_auth {
150 " *".yellow().to_string()
151 } else {
152 String::new()
153 };
154 println!(
155 " {:<30} {}{}",
156 entry.command.green(),
157 entry.summary.dimmed(),
158 auth_marker
159 );
160 }
161 }
162 }
163
164 println!();
165 println!(
166 " {} {}",
167 "*".yellow(),
168 "marked commands require server:login before use.".dimmed()
169 );
170 println!(
171 " {}",
172 "Run `help <command>` for detailed usage on any command.".dimmed()
173 );
174 println!();
175}
176
177pub fn print_command(command: &str) {
181 let entry = COMMANDS.iter().find(|e| {
182 e.command == command
183 || e.command == format!("server:{}", command)
184 || e.command == format!("help {}", command)
185 });
186
187 match entry {
188 None => {
189 println!("{} {}", "No help entry found for:".red(), command.white());
190 println!("{}", "Run `help` to see all available commands.".dimmed());
191 }
192 Some(e) => {
193 println!();
194 println!(" {}", e.command.cyan().bold());
195 println!(
196 "{}",
197 " ─────────────────────────────────────────────────────".dimmed()
198 );
199 println!(
200 " {:<16} {}",
201 "Description:".white(),
202 e.description.dimmed()
203 );
204 println!(" {:<16} {}", "Usage:".white(), e.usage.green());
205 println!(
206 " {:<16} {}",
207 "Auth required:".white(),
208 if e.requires_auth {
209 "yes".yellow().to_string()
210 } else {
211 "no".dimmed().to_string()
212 }
213 );
214
215 println!(
216 " {:<16} {}",
217 "Admin permissions required:".white(),
218 if e.requires_admin {
219 "yes".yellow().to_string()
220 } else {
221 "no".dimmed().to_string()
222 }
223 );
224
225 if !e.params.is_empty() {
226 println!(" {}", "Parameters:".white());
227 for (name, desc) in e.params {
228 println!(" {:<16} {}", name.green(), desc.dimmed());
229 }
230 }
231
232 println!();
233 }
234 }
235}