use clap::Parser;
use colored::*;
use create_lamdera_app_rs::*;
use std::env;
use std::fs;
use std::path::PathBuf;
fn main() -> Result<()> {
let args = args::Args::parse();
if let Err(e) = args.validate() {
eprintln!("{}", format!("❌ {}", e).red());
std::process::exit(1);
}
if args.init {
return handle_init_mode();
}
if args.install_precommit {
return handle_precommit_install();
}
create_project(args)
}
fn create_project(args: args::Args) -> Result<()> {
let is_interactive = args.name.is_none();
let project_name = if let Some(ref name) = args.name {
name.clone()
} else {
interactive::prompt_project_name()?
};
let create_github = if let Some(create) = args.should_create_github() {
create
} else {
interactive::prompt_create_github()?
};
let is_public = if create_github && !args.public {
interactive::prompt_repository_visibility()?
} else {
args.public
};
let package_manager = if is_interactive {
interactive::prompt_package_manager()?
} else {
args.get_package_manager()
};
let simple = if is_interactive {
interactive::prompt_boilerplate_type()?
} else {
args.simple
};
let project_path = PathBuf::from(&project_name);
if project_path.exists() {
eprintln!(
"{}",
format!("❌ Directory '{}' already exists", project_name).red()
);
std::process::exit(1);
}
fs::create_dir_all(&project_path)?;
env::set_current_dir(&project_path)?;
let current_dir = PathBuf::from(".");
templates::copy_boilerplate(¤t_dir, simple)?;
templates::update_package_json(¤t_dir, package_manager.as_str())?;
git::init_repository(¤t_dir)?;
git::make_hooks_executable(¤t_dir)?;
if !args.skip_install {
package_manager::install_dependencies(¤t_dir, &package_manager)?;
}
git::initial_commit(¤t_dir)?;
git::configure_hooks(¤t_dir)?;
if create_github {
if !github::is_gh_cli_installed() {
eprintln!("{}", "⚠️ GitHub CLI (gh) not installed. Skipping repository creation.".yellow());
eprintln!("{}", " Install it from: https://cli.github.com/".yellow());
} else if !github::is_gh_cli_authenticated() {
eprintln!("{}", "⚠️ GitHub CLI not authenticated. Run 'gh auth login' first.".yellow());
} else {
match github::create_repository(&project_name, is_public) {
Ok(_) => {
git::push_to_remote(¤t_dir)?;
}
Err(e) => {
eprintln!("{}", format!("⚠️ Failed to create GitHub repository: {}", e).yellow());
}
}
}
}
print_success_message(&project_name, &package_manager, simple);
Ok(())
}
fn handle_init_mode() -> Result<()> {
println!("{}", "🚧 Init mode not yet implemented".yellow());
Ok(())
}
fn handle_precommit_install() -> Result<()> {
let current_dir = env::current_dir()?;
git::configure_hooks(¤t_dir)?;
println!("{}", "✓ Pre-commit hooks installed".green());
Ok(())
}
fn print_success_message(project_name: &str, package_manager: &args::PackageManager, simple: bool) {
println!("\n{}", "✨ Project setup complete!".green().bold());
let pm = package_manager.as_str();
let run_script = if pm == "npm" { "npm run" } else { "bun run" };
println!("\n📦 {}", "To start development:".bold());
println!(" cd {}", project_name);
println!(" {} install (install dependencies first)", pm);
println!(" {} start (runs Lamdera + Tailwind watcher)", pm);
println!("\n🔧 {}", "Development commands:".bold());
println!(" PORT=3000 {} start (custom port)", pm);
println!(" {} run start:hot (with elm-pkg-js hot-reload)", pm);
println!("\n🧪 {}", "Testing:".bold());
println!(" {} test", run_script);
println!(" {} check", run_script);
println!(" Check tests/Tests.elm for lamdera-program-test examples");
println!("\n🌐 {}", "Features included:".bold());
println!(" • Tailwind CSS + Dark mode");
println!(" • i18n (EN/FR) with localStorage");
println!(" • Authentication (Google, GitHub, Email)");
println!(" • lamdera-program-test integration");
println!(" • Development config panel (bottom-left in dev mode)");
println!(" • Pre-commit hooks with elm-review");
if !simple {
println!(" • Counter demo (increment/decrement)");
println!(" • Chat system (real-time messaging)");
}
println!("\n📚 {}", "Documentation:".bold());
println!(" • HOW_TO_WRITE_TESTS.md");
println!(" • GOOGLE_ONE_TAP_SETUP.md");
println!(" • GITHUB_OAUTH_SETUP.md");
println!(" • ENVIRONMENT_SETUP.md (set passwordSecret before production)");
}