1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
#[macro_use] extern crate failure; extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; use std::collections::HashMap; use std::fs::File; use std::path::PathBuf; use std::process::Command; use failure::Error; #[derive(Deserialize)] struct NpmPackageConfig { scripts: Option<HashMap<String, String>>, } pub struct NpmScripts { path: PathBuf, } impl NpmScripts { pub fn new<P>(path: P) -> Self where P: Into<PathBuf>, { NpmScripts { path: path.into() } } pub fn is_available(&self) -> bool { self.path.exists() } fn ensure_available(&self) -> Result<(), Error> { if !self.is_available() { bail!("no package.json found"); } Ok(()) } pub fn install(&self) -> Result<(), Error> { self.ensure_available()?; Command::new("npm") .arg("install") .current_dir(&self.path) .output()?; Ok(()) } fn get_package_cfg(&self) -> Result<NpmPackageConfig, Error> { let mut file = File::open(&self.path.join("package.json"))?; let parsed = serde_json::from_reader(&mut file)?; Ok(parsed) } pub fn has_script(&self, script: &str) -> Result<bool, Error> { self.ensure_available()?; let cfg = self.get_package_cfg()?; Ok(cfg.scripts.is_some() && cfg.scripts.unwrap().contains_key(script)) } pub fn run_script(&self, script: &str) -> Result<(), Error> { self.ensure_available()?; if let Err(err) = self.has_script(script) { return Err(err); } Command::new("npm") .arg("run") .arg(script) .current_dir(&self.path) .output()?; Ok(()) } } #[cfg(test)] mod tests { use super::*; #[test] fn it_detects_missing_package_json() { let scripts = NpmScripts::new("./examples"); let has_some = scripts.has_script(&"build".to_owned()); assert!(has_some.is_err()); } #[test] fn test_package_does_not_have_script() { let scripts = NpmScripts::new("./examples/ex1"); let has_some = scripts.has_script("build").unwrap(); assert!(!has_some); } #[test] fn test_package_has_script() { let scripts = NpmScripts::new("./examples/ex2"); let has_some = scripts.has_script("build").unwrap(); assert!(has_some); } #[test] fn test_running_a_script() { let scripts = NpmScripts::new("./examples/ex3"); let res = scripts.run_script("build"); assert!(res.is_ok()); } #[test] fn it_installs_dependencies() { let scripts = NpmScripts::new("./examples/ex4"); let res = scripts.install(); assert!(res.is_ok()); } }