Skip to main content

influxdb3_plugin_cli/
config.rs

1//! Top-level embeddable CLI config.
2
3use clap::Parser;
4
5/// `<version>, revision <sha>` fragment fed to clap's `version` attribute.
6///
7/// `build.rs` writes the SHA value (a 40-char lowercase hex string, or
8/// the literal `unknown`) to `$OUT_DIR/version_fragment.rs`; we splice
9/// it onto `CARGO_PKG_VERSION` with the `, revision ` separator. clap
10/// prepends the binary `name` when rendering `--version`, producing:
11///
12/// ```text
13/// influxdb3-plugin <version>, revision <sha>
14/// ```
15const VERSION_STRING: &str = concat!(
16    env!("CARGO_PKG_VERSION"),
17    ", revision ",
18    include!(concat!(env!("OUT_DIR"), "/version_fragment.rs")),
19);
20
21/// Top-level embeddable CLI config for the `influxdb3-plugin` binary.
22///
23/// Parsed from argv via clap and dispatched through [`PluginConfig::run`].
24/// An embedding host can mount this as a variant of its own top-level
25/// command enum and invoke `run()` from its existing tokio runtime.
26#[derive(Debug, Parser)]
27#[command(
28    name = "influxdb3-plugin",
29    version = VERSION_STRING,
30    about = "Author-side tooling for InfluxDB 3 plugins.",
31    long_about = None,
32)]
33pub struct PluginConfig {
34    #[command(subcommand)]
35    command: Command,
36}
37
38#[derive(Debug, clap::Subcommand)]
39enum Command {
40    /// Scaffold a new plugin or index from a built-in template.
41    #[command(subcommand)]
42    New(crate::commands::new::NewCommand),
43    /// Search plugins in a local registry index.
44    Search(crate::commands::index::SearchArgs),
45    /// Inspect one plugin in a local registry index.
46    Info(crate::commands::index::InfoArgs),
47    /// Validate a plugin directory.
48    Validate(crate::commands::validate::Args),
49    /// Validate, archive, hash, and emit a derived index entry.
50    Package(crate::commands::package::Args),
51    /// Toggle the `yanked` flag on an existing index entry.
52    Yank(crate::commands::yank::Args),
53}
54
55impl PluginConfig {
56    /// Runs the parsed subcommand.
57    ///
58    /// `async` even though the current implementation is internally sync, so
59    /// an embedding host can `.await` this without a runtime switch. Errors
60    /// are returned via `Result`; this surface must not call
61    /// `std::process::exit`.
62    ///
63    /// # Examples
64    ///
65    /// Standalone binary entry — `main.rs` does the equivalent of:
66    ///
67    /// ```rust,no_run
68    /// # async fn _doc() -> anyhow::Result<()> {
69    /// use clap::Parser;
70    /// use influxdb3_plugin_cli::PluginConfig;
71    ///
72    /// let config = PluginConfig::parse();
73    /// config.run().await?;
74    /// # Ok(())
75    /// # }
76    /// ```
77    ///
78    /// Embedding host — invoke from the host's existing tokio runtime; no
79    /// nested runtime is needed:
80    ///
81    /// ```rust,no_run
82    /// # fn _doc(host_argv: Vec<String>) -> anyhow::Result<()> {
83    /// use clap::Parser;
84    /// use influxdb3_plugin_cli::PluginConfig;
85    ///
86    /// let config = PluginConfig::try_parse_from(host_argv)?;
87    /// let runtime = tokio::runtime::Builder::new_current_thread()
88    ///     .enable_all()
89    ///     .build()?;
90    /// runtime.block_on(config.run())?;
91    /// # Ok(())
92    /// # }
93    /// ```
94    pub async fn run(self) -> anyhow::Result<()> {
95        match self.command {
96            Command::New(sub) => sub.run(),
97            Command::Search(args) => args.run(),
98            Command::Info(args) => args.run(),
99            Command::Validate(args) => args.run(),
100            Command::Package(args) => args.run(),
101            Command::Yank(args) => args.run(),
102        }
103    }
104}