use anyhow::Result;
use clap::Subcommand;
mod add;
mod dev;
mod generate;
mod new;
mod validate;
#[derive(Subcommand)]
pub enum ServiceCommands {
New {
#[arg(value_name = "SERVICE_NAME")]
name: String,
#[arg(long, default_value = "true")]
http: bool,
#[arg(long)]
grpc: bool,
#[arg(long)]
full: bool,
#[arg(long, value_name = "TYPE")]
database: Option<String>,
#[arg(long, value_name = "TYPE")]
cache: Option<String>,
#[arg(long, value_name = "TYPE")]
events: Option<String>,
#[arg(long, value_name = "TYPE")]
auth: Option<String>,
#[arg(long)]
observability: bool,
#[arg(long)]
resilience: bool,
#[arg(long, name = "rate-limit")]
rate_limit: bool,
#[arg(long)]
openapi: bool,
#[arg(long, value_name = "NAME")]
template: Option<String>,
#[arg(long, value_name = "DIR")]
path: Option<String>,
#[arg(long, name = "no-git")]
no_git: bool,
#[arg(short, long)]
interactive: bool,
#[arg(short, long)]
yes: bool,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
#[command(subcommand)]
Add(AddCommands),
#[command(subcommand)]
Generate(GenerateCommands),
Validate {
#[arg(value_name = "PATH", default_value = ".")]
path: String,
#[arg(long, value_name = "TYPE")]
check: Option<String>,
#[arg(long)]
all: bool,
#[arg(long)]
deployment: bool,
#[arg(long)]
security: bool,
#[arg(long, value_name = "FORMAT", default_value = "text")]
format: String,
#[arg(short, long)]
verbose: bool,
#[arg(short, long)]
quiet: bool,
#[arg(long)]
ci: bool,
#[arg(long, value_name = "SCORE", default_value = "8.0")]
min_score: f32,
#[arg(long)]
strict: bool,
#[arg(long)]
fix: bool,
#[arg(long, value_name = "FILE")]
report: Option<String>,
},
#[command(subcommand)]
Dev(DevCommands),
}
#[derive(Subcommand)]
pub enum AddCommands {
#[command(disable_version_flag = true)]
Endpoint {
#[arg(value_name = "METHOD")]
method: String,
#[arg(value_name = "PATH")]
path: String,
#[arg(long, value_name = "VERSION", default_value = "v1")]
version: String,
#[arg(long, value_name = "NAME")]
handler: Option<String>,
#[arg(long, value_name = "TYPE")]
auth: Option<String>,
#[arg(long, value_name = "LIMIT")]
rate_limit: Option<u32>,
#[arg(long, value_name = "NAME")]
model: Option<String>,
#[arg(long)]
validate: bool,
#[arg(long, value_name = "TYPE", default_value = "json")]
response: String,
#[arg(long)]
cache: bool,
#[arg(long, value_name = "NAME")]
event: Option<String>,
#[arg(long)]
openapi: bool,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
Grpc {
#[arg(value_name = "SERVICE_NAME")]
service_name: String,
#[arg(long, value_name = "NAME")]
package: Option<String>,
#[arg(long, value_name = "NAME")]
method: Option<String>,
#[arg(long, value_name = "TYPE")]
request: Option<String>,
#[arg(long, value_name = "TYPE")]
response: Option<String>,
#[arg(long, default_value = "true")]
health: bool,
#[arg(long, default_value = "true")]
reflection: bool,
#[arg(long)]
streaming: bool,
#[arg(long)]
handler: bool,
#[arg(long)]
client: bool,
#[arg(long, value_name = "TYPE")]
interceptor: Option<String>,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
Worker {
#[arg(value_name = "NAME")]
name: String,
#[arg(long, value_name = "SOURCE")]
source: String,
#[arg(long, value_name = "NAME")]
stream: String,
#[arg(long, value_name = "PATTERN")]
subject: Option<String>,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
Middleware {
#[arg(value_name = "TYPE")]
middleware_type: String,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
#[command(disable_version_flag = true)]
Version {
#[arg(value_name = "VERSION")]
version: String,
#[arg(long, value_name = "FROM")]
from: Option<String>,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
}
#[derive(Subcommand)]
pub enum GenerateCommands {
Deployment {
#[arg(long, value_name = "TYPE")]
platform: Option<String>,
#[arg(long)]
all: bool,
#[arg(long, value_name = "N", default_value = "3")]
replicas: u32,
#[arg(long)]
hpa: bool,
#[arg(long, value_name = "SIZE", default_value = "512Mi")]
memory: String,
#[arg(long, value_name = "MILLICORES", default_value = "500m")]
cpu: String,
#[arg(long, value_name = "NAME")]
namespace: Option<String>,
#[arg(long)]
monitoring: bool,
#[arg(long)]
alerts: bool,
#[arg(long)]
ingress: bool,
#[arg(long)]
tls: bool,
#[arg(long, value_name = "STAGE")]
env: Option<String>,
#[arg(long, value_name = "URL")]
registry: Option<String>,
#[arg(long, value_name = "TAG", default_value = "latest")]
image_tag: String,
#[arg(long, name = "dry-run")]
dry_run: bool,
#[arg(long, value_name = "DIR", default_value = "./deployment")]
output: String,
},
Config {
#[arg(long, value_name = "PATH")]
output: Option<String>,
#[arg(long)]
examples: bool,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
Proto {
#[arg(value_name = "SERVICE")]
service: String,
#[arg(long, value_name = "PATH")]
output: Option<String>,
#[arg(long, name = "dry-run")]
dry_run: bool,
},
}
#[derive(Subcommand)]
pub enum DevCommands {
Run {
#[arg(long)]
watch: bool,
#[arg(long, value_name = "PORT")]
port: Option<u16>,
},
Health {
#[arg(long)]
verbose: bool,
#[arg(long, value_name = "URL", default_value = "http://localhost:8080")]
url: String,
},
Logs {
#[arg(short, long)]
follow: bool,
#[arg(long, value_name = "LEVEL")]
level: Option<String>,
#[arg(long, value_name = "PATTERN")]
filter: Option<String>,
},
}
pub async fn execute(command: ServiceCommands) -> Result<()> {
match command {
ServiceCommands::New {
name,
http,
grpc,
full,
database,
cache,
events,
auth,
observability,
resilience,
rate_limit,
openapi,
template,
path,
no_git,
interactive,
yes,
dry_run,
} => {
new::execute(
name,
http,
grpc,
full,
database,
cache,
events,
auth,
observability,
resilience,
rate_limit,
openapi,
template,
path,
no_git,
interactive,
yes,
dry_run,
)
.await
}
ServiceCommands::Add(add_command) => match add_command {
AddCommands::Endpoint {
method,
path,
version,
handler,
auth,
rate_limit,
model,
validate,
response,
cache,
event,
openapi,
dry_run,
} => {
add::endpoint::execute(
method, path, version, handler, auth, rate_limit, model, validate, response,
cache, event, openapi, dry_run,
)
.await
}
AddCommands::Grpc {
service_name,
package,
method,
request,
response,
health,
reflection,
streaming,
handler,
client,
interceptor,
dry_run,
} => {
add::grpc::execute(
service_name,
package,
method,
request,
response,
health,
reflection,
streaming,
handler,
client,
interceptor,
dry_run,
)
.await
}
AddCommands::Worker {
name,
source,
stream,
subject,
dry_run,
} => add::worker::execute(name, source, stream, subject, dry_run).await,
AddCommands::Middleware {
middleware_type,
dry_run,
} => add::middleware::execute(middleware_type, dry_run).await,
AddCommands::Version {
version,
from,
dry_run,
} => add::version::execute(version, from, dry_run).await,
},
ServiceCommands::Generate(gen_command) => match gen_command {
GenerateCommands::Deployment {
platform,
all,
replicas,
hpa,
memory,
cpu,
namespace,
monitoring,
alerts,
ingress,
tls,
env,
registry,
image_tag,
dry_run,
output,
} => {
generate::deployment::execute(
platform, all, replicas, hpa, memory, cpu, namespace, monitoring, alerts,
ingress, tls, env, registry, image_tag, dry_run, output,
)
.await
}
GenerateCommands::Config {
output,
examples,
dry_run,
} => generate::config::execute(output, examples, dry_run).await,
GenerateCommands::Proto {
service,
output,
dry_run,
} => generate::proto::execute(service, output, dry_run).await,
},
ServiceCommands::Validate {
path,
check,
all,
deployment,
security,
format,
verbose,
quiet,
ci,
min_score,
strict,
fix,
report,
} => {
validate::execute(
path, check, all, deployment, security, format, verbose, quiet, ci, min_score,
strict, fix, report,
)
.await
}
ServiceCommands::Dev(dev_command) => match dev_command {
DevCommands::Run { watch, port } => dev::run::execute(watch, port).await,
DevCommands::Health { verbose, url } => dev::health::execute(verbose, url).await,
DevCommands::Logs {
follow,
level,
filter,
} => dev::logs::execute(follow, level, filter).await,
},
}
}