use std::collections::BTreeMap;
use std::path::Path;
use std::path::PathBuf;
use serde::Deserialize;
use crate::error::Error;
use crate::error::Result;
#[derive(Debug, Default, Clone, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct Config {
pub package: Option<String>,
pub output: Option<PathBuf>,
#[serde(default)]
pub generate: Generate,
#[serde(default)]
pub output_options: OutputOptions,
#[serde(default)]
pub import_mapping: BTreeMap<String, String>,
}
#[derive(Debug, Default, Clone, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct Generate {
#[serde(default)]
pub models: bool,
#[serde(default)]
pub std_http_server: bool,
#[serde(default)]
pub client: bool,
#[serde(default)]
pub embedded_spec: bool,
#[serde(default)]
pub server_urls: bool,
}
pub(crate) const OUTPUT_OPTIONS_KEY: &str = "output-options";
pub(crate) const RESPONSE_TYPE_SUFFIX_KEY: &str = "response-type-suffix";
pub(crate) const DEFAULT_RESPONSE_SUFFIX: &str = "response";
pub(crate) const TYPE_NAME_SUFFIX_KEY: &str = "type-name-suffix";
#[derive(Debug, Default, Clone, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct OutputOptions {
#[serde(default)]
pub skip_prune: bool,
#[serde(default)]
pub include_tags: Vec<String>,
#[serde(default)]
pub exclude_tags: Vec<String>,
#[serde(default)]
pub include_operation_ids: Vec<String>,
#[serde(default)]
pub exclude_operation_ids: Vec<String>,
#[serde(default)]
pub exclude_schemas: Vec<String>,
#[serde(default)]
pub response_type_suffix: Option<String>,
#[serde(default)]
pub type_name_suffix: Option<String>,
}
impl Config {
pub fn load(path: &Path) -> Result<Self> {
let text = std::fs::read_to_string(path).map_err(|source| {
return Error::ReadConfig {
path: path.display().to_string(),
source,
};
})?;
let config: Config = serde_yaml::from_str(&text).map_err(|source| {
return Error::ParseConfig {
path: path.display().to_string(),
source,
};
})?;
return Ok(config);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn config_keys_match_serde_names() {
let yaml =
format!("{OUTPUT_OPTIONS_KEY}:\n {RESPONSE_TYPE_SUFFIX_KEY}: Resp\n {TYPE_NAME_SUFFIX_KEY}: Alt\n",);
let config: Config = serde_yaml::from_str(&yaml).expect("config parses");
assert_eq!(
config.output_options.response_type_suffix.as_deref(),
Some("Resp"),
"OUTPUT_OPTIONS_KEY/RESPONSE_TYPE_SUFFIX_KEY drifted from the serde field names",
);
assert_eq!(
config.output_options.type_name_suffix.as_deref(),
Some("Alt"),
"TYPE_NAME_SUFFIX_KEY drifted from the serde field name",
);
}
#[test]
fn type_name_suffix_defaults_to_unset() {
let config: Config = serde_yaml::from_str("package: demo\n").expect("config parses");
assert_eq!(config.output_options.type_name_suffix, None);
}
#[test]
fn default_response_suffix_pascalizes_to_response() {
use crate::naming::Case;
use crate::naming::to_ident;
assert_eq!(to_ident(DEFAULT_RESPONSE_SUFFIX, Case::Pascal).logical(), "Response");
}
}