cuenv_workspaces/materializer/
node_modules.rs1use super::Materializer;
4use crate::core::types::{LockfileEntry, PackageManager, Workspace};
5use crate::error::{Error, Result};
6use std::path::{Path, PathBuf};
7
8#[cfg(unix)]
9use std::os::unix::fs::symlink;
10#[cfg(windows)]
11use std::os::windows::fs::symlink_dir as symlink;
12
13pub struct NodeModulesMaterializer;
15
16impl Materializer for NodeModulesMaterializer {
17 fn materialize(
18 &self,
19 workspace: &Workspace,
20 _entries: &[LockfileEntry],
21 target_dir: &Path,
22 ) -> Result<()> {
23 if !matches!(
24 workspace.manager,
25 PackageManager::Npm
26 | PackageManager::Bun
27 | PackageManager::Pnpm
28 | PackageManager::YarnClassic
29 | PackageManager::YarnModern
30 ) {
31 return Ok(());
32 }
33
34 let workspace_nm = workspace.root.join("node_modules");
41 let target_nm = target_dir.join("node_modules");
42
43 if workspace_nm.exists() {
44 if !target_nm.exists() {
45 symlink(&workspace_nm, &target_nm).map_err(|e| Error::Io {
46 source: e,
47 path: Some(target_nm.clone()),
48 operation: "symlink node_modules".to_string(),
49 })?;
50 }
51 } else {
52 }
56
57 Ok(())
58 }
59}
60
61impl NodeModulesMaterializer {
62 pub fn detect_cache_dir(manager: PackageManager) -> Option<PathBuf> {
66 let home = std::env::var_os("HOME")
67 .or_else(|| std::env::var_os("USERPROFILE"))
68 .map(PathBuf::from)?;
69
70 match manager {
71 PackageManager::Npm => Some(home.join(".npm")),
72 PackageManager::Pnpm => {
73 Some(home.join(".local/share/pnpm/store/v3"))
75 }
76 PackageManager::Bun => Some(home.join(".bun/install/cache")),
77 PackageManager::YarnClassic => Some(home.join(".yarn/cache")),
78 PackageManager::YarnModern => Some(home.join(".yarn/berry/cache")),
79 PackageManager::Deno => Some(home.join(".cache/deno")),
80 PackageManager::Cargo => None,
81 }
82 }
83}