use crate::prelude::internal::*;
mod error;
pub use error::*;
mod toml_str;
mod manifest;
pub use manifest::*;
pub const GTCONFIG_FILE: &str = "genotype.toml";
const fn default_package() -> bool {
true
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct GtpConfig {
pub name: Option<String>,
pub version: Option<Version>,
#[serde(default = "default_package")]
pub package: bool,
#[serde(default)]
pub root: GtpConfigDirRelativeRootDirPath,
#[serde(default)]
pub dist: GtpRootDirRelativeDistDirPath,
#[serde(default)]
pub src: GtpRootDirRelativeSrcDirPath,
#[serde(default)]
pub entry: GtpSrcDirRelativeEntryPattern,
#[serde(default)]
pub formatters: Vec<GtpFormatter>,
#[serde(default, alias = "typescript")]
pub ts: TsConfig,
#[serde(default, alias = "python")]
pub py: PyConfig,
#[serde(default, alias = "rust")]
pub rs: RsConfig,
#[serde(skip)]
source_toml_str: String,
}
impl Default for GtpConfig {
fn default() -> Self {
Self {
name: None,
version: None,
package: true,
root: Default::default(),
dist: Default::default(),
src: Default::default(),
entry: Default::default(),
formatters: Default::default(),
ts: Default::default(),
py: Default::default(),
rs: Default::default(),
source_toml_str: String::new(),
}
}
}
impl GtpConfig {
pub fn parse(source: String) -> Result<Self> {
let config: GtpConfig = Self::from_toml_str(&source)?;
Ok(config)
}
pub fn lang(&self, lang: GtLang) -> &dyn GtpLangConfig {
match lang {
GtLang::Py => &self.py,
GtLang::Rs => &self.rs,
GtLang::Ts => &self.ts,
}
}
pub fn lang_package_enabled(&self, lang_config: &dyn GtpLangConfig) -> bool {
lang_config.common().package.unwrap_or(self.package)
}
pub fn lang_enabled(&self, lang: GtLang) -> bool {
match lang {
GtLang::Py => self.python_enabled(),
GtLang::Rs => self.rust_enabled(),
GtLang::Ts => self.ts_enabled(),
}
}
pub fn ts_enabled(&self) -> bool {
self.ts.common.enabled
}
pub fn python_enabled(&self) -> bool {
self.py.common.enabled
}
pub fn rust_enabled(&self) -> bool {
self.rs.common.enabled
}
pub fn from_root(name: &str, root: &str) -> Self {
GtpConfig {
name: Some(name.into()),
version: None,
root: root.into(),
src: ".".into(),
source_toml_str: String::new(),
..GtpConfig::default()
}
}
pub fn from_entry(name: &str, root: &str, entry: &str) -> Self {
GtpConfig {
name: Some(name.into()),
version: None,
root: root.into(),
entry: entry.into(),
src: ".".into(),
source_toml_str: String::new(),
..GtpConfig::default()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_global_version() {
let config = toml::from_str::<GtpConfig>("version = \"0.2.0\"\n").unwrap();
assert_eq!(config.version, Some(Version::parse("0.2.0").unwrap()));
}
#[test]
fn test_parse_language_full_aliases() {
let config = toml::from_str::<GtpConfig>(
r#"[python]
enabled = true
version = "latest"
[rust]
enabled = true
"#,
)
.unwrap();
assert!(config.python_enabled());
assert!(config.rust_enabled());
}
#[test]
fn test_parse_language_short_aliases() {
let config = toml::from_str::<GtpConfig>(
r#"[py]
enabled = true
version = "latest"
[rs]
enabled = true
"#,
)
.unwrap();
assert!(config.python_enabled());
assert!(config.rust_enabled());
}
#[test]
fn test_package_global() {
let config = toml::from_str::<GtpConfig>("name = \"demo\"\n").unwrap();
assert!(config.package);
}
#[test]
fn test_parse_target() {
let config = toml::from_str::<GtpConfig>(
r#"package = false
[ts]
enabled = true
package = true
tsconfig = { allowImportingTsExtensions = false }
"#,
)
.unwrap();
assert!(!config.package);
assert_eq!(config.ts.common.package, Some(true));
assert_eq!(config.py.common.package, None);
}
#[test]
fn test_parse_root_formatters() {
let config = toml::from_str::<GtpConfig>(
r#"formatters = [
{ kind = "shell", cmd = "npm", args = ["run", "format"] },
{ kind = "pnpm", cmd = "prettier", args = ["--check", "."] },
{ kind = "cargo", cmd = "fmt", args = ["--all"] },
{ kind = "oxfmt", via = "pnpm" },
{ kind = "prettier", via = "npx" },
]
"#,
)
.unwrap();
assert_ron_snapshot!(config.formatters, @r#"
[
__GtpFormatterShellLiteralsSerialize(
cmd: "npm",
args: Some([
"run",
"format",
]),
kind: "shell",
),
GtpFormatterExecutor(
cmd: "prettier",
args: Some([
"--check",
".",
]),
kind: "pnpm",
),
GtpFormatterExecutor(
cmd: "fmt",
args: Some([
"--all",
]),
kind: "cargo",
),
__GtpFormatterPresetOxfmtLiteralsSerialize(
via: Some("pnpm"),
kind: "oxfmt",
),
__GtpFormatterPresetPrettierLiteralsSerialize(
via: Some("npx"),
kind: "prettier",
),
]
"#);
}
#[test]
fn test_parse_target_formatters() {
let config = toml::from_str::<GtpConfig>(
r#"[py]
enabled = true
version = "latest"
formatters = [{ kind = "ruff", via = "uv" }]
"#,
)
.unwrap();
assert_ron_snapshot!(config.py.common.formatters, @r#"
[
__GtpFormatterPresetRuffLiteralsSerialize(
via: Some("uv"),
kind: "ruff",
),
]
"#);
}
}