use clap::{Parser, Subcommand};
use tracing::error;
use crate::{
error::CapturedError,
experimental::{query::command::QueryCommand, tasks::TaskCommand},
invocation_context::{context, init_context},
proguard::ProguardSubcommand,
sourcemaps::{hermes::HermesSubcommand, plain::SourcemapCommand},
};
#[derive(Parser)]
#[command(version, about, long_about = None)]
pub struct Cli {
#[arg(long)]
host: Option<String>,
#[arg(long, default_value = "false")]
no_fail: bool,
#[arg(long, default_value = "false")]
skip_ssl_verification: bool,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
Login,
Exp {
#[command(subcommand)]
cmd: ExpCommand,
},
#[command(about = "Upload a directory of bundled chunks to PostHog")]
Sourcemap {
#[command(subcommand)]
cmd: SourcemapCommand,
},
}
#[derive(Subcommand)]
pub enum ExpCommand {
Task {
#[command(subcommand)]
cmd: TaskCommand,
#[arg(long, default_value = "false")]
skip_ssl_verification: bool,
},
Query {
#[command(subcommand)]
cmd: QueryCommand,
},
#[command(about = "Upload hermes sourcemaps to PostHog")]
Hermes {
#[command(subcommand)]
cmd: HermesSubcommand,
},
#[command(about = "Upload proguard mapping files to PostHog")]
Proguard {
#[command(subcommand)]
cmd: ProguardSubcommand,
},
Schema {
#[command(subcommand)]
cmd: SchemaCommand,
},
}
#[derive(Subcommand)]
pub enum SchemaCommand {
Pull {
#[arg(short, long)]
output: Option<String>,
},
Status,
}
impl Cli {
pub fn run() -> Result<(), CapturedError> {
let command = Cli::parse();
let no_fail = command.no_fail;
match command.run_impl() {
Ok(_) => Ok(()),
Err(e) => {
let msg = match &e.exception_id {
Some(id) => format!("Oops! {} (ID: {})", e.inner, id),
None => format!("Oops! {:?}", e.inner),
};
error!(msg);
if no_fail {
Ok(())
} else {
Err(e)
}
}
}
}
fn run_impl(self) -> Result<(), CapturedError> {
if !matches!(self.command, Commands::Login) {
init_context(self.host.clone(), self.skip_ssl_verification)?;
}
match self.command {
Commands::Login => {
crate::login::login(self.host)?;
}
Commands::Sourcemap { cmd } => match cmd {
SourcemapCommand::Inject(input_args) => {
crate::sourcemaps::plain::inject::inject(&input_args)?;
}
SourcemapCommand::Upload(upload_args) => {
crate::sourcemaps::plain::upload::upload(&upload_args)?;
}
SourcemapCommand::Process(args) => {
let (inject, upload) = args.into();
crate::sourcemaps::plain::inject::inject(&inject)?;
crate::sourcemaps::plain::upload::upload(&upload)?;
}
},
Commands::Exp { cmd } => match cmd {
ExpCommand::Task {
cmd,
skip_ssl_verification: _,
} => {
cmd.run()?;
}
ExpCommand::Query { cmd } => {
crate::experimental::query::command::query_command(&cmd)?
}
ExpCommand::Hermes { cmd } => match cmd {
HermesSubcommand::Inject(args) => {
crate::sourcemaps::hermes::inject::inject(&args)?;
}
HermesSubcommand::Upload(args) => {
crate::sourcemaps::hermes::upload::upload(&args)?;
}
HermesSubcommand::Clone(args) => {
crate::sourcemaps::hermes::clone::clone(&args)?;
}
},
ExpCommand::Proguard { cmd } => match cmd {
ProguardSubcommand::Upload(args) => {
crate::proguard::upload::upload(&args)?;
}
},
ExpCommand::Schema { cmd } => match cmd {
SchemaCommand::Pull { output } => {
crate::experimental::schema::pull(self.host, output)?;
}
SchemaCommand::Status => {
crate::experimental::schema::status()?;
}
},
},
}
context().finish();
Ok(())
}
}