Maintain/
Library.rs

1/*=============================================================================*/
2/* File Path: Element/Maintain/Source/Library.rs */
3/*=============================================================================*/
4/* Module: Library */
5/* */
6/* Brief Description: Entry point for the Maintain binary supporting both */
7/*                    Build and Run workflows. */
8/* */
9/* RESPONSIBILITIES: */
10/* ================ */
11/* */
12/* Primary: */
13/* - Serve as the entry point for the Maintain orchestrator */
14/* - Initialize Build and Run modules based on CLI arguments */
15/* - Route commands to appropriate workflow handlers */
16/* */
17/* Secondary: */
18/* - Provide unified CLI interface for build and run operations */
19/* - Support legacy mode for backward compatibility */
20/* */
21/* ARCHITECTURAL ROLE: */
22/* =================== */
23/* */
24/* Position: */
25/* - Entry point layer */
26/* - Binary initialization and routing */
27/* */
28/* Dependencies (What this module requires): */
29/* - External crates: clap, std */
30/* - Internal modules: Build, Run */
31/* - Traits implemented: None */
32/* */
33/* Dependents (What depends on this module): */
34/* - Cargo.toml (binary definition) */
35/* - Build system entry point */
36/* - Development run entry point */
37/* */
38/*=============================================================================*/
39/* IMPLEMENTATION */
40/*=============================================================================*/
41
42// Disable Windows console for release builds
43#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
44
45// Allow PascalCase naming for function names
46#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
47
48/*=============================================================================*/
49/* MAIN ENTRY POINT */
50/*=============================================================================*/
51
52/// The primary entry point for the Maintain Orchestrator binary.
53///
54/// This function serves as the bridge between the Cargo binary definition
55/// and the Build/Run modules' orchestration logic. It supports three modes:
56///
57/// ## Mode 1: Run Mode (--run flag)
58///
59/// When called with the `--run` flag, uses the development run workflow:
60/// ```bash
61/// cargo run --bin Maintain -- --run --profile debug-mountain
62/// cargo run --bin Maintain -- --run --list-profiles
63/// ```
64///
65/// ## Mode 2: Build Mode (default or --build flag)
66///
67/// When called with CLI arguments (without --run), uses the build workflow:
68/// ```bash
69/// cargo run --bin Maintain -- --profile debug-mountain
70/// cargo run --bin Maintain -- --list-profiles
71/// ```
72///
73/// ## Mode 3: Legacy Mode (environment variable based)
74///
75/// When called with a `--` separator followed by a build command, uses the
76/// traditional environment variable-based build system:
77/// ```bash
78/// ./Target/release/Maintain -- pnpm tauri build --debug
79/// ./Target/release/Maintain -- pnpm tauri dev
80/// ```
81///
82/// The function is marked as `#[allow(dead_code)]` because when this file
83/// is used as a library module, the main function may not be called directly.
84/// However, when compiled as a binary, this main function is the entry point.
85#[allow(dead_code)]
86fn main() {
87    use clap::Parser;
88    use std::env;
89
90    // Collect all arguments
91    let mut args: Vec<String> = env::args().collect();
92
93    // Determine the mode based on arguments:
94    // - Run mode: --run/-r flag, --dev flag, or 'run' subcommand
95    // - Build mode: Direct flags like --list-profiles, --profile, --show-profile, or 'build' subcommand
96    // - Legacy mode: -- followed by a build command (like pnpm, cargo, npm)
97    // - No args: Show help
98
99    if args.len() == 1 {
100        // No arguments - show build help (default)
101        let _ = Build::CLI::Cli::try_parse();
102        return;
103    }
104
105    // Check if first arg after binary is a run-specific flag or subcommand
106    let first_arg = args.get(1).map(|s| s.as_str()).unwrap_or("");
107
108    // Check if we're in legacy mode (-- followed by a command)
109    let is_legacy_mode = first_arg == "--";
110
111    // Check for run mode indicators
112    let is_run_flag = first_arg == "--run" || first_arg == "--dev" || first_arg == "-r";
113    let is_run_subcommand = first_arg == "run";
114    let is_run_mode = is_run_flag || is_run_subcommand;
115
116    // Check for build mode indicators (subcommand or flags)
117    let is_build_subcommand = first_arg == "build";
118
119    // CLI flags that indicate we should use the build CLI mode
120    let build_cli_flags = [
121        "--list-profiles",
122        "--show-profile",
123        "--validate-profile",
124        "--profile",
125        "--dry-run",
126        "--help",
127        "-h",
128        "--version",
129        "-V",
130        "list-profiles",
131        "show-profile",
132        "validate-profile",
133        "resolve",
134    ];
135
136    // Check if first arg is a build CLI flag
137    let is_build_cli_mode = if !is_run_mode && !is_legacy_mode && !is_build_subcommand {
138        build_cli_flags.iter().any(|flag| {
139            first_arg == *flag || first_arg.starts_with(&format!("{}=", flag))
140        }) || (!first_arg.starts_with('-') && !is_build_subcommand)
141    } else {
142        false
143    };
144
145    if is_run_mode {
146        // Strip the --run/--dev/-r flag or 'run' subcommand before passing to Run CLI
147        // This allows Run::CLI to parse the remaining arguments correctly
148        if is_run_flag {
149            // Remove the flag (and its position) from args
150            args.remove(1);
151        } else if is_run_subcommand {
152            // Replace 'run' subcommand with arguments that Run CLI expects
153            args.remove(1);
154        }
155
156        // Use Run mode (development workflow)
157        // Use try_parse_from with our modified args, not try_parse() which reads from env::args()
158        match Run::CLI::Cli::try_parse_from(args) {
159            Ok(cli) => {
160                if let Err(e) = cli.execute() {
161                    eprintln!("Error: {}", e);
162                    std::process::exit(1);
163                }
164            }
165            Err(e) => {
166                // If parsing fails, it might be a --help or --version request
167                // or invalid arguments - let clap handle it
168                e.print().expect("Failed to print error");
169                std::process::exit(e.exit_code());
170            }
171        }
172    } else if is_build_subcommand {
173        // Handle 'build' subcommand - strip it and pass to Build CLI
174        args.remove(1);
175
176        // Use try_parse_from with our modified args
177        match Build::CLI::Cli::try_parse_from(args) {
178            Ok(cli) => {
179                if let Err(e) = cli.execute() {
180                    eprintln!("Error: {}", e);
181                    std::process::exit(1);
182                }
183            }
184            Err(e) => {
185                e.print().expect("Failed to print error");
186                std::process::exit(e.exit_code());
187            }
188        }
189    } else if is_build_cli_mode {
190        // Use Build CLI mode (configuration based)
191        match Build::CLI::Cli::try_parse() {
192            Ok(cli) => {
193                if let Err(e) = cli.execute() {
194                    eprintln!("Error: {}", e);
195                    std::process::exit(1);
196                }
197            }
198            Err(e) => {
199                // If parsing fails, it might be a --help or --version request
200                // or invalid arguments - let clap handle it
201                e.print().expect("Failed to print error");
202                std::process::exit(e.exit_code());
203            }
204        }
205    } else {
206        // Use legacy build mode (environment variable based)
207        // This handles: ./Maintain -- pnpm tauri build
208        Build::Fn::Fn();
209    }
210}
211
212/*=============================================================================*/
213/* MODULE DECLARATIONS */
214/*=============================================================================*/
215
216/// Build Orchestrator Module.
217///
218/// This module contains all the build orchestration logic, including:
219///
220/// - **CLI**: Command-line interface for configuration-based builds
221/// - **Constant**: File paths, delimiters, and environment variable names
222/// - **Definition**: Data structures for arguments, manifests, and file guards
223/// - **Error**: Comprehensive error types for build operations
224/// - **Fn**: Main build orchestration function
225/// - **GetTauriTargetTriple**: Target triple detection
226/// - **JsonEdit**: JSON configuration editing
227/// - **Logger**: Logging utilities
228/// - **Pascalize**: PascalCase conversion utilities
229/// - **Process**: Process management
230/// - **Rhai**: Rhai scripting support
231/// - **TomlEdit**: TOML configuration editing
232/// - **WordsFromPascal**: Extract words from PascalCase strings
233///
234/// See the Build module documentation for detailed information about the
235/// build system's capabilities and usage.
236pub mod Build;
237
238/// Development Run Module.
239///
240/// This module contains all the development run orchestration logic, including:
241///
242/// - **CLI**: Command-line interface for configuration-based runs
243/// - **Constant**: File paths, delimiters, and environment variable names
244/// - **Definition**: Data structures for arguments and run configuration
245/// - **Environment**: Environment variable resolution and management
246/// - **Error**: Comprehensive error types for run operations
247/// - **Fn**: Main run orchestration function
248/// - **Logger**: Logging utilities
249/// - **Process**: Process management for development servers
250/// - **Profile**: Profile resolution and management
251///
252/// See the Run module documentation for detailed information about the
253/// development run system's capabilities and usage.
254pub mod Run;