proto_node/depman/
execute.rs

1use crate::depman::NodeDependencyManager;
2use clean_path::Clean;
3use proto_core::{async_trait, Describable, Executable, Installable, ProtoError};
4use starbase_utils::json::{self, JsonValue};
5use std::path::{Path, PathBuf};
6
7pub fn extract_bin_from_package_json(
8    package_path: PathBuf,
9    bin_name: &str,
10) -> Result<Option<String>, ProtoError> {
11    let mut bin_path = None;
12    let json: JsonValue = json::read_file(package_path)?;
13
14    if let Some(bin_field) = json.get("bin") {
15        match bin_field {
16            JsonValue::String(bin) => {
17                bin_path = Some(bin.to_owned());
18            }
19            JsonValue::Object(bins) => {
20                if let Some(bin) = bins.get(bin_name) {
21                    bin_path = Some(bin.as_str().unwrap_or_default().to_string());
22                }
23            }
24            _ => {}
25        };
26    }
27
28    if bin_path.is_none() {
29        if let Some(main_field) = json.get("main") {
30            bin_path = Some(main_field.as_str().unwrap_or_default().to_string());
31        }
32    }
33
34    Ok(bin_path)
35}
36
37#[async_trait]
38impl Executable<'_> for NodeDependencyManager {
39    async fn find_bin_path(&mut self) -> Result<(), ProtoError> {
40        let install_dir = self.get_install_dir()?;
41        let bin_name = &self.package_name;
42        let package_json = install_dir.join("package.json");
43
44        if package_json.exists() {
45            if let Some(bin_path) = extract_bin_from_package_json(package_json, bin_name)? {
46                self.bin_path = Some(install_dir.join(bin_path).clean());
47
48                return Ok(());
49            }
50        }
51
52        return Err(ProtoError::ExecuteMissingBin(
53            self.get_name(),
54            install_dir.join(format!("bin/{bin_name}.js")),
55        ));
56    }
57
58    fn get_bin_path(&self) -> Result<&Path, ProtoError> {
59        match self.bin_path.as_ref() {
60            Some(bin) => Ok(bin),
61            None => Err(ProtoError::MissingTool(self.get_name())),
62        }
63    }
64
65    fn get_globals_bin_dir(&self) -> Result<Option<PathBuf>, ProtoError> {
66        Ok(Some(
67            self.base_dir
68                .parent()
69                .unwrap()
70                .join("node")
71                .join("globals")
72                .join("bin"),
73        ))
74    }
75}