use clap::{Parser, Subcommand};
use std::error::Error;
use std::path::PathBuf;
use tracing::{error, info};
use dumpling::error::Result;
#[derive(Parser)]
#[command(name = "dumpling")]
#[command(about = "A fast JavaScript runtime and bundler")]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
Run {
file: PathBuf,
#[arg(trailing_var_arg = true)]
args: Vec<String>,
},
Bundle {
entry: PathBuf,
#[arg(short, long)]
output: PathBuf,
#[arg(short, long, default_value = "esm")]
format: String,
#[arg(short, long)]
minify: bool,
#[arg(long)]
sourcemap: bool,
#[arg(long)]
declarations: bool,
#[arg(long)]
split: bool,
#[arg(long, default_value = "50")]
vendor_size: usize,
},
Install {
#[arg(trailing_var_arg = true)]
packages: Vec<String>,
#[arg(short, long)]
dev: bool,
},
Uninstall {
#[arg(trailing_var_arg = true)]
packages: Vec<String>,
},
Prune,
Init {
#[arg(short, long)]
name: Option<String>,
},
Dev {
#[arg(short, long, default_value = "3000")]
port: u16,
#[arg(short, long, default_value = "localhost")]
host: String,
},
RunScript {
script: String,
},
Audit {
#[arg(short, long, default_value = "markdown")]
format: String,
#[arg(long)]
licenses: bool,
},
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let cli = Cli::parse();
if let Err(e) = run(cli).await {
error!("Error: {}", e);
let mut source: Option<&(dyn Error + 'static)> = e.source();
while let Some(s) = source {
error!(" Caused by: {}", s);
source = s.source();
}
std::process::exit(1);
}
}
async fn run(cli: Cli) -> Result<()> {
match cli.command {
Commands::Run { file, args } => {
info!("Running file: {:?}", file);
dumpling::run_file(file, args).await?;
}
Commands::Bundle { entry, output, format, minify, sourcemap, declarations, split, vendor_size } => {
info!("Bundling {:?} -> {:?}", entry, output);
dumpling::bundle_with_splitting(entry, output, &format, minify, sourcemap, declarations, split, vendor_size).await?;
}
Commands::Install { packages, dev } => {
info!("Installing packages: {:?}", packages);
dumpling::install(packages, dev).await?;
}
Commands::Uninstall { packages } => {
info!("Uninstalling packages: {:?}", packages);
dumpling::uninstall(packages).await?;
}
Commands::Prune => {
info!("Pruning unused packages");
dumpling::prune().await?;
}
Commands::Init { name } => {
info!("Initializing project");
dumpling::init(name).await?;
}
Commands::Dev { port, host } => {
info!("Starting dev server on {}:{}", host, port);
dumpling::start_dev_server(host, port).await?;
}
Commands::RunScript { script } => {
info!("Running script: {}", script);
dumpling::run_script(script).await?;
}
Commands::Audit { format, licenses } => {
info!("Running security audit");
dumpling::security::audit(format, licenses).await?;
}
}
Ok(())
}