summaryrefslogtreecommitdiff
path: root/cli/args
diff options
context:
space:
mode:
Diffstat (limited to 'cli/args')
-rw-r--r--cli/args/flags.rs70
-rw-r--r--cli/args/mod.rs7
2 files changed, 73 insertions, 4 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 0e4621d67..b3fe61abd 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -395,6 +395,7 @@ pub struct Flags {
pub ext: Option<String>,
pub ignore: Vec<PathBuf>,
pub import_map_path: Option<String>,
+ pub env_file: Option<String>,
pub inspect_brk: Option<SocketAddr>,
pub inspect_wait: Option<SocketAddr>,
pub inspect: Option<SocketAddr>,
@@ -1030,6 +1031,7 @@ glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}:
.arg(watch_arg(false))
.arg(no_clear_screen_arg())
.arg(script_arg().last(true))
+ .arg(env_file_arg())
})
}
@@ -1191,6 +1193,7 @@ supported in canary.
.action(ArgAction::SetTrue),
)
.arg(executable_ext_arg())
+ .arg(env_file_arg())
.arg(script_arg().required(true).trailing_var_arg(true))
})
}
@@ -1434,6 +1437,7 @@ This command has implicit access to all permissions (--allow-all).",
.value_name("CODE_ARG")
.required(true),
)
+ .arg(env_file_arg())
})
}
@@ -1667,6 +1671,7 @@ These must be added to the path manually if required.")
.help("Forcefully overwrite existing installation")
.action(ArgAction::SetTrue))
)
+ .arg(env_file_arg())
}
fn jupyter_subcommand() -> Command {
@@ -1868,6 +1873,7 @@ fn repl_subcommand() -> Command {
.help("Evaluates the provided code when the REPL starts.")
.value_name("code"),
))
+ .arg(env_file_arg())
}
fn run_subcommand() -> Command {
@@ -1882,6 +1888,7 @@ fn run_subcommand() -> Command {
.required_unless_present("v8-flags")
.trailing_var_arg(true),
)
+ .arg(env_file_arg())
.about("Run a JavaScript or TypeScript program")
.long_about(
"Run a JavaScript or TypeScript program
@@ -2063,6 +2070,7 @@ Directory arguments are expanded to all contained files matching the glob
.help("Select reporter to use. Default to 'pretty'.")
.value_parser(["pretty", "dot", "junit", "tap"])
)
+ .arg(env_file_arg())
)
}
@@ -2643,6 +2651,18 @@ fn import_map_arg() -> Arg {
.value_hint(ValueHint::FilePath)
}
+fn env_file_arg() -> Arg {
+ Arg::new("env")
+ .long("env")
+ .value_name("FILE")
+ .help("Load .env file")
+ .long_help("UNSTABLE: Load environment variables from local file. Only the first environment variable with a given key is used. Existing process environment variables are not overwritten.")
+ .value_hint(ValueHint::FilePath)
+ .default_missing_value(".env")
+ .require_equals(true)
+ .num_args(0..=1)
+}
+
fn reload_arg() -> Arg {
Arg::new("reload")
.short('r')
@@ -3708,6 +3728,7 @@ fn runtime_args_parse(
v8_flags_arg_parse(flags, matches);
seed_arg_parse(flags, matches);
enable_testing_features_arg_parse(flags, matches);
+ env_file_arg_parse(flags, matches);
}
fn inspect_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
@@ -3745,6 +3766,10 @@ fn import_map_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
flags.import_map_path = matches.remove_one::<String>("import-map");
}
+fn env_file_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
+ flags.env_file = matches.remove_one::<String>("env");
+}
+
fn reload_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
if let Some(cache_bl) = matches.remove_many::<String>("reload") {
let raw_cache_blocklist: Vec<String> = cache_bl.collect();
@@ -5175,7 +5200,7 @@ mod tests {
#[test]
fn eval_with_flags() {
#[rustfmt::skip]
- let r = flags_from_vec(svec!["deno", "eval", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "42"]);
+ let r = flags_from_vec(svec!["deno", "eval", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--env=.example.env", "42"]);
assert_eq!(
r.unwrap(),
Flags {
@@ -5204,6 +5229,7 @@ mod tests {
allow_write: Some(vec![]),
allow_ffi: Some(vec![]),
allow_hrtime: true,
+ env_file: Some(".example.env".to_owned()),
..Flags::default()
}
);
@@ -5273,7 +5299,7 @@ mod tests {
#[test]
fn repl_with_flags() {
#[rustfmt::skip]
- let r = flags_from_vec(svec!["deno", "repl", "-A", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors"]);
+ let r = flags_from_vec(svec!["deno", "repl", "-A", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors", "--env=.example.env"]);
assert_eq!(
r.unwrap(),
Flags {
@@ -5304,6 +5330,7 @@ mod tests {
allow_write: Some(vec![]),
allow_ffi: Some(vec![]),
allow_hrtime: true,
+ env_file: Some(".example.env".to_owned()),
unsafely_ignore_certificate_errors: Some(vec![]),
..Flags::default()
}
@@ -6068,6 +6095,39 @@ mod tests {
}
#[test]
+ fn run_env_file_default() {
+ let r = flags_from_vec(svec!["deno", "run", "--env", "script.ts"]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Run(RunFlags {
+ script: "script.ts".to_string(),
+ watch: Default::default(),
+ }),
+ env_file: Some(".env".to_owned()),
+ ..Flags::default()
+ }
+ );
+ }
+
+ #[test]
+ fn run_env_file_defined() {
+ let r =
+ flags_from_vec(svec!["deno", "run", "--env=.another_env", "script.ts"]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Run(RunFlags {
+ script: "script.ts".to_string(),
+ watch: Default::default(),
+ }),
+ env_file: Some(".another_env".to_owned()),
+ ..Flags::default()
+ }
+ );
+ }
+
+ #[test]
fn cache_multiple() {
let r =
flags_from_vec(svec!["deno", "cache", "script.ts", "script_two.ts"]);
@@ -6148,7 +6208,7 @@ mod tests {
#[test]
fn install_with_flags() {
#[rustfmt::skip]
- let r = flags_from_vec(svec!["deno", "install", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--name", "file_server", "--root", "/foo", "--force", "https://deno.land/std/http/file_server.ts", "foo", "bar"]);
+ let r = flags_from_vec(svec!["deno", "install", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--name", "file_server", "--root", "/foo", "--force", "--env=.example.env", "https://deno.land/std/http/file_server.ts", "foo", "bar"]);
assert_eq!(
r.unwrap(),
Flags {
@@ -6174,6 +6234,7 @@ mod tests {
allow_net: Some(vec![]),
unsafely_ignore_certificate_errors: Some(vec![]),
allow_read: Some(vec![]),
+ env_file: Some(".example.env".to_owned()),
..Flags::default()
}
);
@@ -7557,7 +7618,7 @@ mod tests {
#[test]
fn compile_with_flags() {
#[rustfmt::skip]
- let r = flags_from_vec(svec!["deno", "compile", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--no-terminal", "--output", "colors", "https://deno.land/std/examples/colors.ts", "foo", "bar", "-p", "8080"]);
+ let r = flags_from_vec(svec!["deno", "compile", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--no-terminal", "--output", "colors", "--env=.example.env", "https://deno.land/std/examples/colors.ts", "foo", "bar", "-p", "8080"]);
assert_eq!(
r.unwrap(),
Flags {
@@ -7584,6 +7645,7 @@ mod tests {
allow_net: Some(vec![]),
v8_flags: svec!["--help", "--random-seed=1"],
seed: Some(1),
+ env_file: Some(".example.env".to_owned()),
..Flags::default()
}
);
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 94eaf2a3e..b8b0a81f5 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -52,6 +52,7 @@ use deno_runtime::deno_tls::rustls_pemfile;
use deno_runtime::deno_tls::webpki_roots;
use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::permissions::PermissionsOptions;
+use dotenvy::from_filename;
use once_cell::sync::Lazy;
use once_cell::sync::OnceCell;
use serde::Deserialize;
@@ -651,6 +652,12 @@ impl CliOptions {
let maybe_vendor_folder =
resolve_vendor_folder(&initial_cwd, &flags, maybe_config_file.as_ref());
+ if let Some(env_file_name) = &flags.env_file {
+ if (from_filename(env_file_name)).is_err() {
+ bail!("Unable to load '{env_file_name}' environment variable file")
+ }
+ }
+
Ok(Self {
flags,
initial_cwd,