Skip to content

Commit 43b1c85

Browse files
authored
refactor: replace dotenvy with deno_dotenv (#32263)
1 parent 1c5a718 commit 43b1c85

File tree

22 files changed

+116
-40
lines changed

22 files changed

+116
-40
lines changed

Cargo.lock

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ comrak = "0.29.0"
184184
dashmap = "5.5.3"
185185
data-encoding = "2.3.3"
186186
data-url = "=0.3.1"
187-
dotenvy = "0.15.7"
188187
dyn-clone = "1"
189188
encoding_rs = "=0.8.35"
190189
error_reporter = "1"

cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ comrak.workspace = true
108108
console_static_text.workspace = true
109109
crossterm.workspace = true
110110
dashmap.workspace = true
111+
deno_dotenv.workspace = true
111112
dhat = { workspace = true, optional = true }
112113
dissimilar.workspace = true
113-
dotenvy.workspace = true
114114
dprint-core.workspace = true
115115
dprint-plugin-json.workspace = true
116116
dprint-plugin-jupyter.workspace = true

cli/standalone/binary.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,9 +1257,9 @@ fn get_dev_binary_path() -> Option<OsString> {
12571257
/// in the passed environment file.
12581258
fn get_file_env_vars(
12591259
filename: String,
1260-
) -> Result<IndexMap<String, String>, dotenvy::Error> {
1260+
) -> Result<IndexMap<String, String>, deno_dotenv::Error> {
12611261
let mut file_env_vars = IndexMap::new();
1262-
for item in dotenvy::from_filename_iter(filename)? {
1262+
for item in deno_dotenv::from_path_sanitized_iter(filename)? {
12631263
let Ok((key, val)) = item else {
12641264
continue; // this failure will be warned about on load
12651265
};

cli/util/watch_env_tracker.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,36 +52,34 @@ impl WatchEnvTracker {
5252
}
5353

5454
// Consolidated error handling function
55-
fn handle_dotenvy_error(
56-
error: dotenvy::Error,
55+
fn handle_dotenv_error(
56+
error: deno_dotenv::Error,
5757
file_path: &Path,
5858
log_level: Option<log::Level>,
5959
) {
6060
#[allow(clippy::print_stderr)]
6161
if log_level.map(|l| l >= log::Level::Info).unwrap_or(true) {
6262
match error {
63-
dotenvy::Error::LineParse(line, index) => eprintln!(
63+
deno_dotenv::Error::LineParse(line, index) => eprintln!(
6464
"{} Parsing failed within the specified environment file: {} at index: {} of the value: {}",
6565
colors::yellow("Warning"),
6666
file_path.display(),
6767
index,
6868
line
6969
),
70-
dotenvy::Error::Io(_) => eprintln!(
71-
"{} The `--env-file` flag was used, but the environment file specified '{}' was not found.",
72-
colors::yellow("Warning"),
73-
file_path.display()
74-
),
75-
dotenvy::Error::EnvVar(_) => eprintln!(
76-
"{} One or more of the environment variables isn't present or not unicode within the specified environment file: {}",
77-
colors::yellow("Warning"),
78-
file_path.display()
79-
),
80-
_ => eprintln!(
81-
"{} Unknown failure occurred with the specified environment file: {}",
82-
colors::yellow("Warning"),
83-
file_path.display()
84-
),
70+
deno_dotenv::Error::Io(e) => match e.kind() {
71+
std::io::ErrorKind::NotFound => eprintln!(
72+
"{} The `--env-file` flag was used, but the environment file specified '{}' was not found.",
73+
colors::yellow("Warning"),
74+
file_path.display(),
75+
),
76+
_ => eprintln!(
77+
"{} Error reading from environment file '{}': {}.",
78+
colors::yellow("Warning"),
79+
file_path.display(),
80+
e,
81+
),
82+
},
8583
}
8684
}
8785
}
@@ -107,7 +105,7 @@ impl WatchEnvTracker {
107105
return;
108106
}
109107

110-
match dotenvy::from_path_iter(&file_path) {
108+
match deno_dotenv::from_path_sanitized_iter(&file_path) {
111109
Ok(iter) => {
112110
for item in iter {
113111
match item {
@@ -148,7 +146,7 @@ impl WatchEnvTracker {
148146
inner.unused_variables.remove(&key_os);
149147
}
150148
Err(e) => {
151-
Self::handle_dotenvy_error(e, &file_path, log_level);
149+
Self::handle_dotenv_error(e, &file_path, log_level);
152150
}
153151
}
154152
}
@@ -244,10 +242,10 @@ pub fn load_env_variables_from_env_files(
244242
};
245243

246244
for env_file_name in env_file_names.iter().rev() {
247-
match dotenvy::from_filename(env_file_name) {
245+
match deno_dotenv::from_path(env_file_name) {
248246
Ok(_) => (),
249247
Err(error) => {
250-
WatchEnvTracker::handle_dotenvy_error(
248+
WatchEnvTracker::handle_dotenv_error(
251249
error,
252250
env_file_name,
253251
flags_log_level,

libs/dotenv/lib.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2018-2026 the Deno authors. MIT license.
22

33
use std::borrow::Cow;
4+
use std::path::Path;
45

56
const CHAR_NL: u8 = b'\n';
67
const CHAR_CR: u8 = b'\r';
@@ -14,6 +15,38 @@ const CHAR_BQUOTE: u8 = b'`';
1415
const CHAR_BSLASH: u8 = b'\\';
1516
const CHAR_N: u8 = b'n';
1617

18+
#[derive(Debug)]
19+
pub enum Error {
20+
LineParse(String, usize),
21+
Io(std::io::Error),
22+
}
23+
24+
impl std::fmt::Display for Error {
25+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26+
match self {
27+
Error::LineParse(line, index) => {
28+
write!(f, "Error parsing line at index {}: {}", index, line)
29+
}
30+
Error::Io(err) => write!(f, "{}", err),
31+
}
32+
}
33+
}
34+
35+
impl std::error::Error for Error {
36+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
37+
match self {
38+
Error::Io(err) => Some(err),
39+
_ => None,
40+
}
41+
}
42+
}
43+
44+
impl From<std::io::Error> for Error {
45+
fn from(err: std::io::Error) -> Self {
46+
Error::Io(err)
47+
}
48+
}
49+
1750
/// Ported from:
1851
/// https://github.com/nodejs/node/blob/9cc7fcc26dece769d9ffa06c453f0171311b01f8/src/node_dotenv.cc#L138-L315
1952
pub fn parse_env_content_hook(content: &str, mut cb: impl FnMut(&str, &str)) {
@@ -244,6 +277,37 @@ pub fn parse_env_content_hook(content: &str, mut cb: impl FnMut(&str, &str)) {
244277
}
245278
}
246279

280+
type IterElement = Result<(String, String), Error>;
281+
282+
pub fn from_path_sanitized_iter(
283+
path: impl AsRef<Path>,
284+
) -> Result<std::vec::IntoIter<IterElement>, Error> {
285+
let content = std::fs::read_to_string(path.as_ref()).map_err(Error::Io)?;
286+
let mut pairs = Vec::new();
287+
parse_env_content_hook(&content, |k, v| {
288+
if let Some(index) = k
289+
.find('\0')
290+
.or_else(|| v.find('\0').map(|i| k.len() + i + 1))
291+
{
292+
pairs.push(Err(Error::LineParse(format!("{}={}", k, v), index)));
293+
} else {
294+
pairs.push(Ok((k.to_string(), v.to_string())));
295+
}
296+
});
297+
Ok(pairs.into_iter())
298+
}
299+
300+
pub fn from_path(filename: impl AsRef<Path>) -> Result<(), Error> {
301+
for item in from_path_sanitized_iter(filename)? {
302+
let (key, val) = item?;
303+
#[allow(clippy::undocumented_unsafe_blocks)]
304+
unsafe {
305+
std::env::set_var(&key, &val);
306+
}
307+
}
308+
Ok(())
309+
}
310+
247311
fn trim_spaces_slice(input: &[u8]) -> &[u8] {
248312
if input.is_empty() {
249313
return input;

tests/specs/compile/env_vars_support/compile.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Warning Parsing failed within the specified environment file: environment.env at index: 3 of the value: c:\path
1+
Warning Parsing failed within the specified environment file: environment.env at index: 14 of the value: ANOTHER_FOO=c:ath
22
Check [WILDCARD]main.ts
33
Compile [WILDCARD]main.ts to out[WILDCARD]
44
Warning Environment variables from the file "environment.env" were embedded in the generated executable file
-1 Bytes
Binary file not shown.

tests/specs/eval/env_file/main.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ANOTHER_BAR
1+
ANOTHER_${FOO}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"args": "eval --env-file=invalid_utf8_env console.log(Deno.env.get(\"BAR\"))",
3+
"output": "main.out"
4+
}

0 commit comments

Comments
 (0)