use clap::{Parser, Subcommand};
use std::path::PathBuf;
#[derive(Parser)]
#[command(name = "graphql-codegen-rust")]
#[command(version = env!("CARGO_PKG_VERSION"))]
#[command(about = "Generate Rust ORM code from GraphQL schemas")]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
#[arg(short, long, action = clap::ArgAction::Count)]
pub verbose: u8,
}
#[derive(Subcommand)]
pub enum Commands {
Init {
#[arg(short, long)]
url: String,
#[arg(short, long, value_enum, default_value = "diesel")]
orm: OrmType,
#[arg(short, long, value_enum, default_value = "sqlite")]
db: DatabaseType,
#[arg(long, default_value = "./generated")]
output: PathBuf,
#[arg(short = 'H', long, value_parser = parse_header)]
headers: Vec<(String, String)>,
},
Generate {
#[arg(short, long)]
config: Option<PathBuf>,
#[arg(short, long)]
output: Option<PathBuf>,
},
}
#[derive(
Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, clap::ValueEnum, Default,
)]
pub enum OrmType {
#[default]
Diesel,
SeaOrm,
}
#[derive(
Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, clap::ValueEnum, Default,
)]
pub enum DatabaseType {
#[default]
Sqlite,
Postgres,
Mysql,
}
pub fn parse_header(s: &str) -> Result<(String, String), String> {
let parts: Vec<&str> = s.splitn(2, ':').collect();
if parts.len() != 2 {
return Err(format!(
"Invalid header format '{}'. Headers must be in 'key:value' format.\nExample: --header 'Authorization:Bearer token123'",
s
));
}
let key = parts[0].trim();
let value = parts[1].trim();
if key.is_empty() {
return Err("Header key cannot be empty. Format: 'key:value'".to_string());
}
if value.is_empty() {
return Err("Header value cannot be empty. Format: 'key:value'".to_string());
}
Ok((key.to_string(), value.to_string()))
}