npm_run_scripts/utils/
paths.rs1use std::path::{Path, PathBuf};
4
5use anyhow::{Context, Result};
6
7use crate::error::NrsError;
8
9pub const MAX_SEARCH_DEPTH: usize = 10;
11
12pub fn find_package_json(start_dir: &Path) -> Result<PathBuf> {
20 let start = start_dir.canonicalize().with_context(|| {
21 format!(
22 "Cannot access directory '{}': path does not exist or is not accessible",
23 start_dir.display()
24 )
25 })?;
26
27 let mut current = start.as_path();
28 let mut depth = 0;
29
30 while depth < MAX_SEARCH_DEPTH {
31 let package_json = current.join("package.json");
32 if package_json.exists() {
33 return Ok(package_json);
34 }
35
36 match current.parent() {
37 Some(parent) if parent != current => {
38 current = parent;
39 depth += 1;
40 }
41 _ => break,
42 }
43 }
44
45 Err(NrsError::NoPackageJson {
46 path: start,
47 depth: MAX_SEARCH_DEPTH,
48 }
49 .into())
50}
51
52pub fn find_project_root(start_dir: &Path) -> Result<PathBuf> {
58 let package_json = find_package_json(start_dir)?;
59 Ok(package_json
60 .parent()
61 .expect("package.json should have parent")
62 .to_path_buf())
63}
64
65pub fn config_dir() -> Option<PathBuf> {
69 dirs::config_dir().map(|p| p.join("nrs"))
70}
71
72pub fn history_file() -> Option<PathBuf> {
76 config_dir().map(|p| p.join("history.json"))
77}
78
79pub fn global_config_file() -> Option<PathBuf> {
83 config_dir().map(|p| p.join("config.toml"))
84}
85
86pub fn local_config_file(project_dir: &Path) -> Option<PathBuf> {
90 let config_file = project_dir.join(".nrsrc.toml");
91 if config_file.exists() {
92 Some(config_file)
93 } else {
94 None
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use tempfile::TempDir;
102
103 #[test]
104 fn test_find_package_json_in_current_dir() {
105 let temp = TempDir::new().unwrap();
106 std::fs::write(temp.path().join("package.json"), "{}").unwrap();
107
108 let result = find_package_json(temp.path());
109 assert!(result.is_ok());
110 assert!(result.unwrap().ends_with("package.json"));
111 }
112
113 #[test]
114 fn test_find_package_json_in_parent() {
115 let temp = TempDir::new().unwrap();
116 std::fs::write(temp.path().join("package.json"), "{}").unwrap();
117
118 let subdir = temp.path().join("src");
119 std::fs::create_dir(&subdir).unwrap();
120
121 let result = find_package_json(&subdir);
122 assert!(result.is_ok());
123 }
124
125 #[test]
126 fn test_find_package_json_not_found() {
127 let temp = TempDir::new().unwrap();
128 let result = find_package_json(temp.path());
129 assert!(result.is_err());
130 }
131}