Compare commits
4
Commits
c555f6cecb
...
791e3a6c6d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
791e3a6c6d | ||
|
|
03c1c3329f | ||
|
|
bfe779cf9a | ||
|
|
6309440501 |
No files matched your search
@@ -0,0 +1 @@
|
|||||||
|
tab_spaces = 2
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(name = "onx")]
|
||||||
|
#[command(version)]
|
||||||
|
#[command(about)]
|
||||||
|
pub struct Cli {
|
||||||
|
#[arg(long)]
|
||||||
|
#[arg(short = 'k')]
|
||||||
|
#[arg(env = "ONSPRING_API_KEY")]
|
||||||
|
#[arg(help = "The API key for the Onspring instance")]
|
||||||
|
pub api_key: Option<String>,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
#[arg(short = 'u')]
|
||||||
|
#[arg(env = "ONSPRING_BASE_URL")]
|
||||||
|
#[arg(help = "The base URL for the Onspring API")]
|
||||||
|
pub base_url: Option<String>,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
#[arg(short = 'p')]
|
||||||
|
#[arg(help = "Pretty-print JSON output")]
|
||||||
|
#[arg(default_value_t = false)]
|
||||||
|
pub pretty: bool,
|
||||||
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
mod cli;
|
||||||
|
mod output;
|
||||||
|
|
||||||
|
use clap::{Parser, error::ErrorKind};
|
||||||
|
use cli::Cli;
|
||||||
|
|
||||||
|
use output::render_error;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct CliError {
|
||||||
|
pub code: i32,
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CliError {
|
||||||
|
pub fn info(message: impl Into<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
code: 0,
|
||||||
|
message: message.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn runtime(message: impl Into<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
code: 1,
|
||||||
|
message: message.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn usage(message: impl Into<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
code: 2,
|
||||||
|
message: message.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type CliResult<T> = Result<T, CliError>;
|
||||||
|
|
||||||
|
pub async fn run(_cli: Cli) -> CliResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_cli_from<I, T>(args: I) -> CliResult<Cli>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = T>,
|
||||||
|
T: Into<std::ffi::OsString> + Clone,
|
||||||
|
{
|
||||||
|
Cli::try_parse_from(args).map_err(|e| match e.kind() {
|
||||||
|
ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => CliError::info(e.to_string()),
|
||||||
|
_ => CliError::usage(e.to_string()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_cli_error(err: &CliError, pretty: bool) -> String {
|
||||||
|
render_error(err, pretty)
|
||||||
|
.unwrap_or_else(|_| "{\"error\":{\"code\":1,\"message\":\"Unexpected error.\"}}".to_string())
|
||||||
|
}
|
||||||
+22
-2
@@ -1,3 +1,23 @@
|
|||||||
fn main() {
|
use std::process;
|
||||||
println!("Hello, world!");
|
|
||||||
|
use onx::{parse_cli_from, render_cli_error, run};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let cli = match parse_cli_from(std::env::args_os()) {
|
||||||
|
Ok(cli) => cli,
|
||||||
|
Err(err) => {
|
||||||
|
if err.code == 0 {
|
||||||
|
print!("{}", err.message);
|
||||||
|
process::exit(0);
|
||||||
|
}
|
||||||
|
eprintln!("{}", render_cli_error(&err, false));
|
||||||
|
process::exit(err.code)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(err) = run(cli).await {
|
||||||
|
eprintln!("{}", render_cli_error(&err, false));
|
||||||
|
process::exit(err.code)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::{CliError, CliResult};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
struct ErrorBody<'a> {
|
||||||
|
pub code: i32,
|
||||||
|
pub message: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
struct ErrorEnvelope<'a> {
|
||||||
|
pub error: ErrorBody<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_json<T: Serialize>(value: &T, pretty: bool) -> CliResult<String> {
|
||||||
|
if pretty {
|
||||||
|
serde_json::to_string_pretty(value).map_err(|_| CliError::runtime("Failed to serialize output"))
|
||||||
|
} else {
|
||||||
|
serde_json::to_string(value).map_err(|_| CliError::runtime("Failed to serialize output"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_error(err: &CliError, pretty: bool) -> CliResult<String> {
|
||||||
|
let envelope = ErrorEnvelope {
|
||||||
|
error: ErrorBody {
|
||||||
|
code: err.code,
|
||||||
|
message: &err.message,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
render_json(&envelope, pretty)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user