pub mod scaffolding;
pub mod database;
pub mod monitoring;
pub mod builder;
pub mod utils;
pub mod packages;
pub mod publisher;
pub use scaffolding::*;
pub use database::*;
pub use monitoring::*;
pub use builder::*;
pub use utils::*;
use std::env;
use rustbasic_core::dotenvy::dotenv;
use rustbasic_core::colored::*;
use std::future::Future;
use std::pin::Pin;
pub type AsyncHook = Box<dyn Fn() -> Pin<Box<dyn Future<Output = ()>>>>;
pub async fn run_cli<F, G>(migrate_fn: F, seed_fn: G)
where
F: Fn(String) -> Pin<Box<dyn Future<Output = Result<(), String>>>>,
G: Fn() -> Pin<Box<dyn Future<Output = ()>>>
{
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
print_help();
return;
}
let command = &args[1];
if command != "new" {
let _ = dotenv();
ensure_session().await;
}
match command.as_str() {
"migrate" | "migrate:refresh" | "migrate:back" | "migrate:rollback" => {
match migrate_fn(command.clone()).await {
Ok(_) => println!("\n{} Operasi '{}' berhasil.", "â
".green(), command),
Err(e) => eprintln!("\n{} Gagal: {}", "â".red(), e),
}
}
"db:seed" => {
println!("{}", "đą Menjalankan seeder database...".cyan());
seed_fn().await;
println!("\n{} Database seeding berhasil.", "â
".green());
}
_ => {
}
}
}
pub fn print_help() {
println!("Gunakan 'rustbasic' untuk melihat opsi perintah.");
}
pub async fn handle<M: rustbasic_core::MigratorTrait + Send + Sync + 'static>(args: &[String]) -> bool {
if args.len() < 2 {
return false;
}
let command = args[1].as_str();
let is_migration_cmd = command.starts_with("migrate") || command == "db:seed";
let is_storage_cmd = command == "storage:link";
let is_build_cmd = command == "build";
let is_server_cmd = command == "server" || command == "serve";
if is_server_cmd {
let run_android = args.iter().any(|arg| arg == "--android");
let run_desktop = args.iter().any(|arg| arg == "--desktop");
if run_android || run_desktop {
builder::run_native(run_android, run_desktop);
return true;
}
return false; }
if !is_migration_cmd && !is_storage_cmd && !is_build_cmd {
return false;
}
println!("đ ī¸ RustBasic Local CLI - Command: {}", command);
if is_build_cmd {
builder::build_interactive(args);
return true;
}
if is_storage_cmd {
handle_storage_link();
return true;
}
ensure_session().await;
let db = crate::database::connect().await;
match command {
"migrate" => {
println!("đ {}", "Menjalankan migrasi database...".cyan());
if let Err(e) = M::up(&db, None).await {
println!("â {} {}", "Gagal menjalankan migrasi:".red().bold(), e);
} else {
println!("â
{}", "Migrasi selesai!".green().bold());
}
}
"migrate:refresh" => {
println!("đ {}", "Mereset dan menjalankan ulang migrasi...".cyan());
if let Err(e) = M::fresh(&db).await {
println!("â {} {}", "Gagal refresh migrasi:".red().bold(), e);
} else {
println!("â
{}", "Database berhasil di-refresh!".green().bold());
}
}
"migrate:back" | "migrate:rollback" => {
println!("âŦ
ī¸ {}", "Rollback migrasi terakhir...".cyan());
if let Err(e) = M::down(&db, None).await {
println!("â {} {}", "Gagal rollback:".red().bold(), e);
} else {
println!("â
{}", "Rollback berhasil!".green().bold());
}
}
"db:seed" => {
println!("đą {}", "Fitur db:seed membutuhkan implementasi lokal.".yellow());
}
_ => return false,
}
true
}
fn handle_storage_link() {
let target = "public/storage";
let source = "storage/app/public";
if let Err(e) = std::fs::create_dir_all(source) {
println!("â {} {}", "Gagal membuat direktori storage:".red().bold(), e);
return;
}
let path = std::path::Path::new(target);
if path.exists() || path.is_symlink() {
println!("âšī¸ {}", "Link 'public/storage' sudah ada atau berupa file/folder lain.".yellow());
return;
}
println!("đ {}", "Membuat symbolic link...".cyan());
#[cfg(unix)]
{
use std::os::unix::fs::symlink;
if let Err(e) = symlink("../storage/app/public", target) {
println!("â {} {}", "Gagal membuat symlink:".red().bold(), e);
} else {
println!("â
{} [public/storage -> storage/app/public]", "Link storage berhasil dibuat!".green().bold());
}
}
#[cfg(windows)]
{
use std::os::windows::fs::symlink_dir;
if let Err(e) = symlink_dir("../storage/app/public", target) {
println!("â {} {}", "Gagal membuat symlink:".red().bold(), e);
} else {
println!("â
{} [public/storage -> storage/app/public]", "Link storage berhasil dibuat!".green().bold());
}
}
}