diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c112e27..23d77818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +- **Fixed** Missing env vars requested through `@voidzero-dev/vite-task-client` now return `undefined` instead of `null`, preserving Vite production `NODE_ENV` semantics when builds run through `vp run` ([#508](https://github.com/voidzero-dev/vite-task/pull/508)). - **Fixed** Windows builds no longer hang on CI when a `node_modules/.bin` `.cmd` shim is routed through PowerShell: the npm/pnpm/yarn `.ps1` wrappers read stdin and block forever on a non-TTY pipe, so the PowerShell rewrite is now skipped when stdin is not an interactive terminal, falling back to the `.cmd` (which never reads stdin) ([#491](https://github.com/voidzero-dev/vite-task/pull/491)). - **Added** First-party support for caching `vite build` with zero cache config, giving Vite projects correct cache hits out of the box ([vitejs/vite#22453](https://github.com/vitejs/vite/pull/22453)). - **Added** Support for specifying tasks from dependency packages in `dependsOn`, such as `dependsOn: [{ "task": "build", "from": "dependencies" }]` ([#479](https://github.com/voidzero-dev/vite-task/pull/479)). diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/scripts/assert_undefined_env.mjs b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/scripts/assert_undefined_env.mjs new file mode 100644 index 00000000..c1549ae8 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/scripts/assert_undefined_env.mjs @@ -0,0 +1,10 @@ +import { getEnv } from '@voidzero-dev/vite-task-client'; + +const name = '__VITE_TASK_CLIENT_MISSING_ENV__'; +const value = getEnv(name); + +if (value !== undefined) { + throw new Error(`expected ${name} to be undefined, got ${value}`); +} + +console.log('missing undefined'); diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots.toml b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots.toml index 7d27979a..64f809c2 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots.toml +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots.toml @@ -276,6 +276,20 @@ steps = [ ], comment = "summary reports the replayed cache hit" }, ] +[[e2e]] +name = "fetch_env_missing_returns_undefined" +comment = """ +Exercises the public `getEnv(name)` contract for an absent env var. The client API must expose `undefined` so callers can distinguish absence using the documented API. +""" +ignore = true +steps = [ + { argv = [ + "vt", + "run", + "fetch-missing-env", + ], comment = "missing env values are normalized to undefined" }, +] + [[e2e]] name = "fetch_env_reads_undeclared_env" comment = """ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots/fetch_env_missing_returns_undefined.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots/fetch_env_missing_returns_undefined.md new file mode 100644 index 00000000..ef6d4c5f --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots/fetch_env_missing_returns_undefined.md @@ -0,0 +1,12 @@ +# fetch_env_missing_returns_undefined + +Exercises the public `getEnv(name)` contract for an absent env var. The client API must expose `undefined` so callers can distinguish absence using the documented API. + +## `vt run fetch-missing-env` + +missing env values are normalized to undefined + +``` +$ node scripts/assert_undefined_env.mjs +missing undefined +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/vite-task.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/vite-task.json index dbbdfeb7..4f00c3ce 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/vite-task.json +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/vite-task.json @@ -58,6 +58,10 @@ "command": "node scripts/fetch_env.mjs PROBE_ENV", "cache": true }, + "fetch-missing-env": { + "command": "node scripts/assert_undefined_env.mjs", + "cache": true + }, "fetch-env-explicit-input": { "command": "node scripts/fetch_env.mjs PROBE_ENV", "input": [], diff --git a/crates/vite_task_client_napi/src/lib.rs b/crates/vite_task_client_napi/src/lib.rs index 81f4a005..72e170c3 100644 --- a/crates/vite_task_client_napi/src/lib.rs +++ b/crates/vite_task_client_napi/src/lib.rs @@ -30,7 +30,7 @@ )] use std::{collections::HashMap, ffi::OsStr}; -use napi::{Either, Error, Result}; +use napi::{Either, Error, Result, bindgen_prelude::Undefined}; use napi_derive::napi; use vite_task_client::{Client, GetEnvsQuery}; @@ -85,17 +85,24 @@ impl RunnerClient { } #[napi] - pub fn get_env(&self, name: String, options: Option) -> Result> { + pub fn get_env( + &self, + name: String, + options: Option, + ) -> Result> { let tracked = options.and_then(|o| o.tracked).unwrap_or(true); let value = self .client .get_env(OsStr::new(&name), tracked) .map_err(|err| err_string(vite_str::format!("{err}")))?; - value.map_or(Ok(None), |value| { - value.to_str().map(|s| Some(s.to_owned())).ok_or_else(|| { - err_string(vite_str::format!("env value for {name} is not valid UTF-8")) + let value = value + .map(|value| { + value.to_str().map(str::to_owned).ok_or_else(|| { + err_string(vite_str::format!("env value for {name} is not valid UTF-8")) + }) }) - }) + .transpose()?; + Ok(value.into()) } #[napi]