Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)).
Expand Down
Original file line number Diff line number Diff line change
@@ -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');
Original file line number Diff line number Diff line change
Expand Up @@ -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 = """
Expand Down
Original file line number Diff line number Diff line change
@@ -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
```
Original file line number Diff line number Diff line change
Expand Up @@ -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": [],
Expand Down
19 changes: 13 additions & 6 deletions crates/vite_task_client_napi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -85,17 +85,24 @@ impl RunnerClient {
}

#[napi]
pub fn get_env(&self, name: String, options: Option<GetEnvOptions>) -> Result<Option<String>> {
pub fn get_env(
&self,
name: String,
options: Option<GetEnvOptions>,
) -> Result<Either<String, Undefined>> {
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]
Expand Down
Loading