Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { readFileSync } from 'node:fs'
import { join } from 'node:path'

const mode = process.argv[2]
const expected = {
managed: {
env: 'export PNPM_CONFIG_RUNTIME=false',
'env.fish': 'set -gx PNPM_CONFIG_RUNTIME false',
'env.nu': '$env.PNPM_CONFIG_RUNTIME = "false"',
'env.ps1': '$env:PNPM_CONFIG_RUNTIME = "false"',
},
'system-first': {
env: 'unset PNPM_CONFIG_RUNTIME',
'env.fish': 'set -e PNPM_CONFIG_RUNTIME',
'env.nu': 'if ("PNPM_CONFIG_RUNTIME" in $env) { hide-env PNPM_CONFIG_RUNTIME }',
'env.ps1': 'Remove-Item Env:\\PNPM_CONFIG_RUNTIME -ErrorAction SilentlyContinue',
},
}[mode]

if (!expected)
throw new Error(`Unknown mode: ${mode}`)

for (const [file, line] of Object.entries(expected)) {
const setup = readFileSync(join(process.env.VP_HOME, file), 'utf8').split('\n').slice(0, 6)
if (!setup.includes(line))
throw new Error(`${file} does not configure pnpm for ${mode} mode`)
}

console.log(`All shell environments match ${mode} mode`)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { spawnSync } from 'node:child_process'

const script = [
'. "$VP_HOME/env"',
'[ "$PNPM_CONFIG_RUNTIME" = false ] || exit 1',
'vp env off >/dev/null || exit 1',
'[ -z "${PNPM_CONFIG_RUNTIME+x}" ] || exit 1',
'vp env on >/dev/null || exit 1',
'[ "$PNPM_CONFIG_RUNTIME" = false ] || exit 1',
'vp -C "$PWD" env off >/dev/null || exit 1',
'[ -z "${PNPM_CONFIG_RUNTIME+x}" ] || exit 1',
'vp "-C$PWD" env on >/dev/null || exit 1',
'[ "$PNPM_CONFIG_RUNTIME" = false ] || exit 1',
'vp "-C=$PWD" env off >/dev/null || exit 1',
'[ -z "${PNPM_CONFIG_RUNTIME+x}" ] || exit 1',
'vp env on >/dev/null || exit 1',
'[ "$PNPM_CONFIG_RUNTIME" = false ] || exit 1',
].join('\n')
const result = spawnSync('/bin/sh', ['-c', script], { env: process.env, encoding: 'utf8' })

if (result.status !== 0)
throw new Error(result.stderr || `shell exited with ${result.status}`)

console.log('Current shell follows Vite+ environment mode')
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[[case]]
name = "command_env_pnpm_runtime"
vp = "global"
steps = [
{ argv = ["node", "assert-env-files.mjs", "managed"], comment = "managed mode disables pnpm runtime management in every generated shell environment" },
{ argv = ["node", "-e", "const {execFileSync}=require('node:child_process');const text=execFileSync('vp',['env','doctor'],{encoding:'utf8',env:{...process.env,PNPM_CONFIG_RUNTIME:'false'}}).replace(/\\u001b\\[[0-9;]*m/g,'');const line=text.split('\\n').find(line=>line.includes('pnpm runtime'));if(!line)process.exit(1);console.log(line.trim());"], comment = "doctor reports the managed-mode pnpm runtime setting" },
{ argv = ["vp", "env", "off"], snapshot = false },
{ argv = ["node", "assert-env-files.mjs", "system-first"], comment = "system-first mode removes the setting from every generated shell environment" },
{ argv = ["node", "-e", "const {execFileSync}=require('node:child_process');const text=execFileSync('vp',['env','doctor'],{encoding:'utf8'}).replace(/\\u001b\\[[0-9;]*m/g,'');const line=text.split('\\n').find(line=>line.includes('pnpm runtime'));if(!line)process.exit(1);console.log(line.trim());"], comment = "doctor reports the system-first pnpm runtime setting" },
{ argv = ["vp", "env", "on"], snapshot = false },
{ argv = ["node", "assert-env-files.mjs", "managed"], comment = "managed mode restores the setting" },
]

