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		return;
87	}
88
89	// Check if first arg after binary is a run-specific flag or subcommand
90	let first_arg = args.get(1).map(|s| s.as_str()).unwrap_or("");
91
92	// Check if we're in legacy mode (-- followed by a command)
93	let is_legacy_mode = first_arg == "--";
94
95	// Check for run mode indicators
96	let is_run_flag = first_arg == "--run" || first_arg == "--dev" || first_arg == "-r";
97	let is_run_subcommand = first_arg == "run";
98	let is_run_mode = is_run_flag || is_run_subcommand;
99
100	// Check for build mode indicators (subcommand or flags)
101	let is_build_subcommand = first_arg == "build";
102
103	// CLI flags that indicate we should use the build CLI mode
104	let build_cli_flags = [
105		"--list-profiles",
106		"--show-profile",
107		"--validate-profile",
108		"--profile",
109		"--dry-run",
110		"--help",
111		"-h",
112		"--version",
113		"-V",
114		"list-profiles",
115		"show-profile",
116		"validate-profile",
117		"resolve",
118	];
119
120	// Check if first arg is a build CLI flag
121	let is_build_cli_mode = if !is_run_mode && !is_legacy_mode && !is_build_subcommand {
122		build_cli_flags
123			.iter()
124			.any(|flag| first_arg == *flag || first_arg.starts_with(&format!("{}=", flag)))
125			|| (!first_arg.starts_with('-') && !is_build_subcommand)
126	} else {
127		false
128	};
129
130	if is_run_mode {
131		// Strip the --run/--dev/-r flag or 'run' subcommand before passing to Run CLI
132		// This allows Run::CLI to parse the remaining arguments correctly
133		if is_run_flag {
134			// Remove the flag (and its position) from args
135			args.remove(1);
136		} else if is_run_subcommand {
137			// Replace 'run' subcommand with arguments that Run CLI expects
138			args.remove(1);
139		}
140
141		// Use Run mode (development workflow)
142		// Use try_parse_from with our modified args, not try_parse() which reads from
143		// env::args()
144		match Run::CLI::Cli::try_parse_from(args) {
145			Ok(cli) => {
146				if let Err(e) = cli.execute() {
147					eprintln!("Error: {}", e);
148					std::process::exit(1);
149				}
150			},
151			Err(e) => {
152				// If parsing fails, it might be a --help or --version request
153				// or invalid arguments - let clap handle it
154				e.print().expect("Failed to print error");
155				std::process::exit(e.exit_code());
156			},
157		}
158	} else if is_build_subcommand {
159		// Handle 'build' subcommand - strip it and pass to Build CLI
160		args.remove(1);
161
162		// Use try_parse_from with our modified args
163		match Build::CLI::Cli::try_parse_from(args) {
164			Ok(cli) => {
165				if let Err(e) = cli.execute() {
166					eprintln!("Error: {}", e);
167					std::process::exit(1);
168				}
169			},
170			Err(e) => {
171				e.print().expect("Failed to print error");
172				std::process::exit(e.exit_code());
173			},
174		}
175	} else if is_build_cli_mode {
176		// Use Build CLI mode (configuration based)
177		match Build::CLI::Cli::try_parse() {
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				// If parsing fails, it might be a --help or --version request
186				// or invalid arguments - let clap handle it
187				e.print().expect("Failed to print error");
188				std::process::exit(e.exit_code());
189			},
190		}
191	} else {
192		// Use legacy build mode (environment variable based)
193		// This handles: ./Maintain -- pnpm tauri build
194		Build::Fn::Fn();
195	}
196}
197
198// =============================================================================
199// MODULE DECLARATIONS
200// =============================================================================
201
202/// Build Orchestrator Module.
203///
204/// This module contains all the build orchestration logic, including:
205///
206/// - **CLI**: Command-line interface for configuration-based builds
207/// - **Constant**: File paths, delimiters, and environment variable names
208/// - **Definition**: Data structures for arguments, manifests, and file guards
209/// - **Error**: Comprehensive error types for build operations
210/// - **Fn**: Main build orchestration function
211/// - **GetTauriTargetTriple**: Target triple detection
212/// - **JsonEdit**: JSON configuration editing
213/// - **Logger**: Logging utilities
214/// - **Pascalize**: PascalCase conversion utilities
215/// - **Process**: Process management
216/// - **Rhai**: Rhai scripting support
217/// - **TomlEdit**: TOML configuration editing
218/// - **WordsFromPascal**: Extract words from PascalCase strings
219///
220/// See the Build module documentation for detailed information about the
221/// build system's capabilities and usage.
222pub mod Build;
223
224/// Development Run Module.
225///
226/// This module contains all the development run orchestration logic, including:
227///
228/// - **CLI**: Command-line interface for configuration-based runs
229/// - **Constant**: File paths, delimiters, and environment variable names
230/// - **Definition**: Data structures for arguments and run configuration
231/// - **Environment**: Environment variable resolution and management
232/// - **Error**: Comprehensive error types for run operations
233/// - **Fn**: Main run orchestration function
234/// - **Logger**: Logging utilities
235/// - **Process**: Process management for development servers
236/// - **Profile**: Profile resolution and management
237///
238/// See the Run module documentation for detailed information about the
239/// development run system's capabilities and usage.
240pub mod Run;
241pub mod Architecture;