polkadot_omni_node_lib/extra_subcommand.rs
1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: Apache-2.0
4
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17//! Optional / additional CLI options for binaries built with
18//! `polkadot‑omni‑node‑lib`.
19/// * Binaries that need extra utilities (e.g. `export-chain-spec`) should pass
20/// [`DefaultExtraSubcommands`] to `run_with_custom_cli`, which injects that one command.
21/// * Binaries that should stay minimal pass [`NoExtraSubcommand`], which requests no extras at
22/// all.
23use clap::Subcommand;
24use sc_cli::{ExportChainSpecCmd, Result};
25
26use crate::RunConfig;
27
28/// A trait for injecting and handling additional CLI subcommands in a composable way.
29///
30/// This trait allows downstream crates using `polkadot-omni-node-lib` to plug in their own custom
31/// subcommands without having to modify the main CLI definition. This is especially useful for
32/// parachain node binaries that want to define optional utilities.
33///
34/// ## Implementing a Custom Extra Command
35///
36/// To create your own subcommand:
37///
38/// 1. Define the subcommand using [`clap::Subcommand`].
39/// 2. Implement this trait for it.
40/// 3. Use it when running the node via `run_with_custom_cli::<CliConfig,
41/// YourExtraCommand>(run_config)`
42///
43/// ### Minimal Example:
44///
45///
46/// use clap::Parser;
47/// use polkadot_omni_node_lib::{ExtraSubcommand, RunConfig};
48///
49/// #[derive(Debug, Clone, Subcommand)]
50/// pub enum ExtraCmd {
51/// NewCmd,
52/// }
53///
54/// impl ExtraSubcommand for ExtraCmd {
55///
56/// fn handle(_cmd: ExtraCmd, _config: &RunConfig) -> sc_cli::Result<()> {
57/// println!("Hello from Extra!");
58/// Ok(())
59/// }
60/// }
61///
62///
63/// To use this in a binary:
64///
65///
66/// let config = RunConfig::new(...);
67/// run_with_custom_cli::<CliConfig, ExtraCmd>(config)?;
68///
69///
70/// Running it:
71///
72/// ```bash
73/// $ your-binary new-cmd
74/// Hello from Extra!
75/// ```
76///
77/// ## Supporting Multiple Subcommands
78///
79/// You can compose multiple extra commands via an enum. Just derive [`clap::Subcommand`] and match
80/// over the variants in `handle`.
81///
82///
83/// #[derive(Debug, clap::Parser)]
84/// pub enum MyExtras {
85/// Foo(FooCmd),
86/// Bar(BarCmd),
87/// }
88///
89/// impl ExtraSubcommand for MyExtras {
90///
91/// fn handle(cmd: Self, config: &RunConfig) -> sc_cli::Result<()> {
92/// match cmd {
93/// MyExtras::Foo(foo) => { ... }
94/// MyExtras::Bar(bar) => { ... }
95/// }
96/// Ok(())
97/// }
98/// }
99
100/// Trait implemented by a set of optional sub‑commands**.
101pub trait ExtraSubcommand: Subcommand {
102 /// Handle the command once it's been parsed.
103 fn handle(self, cfg: &RunConfig) -> Result<()>;
104}
105
106/// Built-in extra subcommands provided by `polkadot-omni-node-lib`.
107///
108/// Currently, it includes:
109/// - `export-chain-spec`
110///
111/// You can use this by passing [`DefaultExtraSubcommands`] to `run_with_custom_cli`
112/// or by just calling `run` as this is the default.
113///
114/// This enables default support for utilities like:
115/// ```bash
116/// $ your-binary export-chain-spec --chain westmint
117/// ```
118#[derive(Debug, Subcommand)]
119pub enum DefaultExtraSubcommands {
120 /// Export the chain spec to JSON.
121 ExportChainSpec(ExportChainSpecCmd),
122}
123
124impl ExtraSubcommand for DefaultExtraSubcommands {
125 fn handle(self, cfg: &RunConfig) -> Result<()> {
126 match self {
127 DefaultExtraSubcommands::ExportChainSpec(cmd) => {
128 let spec = cfg.chain_spec_loader.load_spec(&cmd.chain)?;
129 cmd.run(spec)?;
130 },
131 }
132 Ok(())
133 }
134}
135
136/// No-op subcommand handler. Use this when a binary does not expose any extra subcommands.
137///
138/// You can use this by passing [`NoExtraSubcommand`] to `run_with_custom_cli`.
139#[derive(Debug, Subcommand)]
140pub enum NoExtraSubcommand {}
141
142impl ExtraSubcommand for NoExtraSubcommand {
143 fn handle(self, _cfg: &RunConfig) -> Result<()> {
144 Ok(())
145 }
146}