feat: add crunch init command

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-09-25 21:03:58 +02:00
parent afc69342b1
commit 5561329510
Signed by: kjuulh
GPG Key ID: 9AA7BC13CE474394
4 changed files with 169 additions and 0 deletions

92
Cargo.lock generated
View File

@ -474,6 +474,31 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crossterm"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
dependencies = [
"bitflags 1.3.2",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "crunch"
version = "0.1.0"
@ -502,6 +527,8 @@ dependencies = [
"clap",
"crunch-codegen",
"crunch-file",
"inquire",
"regex",
"thiserror",
"tokio",
"tracing",
@ -654,6 +681,12 @@ dependencies = [
"generic-array",
]
[[package]]
name = "dyn-clone"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd"
[[package]]
name = "ed25519"
version = "1.5.3"
@ -956,6 +989,22 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inquire"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c33e7c1ddeb15c9abcbfef6029d8e29f69b52b6d6c891031b88ed91b5065803b"
dependencies = [
"bitflags 1.3.2",
"crossterm",
"dyn-clone",
"lazy_static",
"newline-converter",
"thiserror",
"unicode-segmentation",
"unicode-width",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -1080,6 +1129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys",
]
@ -1126,6 +1176,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "newline-converter"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f71d09d5c87634207f894c6b31b6a2b2c64ea3bdcf71bd5599fdbbe1600c00f"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "nkeys"
version = "0.2.0"
@ -1736,6 +1795,27 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
@ -2096,6 +2176,18 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "untrusted"
version = "0.7.1"

View File

@ -32,5 +32,6 @@ tempfile = {version = "3.8.0"}
genco = {version = "0.17.5"}
walkdir = {version = "2.4.0"}
regex = {version = "1.9.5"}
inquire = {version = "0.6.2"}
pretty_assertions = "1.4.0"

View File

@ -5,6 +5,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "crunch"
path = "src/main.rs"
[dependencies]
crunch-file.workspace = true
crunch-codegen.workspace = true
@ -16,3 +20,5 @@ thiserror.workspace = true
async-trait.workspace = true
tracing-subscriber.workspace = true
clap.workspace = true
inquire.workspace = true
regex.workspace = true

View File

@ -4,7 +4,10 @@ use std::path::PathBuf;
use anyhow::anyhow;
use clap::{Args, Parser, Subcommand};
use inquire::validator::Validation;
use logging::LogArg;
use regex::Regex;
use tokio::io::AsyncWriteExt;
#[derive(Parser, Clone)]
#[command(author, version, about, long_about = None, subcommand_required = true)]
@ -19,6 +22,7 @@ struct Cli {
#[derive(Subcommand, Clone)]
enum Commands {
Generate {},
Init {},
}
#[derive(Args, Clone)]
@ -69,6 +73,72 @@ async fn main() -> anyhow::Result<()> {
}
}
}
Commands::Init {} => {
match config::get_file(&cli.global_args.crunch_file).await {
Ok(_) => anyhow::bail!("config file already exists"),
Err(_) => {}
}
let path = &cli.global_args.crunch_file;
let file_name = path
.file_name()
.ok_or(anyhow::anyhow!("not a valid file name"))?;
if file_name != ".crunch.toml" {
anyhow::bail!("--crunch-file always has to end with file: .crunch.toml");
}
if let Some(dir) = path.parent() {
if !dir.exists() {
tokio::fs::create_dir_all(dir).await?;
}
}
fn validate_text(
text: &str,
) -> Result<Validation, Box<dyn std::error::Error + Send + Sync + 'static>>
{
let regex = Regex::new("^[a-z0-9-_]+$").expect("is required to be valid regex");
if regex.is_match(text) {
Ok(Validation::Valid)
} else {
Ok(Validation::Invalid(
"a service name can only contain lowercase letter, numbers, - and _".into(),
))
}
}
let service = inquire::Text::new("service")
.with_help_message("please insert your service name")
.with_validator(validate_text)
.prompt()?;
let domain = inquire::Text::new("domain")
.with_help_message("please insert your domain")
.with_validator(validate_text)
.prompt()?;
let codegen = inquire::MultiSelect::new("codegen", vec!["rust", "go"])
.with_help_message("which types of client code should be generated for you?")
.prompt()?;
let mut crunch_file = tokio::fs::File::create(path).await?;
crunch_file
.write_all(
format!(
r#"[service]
service = "{service}"
domain = "{domain}"
codegen = [{}]
"#,
codegen
.iter()
.map(|c| format!(r#""{c}""#))
.collect::<Vec<_>>()
.join(", ")
)
.as_bytes(),
)
.await?;
println!("Success! generated file at: {}", path.display());
}
}
Ok(())