nestrs-cli-rs 0.1.0

Rust port of the Nest CLI for the nestrs organization.
Documentation
//! Upstream source: `../nest-cli/lib/compiler/helpers/tsconfig-provider.ts`.

use std::fs;
use std::path::PathBuf;

use serde_json::Value;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TsConfigProvider {
    pub cwd: PathBuf,
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct TsConfigData {
    pub options: Value,
    pub file_names: Vec<PathBuf>,
    pub project_references: Vec<PathBuf>,
}

impl TsConfigProvider {
    pub fn new(cwd: impl Into<PathBuf>) -> Self {
        Self { cwd: cwd.into() }
    }

    pub fn get_by_config_filename(&self, config_filename: &str) -> Result<TsConfigData, String> {
        let config_path = self.cwd.join(config_filename);
        if !config_path.exists() {
            return Err(format!(
                "Could not find legacy compiler configuration file \"{config_filename}\"."
            ));
        }
        let content = fs::read_to_string(&config_path)
            .map_err(|error| format!("Failed to read \"{}\": {error}", config_path.display()))?;
        let value: Value = serde_json::from_str(&content).map_err(|error| {
            format!(
                "Failed to parse legacy compiler configuration file \"{}\": {error}",
                config_path.display()
            )
        })?;
        let options = value
            .get("compilerOptions")
            .cloned()
            .unwrap_or_else(|| Value::Object(Default::default()));
        let file_names = value
            .get("files")
            .and_then(Value::as_array)
            .map(|files| {
                files
                    .iter()
                    .filter_map(Value::as_str)
                    .map(PathBuf::from)
                    .collect()
            })
            .unwrap_or_default();
        let project_references = value
            .get("references")
            .and_then(Value::as_array)
            .map(|refs| {
                refs.iter()
                    .filter_map(|reference| reference.get("path").and_then(Value::as_str))
                    .map(PathBuf::from)
                    .collect()
            })
            .unwrap_or_default();

        Ok(TsConfigData {
            options,
            file_names,
            project_references,
        })
    }
}