use std::fs;
use std::path::{Path, PathBuf};
use serde_json::Value;
use super::super::defaults::swc_defaults::{
SourceCompilerOptions, SwcDefaults, swc_defaults_factory,
};
pub use super::super::{SwcCliOptions, SwcCompilerPlan};
pub type SwcCompilerExtras = SwcCompilerPlan;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct SwcCompiler;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SwcRunPlan {
pub defaults: SwcDefaults,
pub swcrc_path: PathBuf,
pub swcrc: Option<Value>,
pub cli_options: SwcCliOptions,
pub watch_files: bool,
pub type_check: bool,
}
impl SwcCompiler {
pub fn plan_run(
cwd: impl AsRef<Path>,
ts_options: Option<&SourceCompilerOptions>,
configuration: Option<&crate::configuration::Configuration>,
swcrc_file_path: Option<&Path>,
watch: bool,
type_check: bool,
) -> Result<SwcRunPlan, String> {
let defaults = swc_defaults_factory(ts_options, configuration);
let swcrc_path = swcrc_file_path
.map(Path::to_path_buf)
.unwrap_or_else(|| PathBuf::from(".swcrc"));
let swcrc = get_swcrc_file_content_if_exists(cwd.as_ref(), swcrc_file_path)?;
let mut cli_options = defaults.cli_options.clone();
cli_options.watch = watch;
Ok(SwcRunPlan {
defaults,
swcrc_path,
swcrc,
cli_options,
watch_files: watch,
type_check,
})
}
pub fn load_swc_cli_binary() -> Result<&'static str, String> {
Err("Failed to load \"@swc/cli\" and/or \"@swc/core\" required packages. Please, make sure to install them as development dependencies.".to_string())
}
pub fn deep_merge(left: Value, right: Value) -> Value {
match (left, right) {
(Value::Object(mut left), Value::Object(right)) => {
for (key, value) in right {
let merged = left
.remove(&key)
.map(|left_value| Self::deep_merge(left_value, value.clone()))
.unwrap_or(value);
left.insert(key, merged);
}
Value::Object(left)
}
(Value::Array(mut left), Value::Array(right)) => {
for (index, value) in right.into_iter().enumerate() {
match left.get_mut(index) {
Some(left_value) => {
let merged = Self::deep_merge(left_value.clone(), value);
*left_value = merged;
}
None => left.push(value),
}
}
Value::Array(left)
}
(_, right) => right,
}
}
}
pub fn get_swcrc_file_content_if_exists(
cwd: &Path,
swcrc_file_path: Option<&Path>,
) -> Result<Option<Value>, String> {
let explicit = swcrc_file_path.is_some();
let path = cwd.join(swcrc_file_path.unwrap_or_else(|| Path::new(".swcrc")));
match fs::read_to_string(&path) {
Ok(content) => serde_json::from_str(&content)
.map(Some)
.map_err(|error| format!("Failed to load \"{}\". Please, check if the file exists and is valid JSON. {error}", path.display())),
Err(error) if error.kind() == std::io::ErrorKind::NotFound && !explicit => Ok(None),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Err(format!(
"Failed to load \"{}\". Please, check if the file exists and is valid JSON.",
path.display()
)),
Err(error) => Err(format!("Failed to load \"{}\": {error}", path.display())),
}
}