[[case]]
name = "command_env_pnpm_runtime_current_shell"
vp = "global"
skip-platforms = ["windows"]
steps = [
{ argv = ["node", "assert-posix-wrapper.mjs"], comment = "vp env on and off update the current shell, including through the global -C flag" },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# command_env_pnpm_runtime

## `node assert-env-files.mjs managed`

managed mode disables pnpm runtime management in every generated shell environment

```
All shell environments match managed mode
```

## `node -e 'const {execFileSync}=require('\''node:child_process'\'');const text=execFileSync('\''vp'\'',['\''env'\'','\''doctor'\''],{encoding:'\''utf8'\'',env:{...process.env,PNPM_CONFIG_RUNTIME:'\''false'\''}}).replace(/\u001b\[[0-9;]*m/g,'\'''\'');const line=text.split('\''\n'\'').find(line=>line.includes('\''pnpm runtime'\''));if('\!'line)process.exit(1);console.log(line.trim());'`

doctor reports the managed-mode pnpm runtime setting

```
✓ pnpm runtime PNPM_CONFIG_RUNTIME=false
```

## `vp env off`


## `node assert-env-files.mjs system-first`

system-first mode removes the setting from every generated shell environment

```
All shell environments match system-first mode
```

## `node -e 'const {execFileSync}=require('\''node:child_process'\'');const text=execFileSync('\''vp'\'',['\''env'\'','\''doctor'\''],{encoding:'\''utf8'\''}).replace(/\u001b\[[0-9;]*m/g,'\'''\'');const line=text.split('\''\n'\'').find(line=>line.includes('\''pnpm runtime'\''));if('\!'line)process.exit(1);console.log(line.trim());'`

doctor reports the system-first pnpm runtime setting

```
✓ pnpm runtime PNPM_CONFIG_RUNTIME unset
```

## `vp env on`


## `node assert-env-files.mjs managed`

managed mode restores the setting

```
All shell environments match managed mode
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# command_env_pnpm_runtime_current_shell

## `node assert-posix-wrapper.mjs`

vp env on and off update the current shell, including through the global -C flag

```
Current shell follows Vite+ environment mode
```
48 changes: 45 additions & 3 deletions crates/vp_global_cli/src/commands/env/doctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ use owo_colors::OwoColorize;
use vp_shared::{env_vars, output};
use vt_path::{AbsolutePathBuf, current_dir};

use super::config::{self, ShimMode, get_bin_dir, get_vp_home, load_config, resolve_version};
use super::{
PNPM_CONFIG_RUNTIME,
config::{self, ShimMode, get_bin_dir, get_vp_home, load_config, resolve_version},
setup::SHIM_TOOLS,
};
use crate::{
commands::shell::{ALL_SHELL_PROFILES, IDE_SHELL_PROFILES, ShellProfile, resolve_profile_path},
error::Error,
Expand All @@ -33,8 +37,6 @@ const KNOWN_VERSION_MANAGERS: &[(&str, &str)] = &[
("n", "N_PREFIX"),
];

use super::setup::SHIM_TOOLS;

/// Column width for left-side keys in aligned output
const KEY_WIDTH: usize = 18;

Expand Down Expand Up @@ -85,6 +87,7 @@ pub async fn execute(cwd: AbsolutePathBuf) -> Result<ExitStatus, Error> {
// Section: Configuration
print_section("Configuration");
let (shim_mode, system_node_path) = check_shim_mode().await;
check_pnpm_runtime(shim_mode);

// Check env sourcing: IDE-relevant profiles first, then all shell profiles
let env_status = cfg!(not(windows)).then(check_env_sourcing);
Expand Down Expand Up @@ -260,6 +263,45 @@ async fn check_shim_mode() -> (ShimMode, Option<AbsolutePathBuf>) {
(config.shim_mode, system_node_path)
}

fn check_pnpm_runtime(shim_mode: ShimMode) {
let value =
std::env::var_os(PNPM_CONFIG_RUNTIME).map(|value| value.to_string_lossy().into_owned());

match (shim_mode, value.as_deref()) {
(ShimMode::Managed, Some(value)) if value.eq_ignore_ascii_case("false") => {
print_check(
&output::CHECK.green().to_string(),
"pnpm runtime",
&format!("{PNPM_CONFIG_RUNTIME}={value}"),
);
}
(ShimMode::SystemFirst, None) => {
print_check(
&output::CHECK.green().to_string(),
"pnpm runtime",
&format!("{PNPM_CONFIG_RUNTIME} unset"),
);
}
(ShimMode::Managed, value) => {
let value = value.unwrap_or("unset");
print_check(
&output::WARN_SIGN.yellow().to_string(),
"pnpm runtime",
&format!("{PNPM_CONFIG_RUNTIME}={value} (expected false)").yellow().to_string(),
);
print_hint("Re-source the Vite+ environment file or restart your shell.");
}
(ShimMode::SystemFirst, Some(value)) => {
print_check(
&output::WARN_SIGN.yellow().to_string(),
"pnpm runtime",
&format!("{PNPM_CONFIG_RUNTIME}={value} (expected unset)").yellow().to_string(),
);
print_hint("Re-source the Vite+ environment file or restart your shell.");
}
}
}

/// Check profile files for env sourcing and classify where it was found.
///
/// Tries IDE-relevant profiles first, then falls back to all shell profiles.
Expand Down
2 changes: 2 additions & 0 deletions crates/vp_global_cli/src/commands/env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ use crate::{
error::Error,
};

const PNPM_CONFIG_RUNTIME: &str = "PNPM_CONFIG_RUNTIME";

fn print_env_header() {
vp_shared::header::print_header();
}
Expand Down
7 changes: 6 additions & 1 deletion crates/vp_global_cli/src/commands/env/off.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@

use std::process::ExitStatus;

use super::config::{ShimMode, load_config, save_config};
use super::{
config::{ShimMode, load_config, save_config},
setup,
};
use crate::{error::Error, help};

/// Execute the `vp env off` command.
pub async fn execute() -> Result<ExitStatus, Error> {
let mut config = load_config().await?;

if config.shim_mode == ShimMode::SystemFirst {
setup::refresh_env_files().await?;
println!("Node.js management is already set to system-first.");
println!(
"All vp commands and shims will prefer system Node.js, falling back to managed if not found."
Expand All @@ -22,6 +26,7 @@ pub async fn execute() -> Result<ExitStatus, Error> {

config.shim_mode = ShimMode::SystemFirst;
save_config(&config).await?;
setup::refresh_env_files().await?;

println!("\u{2713} Node.js management set to system-first.");
println!();
Expand Down
7 changes: 6 additions & 1 deletion crates/vp_global_cli/src/commands/env/on.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@

use std::process::ExitStatus;

use super::config::{ShimMode, load_config, save_config};
use super::{
config::{ShimMode, load_config, save_config},
setup,
};
use crate::{error::Error, help};

/// Execute the `vp env on` command.
pub async fn execute() -> Result<ExitStatus, Error> {
let mut config = load_config().await?;

if config.shim_mode == ShimMode::Managed {
setup::refresh_env_files().await?;
println!("Node.js management is already set to managed.");
println!("All vp commands and shims will always use Vite+ managed Node.js.");
return Ok(ExitStatus::default());
}

config.shim_mode = ShimMode::Managed;
save_config(&config).await?;
setup::refresh_env_files().await?;

println!("\u{2713} Node.js management set to managed.");
println!();
Expand Down
Loading
Loading