mod host;
mod module;
use clap::{Args, Parser, Subcommand};
#[derive(Debug, Parser)]
#[command(
name = "lenso",
version,
about = "Scaffold and operate Lenso backend projects",
propagate_version = true
)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
Host {
#[command(subcommand)]
command: HostCommand,
},
Module {
#[command(subcommand)]
command: ModuleCommand,
},
ConsolePackage {
#[command(subcommand)]
command: ConsolePackageCommand,
},
}
#[derive(Debug, Subcommand)]
enum HostCommand {
Init {
dir: String,
#[arg(long)]
name: Option<String>,
#[arg(long)]
force: bool,
},
UpdateConsole {
#[arg(long)]
repo_root: Option<std::path::PathBuf>,
},
}
#[derive(Debug, Subcommand)]
enum ModuleCommand {
Create(ModuleCreateArgs),
Install(RemoteModuleInstallArgs),
Add(RemoteModuleInstallArgs),
Uninstall(RemoteModuleUninstallArgs),
Doctor(ModuleDoctorArgs),
Catalog {
#[command(subcommand)]
command: ModuleCatalogCommand,
},
Marketplace {
#[command(subcommand)]
command: ModuleMarketplaceCommand,
},
}
#[derive(Debug, Subcommand)]
enum ModuleCatalogCommand {
Add(ModuleCatalogAddArgs),
}
#[derive(Debug, Subcommand)]
enum ModuleMarketplaceCommand {
Install(RemoteModuleInstallArgs),
}
#[derive(Debug, Args, Clone)]
struct RemoteModuleInstallArgs {
manifest_reference: String,
#[arg(long, default_value = "remote")]
source: String,
#[arg(long)]
repo_root: Option<std::path::PathBuf>,
#[arg(long)]
env_file: Option<std::path::PathBuf>,
#[arg(long)]
install_plan_file: Option<std::path::PathBuf>,
#[arg(long)]
module_services_file: Option<std::path::PathBuf>,
#[arg(long)]
runtime_console_root: Option<std::path::PathBuf>,
#[arg(long)]
base_url: Option<String>,
#[arg(long = "no-console-plan", action = clap::ArgAction::SetFalse, default_value_t = true)]
console_plan: bool,
#[arg(long)]
run_install_commands: bool,
#[arg(long)]
dry_run: bool,
}
#[derive(Debug, Args, Clone)]
struct RemoteModuleUninstallArgs {
module_name: String,
#[arg(long)]
source: Option<String>,
#[arg(long)]
repo_root: Option<std::path::PathBuf>,
#[arg(long)]
env_file: Option<std::path::PathBuf>,
#[arg(long)]
install_plan_file: Option<std::path::PathBuf>,
#[arg(long)]
module_services_file: Option<std::path::PathBuf>,
#[arg(long)]
dry_run: bool,
}
#[derive(Debug, Args, Clone)]
struct ModuleDoctorArgs {
module_name: Option<String>,
#[arg(long)]
repo_root: Option<std::path::PathBuf>,
#[arg(long)]
env_file: Option<std::path::PathBuf>,
#[arg(long)]
module_services_file: Option<std::path::PathBuf>,
}
#[derive(Debug, Args)]
struct ModuleCatalogAddArgs {
manifest_reference: String,
#[arg(long)]
repo_root: Option<std::path::PathBuf>,
#[arg(long)]
catalog_file: Option<std::path::PathBuf>,
#[arg(long)]
base_url: Option<String>,
#[arg(long)]
summary: Option<String>,
#[arg(long)]
dry_run: bool,
}
#[derive(Debug, Subcommand)]
enum ConsolePackageCommand {
Create(ConsolePackageCreateArgs),
ApplyPlan(ConsolePackageApplyPlanArgs),
}
#[derive(Debug, Args, Clone)]
struct ModuleCreateArgs {
module_id: String,
#[arg(long)]
repo_root: Option<std::path::PathBuf>,
#[arg(long)]
output_dir: Option<std::path::PathBuf>,
#[arg(long)]
runtime_console_root: Option<std::path::PathBuf>,
#[arg(long)]
area: Option<String>,
#[arg(long)]
label: Option<String>,
#[arg(long)]
route: Option<String>,
#[arg(long)]
capability: Option<String>,
#[arg(long)]
icon: Option<String>,
#[arg(long)]
source: Option<String>,
#[arg(long)]
remote: bool,
#[arg(long)]
with_console: bool,
#[arg(long)]
package_slug: Option<String>,
#[arg(long)]
package_scope: Option<String>,
#[arg(long)]
package_name: Option<String>,
#[arg(long)]
surface_name: Option<String>,
#[arg(long)]
package_root: Option<String>,
#[arg(long)]
dry_run: bool,
}
#[derive(Debug, Args, Clone)]
struct ConsolePackageCreateArgs {
module_id: String,
#[arg(long)]
runtime_console_root: Option<std::path::PathBuf>,
#[arg(long)]
area: Option<String>,
#[arg(long)]
label: Option<String>,
#[arg(long)]
route: Option<String>,
#[arg(long)]
capability: Option<String>,
#[arg(long)]
icon: Option<String>,
#[arg(long)]
source: Option<String>,
#[arg(long)]
package_slug: Option<String>,
#[arg(long)]
package_scope: Option<String>,
#[arg(long)]
package_name: Option<String>,
#[arg(long)]
surface_name: Option<String>,
#[arg(long)]
dry_run: bool,
}
#[derive(Debug, Args, Clone)]
struct ConsolePackageApplyPlanArgs {
#[arg(long)]
repo_root: Option<std::path::PathBuf>,
#[arg(long)]
runtime_console_root: Option<std::path::PathBuf>,
#[arg(long)]
install_plan_file: Option<std::path::PathBuf>,
#[arg(long)]
dependency_version: Option<String>,
#[arg(long)]
dry_run: bool,
}
impl From<&RemoteModuleInstallArgs> for module::RemoteModuleInstallOptions {
fn from(args: &RemoteModuleInstallArgs) -> Self {
Self {
base_url: args.base_url.clone(),
console_plan: args.console_plan,
dry_run: args.dry_run,
env_file: args.env_file.clone(),
install_plan_file: args.install_plan_file.clone(),
module_services_file: args.module_services_file.clone(),
repo_root: args.repo_root.clone(),
run_install_commands: args.run_install_commands,
runtime_console_root: args.runtime_console_root.clone(),
source: args.source.clone(),
}
}
}
impl From<&RemoteModuleUninstallArgs> for module::RemoteModuleUninstallOptions {
fn from(args: &RemoteModuleUninstallArgs) -> Self {
Self {
dry_run: args.dry_run,
env_file: args.env_file.clone(),
install_plan_file: args.install_plan_file.clone(),
module_services_file: args.module_services_file.clone(),
repo_root: args.repo_root.clone(),
source: args.source.clone(),
}
}
}
impl From<&ModuleDoctorArgs> for module::ModuleDoctorOptions {
fn from(args: &ModuleDoctorArgs) -> Self {
Self {
env_file: args.env_file.clone(),
module_name: args.module_name.clone(),
module_services_file: args.module_services_file.clone(),
repo_root: args.repo_root.clone(),
}
}
}
impl From<&ModuleCreateArgs> for module::ModuleCreateOptions {
fn from(args: &ModuleCreateArgs) -> Self {
Self {
area: args.area.clone(),
capability: args.capability.clone(),
dry_run: args.dry_run,
icon: args.icon.clone(),
label: args.label.clone(),
module_id: args.module_id.clone(),
output_dir: args.output_dir.clone(),
package_name: args.package_name.clone(),
package_root: args.package_root.clone(),
package_scope: args.package_scope.clone(),
package_slug: args.package_slug.clone(),
remote: args.remote,
repo_root: args.repo_root.clone(),
route: args.route.clone(),
runtime_console_root: args.runtime_console_root.clone(),
source: args.source.clone(),
surface_name: args.surface_name.clone(),
with_console: args.with_console,
}
}
}
impl From<&ConsolePackageCreateArgs> for module::ConsolePackageCreateOptions {
fn from(args: &ConsolePackageCreateArgs) -> Self {
Self {
area: args.area.clone(),
capability: args.capability.clone(),
dry_run: args.dry_run,
icon: args.icon.clone(),
label: args.label.clone(),
module_id: args.module_id.clone(),
package_name: args.package_name.clone(),
package_scope: args.package_scope.clone(),
package_slug: args.package_slug.clone(),
route: args.route.clone(),
runtime_console_root: args.runtime_console_root.clone(),
source: args.source.clone(),
surface_name: args.surface_name.clone(),
}
}
}
impl From<&ModuleCatalogAddArgs> for module::ModuleCatalogAddOptions {
fn from(args: &ModuleCatalogAddArgs) -> Self {
Self {
base_url: args.base_url.clone(),
catalog_file: args.catalog_file.clone(),
dry_run: args.dry_run,
repo_root: args.repo_root.clone(),
summary: args.summary.clone(),
}
}
}
impl From<&ConsolePackageApplyPlanArgs> for module::ConsolePackageApplyPlanOptions {
fn from(args: &ConsolePackageApplyPlanArgs) -> Self {
Self {
dependency_version: args.dependency_version.clone(),
dry_run: args.dry_run,
install_plan_file: args.install_plan_file.clone(),
log_next_steps: true,
repo_root: args.repo_root.clone(),
runtime_console_root: args.runtime_console_root.clone(),
}
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Command::Host { command } => match command {
HostCommand::Init { dir, name, force } => host::init(&dir, name.as_deref(), force)?,
HostCommand::UpdateConsole { repo_root } => {
host::update_console(repo_root.as_deref())?;
}
},
Command::Module { command } => match command {
ModuleCommand::Create(args) => {
module::create_module((&args).into()).await?;
}
ModuleCommand::Install(args) => {
module::install_module(&args.manifest_reference, (&args).into()).await?;
}
ModuleCommand::Add(args) => {
module::install_module(&args.manifest_reference, (&args).into()).await?;
}
ModuleCommand::Uninstall(args) => {
module::uninstall_module(&args.module_name, (&args).into()).await?;
}
ModuleCommand::Doctor(args) => {
module::doctor_module((&args).into()).await?;
}
ModuleCommand::Catalog { command } => match command {
ModuleCatalogCommand::Add(args) => {
module::add_module_catalog_entry(&args.manifest_reference, (&args).into())
.await?;
}
},
ModuleCommand::Marketplace { command } => match command {
ModuleMarketplaceCommand::Install(args) => {
module::install_module(&args.manifest_reference, (&args).into()).await?;
}
},
},
Command::ConsolePackage { command } => match command {
ConsolePackageCommand::Create(args) => {
module::create_console_package((&args).into()).await?;
}
ConsolePackageCommand::ApplyPlan(args) => {
module::apply_console_package_install_plan((&args).into()).await?;
}
},
}
Ok(())
}