Skip to content

Commit cc66aad

Browse files
committed
feat(env): show message when switching version automatically
1 parent 277648f commit cc66aad

File tree

9 files changed

+142
-4
lines changed

9 files changed

+142
-4
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/vite_global_cli/src/commands/env/config.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,15 @@ pub async fn resolve_version(cwd: &AbsolutePath) -> Result<VersionResolution, Er
230230
});
231231
}
232232

233+
resolve_version_from_project(cwd).await
234+
}
235+
236+
/// Resolve the Node.js version from project files only (`.node-version`, `engines.node`, etc.).
237+
///
238+
/// Unlike [`resolve_version`], this skips session overrides (env var and session file).
239+
/// Use this when the caller IS the session setter (e.g., `vp env use` resolving which
240+
/// version a project needs, independent of what's currently active).
241+
pub async fn resolve_version_from_project(cwd: &AbsolutePath) -> Result<VersionResolution, Error> {
233242
let provider = NodeProvider::new();
234243

235244
// Use shared version resolution with directory walking

crates/vite_global_cli/src/commands/env/setup.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,23 @@ vp() {
319319
command vp "$@"
320320
fi
321321
}
322+
323+
# Auto-switch Node.js version on directory change
324+
__vp_use_on_cd() {
325+
vp env use --silent-if-unchanged
326+
}
327+
if [ -n "${ZSH_VERSION-}" ]; then
328+
if [[ ! " ${chpwd_functions[*]-} " == *" __vp_use_on_cd "* ]]; then
329+
chpwd_functions+=(__vp_use_on_cd)
330+
fi
331+
else
332+
__vpcd() {
333+
\cd "$@" || return $?
334+
__vp_use_on_cd
335+
}
336+
alias cd=__vpcd
337+
fi
338+
__vp_use_on_cd
322339
"#
323340
.replace("__VP_BIN__", &bin_path_ref);
324341
let env_file = vite_plus_home.join("env");
@@ -344,6 +361,15 @@ function vp
344361
command vp $argv
345362
end
346363
end
364+
365+
# Auto-switch Node.js version on directory change
366+
function __vp_use_on_cd --on-variable PWD --description 'Auto-switch Node.js version'
367+
if status is-command-substitution
368+
return
369+
end
370+
vp env use --silent-if-unchanged
371+
end
372+
__vp_use_on_cd
347373
"#
348374
.replace("__VP_BIN__", &bin_path_ref);
349375
let env_fish_file = vite_plus_home.join("env.fish");
@@ -379,6 +405,19 @@ function vp {
379405
& (Join-Path $__vp_bin "vp.exe") @args
380406
}
381407
}
408+
409+
# Auto-switch Node.js version on directory change
410+
$__vp_original_prompt = $function:prompt
411+
function prompt {
412+
$loc = Get-Location
413+
if ($global:__vp_last_dir -ne $loc.Path) {
414+
$global:__vp_last_dir = $loc.Path
415+
vp env use --silent-if-unchanged
416+
}
417+
& $__vp_original_prompt
418+
}
419+
$global:__vp_last_dir = (Get-Location).Path
420+
vp env use --silent-if-unchanged
382421
"#;
383422

384423
// For PowerShell, use the actual absolute path (not $HOME-relative)
@@ -688,6 +727,70 @@ mod tests {
688727
);
689728
}
690729

