bat-cli 0.12.1

Blockchain Auditor Toolkit (BAT)
use error_stack::{Result, ResultExt};
use log::Level;

use serde_json::Map;
use serde_json::{json, Value};

use crate::batbelt::path::BatFile;
use crate::batbelt::templates::{TemplateError, TemplateResult};

use crate::commands::{BatPackageJsonCommand, BatPackageJsonCommandOptions};
use crate::BatCommands;

pub struct PackageJsonTemplate;

impl PackageJsonTemplate {
    pub fn create_package_json(log_level: Option<Level>) -> Result<(), TemplateError> {
        BatFile::PackageJson
            .write_content(false, &Self::get_package_json_content(log_level)?)
            .change_context(TemplateError)?;
        Ok(())
    }

    fn get_package_json_content(log_level: Option<Level>) -> TemplateResult<String> {
        let scripts_value = Self::get_scripts_serde_value(log_level)?;
        let package_json = json!({
        "name": "bat_project",
        "version": "1.0.0",
        "description": "Bat project",
        "main": "index.js",
        "scripts": scripts_value,
        "author": "",
        "license": "ISC"
        });

        Ok(serde_json::to_string_pretty(&package_json).unwrap())
    }

    fn get_scripts_serde_value(log_level: Option<Level>) -> TemplateResult<Value> {
        let (verbosity_flag, verbosity_level_name) = if let Some(level) = log_level {
            match level {
                Level::Warn => ("v".to_string(), level.to_string()),
                Level::Info => ("vv".to_string(), level.to_string()),
                Level::Debug => ("vvv".to_string(), level.to_string()),
                Level::Trace => ("vvvv".to_string(), level.to_string()),
                _ => ("".to_string(), "".to_string()),
            }
        } else {
            ("".to_string(), "".to_string())
        };
        let (script_key_prefix, script_value_prefix) = if cfg!(debug_assertions) {
            let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
            if verbosity_flag.is_empty() {
                (
                    "".to_string(),
                    format!("cargo run --manifest-path {} --", manifest_path),
                )
            } else {
                (
                    format!("{}::", verbosity_level_name),
                    format!(
                        "cargo run --manifest-path {} -- -{}",
                        manifest_path, verbosity_flag
                    ),
                )
            }
        } else if verbosity_flag.is_empty() {
            ("".to_string(), "bat-cli".to_string())
        } else {
            (
                format!("{}::", verbosity_level_name),
                format!("bat-cli -{}", verbosity_flag),
            )
        };
        let project_type = crate::config::BatConfig::get_config()
            .map(|c| c.project_type)
            .unwrap_or_default();
        let bat_package_json_commands_vec =
            BatCommands::get_bat_package_json_commands(&project_type);
        let mut scripts_map = Map::new();
        for bat_command in bat_package_json_commands_vec {
            let BatPackageJsonCommand {
                command_name,
                command_options,
            } = bat_command;
            if command_options.is_empty() {
                let script_key = format!("{}{}", script_key_prefix, command_name);
                let script_value = format!("{} {}", script_value_prefix, command_name);
                scripts_map.insert(script_key, script_value.into());
                continue;
            }
            for command_option in command_options {
                let command_option_clone = command_option.clone();

                let BatPackageJsonCommandOptions {
                    command_option_name,
                    command_option_flags,
                } = command_option;
                if command_name == "sonar" {
                    let script_key = format!("{}{}", script_key_prefix, command_name);
                    let script_value = format!("{} {}", script_value_prefix, command_name);
                    scripts_map.insert(script_key.clone(), script_value.clone().into());
                } else {
                    let script_key = format!(
                        "{}{}::{}",
                        script_key_prefix, command_name, command_option_name
                    );
                    let script_value = format!(
                        "{} {} {}",
                        script_value_prefix, command_name, command_option_name
                    );
                    scripts_map.insert(script_key.clone(), script_value.clone().into());
                };

                if !command_option_flags.is_empty() {
                    let combinations_vec = command_option_clone
                        .clone()
                        .get_combinations_vec(&command_name);
                    for combination in combinations_vec {
                        let key_string = combination
                            .clone()
                            .into_iter()
                            .fold("".to_string(), |result, current| {
                                format!("{}::{}", result, current)
                            });
                        let value_string = combination
                            .clone()
                            .into_iter()
                            .fold("".to_string(), |result, current| {
                                format!("{} --{}", result, current)
                            });
                        if command_name == "sonar" {
                            let script_key =
                                format!("{}{}{}", script_key_prefix, command_name, key_string);
                            let script_value = format!(
                                "{} {} {}",
                                script_value_prefix, command_name, value_string
                            );
                            scripts_map.insert(script_key.clone(), script_value.clone().into());
                        } else {
                            let script_key = format!(
                                "{}{}::{}{}",
                                script_key_prefix, command_name, command_option_name, key_string
                            );
                            let script_value = format!(
                                "{} {} {} {}",
                                script_value_prefix,
                                command_name,
                                command_option_name,
                                value_string
                            );
                            scripts_map.insert(script_key, script_value.into());
                        }
                    }
                }
            }
        }
        let serde_value: Value = scripts_map.into();
        Ok(serde_value)
    }
}

#[cfg(test)]
mod template_test {
    use crate::batbelt::templates::package_json_template::PackageJsonTemplate;

    #[test]
    fn test_get_package_json_content() {
        let json_content = PackageJsonTemplate::get_package_json_content(None).unwrap();
        println!("{}", json_content);
    }
}