use super::frameworks::*;
use super::registry::{FrameworkDetector, PluginRegistry};
use crate::config::Config;
use crate::core::Result;
use std::path::Path;
pub fn detect_frameworks(
root_path: &Path,
config: &Config,
) -> Result<Vec<Box<dyn FrameworkDetector>>> {
let mut detectors: Vec<Box<dyn FrameworkDetector>> = Vec::new();
let registry = PluginRegistry::with_builtins();
let deps = read_dependencies(root_path);
for name in &config.plugins.enabled {
if let Some(detector) = find_detector_by_name(®istry, name) {
detectors.push(detector);
}
}
if config.plugins.auto_detect {
for builtin in registry.detectors() {
let name = builtin.name();
if config.plugins.disabled.contains(&name.to_string()) {
continue;
}
if config.plugins.enabled.contains(&name.to_string()) {
continue;
}
if builtin.detect_from_dependencies(&deps) {
detectors.push(create_detector(name));
}
}
}
Ok(detectors)
}
fn read_dependencies(root_path: &Path) -> Vec<String> {
let package_json_path = root_path.join("package.json");
if !package_json_path.exists() {
return Vec::new();
}
let content = match std::fs::read_to_string(&package_json_path) {
Ok(c) => c,
Err(_) => return Vec::new(),
};
let pkg: serde_json::Value = match serde_json::from_str(&content) {
Ok(v) => v,
Err(_) => return Vec::new(),
};
let mut deps = Vec::new();
if let Some(obj) = pkg.get("dependencies").and_then(|v| v.as_object()) {
deps.extend(obj.keys().cloned());
}
if let Some(obj) = pkg.get("devDependencies").and_then(|v| v.as_object()) {
deps.extend(obj.keys().cloned());
}
if let Some(obj) = pkg.get("peerDependencies").and_then(|v| v.as_object()) {
deps.extend(obj.keys().cloned());
}
deps
}
fn find_detector_by_name(
registry: &PluginRegistry,
name: &str,
) -> Option<Box<dyn FrameworkDetector>> {
for detector in registry.detectors() {
if detector.name() == name {
return Some(create_detector(name));
}
}
None
}
fn create_detector(name: &str) -> Box<dyn FrameworkDetector> {
match name {
"nextjs" => Box::new(NextJsDetector::new()),
"jest" => Box::new(JestDetector::new()),
"vitest" => Box::new(VitestDetector::new()),
"express" => Box::new(ExpressDetector::new()),
_ => Box::new(NextJsDetector::new()), }
}