mod commands;
mod config;
mod error;
mod output;
mod spike;
mod storage;
mod tui;
use clap::{Parser, Subcommand};
use commands::deploy::DeployOptions;
use commands::export::ExportFormat;
use commands::inject::InjectOptions;
use commands::list::ListOptions;
use commands::pull::PullOptions;
use commands::push::PushOptions;
use commands::serve::ServeOptions;
#[derive(Parser)]
#[command(name = "spikes")]
#[command(about = "Feedback collection for static mockups", long_about = None)]
#[command(version)]
struct Cli {
#[command(subcommand)]
command: Option<Commands>,
#[arg(long, short, default_value = "3847", global = true)]
port: u16,
}
#[derive(Subcommand)]
enum Commands {
Init {
#[arg(long)]
json: bool,
},
List {
#[arg(long)]
json: bool,
#[arg(long)]
page: Option<String>,
#[arg(long)]
reviewer: Option<String>,
#[arg(long)]
rating: Option<String>,
},
Show {
id: String,
#[arg(long)]
json: bool,
},
Export {
#[arg(long, short, default_value = "json")]
format: String,
},
Hotspots {
#[arg(long)]
json: bool,
},
Reviewers {
#[arg(long)]
json: bool,
},
Inject {
directory: String,
#[arg(long)]
remove: bool,
#[arg(long)]
widget_url: Option<String>,
#[arg(long)]
json: bool,
},
Serve {
#[arg(long, short, default_value = "3847")]
port: u16,
#[arg(long, short, default_value = ".")]
dir: String,
#[arg(long, short)]
marked: bool,
},
Deploy {
#[command(subcommand)]
backend: DeployBackend,
},
Pull {
#[arg(long)]
endpoint: Option<String>,
#[arg(long)]
token: Option<String>,
#[arg(long)]
json: bool,
},
Push {
#[arg(long)]
endpoint: Option<String>,
#[arg(long)]
token: Option<String>,
#[arg(long)]
json: bool,
},
Sync {
#[arg(long)]
json: bool,
},
Remote {
#[command(subcommand)]
action: RemoteAction,
},
Config {
#[arg(long)]
json: bool,
},
Version,
Dashboard {
#[arg(long)]
json: bool,
},
}
#[derive(Subcommand)]
enum DeployBackend {
Cloudflare {
#[arg(long)]
dir: Option<String>,
#[arg(long)]
json: bool,
},
}
#[derive(Subcommand)]
enum RemoteAction {
Add {
endpoint: String,
#[arg(long)]
token: Option<String>,
#[arg(long)]
hosted: bool,
},
Remove,
Show {
#[arg(long)]
json: bool,
},
}
fn main() {
let cli = Cli::parse();
let result = match cli.command {
None => commands::magic::run(cli.port),
Some(Commands::Init { json }) => commands::init::run(json),
Some(Commands::List {
json,
page,
reviewer,
rating,
}) => commands::list::run(ListOptions {
json,
page,
reviewer,
rating,
}),
Some(Commands::Show { id, json }) => commands::show::run(&id, json),
Some(Commands::Export { format }) => {
let fmt = match format.parse::<ExportFormat>() {
Ok(f) => f,
Err(e) => {
eprintln!("Error: {}", e);
std::process::exit(1);
}
};
commands::export::run(fmt)
}
Some(Commands::Hotspots { json }) => commands::hotspots::run(json),
Some(Commands::Reviewers { json }) => commands::reviewers::run(json),
Some(Commands::Inject {
directory,
remove,
widget_url,
json,
}) => commands::inject::run(InjectOptions {
directory,
remove,
widget_url,
json,
}),
Some(Commands::Serve { port, dir, marked }) => commands::serve::run(ServeOptions {
port,
directory: dir,
marked,
}),
Some(Commands::Deploy { backend }) => match backend {
DeployBackend::Cloudflare { dir, json } => {
commands::deploy::run(DeployOptions { dir, json })
}
},
Some(Commands::Pull {
endpoint,
token,
json,
}) => commands::pull::run(PullOptions {
endpoint,
token,
json,
}),
Some(Commands::Push {
endpoint,
token,
json,
}) => commands::push::run(PushOptions {
endpoint,
token,
json,
}),
Some(Commands::Sync { json }) => commands::sync::run(json),
Some(Commands::Remote { action }) => match action {
RemoteAction::Add { endpoint, token, hosted } => {
commands::remote::add(&endpoint, token, hosted)
}
RemoteAction::Remove => commands::remote::remove(),
RemoteAction::Show { json } => commands::remote::show(json),
},
Some(Commands::Config { json }) => commands::config_cmd::run(json),
Some(Commands::Version) => {
println!("spikes {}", env!("CARGO_PKG_VERSION"));
Ok(())
}
Some(Commands::Dashboard { json }) => commands::dashboard::run(json),
};
if let Err(e) = result {
eprintln!("Error: {}", e);
std::process::exit(1);
}
}