Skip to main content

Maintain/
Library.rs

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