holochain_cli/lib.rs
1#![warn(missing_docs)]
2
3//! A library and CLI to help create, run, and interact with Holochain conductor setups.
4//! **Warning this is still WIP and subject to change**
5//! There's probably a few bugs. If you find one please open an [issue](https://github.com/holochain/holochain/issues)
6//! or make a PR.
7//!
8//! ## CLI
9//!
10//! The `hc` CLI makes it easy to create, modify, and run hApps that
11//! you are working on or someone has sent you.
12//! It has been designed to use sensible defaults but still give you
13//! the configurability when that's required.
14//!
15//! Setups are stored in tmp directories by default and the paths are
16//! persisted in a `.hc` file which is created wherever you are using
17//! the CLI.
18
19// Useful to have this public when using this as a library.
20use clap::{crate_version, Parser, Subcommand};
21pub use holochain_cli_bundle as hc_bundle;
22use holochain_cli_sandbox as hc_sandbox;
23use lazy_static::lazy_static;
24use std::process::Command;
25
26mod external_subcommands;
27
28// TODO: change this so it inherits clap's formatting.
29// Clap 3 and 4 format helptext using colours and bold/underline respectively.
30// https://github.com/clap-rs/clap/pull/4765 introduces the ability to style your own help text
31// using a library like `color_print`.
32// https://github.com/clap-rs/clap/issues/4786 requests that the styler's built-in helper methods
33// be exposed to consumers, thereby allowing us to durably make our styling consistent
34// with whatever clap's happens to be at the moment.
35// I'd prefer the latter approach, if it lands.
36lazy_static! {
37 static ref HELP: &'static str = {
38 let extensions = external_subcommands::list_external_subcommands()
39 .into_iter()
40 .map(|s| format!(" {s}\t Run \"hc {s} help\" to see its help"))
41 .collect::<Vec<String>>()
42 .join("\n");
43
44 let extensions_str = match extensions.len() {
45 0 => String::from(""),
46 _ => format!(
47 r#"
48Extensions:
49{extensions}"#
50 ),
51 };
52
53 let s = format!(
54 r#"Holochain CLI
55
56Work with DNA, hApp and web-hApp bundle files, set up sandbox environments for testing and development purposes, make direct admin calls to running conductors, and more.
57{extensions_str}"#
58 );
59 Box::leak(s.into_boxed_str())
60 };
61}
62
63fn builtin_commands() -> Vec<String> {
64 ["hc-web-app", "hc-dna", "hc-app", "hc-sandbox"]
65 .iter()
66 .map(|s| s.to_string())
67 .collect()
68}
69
70/// The main entry-point for the command.
71#[allow(clippy::large_enum_variant)]
72#[derive(Debug, Parser)]
73#[command(about = *HELP, infer_subcommands = true, allow_external_subcommands = true, version = crate_version!())]
74pub struct Cli {
75 /// The `hc` subcommand to run.
76 #[command(subcommand)]
77 pub subcommand: CliSubcommand,
78}
79
80/// Describes all the possible CLI arguments for `hc`, including external subcommands like `hc-scaffold`.
81#[derive(Debug, Subcommand)]
82#[allow(clippy::large_enum_variant)]
83pub enum CliSubcommand {
84 /// Work with DNA bundles.
85 Dna(hc_bundle::HcDnaBundle),
86 /// Work with hApp bundles.
87 App(hc_bundle::HcAppBundle),
88 /// Work with web-hApp bundles.
89 WebApp(hc_bundle::HcWebAppBundle),
90 /// Work with sandboxed environments for testing and development.
91 Sandbox(hc_sandbox::HcSandbox),
92 /// Allow redirect of external subcommands (like `hc-scaffold` and `hc-launch`).
93 #[command(external_subcommand)]
94 External(Vec<String>),
95}
96
97impl CliSubcommand {
98 /// Run this command.
99 pub async fn run(self) -> anyhow::Result<()> {
100 match self {
101 CliSubcommand::App(cmd) => cmd.run().await?,
102 CliSubcommand::Dna(cmd) => cmd.run().await?,
103 CliSubcommand::WebApp(cmd) => cmd.run().await?,
104 CliSubcommand::Sandbox(cmd) => cmd.run().await?,
105 CliSubcommand::External(args) => {
106 let command_suffix = args.first().expect("Missing subcommand name");
107 Command::new(format!("hc-{command_suffix}"))
108 .args(&args[1..])
109 .status()
110 .expect("Failed to run external subcommand");
111 }
112 }
113 Ok(())
114 }
115}