-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcli.rs
More file actions
168 lines (142 loc) · 6.32 KB
/
Copy pathcli.rs
File metadata and controls
168 lines (142 loc) · 6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! Top-level clap derive entry point.
//!
//! This file is the single source of truth for the CLI shape. Subcommand
//! bodies live under `commands::*` and dispatch happens via [`Cli::run`].
use std::io::Write;
use clap::{ArgAction, CommandFactory, Parser, Subcommand};
use clap_complete::Shell;
use crate::commands;
use crate::context::{Ctx, GlobalArgs};
use crate::errors::CliError;
use crate::output::Format;
/// qn — command-line interface for the Quicknode API.
#[derive(Debug, Parser)]
#[command(
name = "qn",
version,
about = "Command-line interface for the Quicknode API.",
long_about = "qn lets you manage Quicknode endpoints, streams, webhooks, and the KV store from the terminal.\n\n\
Use `qn <noun> --help` (e.g. `qn endpoint --help`) for command details.\n\n\
Authentication is resolved in this order: --api-key flag, QN_CLI__API_KEY env var,\n\
~/.config/qn/config.toml. Run `qn auth login` to save a key the first time.",
propagate_version = true,
disable_help_subcommand = true
)]
pub struct Cli {
/// API key. Overrides QN_CLI__API_KEY and the config file.
#[arg(long, global = true, env = "QN_CLI__API_KEY", hide_env_values = true)]
pub api_key: Option<String>,
/// Output format. `table` is the default human view; the others are
/// pipeline-friendly serialized forms. If unset, falls back to the
/// `[output] format = "…"` value in ~/.config/qn/config.toml, then `table`.
#[arg(short = 'o', long = "format", global = true, value_enum)]
pub format: Option<Format>,
/// Disable ANSI colors. Also honored: NO_COLOR env var, TERM=dumb, non-TTY stdout.
#[arg(long, global = true)]
pub no_color: bool,
/// Suppress non-essential output (state-change confirmations on stderr).
#[arg(short, long, global = true)]
pub quiet: bool,
/// Show additional columns in list-style tables (e.g. URLs in `endpoint list`).
/// Mirrors `kubectl get -o wide`. Only affects `table` and `md` formats —
/// `json`/`yaml`/`toon` always include everything.
#[arg(short = 'w', long = "wide", global = true)]
pub wide: bool,
/// Verbose output: include error bodies and other details.
#[arg(short, long, global = true)]
pub verbose: bool,
/// Never prompt interactively; fail with a clear message if input is needed.
#[arg(long, global = true)]
pub no_input: bool,
/// Skip confirmation prompts. Pass twice for destructive bulk operations like `stream delete-all`.
#[arg(short = 'y', long = "yes", global = true, action = ArgAction::Count)]
pub yes: u8,
/// Override the Quicknode API base URL (used for testing or on-prem mirrors).
/// All four sub-clients (admin/streams/webhooks/kv) hang off this host.
#[arg(long, global = true, hide = true)]
pub base_url: Option<String>,
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Subcommand)]
pub enum Command {
/// Manage CLI authentication (API key).
Auth(commands::auth::Args),
/// Manage RPC endpoints on your account.
#[command(visible_alias = "endpoints")]
Endpoint(commands::endpoint::Args),
/// Manage teams.
#[command(visible_alias = "teams")]
Team(commands::team::Args),
/// View account usage.
Usage(commands::usage::Args),
/// View account or endpoint metrics.
Metrics(commands::metrics::Args),
/// List supported blockchains.
#[command(visible_alias = "chains")]
Chain(commands::chain::Args),
/// View invoices and payments.
Billing(commands::billing::Args),
/// Manage blockchain data streams.
#[command(visible_alias = "streams")]
Stream(commands::stream::Args),
/// Manage filter-template webhooks.
#[command(visible_alias = "webhooks")]
Webhook(commands::webhook::Args),
/// Manage the Quicknode KV store (sets and lists).
Kv(commands::kv::Args),
/// Generate shell completions.
Completions {
/// Shell to generate completions for.
#[arg(value_enum)]
shell: Shell,
},
}
impl Cli {
/// Build a [`GlobalArgs`] suitable for [`Ctx::from_global`].
pub fn global_args(&self) -> GlobalArgs {
GlobalArgs {
api_key: self.api_key.clone(),
format: self.format,
wide: self.wide,
// format resolved-from-config in Ctx::from_global; auth.rs falls
// back to Table directly if it stays None there.
no_color: self.no_color,
quiet: self.quiet,
verbose: self.verbose,
no_input: self.no_input,
yes_count: self.yes,
base_url: self.base_url.clone(),
}
}
/// Dispatch the parsed command.
///
/// Some commands (auth, completions) are handled without constructing the
/// SDK — they have nothing to talk to and shouldn't trigger an API-key
/// prompt.
pub async fn run(self) -> Result<(), CliError> {
let global = self.global_args();
match self.command {
Command::Completions { shell } => {
let mut cmd = <Self as CommandFactory>::command();
let bin_name = cmd.get_name().to_string();
let mut out = std::io::stdout().lock();
clap_complete::generate(shell, &mut cmd, bin_name, &mut out);
out.flush()?;
Ok(())
}
Command::Auth(args) => commands::auth::run(args, global).await,
Command::Endpoint(args) => {
commands::endpoint::run(args, Ctx::from_global(global)?).await
}
Command::Team(args) => commands::team::run(args, Ctx::from_global(global)?).await,
Command::Usage(args) => commands::usage::run(args, Ctx::from_global(global)?).await,
Command::Metrics(args) => commands::metrics::run(args, Ctx::from_global(global)?).await,
Command::Chain(args) => commands::chain::run(args, Ctx::from_global(global)?).await,
Command::Billing(args) => commands::billing::run(args, Ctx::from_global(global)?).await,
Command::Stream(args) => commands::stream::run(args, Ctx::from_global(global)?).await,
Command::Webhook(args) => commands::webhook::run(args, Ctx::from_global(global)?).await,
Command::Kv(args) => commands::kv::run(args, Ctx::from_global(global)?).await,
}
}
}