use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use super::SourceCrate;
use super::e2e::E2eConfig;
use super::extras::{AdapterConfig, Language};
use super::languages::{
CSharpConfig, CustomModulesConfig, CustomRegistrationsConfig, DartConfig, ElixirConfig, FfiConfig, GleamConfig,
GoConfig, JavaConfig, KotlinConfig, NodeConfig, PhpConfig, PythonConfig, RConfig, RubyConfig, SwiftConfig,
WasmConfig, ZigConfig,
};
use super::output::{
BuildCommandConfig, CleanConfig, ExcludeConfig, IncludeConfig, LintConfig, OutputConfig, ReadmeConfig,
ScaffoldConfig, SetupConfig, TestConfig, UpdateConfig,
};
use super::publish::PublishConfig;
use super::trait_bridge::TraitBridgeConfig;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RawCrateConfig {
pub name: String,
#[serde(default)]
pub sources: Vec<PathBuf>,
#[serde(default)]
pub version_from: Option<String>,
#[serde(default)]
pub core_import: Option<String>,
#[serde(default)]
pub workspace_root: Option<PathBuf>,
#[serde(default)]
pub skip_core_import: bool,
#[serde(default)]
pub error_type: Option<String>,
#[serde(default)]
pub error_constructor: Option<String>,
#[serde(default)]
pub features: Vec<String>,
#[serde(default)]
pub path_mappings: HashMap<String, String>,
#[serde(default)]
pub extra_dependencies: HashMap<String, toml::Value>,
#[serde(default)]
pub auto_path_mappings: Option<bool>,
#[serde(default)]
pub source_crates: Vec<SourceCrate>,
#[serde(default)]
pub languages: Option<Vec<Language>>,
#[serde(default)]
pub python: Option<PythonConfig>,
#[serde(default)]
pub node: Option<NodeConfig>,
#[serde(default)]
pub ruby: Option<RubyConfig>,
#[serde(default)]
pub php: Option<PhpConfig>,
#[serde(default)]
pub elixir: Option<ElixirConfig>,
#[serde(default)]
pub wasm: Option<WasmConfig>,
#[serde(default)]
pub ffi: Option<FfiConfig>,
#[serde(default)]
pub gleam: Option<GleamConfig>,
#[serde(default)]
pub go: Option<GoConfig>,
#[serde(default)]
pub java: Option<JavaConfig>,
#[serde(default)]
pub dart: Option<DartConfig>,
#[serde(default)]
pub kotlin: Option<KotlinConfig>,
#[serde(default)]
pub swift: Option<SwiftConfig>,
#[serde(default)]
pub csharp: Option<CSharpConfig>,
#[serde(default)]
pub r: Option<RConfig>,
#[serde(default)]
pub zig: Option<ZigConfig>,
#[serde(default)]
pub exclude: ExcludeConfig,
#[serde(default)]
pub include: IncludeConfig,
#[serde(default)]
pub output: OutputConfig,
#[serde(default)]
pub generate: Option<super::GenerateConfig>,
#[serde(default)]
pub format: Option<super::FormatConfig>,
#[serde(default)]
pub dto: Option<super::DtoConfig>,
#[serde(default)]
pub format_overrides: HashMap<String, super::FormatConfig>,
#[serde(default)]
pub generate_overrides: HashMap<String, super::GenerateConfig>,
#[serde(default)]
pub lint: HashMap<String, LintConfig>,
#[serde(default)]
pub test: HashMap<String, TestConfig>,
#[serde(default)]
pub setup: HashMap<String, SetupConfig>,
#[serde(default)]
pub update: HashMap<String, UpdateConfig>,
#[serde(default)]
pub clean: HashMap<String, CleanConfig>,
#[serde(default)]
pub build_commands: HashMap<String, BuildCommandConfig>,
#[serde(default)]
pub publish: Option<PublishConfig>,
#[serde(default)]
pub e2e: Option<E2eConfig>,
#[serde(default)]
pub adapters: Vec<AdapterConfig>,
#[serde(default)]
pub trait_bridges: Vec<TraitBridgeConfig>,
#[serde(default)]
pub scaffold: Option<ScaffoldConfig>,
#[serde(default)]
pub readme: Option<ReadmeConfig>,
#[serde(default)]
pub custom_files: HashMap<String, Vec<PathBuf>>,
#[serde(default)]
pub custom_modules: CustomModulesConfig,
#[serde(default)]
pub custom_registrations: CustomRegistrationsConfig,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn raw_crate_config_minimal_deserializes() {
let toml_str = r#"
name = "spikard"
sources = ["src/lib.rs"]
"#;
let cfg: RawCrateConfig = toml::from_str(toml_str).unwrap();
assert_eq!(cfg.name, "spikard");
assert_eq!(cfg.sources, vec![PathBuf::from("src/lib.rs")]);
assert!(cfg.python.is_none());
assert!(cfg.publish.is_none());
assert!(cfg.e2e.is_none());
}
#[test]
fn raw_crate_config_with_source_crates() {
let toml_str = r#"
name = "spikard"
sources = []
features = ["di"]
core_import = "spikard"
[[source_crates]]
name = "spikard-core"
sources = ["crates/spikard-core/src/http.rs"]
[[source_crates]]
name = "spikard-http"
sources = ["crates/spikard-http/src/lib.rs"]
"#;
let cfg: RawCrateConfig = toml::from_str(toml_str).unwrap();
assert_eq!(cfg.source_crates.len(), 2);
assert_eq!(cfg.source_crates[0].name, "spikard-core");
assert_eq!(cfg.features, vec!["di"]);
}
#[test]
fn raw_crate_config_with_per_crate_python_and_lint_override() {
let toml_str = r#"
name = "spikard"
sources = []
[python]
module_name = "_spikard"
pip_name = "spikard"
release_gil = true
[lint.python]
check = "ruff check crates/spikard-py/"
"#;
let cfg: RawCrateConfig = toml::from_str(toml_str).unwrap();
let py = cfg.python.expect("python section present");
assert_eq!(py.module_name.as_deref(), Some("_spikard"));
assert_eq!(py.pip_name.as_deref(), Some("spikard"));
assert!(py.release_gil);
let lint_py = cfg.lint.get("python").expect("lint.python override present");
assert_eq!(
lint_py.check.as_ref().unwrap().commands(),
vec!["ruff check crates/spikard-py/"]
);
}
}