730+
#[tokio::test]
731+
async fn test_create_env_files_posix_contains_cd_hook() {
732+
let temp_dir = TempDir::new().unwrap();
733+
let home = AbsolutePathBuf::new(temp_dir.path().to_path_buf()).unwrap();
734+
let _guard = home_guard(temp_dir.path());
735+
736+
create_env_files(&home).await.unwrap();
737+
738+
let env_content = tokio::fs::read_to_string(home.join("env")).await.unwrap();
739+
740+
// Verify cd hook components
741+
assert!(
742+
env_content.contains("__vp_use_on_cd"),
743+
"env file should contain __vp_use_on_cd function"
744+
);
745+
assert!(
746+
env_content.contains("chpwd_functions"),
747+
"env file should use chpwd_functions for zsh"
748+
);
749+
assert!(env_content.contains("alias cd=__vpcd"), "env file should alias cd for bash");
750+
}
751+
752+
#[tokio::test]
753+
async fn test_create_env_files_fish_contains_cd_hook() {
754+
let temp_dir = TempDir::new().unwrap();
755+
let home = AbsolutePathBuf::new(temp_dir.path().to_path_buf()).unwrap();
756+
let _guard = home_guard(temp_dir.path());
757+
758+
create_env_files(&home).await.unwrap();
759+
760+
let fish_content = tokio::fs::read_to_string(home.join("env.fish")).await.unwrap();
761+
762+
// Verify fish cd hook
763+
assert!(
764+
fish_content.contains("__vp_use_on_cd"),
765+
"env.fish should contain __vp_use_on_cd function"
766+
);
767+
assert!(
768+
fish_content.contains("--on-variable PWD"),
769+
"env.fish should use --on-variable PWD for cd detection"
770+
);
771+
}
772+
773+
#[tokio::test]
774+
async fn test_create_env_files_ps1_contains_cd_hook() {
775+
let temp_dir = TempDir::new().unwrap();
776+
let home = AbsolutePathBuf::new(temp_dir.path().to_path_buf()).unwrap();
777+
let _guard = home_guard(temp_dir.path());
778+
779+
create_env_files(&home).await.unwrap();
780+
781+
let ps1_content = tokio::fs::read_to_string(home.join("env.ps1")).await.unwrap();
782+
783+
// Verify PowerShell cd hook
784+
assert!(
785+
ps1_content.contains("__vp_last_dir"),
786+
"env.ps1 should contain __vp_last_dir for directory change detection"
787+
);
788+
assert!(
789+
ps1_content.contains("--silent-if-unchanged"),
790+
"env.ps1 should call vp env use --silent-if-unchanged"
791+
);
792+
}
793+
691794
#[tokio::test]
692795
async fn test_execute_env_only_creates_home_dir_and_env_files() {
693796
let temp_dir = TempDir::new().unwrap();

crates/vite_global_cli/src/commands/env/use.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ pub async fn execute(
9898
let resolved = config::resolve_version_alias(ver, &provider).await?;
9999
(resolved, format!("{ver}"))
100100
} else {
101-
let resolution = config::resolve_version(&cwd).await?;
101+
let resolution = config::resolve_version_from_project(&cwd).await?;
102102
let source = resolution.source.clone();
103103
(resolution.version, source)
104104
};
@@ -154,7 +154,7 @@ pub async fn execute(
154154
}
155155

156156
// Status message to stderr (visible to user)
157-
eprintln!("Using Node.js v{} (resolved from {})", resolved_version, source_desc);
157+
eprintln!("vp: Using Node.js v{} (from {})", resolved_version, source_desc);
158158

159159
Ok(ExitStatus::default())
160160
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
20.18.0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "command-env-use-silent-if-unchanged",
3+
"version": "1.0.0",
4+
"private": true
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
> vp env use --silent-if-unchanged # first call - should show message
2+
export VITE_PLUS_NODE_VERSION=20.18.0
3+
vp: Using Node.js v<semver> (from .node-version)
4+
5+
> VITE_PLUS_NODE_VERSION=20.18.0 vp env use --silent-if-unchanged # same version - should be silent
6+
export VITE_PLUS_NODE_VERSION=20.18.0
7+
8+
> VITE_PLUS_NODE_VERSION=22.0.0 vp env use --silent-if-unchanged # different version - should show message
9+
export VITE_PLUS_NODE_VERSION=20.18.0
10+
vp: Using Node.js v<semver> (from .node-version)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"env": {
3+
"VITE_PLUS_ENV_USE_EVAL_ENABLE": "1"
4+
},
5+
"ignoredPlatforms": ["win32"],
6+
"commands": [
7+
"vp env use --silent-if-unchanged # first call - should show message",
8+
"VITE_PLUS_NODE_VERSION=20.18.0 vp env use --silent-if-unchanged # same version - should be silent",
9+
"VITE_PLUS_NODE_VERSION=22.0.0 vp env use --silent-if-unchanged # different version - should show message"
10+
]
11+
}

packages/global/snap-tests/command-env-use/snap.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Options:
1414

1515
> vp env use 20.18.0 --no-install # should output export command to stdout
1616
export VITE_PLUS_NODE_VERSION=20.18.0
17-
Using Node.js v<semver> (resolved from <semver>)
17+
vp: Using Node.js v<semver> (from <semver>)
1818

1919
> vp env use --unset # should output unset command to stdout
2020
unset VITE_PLUS_NODE_VERSION

0 commit comments

Comments
 (0)