diplo 1.0.0

Diplo is a script runner and dependency manager made in rust
Documentation
use crate::{DIPLO_CONFIG, DOTDIPLO};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{
    collections::HashMap,
    fs::{create_dir_all, read_to_string, write},
};
use toml_edit::Document;

#[derive(Serialize, Deserialize, Default, Clone)]
pub struct Dependency {
    pub url: String,
    pub exports: Option<String>,
    pub locked: bool,
    ///Types defined by // @deno-types="url"
    pub types: Option<String>,
}

#[derive(Serialize, Deserialize, Default)]
pub struct Config {
    pub name: Option<String>,
    pub scripts: Option<HashMap<String, String>>,
    pub load_env: Option<bool>,
    pub import_map: Option<bool>,
    pub dependencies: Option<HashMap<String, Dependency>>,
    pub watcher: Option<WatcherClass>,
}

#[derive(Serialize, Deserialize, Default)]
pub struct ConfigParse {
    pub name: Option<String>,
    pub scripts: Option<HashMap<String, String>>,
    pub load_env: Option<bool>,
    pub import_map: Option<bool>,
    pub dependencies: Option<HashMap<String, Value>>,
    pub watcher: Option<WatcherClass>,
}

#[derive(Serialize, Deserialize)]
pub struct WatcherClass {
    pub directory: Option<String>,
    pub default_ignores: Option<bool>,
    pub clear: Option<bool>,
    pub no_ignore: Option<bool>,
    pub respect_gitignore: Option<bool>,
}

pub fn create_config() -> Config {
    create_dir_all(&*DOTDIPLO).unwrap();
    let data = read_to_string(&*DIPLO_CONFIG);

    let config: ConfigParse = match data {
        Ok(data) => toml::from_str(&data).unwrap(),
        _ => ConfigParse {
            load_env: Some(false),
            import_map: Some(false),
            name: None,
            scripts: Some(HashMap::new()),
            dependencies: Some(HashMap::new()),
            watcher: None,
        },
    };
    let mut new_deps: HashMap<String, Dependency> = HashMap::new();
    if let Some(deps) = config.dependencies {
        for (key, val) in deps.iter() {
            if val.is_object() {
                new_deps.insert(
                    key.to_string(),
                    Dependency {
                        url: val["url"].as_str().unwrap().to_owned(),
                        exports: val["exports"].as_str().map(|exports| exports.to_string()),
                        types: val["types"].as_str().map(|types| types.to_string()),
                        locked: val["locked"].as_bool().unwrap_or(false),
                    },
                );
            } else {
                new_deps.insert(
                    key.to_string(),
                    Dependency {
                        url: val.as_str().unwrap().to_owned(),
                        exports: None,
                        locked: false,
                        types: None,
                    },
                );
            }
        }
    }
    Config {
        name: config.name,
        scripts: config.scripts,
        load_env: config.load_env,
        import_map: config.import_map,
        dependencies: Some(new_deps),
        watcher: config.watcher,
    }
}

pub fn merge(a: &mut Value, b: Value) {
    match (a, b) {
        (a @ &mut Value::Object(_), Value::Object(b)) => {
            let a = a.as_object_mut().unwrap();
            for (k, v) in b {
                merge(a.entry(k).or_insert(Value::Null), v);
            }
        }
        (a, b) => *a = b,
    }
}

pub fn update_config_toml(config: Document) {
    write(&*DIPLO_CONFIG, config.to_string()).unwrap();
}