#[cfg(feature = "cli")]
use clap::Parser;
use serde::Deserialize;
use std::path::PathBuf;
#[derive(Debug, Deserialize, Default, Clone)]
#[cfg_attr(feature = "cli", derive(Parser))]
#[serde(default)]
#[cfg_attr(feature = "cli", command(author, version, about, long_about = None))]
pub struct Config {
#[cfg_attr(feature = "cli", arg(short = 'i', long = "input"))]
pub input: Option<Vec<PathBuf>>,
#[cfg_attr(feature = "cli", arg(long = "include"))]
pub include: Option<Vec<PathBuf>>,
#[cfg_attr(feature = "cli", arg(short = 'o', long = "output", alias = "out"))]
pub output: Option<Vec<PathBuf>>,
#[cfg_attr(feature = "cli", arg(long = "output-schemas"))]
pub output_schemas: Option<Vec<PathBuf>>,
#[cfg_attr(feature = "cli", arg(long = "output-paths"))]
pub output_paths: Option<Vec<PathBuf>>,
#[cfg_attr(feature = "cli", arg(long = "output-fragments"))]
pub output_fragments: Option<Vec<PathBuf>>,
#[cfg_attr(feature = "cli", arg(long = "config"))]
#[serde(skip)]
pub config_file: Option<PathBuf>,
}
#[derive(Deserialize)]
struct CargoConfig {
package: Option<CargoPackage>,
}
#[derive(Deserialize)]
struct CargoPackage {
metadata: Option<CargoMetadata>,
}
#[derive(Deserialize)]
struct CargoMetadata {
#[serde(rename = "oas-forge")]
oas_forge: Option<Config>,
}
impl Config {
#[cfg(feature = "cli")]
pub fn load() -> Self {
let cli_args = Config::parse();
let mut final_config = Config::default();
if let Ok(cargo_conf) = load_cargo_toml() {
final_config.merge(cargo_conf);
}
if let Ok(toml_conf) = load_toml_file("openapi.toml") {
final_config.merge(toml_conf);
}
if let Some(path) = &cli_args.config_file {
if let Ok(file_conf) = load_toml_file(path) {
final_config.merge(file_conf);
}
}
final_config.merge(cli_args);
final_config
}
fn merge(&mut self, other: Config) {
if let Some(input) = other.input {
self.input = Some(input);
}
if let Some(include) = other.include {
self.include = Some(include);
}
if let Some(output) = other.output {
self.output = Some(output);
}
if let Some(output_schemas) = other.output_schemas {
self.output_schemas = Some(output_schemas);
}
if let Some(output_paths) = other.output_paths {
self.output_paths = Some(output_paths);
}
if let Some(output_fragments) = other.output_fragments {
self.output_fragments = Some(output_fragments);
}
}
}
fn load_cargo_toml() -> Result<Config, Box<dyn std::error::Error>> {
let content = std::fs::read_to_string("Cargo.toml")?;
let config: CargoConfig = toml::from_str(&content)?;
Ok(config
.package
.and_then(|p| p.metadata)
.and_then(|m| m.oas_forge)
.unwrap_or_default())
}
fn load_toml_file<P: AsRef<std::path::Path>>(
path: P,
) -> Result<Config, Box<dyn std::error::Error>> {
let content = std::fs::read_to_string(path)?;
let config: Config = toml::from_str(&content)?;
Ok(config)
}