1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -05:00

feat: add --no-npm flag to disable npm: imports (#15673)

This commit adds "--no-npm" flag, it's similar to "--no-remote"
flag. This flag makes Deno error out if "npm:" specifier is encountered.
This commit is contained in:
Bartek Iwańczuk 2022-09-07 15:33:51 +02:00 committed by GitHub
parent 3b1204eb2d
commit 4a250b2f25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 144 additions and 2 deletions

View file

@ -312,6 +312,7 @@ pub struct Flags {
pub lock: Option<PathBuf>, pub lock: Option<PathBuf>,
pub log_level: Option<Level>, pub log_level: Option<Level>,
pub no_remote: bool, pub no_remote: bool,
pub no_npm: bool,
pub no_prompt: bool, pub no_prompt: bool,
pub reload: bool, pub reload: bool,
pub seed: Option<u64>, pub seed: Option<u64>,
@ -1732,6 +1733,7 @@ fn compile_args(app: Command) -> Command {
app app
.arg(import_map_arg()) .arg(import_map_arg())
.arg(no_remote_arg()) .arg(no_remote_arg())
.arg(no_npm_arg())
.arg(no_config_arg()) .arg(no_config_arg())
.arg(config_arg()) .arg(config_arg())
.arg(no_check_arg()) .arg(no_check_arg())
@ -1746,6 +1748,7 @@ fn compile_args_without_check_args(app: Command) -> Command {
app app
.arg(import_map_arg()) .arg(import_map_arg())
.arg(no_remote_arg()) .arg(no_remote_arg())
.arg(no_npm_arg())
.arg(config_arg()) .arg(config_arg())
.arg(no_config_arg()) .arg(no_config_arg())
.arg(reload_arg()) .arg(reload_arg())
@ -2140,6 +2143,12 @@ fn no_remote_arg<'a>() -> Arg<'a> {
.help("Do not resolve remote modules") .help("Do not resolve remote modules")
} }
fn no_npm_arg<'a>() -> Arg<'a> {
Arg::new("no-npm")
.long("no-npm")
.help("Do not resolve npm modules")
}
fn unsafely_ignore_certificate_errors_arg<'a>() -> Arg<'a> { fn unsafely_ignore_certificate_errors_arg<'a>() -> Arg<'a> {
Arg::new("unsafely-ignore-certificate-errors") Arg::new("unsafely-ignore-certificate-errors")
.long("unsafely-ignore-certificate-errors") .long("unsafely-ignore-certificate-errors")
@ -2785,6 +2794,7 @@ fn vendor_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
fn compile_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { fn compile_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
import_map_arg_parse(flags, matches); import_map_arg_parse(flags, matches);
no_remote_arg_parse(flags, matches); no_remote_arg_parse(flags, matches);
no_npm_arg_parse(flags, matches);
config_args_parse(flags, matches); config_args_parse(flags, matches);
no_check_arg_parse(flags, matches); no_check_arg_parse(flags, matches);
check_arg_parse(flags, matches); check_arg_parse(flags, matches);
@ -2799,6 +2809,7 @@ fn compile_args_without_no_check_parse(
) { ) {
import_map_arg_parse(flags, matches); import_map_arg_parse(flags, matches);
no_remote_arg_parse(flags, matches); no_remote_arg_parse(flags, matches);
no_npm_arg_parse(flags, matches);
config_args_parse(flags, matches); config_args_parse(flags, matches);
reload_arg_parse(flags, matches); reload_arg_parse(flags, matches);
lock_args_parse(flags, matches); lock_args_parse(flags, matches);
@ -3040,6 +3051,12 @@ fn no_remote_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
} }
} }
fn no_npm_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
if matches.is_present("no-npm") {
flags.no_npm = true;
}
}
fn inspect_arg_validate(val: &str) -> Result<(), String> { fn inspect_arg_validate(val: &str) -> Result<(), String> {
match val.parse::<SocketAddr>() { match val.parse::<SocketAddr>() {
Ok(_) => Ok(()), Ok(_) => Ok(()),
@ -4998,6 +5015,21 @@ mod tests {
); );
} }
#[test]
fn no_npm() {
let r = flags_from_vec(svec!["deno", "run", "--no-npm", "script.ts"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Run(RunFlags {
script: "script.ts".to_string(),
}),
no_npm: true,
..Flags::default()
}
);
}
#[test] #[test]
fn cached_only() { fn cached_only() {
let r = flags_from_vec(svec!["deno", "run", "--cached-only", "script.ts"]); let r = flags_from_vec(svec!["deno", "run", "--cached-only", "script.ts"]);

View file

@ -331,6 +331,10 @@ impl CliOptions {
self.flags.no_remote self.flags.no_remote
} }
pub fn no_npm(&self) -> bool {
self.flags.no_npm
}
pub fn permissions_options(&self) -> PermissionsOptions { pub fn permissions_options(&self) -> PermissionsOptions {
self.flags.permissions_options() self.flags.permissions_options()
} }

View file

@ -14,8 +14,8 @@ use std::sync::Arc;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail; use deno_core::anyhow::bail;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::custom_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures; use deno_core::futures;
use deno_core::url::Url; use deno_core::url::Url;
use deno_runtime::deno_node::DenoDirNpmResolver; use deno_runtime::deno_node::DenoDirNpmResolver;
@ -77,6 +77,7 @@ pub struct GlobalNpmPackageResolver {
resolution: Arc<NpmResolution>, resolution: Arc<NpmResolution>,
registry_url: Url, registry_url: Url,
unstable: bool, unstable: bool,
no_npm: bool,
} }
impl GlobalNpmPackageResolver { impl GlobalNpmPackageResolver {
@ -85,12 +86,14 @@ impl GlobalNpmPackageResolver {
reload: bool, reload: bool,
cache_setting: CacheSetting, cache_setting: CacheSetting,
unstable: bool, unstable: bool,
no_npm: bool,
) -> Self { ) -> Self {
Self::from_cache( Self::from_cache(
NpmCache::from_deno_dir(dir, cache_setting.clone()), NpmCache::from_deno_dir(dir, cache_setting.clone()),
reload, reload,
cache_setting, cache_setting,
unstable, unstable,
no_npm,
) )
} }
@ -99,6 +102,7 @@ impl GlobalNpmPackageResolver {
reload: bool, reload: bool,
cache_setting: CacheSetting, cache_setting: CacheSetting,
unstable: bool, unstable: bool,
no_npm: bool,
) -> Self { ) -> Self {
let api = NpmRegistryApi::new(cache.clone(), reload, cache_setting); let api = NpmRegistryApi::new(cache.clone(), reload, cache_setting);
let registry_url = api.base_url().to_owned(); let registry_url = api.base_url().to_owned();
@ -109,6 +113,7 @@ impl GlobalNpmPackageResolver {
resolution, resolution,
registry_url, registry_url,
unstable, unstable,
no_npm,
} }
} }
@ -122,11 +127,28 @@ impl GlobalNpmPackageResolver {
&self, &self,
packages: Vec<NpmPackageReq>, packages: Vec<NpmPackageReq>,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
if !self.unstable && !packages.is_empty() { assert!(!packages.is_empty());
if !self.unstable {
bail!( bail!(
"Unstable use of npm specifiers. The --unstable flag must be provided." "Unstable use of npm specifiers. The --unstable flag must be provided."
) )
} }
if self.no_npm {
let fmt_reqs = packages
.iter()
.map(|p| format!("\"{}\"", p))
.collect::<Vec<_>>()
.join(", ");
return Err(custom_error(
"NoNpm",
format!(
"Following npm specifiers were requested: {}; but --no-npm is specified.",
fmt_reqs
),
));
}
self.resolution.add_package_reqs(packages).await self.resolution.add_package_reqs(packages).await
} }

View file

@ -223,6 +223,7 @@ impl ProcState {
cli_options.unstable() cli_options.unstable()
// don't do the unstable error when in the lsp // don't do the unstable error when in the lsp
|| matches!(cli_options.sub_command(), DenoSubcommand::Lsp), || matches!(cli_options.sub_command(), DenoSubcommand::Lsp),
cli_options.no_npm(),
); );
Ok(ProcState(Arc::new(Inner { Ok(ProcState(Arc::new(Inner {

View file

@ -231,6 +231,81 @@ fn cached_only_after_first_run() {
assert_contains!(stdout, "createChalk: chalk"); assert_contains!(stdout, "createChalk: chalk");
} }
#[test]
fn no_npm_after_first_run() {
let _server = http_server();
let deno_dir = util::new_deno_dir();
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("run")
.arg("--unstable")
.arg("--allow-read")
.arg("--allow-env")
.arg("--no-npm")
.arg("npm/no_npm_after_first_run/main1.ts")
.env("NO_COLOR", "1")
.envs(env_vars())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
assert_contains!(
stderr,
"Following npm specifiers were requested: \"chalk@5\"; but --no-npm is specified."
);
assert!(stdout.is_empty());
assert!(!output.status.success());
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("run")
.arg("--unstable")
.arg("--allow-read")
.arg("--allow-env")
.arg("npm/no_npm_after_first_run/main1.ts")
.env("NO_COLOR", "1")
.envs(env_vars())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
assert_contains!(stderr, "Download");
assert_contains!(stdout, "createChalk: chalk");
assert!(output.status.success());
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("run")
.arg("--unstable")
.arg("--allow-read")
.arg("--allow-env")
.arg("--no-npm")
.arg("npm/no_npm_after_first_run/main1.ts")
.env("NO_COLOR", "1")
.envs(env_vars())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
assert_contains!(
stderr,
"Following npm specifiers were requested: \"chalk@5\"; but --no-npm is specified."
);
assert!(stdout.is_empty());
assert!(!output.status.success());
}
#[test] #[test]
fn deno_run_cjs_module() { fn deno_run_cjs_module() {
let _server = http_server(); let _server = http_server();

View file

@ -0,0 +1,3 @@
import chalk from "npm:chalk@5";
console.log(chalk);

View file

@ -321,6 +321,10 @@ fn resolve_shim_data(
executable_args.push("--no-remote".to_string()); executable_args.push("--no-remote".to_string());
} }
if flags.no_npm {
executable_args.push("--no-npm".to_string());
}
if flags.lock_write { if flags.lock_write {
executable_args.push("--lock-write".to_string()); executable_args.push("--lock-write".to_string());
} }

View file

@ -279,6 +279,7 @@ pub fn compile_to_runtime_flags(
.unsafely_ignore_certificate_errors .unsafely_ignore_certificate_errors
.clone(), .clone(),
no_remote: false, no_remote: false,
no_npm: false,
no_prompt: flags.no_prompt, no_prompt: flags.no_prompt,
reload: false, reload: false,
seed: flags.seed, seed: flags.seed,