nestrs-cli-rs 0.1.0

Rust port of the Nest CLI for the nestrs organization.
Documentation
//! Upstream source: `../nest-cli/lib/utils/is-module-available.ts`.

use std::path::{Path, PathBuf};

/// Best-effort Rust equivalent of Node's `require.resolve`.
pub fn is_module_available(module_path: &str) -> bool {
    let path = Path::new(module_path);
    if path.is_absolute() || module_path.starts_with('.') {
        return module_file_exists(path);
    }

    let Ok(cwd) = std::env::current_dir() else {
        return false;
    };

    let mut directory: Option<&Path> = Some(cwd.as_path());
    while let Some(current) = directory {
        let candidate = current.join("node_modules").join(module_path);
        if module_file_exists(&candidate) {
            return true;
        }
        directory = current.parent();
    }

    false
}

fn module_file_exists(path: &Path) -> bool {
    if path.is_file() {
        return true;
    }

    if path.is_dir() {
        return path.join("package.json").is_file()
            || path.join("index.js").is_file()
            || path.join("index.json").is_file()
            || path.join("index.node").is_file();
    }

    with_node_extensions(path).iter().any(|path| path.is_file())
}

fn with_node_extensions(path: &Path) -> [PathBuf; 3] {
    [
        path.with_extension("js"),
        path.with_extension("json"),
        path.with_extension("node"),
    ]
}