11// server/src/cli/cli.rs
22
3- // This file serves as the main entry point for the GraphDB CLI executable.
4- // It parses command-line arguments and dispatches them to appropriate handlers
5- // in other modules.
6-
7- use anyhow:: Result ;
8- use clap:: { CommandFactory , Parser } ;
3+ use clap:: Parser ;
94use std:: process;
10- use std:: env; // Import std::env for accessing command-line arguments
5+ use std:: env;
6+ use std:: collections:: HashMap ;
7+ use tokio:: sync:: { oneshot, Mutex } ;
8+ use tokio:: task:: JoinHandle ;
9+ use std:: sync:: Arc ;
1110
12- // Import necessary items from the cli module (which re-exports from its sub-modules)
1311use crate :: cli:: {
14- commands:: { CliArgs , GraphDbCommands } ,
15- handlers,
16- interactive,
12+ commands:: { CliArgs , GraphDbCommands , StartAction , DaemonCliCommand , RestCliCommand , StorageAction , StatusArgs , StopArgs , ReloadArgs } ,
13+ handlers:: { self as handlers_mod , print_welcome_screen } ,
14+ interactive:: { self as interactive_mod , run_cli_interactive } ,
1715 daemon_management,
18- config,
19- help_display,
16+ config:: { self as config_mod } ,
17+ help_display:: { self as help_display_mod } ,
2018} ;
2119
20+ use anyhow:: Result ;
21+ use clap:: CommandFactory ;
22+ use lib:: storage_engine:: config:: StorageEngineType as LibStorageEngineType ;
23+
2224/// The main entry point for the CLI logic, called by server/src/main.rs
2325/// This function parses command-line arguments and dispatches to appropriate handlers.
2426#[ tokio:: main]
2527pub async fn start_cli ( ) -> Result < ( ) > {
2628 // --- Custom Help Command Handling ---
27- // Manually check for "help" as the first argument to bypass clap's default parsing
2829 let args_vec: Vec < String > = env:: args ( ) . collect ( ) ;
2930 if args_vec. len ( ) > 1 && args_vec[ 1 ] . to_lowercase ( ) == "help" {
30- let help_command_args: Vec < String > = args_vec. into_iter ( ) . skip ( 2 ) . collect ( ) ; // Get args after "graphdb-cli help"
31+ let help_command_args: Vec < String > = args_vec. into_iter ( ) . skip ( 2 ) . collect ( ) ;
3132 let filter_command = if help_command_args. is_empty ( ) {
32- "" . to_string ( ) // No filter, show general help
33+ "" . to_string ( )
3334 } else {
34- help_command_args. join ( " " ) // Join all subsequent arguments as the filter string
35+ help_command_args. join ( " " )
3536 } ;
36- let mut cmd = CliArgs :: command ( ) ; // Get the top-level Command object for clap's help generation
37- help_display :: print_filtered_help_clap_generated ( & mut cmd, & filter_command) ;
38- process:: exit ( 0 ) ; // Exit after displaying help
37+ let mut cmd = CliArgs :: command ( ) ;
38+ help_display_mod :: print_filtered_help_clap_generated ( & mut cmd, & filter_command) ;
39+ process:: exit ( 0 ) ;
3940 }
4041 // --- End Custom Help Command Handling ---
4142
42-
4343 let args = CliArgs :: parse ( ) ;
4444
45- // Handle internal daemon runs first. These are special invocations
46- // where the CLI executable is run as a background daemon.
4745 if args. internal_rest_api_run || args. internal_storage_daemon_run {
46+ let converted_storage_engine = args. internal_storage_engine . map ( |se_cli| {
47+ match se_cli {
48+ config_mod:: StorageEngineType :: Sled => LibStorageEngineType :: Sled ,
49+ config_mod:: StorageEngineType :: RocksDB => LibStorageEngineType :: RocksDB ,
50+ config_mod:: StorageEngineType :: InMemory => LibStorageEngineType :: InMemory ,
51+ }
52+ } ) ;
53+
4854 return daemon_management:: handle_internal_daemon_run (
4955 args. internal_rest_api_run ,
5056 args. internal_storage_daemon_run ,
5157 args. internal_port ,
5258 args. internal_storage_config_path ,
53- args . internal_storage_engine ,
59+ converted_storage_engine ,
5460 ) . await ;
5561 }
5662
57- // Load CLI configuration. If it fails, print an error and exit.
58- let config = match config:: load_cli_config ( ) {
63+ let config = match config_mod:: load_cli_config ( ) {
5964 Ok ( cfg) => cfg,
6065 Err ( e) => {
6166 eprintln ! ( "Error loading configuration: {}" , e) ;
@@ -68,10 +73,8 @@ pub async fn start_cli() -> Result<()> {
6873 }
6974 } ;
7075
71- // Handle direct query execution if the `--query` flag is present.
7276 if let Some ( query_string) = args. query {
7377 println ! ( "Executing direct query: {}" , query_string) ;
74- // Assuming lib::query_parser is accessible and QueryType is defined
7578 use lib:: query_parser:: { parse_query_from_string, QueryType } ;
7679 match parse_query_from_string ( & query_string) {
7780 Ok ( parsed_query) => match parsed_query {
@@ -81,10 +84,17 @@ pub async fn start_cli() -> Result<()> {
8184 } ,
8285 Err ( e) => eprintln ! ( "Error parsing query: {}" , e) ,
8386 }
84- return Ok ( ( ) ) ; // Exit after processing a direct query
87+ return Ok ( ( ) ) ;
8588 }
8689
87- // Handle explicit command execution if a subcommand is provided.
90+ // Shared state for interactive mode to manage daemon processes
91+ let daemon_handles: Arc < Mutex < HashMap < u16 , ( JoinHandle < ( ) > , oneshot:: Sender < ( ) > ) > > > = Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ;
92+ let rest_api_shutdown_tx_opt: Arc < Mutex < Option < oneshot:: Sender < ( ) > > > > = Arc :: new ( Mutex :: new ( None ) ) ;
93+ let rest_api_port_arc: Arc < Mutex < Option < u16 > > > = Arc :: new ( Mutex :: new ( None ) ) ;
94+ let rest_api_handle: Arc < Mutex < Option < JoinHandle < ( ) > > > > = Arc :: new ( Mutex :: new ( None ) ) ;
95+
96+ let should_enter_interactive_mode = args. cli || args. command . is_none ( ) ;
97+
8898 if let Some ( command) = args. command {
8999 if args. enable_plugins {
90100 println ! ( "Experimental plugins are enabled." ) ;
@@ -128,53 +138,108 @@ pub async fn start_cli() -> Result<()> {
128138 println ! ( "Executing cache-node-state with no node ID specified" ) ;
129139 }
130140 }
131- GraphDbCommands :: Start { port, cluster, listen_port, storage_port, storage_config_file } => {
132- // Delegate to the handler module for 'start' command logic
133- handlers:: handle_start_command ( port, cluster, listen_port, storage_port, storage_config_file, & config) . await ?;
141+ GraphDbCommands :: Start ( start_args) => {
142+ match start_args. action {
143+ StartAction :: All { port, cluster, listen_port, storage_port, storage_config_file } => {
144+ handlers_mod:: handle_start_all_interactive (
145+ port,
146+ cluster,
147+ listen_port,
148+ storage_port,
149+ storage_config_file,
150+ daemon_handles. clone ( ) ,
151+ rest_api_shutdown_tx_opt. clone ( ) ,
152+ rest_api_port_arc. clone ( ) ,
153+ rest_api_handle. clone ( ) ,
154+ ) . await ?;
155+ }
156+ StartAction :: Daemon { port, cluster } => {
157+ handlers_mod:: handle_daemon_command_interactive (
158+ DaemonCliCommand :: Start { port, cluster } ,
159+ daemon_handles. clone ( ) ,
160+ ) . await ?;
161+ }
162+ StartAction :: Rest { port, listen_port } => {
163+ handlers_mod:: handle_rest_command_interactive (
164+ RestCliCommand :: Start { port, listen_port } ,
165+ rest_api_shutdown_tx_opt. clone ( ) ,
166+ rest_api_port_arc. clone ( ) ,
167+ rest_api_handle. clone ( ) ,
168+ ) . await ?;
169+ }
170+ StartAction :: Storage { port, config_file } => {
171+ handlers_mod:: handle_storage_command_interactive (
172+ StorageAction :: Start { port, config_file } ,
173+ ) . await ?;
174+ }
175+ }
134176 }
135177 GraphDbCommands :: Stop ( stop_args) => {
136- // Delegate to the handler module for 'stop' command logic
137- handlers:: handle_stop_command ( stop_args) . await ?;
178+ handlers_mod:: handle_stop_command ( stop_args) . await ?;
138179 }
139180 GraphDbCommands :: Status ( status_args) => {
140- // Delegate to the handler module for 'status' command logic
141- handlers:: handle_status_command ( status_args) . await ?;
181+ handlers_mod:: handle_status_command ( status_args) . await ?;
182+ }
183+ GraphDbCommands :: Reload ( reload_args) => {
184+ handlers_mod:: handle_reload_command (
185+ reload_args,
186+ daemon_handles. clone ( ) ,
187+ rest_api_shutdown_tx_opt. clone ( ) ,
188+ rest_api_port_arc. clone ( ) ,
189+ rest_api_handle. clone ( ) ,
190+ ) . await ?;
142191 }
143192 GraphDbCommands :: Storage ( storage_action) => {
144- // Delegate to the handler module for 'storage' command logic
145- handlers:: handle_storage_command ( storage_action) . await ?;
193+ handlers_mod:: handle_storage_command_interactive ( storage_action) . await ?;
146194 }
147195 GraphDbCommands :: Daemon ( daemon_cmd) => {
148- // Delegate to the handler module for 'daemon' command logic
149- handlers:: handle_daemon_command ( daemon_cmd) . await ?;
196+ handlers_mod:: handle_daemon_command_interactive ( daemon_cmd, daemon_handles. clone ( ) ) . await ?;
150197 }
151198 GraphDbCommands :: Rest ( rest_cmd) => {
152- // Delegate to the handler module for 'rest' command logic
153- handlers:: handle_rest_command ( rest_cmd) . await ?;
199+ handlers_mod:: handle_rest_command_interactive (
200+ rest_cmd,
201+ rest_api_shutdown_tx_opt. clone ( ) ,
202+ rest_api_port_arc. clone ( ) ,
203+ rest_api_handle. clone ( ) ,
204+ ) . await ?;
205+ }
206+ GraphDbCommands :: Auth ( auth_args) => {
207+ println ! ( "Auth command received: {:?}" , auth_args) ;
208+ }
209+ GraphDbCommands :: Authenticate ( auth_args) => {
210+ println ! ( "Authenticate command received: {:?}" , auth_args) ;
211+ }
212+ GraphDbCommands :: Register ( register_args) => {
213+ println ! ( "Register command received: {:?}" , register_args) ;
214+ }
215+ GraphDbCommands :: Version => {
216+ println ! ( "Version command received." ) ;
217+ }
218+ GraphDbCommands :: Health => {
219+ println ! ( "Health command received." ) ;
220+ }
221+ GraphDbCommands :: Clear | GraphDbCommands :: Clean => {
222+ handlers_mod:: clear_terminal_screen ( ) . await ?;
154223 }
155- // The GraphDbCommands::Help variant is removed, as 'help' is now handled manually.
156224 }
157- return Ok ( ( ) ) ; // Exit after processing a direct command
225+ return Ok ( ( ) ) ;
158226 }
159227
160- // If no specific command or query is given, and `--cli` flag is present,
161- // or if no arguments are given at all, enter interactive CLI mode.
162- if args. cli {
228+ if should_enter_interactive_mode {
163229 if args. enable_plugins {
164230 println ! ( "Experimental plugins are enabled." ) ;
165231 }
166- interactive:: run_cli_interactive ( ) . await ?;
167- return Ok ( ( ) ) ;
168- }
169-
170- // If only `--enable-plugins` is given without other commands.
171- if args. enable_plugins {
232+ // print_welcome_screen(); // Removed: This is now handled by interactive_mod::run_cli_interactive
233+ interactive_mod:: run_cli_interactive (
234+ daemon_handles,
235+ rest_api_shutdown_tx_opt,
236+ rest_api_port_arc,
237+ rest_api_handle,
238+ ) . await ?;
239+ } else if args. enable_plugins {
172240 println ! ( "Experimental plugins is enabled." ) ;
173- return Ok ( ( ) ) ;
174241 }
175242
176- // Default to interactive CLI if no other commands/args are given
177- interactive:: run_cli_interactive ( ) . await ?;
178243 Ok ( ( ) )
179244}
180245
0 commit comments