mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 19:08:15 +00:00
feat(cli): --ext parameter for run, compile, and bundle (#17172)
Adds `--ext` to `deno run`, closes #5088 Additionally - Adds `--ext` to `deno compile` and `deno bundle`
This commit is contained in:
parent
50b793c9ed
commit
fd0658fb42
27 changed files with 390 additions and 128 deletions
|
@ -124,13 +124,11 @@ pub struct DocFlags {
|
|||
pub struct EvalFlags {
|
||||
pub print: bool,
|
||||
pub code: String,
|
||||
pub ext: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct FmtFlags {
|
||||
pub check: bool,
|
||||
pub ext: String,
|
||||
pub files: FileFlags,
|
||||
pub use_tabs: Option<bool>,
|
||||
pub line_width: Option<NonZeroU32>,
|
||||
|
@ -335,6 +333,7 @@ pub struct Flags {
|
|||
pub node_modules_dir: Option<bool>,
|
||||
pub coverage_dir: Option<String>,
|
||||
pub enable_testing_features: bool,
|
||||
pub ext: Option<String>,
|
||||
pub ignore: Vec<PathBuf>,
|
||||
pub import_map_path: Option<String>,
|
||||
pub inspect_brk: Option<SocketAddr>,
|
||||
|
@ -837,6 +836,7 @@ fn bundle_subcommand<'a>() -> Command<'a> {
|
|||
)
|
||||
.arg(watch_arg(false))
|
||||
.arg(no_clear_screen_arg())
|
||||
.arg(executable_ext_arg())
|
||||
.about("Bundle module and dependencies into single file")
|
||||
.long_about(
|
||||
"Output a single JavaScript file with all dependencies.
|
||||
|
@ -943,6 +943,7 @@ fn compile_subcommand<'a>() -> Command<'a> {
|
|||
"aarch64-apple-darwin",
|
||||
]),
|
||||
)
|
||||
.arg(executable_ext_arg())
|
||||
.about("UNSTABLE: Compile the script into a self contained executable")
|
||||
.long_about(
|
||||
"UNSTABLE: Compiles the given script into a self contained executable.
|
||||
|
@ -1164,22 +1165,16 @@ This command has implicit access to all permissions (--allow-all).",
|
|||
.arg(
|
||||
// TODO(@satyarohith): remove this argument in 2.0.
|
||||
Arg::new("ts")
|
||||
.conflicts_with("ext")
|
||||
.long("ts")
|
||||
.short('T')
|
||||
.help("Treat eval input as TypeScript")
|
||||
.help("deprecated: Treat eval input as TypeScript")
|
||||
.takes_value(false)
|
||||
.multiple_occurrences(false)
|
||||
.multiple_values(false)
|
||||
.hide(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("ext")
|
||||
.long("ext")
|
||||
.help("Set standard input (stdin) content type")
|
||||
.takes_value(true)
|
||||
.default_value("js")
|
||||
.possible_values(["ts", "tsx", "js", "jsx"]),
|
||||
)
|
||||
.arg(executable_ext_arg())
|
||||
.arg(
|
||||
Arg::new("print")
|
||||
.long("print")
|
||||
|
@ -1232,8 +1227,9 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
|
|||
.arg(
|
||||
Arg::new("ext")
|
||||
.long("ext")
|
||||
.help("Set standard input (stdin) content type")
|
||||
.help("Set content type of the supplied file")
|
||||
.takes_value(true)
|
||||
// prefer using ts for formatting instead of js because ts works in more scenarios
|
||||
.default_value("ts")
|
||||
.possible_values(["ts", "tsx", "js", "jsx", "md", "json", "jsonc"]),
|
||||
)
|
||||
|
@ -1615,6 +1611,7 @@ fn run_subcommand<'a>() -> Command<'a> {
|
|||
.conflicts_with("inspect-brk"),
|
||||
)
|
||||
.arg(no_clear_screen_arg())
|
||||
.arg(executable_ext_arg())
|
||||
.trailing_var_arg(true)
|
||||
.arg(script_arg().required(true))
|
||||
.about("Run a JavaScript or TypeScript program")
|
||||
|
@ -2168,6 +2165,18 @@ fn cached_only_arg<'a>() -> Arg<'a> {
|
|||
.help("Require that remote dependencies are already cached")
|
||||
}
|
||||
|
||||
/// Used for subcommands that operate on executable scripts only.
|
||||
/// `deno fmt` has its own `--ext` arg because its possible values differ.
|
||||
/// If --ext is not provided and the script doesn't have a file extension,
|
||||
/// deno_graph::parse_module() defaults to js.
|
||||
fn executable_ext_arg<'a>() -> Arg<'a> {
|
||||
Arg::new("ext")
|
||||
.long("ext")
|
||||
.help("Set content type of the supplied file")
|
||||
.takes_value(true)
|
||||
.possible_values(["ts", "tsx", "js", "jsx"])
|
||||
}
|
||||
|
||||
fn location_arg<'a>() -> Arg<'a> {
|
||||
Arg::new("location")
|
||||
.long("location")
|
||||
|
@ -2456,6 +2465,7 @@ fn bundle_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
};
|
||||
|
||||
watch_arg_parse(flags, matches, false);
|
||||
ext_arg_parse(flags, matches);
|
||||
|
||||
flags.subcommand = DenoSubcommand::Bundle(BundleFlags {
|
||||
source_file,
|
||||
|
@ -2505,6 +2515,7 @@ fn compile_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
Some(f) => f.map(String::from).collect(),
|
||||
None => vec![],
|
||||
};
|
||||
ext_arg_parse(flags, matches);
|
||||
|
||||
flags.subcommand = DenoSubcommand::Compile(CompileFlags {
|
||||
source_file,
|
||||
|
@ -2614,13 +2625,22 @@ fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
flags.allow_write = Some(vec![]);
|
||||
flags.allow_ffi = Some(vec![]);
|
||||
flags.allow_hrtime = true;
|
||||
|
||||
ext_arg_parse(flags, matches);
|
||||
|
||||
// TODO(@satyarohith): remove this flag in 2.0.
|
||||
let as_typescript = matches.is_present("ts");
|
||||
let ext = if as_typescript {
|
||||
"ts".to_string()
|
||||
} else {
|
||||
matches.value_of("ext").unwrap().to_string()
|
||||
};
|
||||
|
||||
if as_typescript {
|
||||
eprintln!(
|
||||
"{}",
|
||||
crate::colors::yellow(
|
||||
"Warning: --ts/-T flag is deprecated. Use --ext=ts instead."
|
||||
),
|
||||
);
|
||||
|
||||
flags.ext = Some("ts".to_string());
|
||||
}
|
||||
|
||||
let print = matches.is_present("print");
|
||||
let mut code: Vec<String> = matches
|
||||
|
@ -2634,12 +2654,13 @@ fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
for v in code_args {
|
||||
flags.argv.push(v);
|
||||
}
|
||||
flags.subcommand = DenoSubcommand::Eval(EvalFlags { print, code, ext });
|
||||
flags.subcommand = DenoSubcommand::Eval(EvalFlags { print, code });
|
||||
}
|
||||
|
||||
fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||
config_args_parse(flags, matches);
|
||||
watch_arg_parse(flags, matches, false);
|
||||
ext_arg_parse(flags, matches);
|
||||
|
||||
let include = match matches.values_of("files") {
|
||||
Some(f) => f.map(PathBuf::from).collect(),
|
||||
|
@ -2649,7 +2670,6 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
Some(f) => f.map(PathBuf::from).collect(),
|
||||
None => vec![],
|
||||
};
|
||||
let ext = matches.value_of("ext").unwrap().to_string();
|
||||
|
||||
let use_tabs = optional_bool_parse(matches, "use-tabs");
|
||||
let line_width = if matches.is_present("line-width") {
|
||||
|
@ -2674,7 +2694,6 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
|
||||
flags.subcommand = DenoSubcommand::Fmt(FmtFlags {
|
||||
check: matches.is_present("check"),
|
||||
ext,
|
||||
files: FileFlags { include, ignore },
|
||||
use_tabs,
|
||||
line_width,
|
||||
|
@ -2827,6 +2846,8 @@ fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
flags.argv.push(v);
|
||||
}
|
||||
|
||||
ext_arg_parse(flags, matches);
|
||||
|
||||
watch_arg_parse(flags, matches, true);
|
||||
flags.subcommand = DenoSubcommand::Run(RunFlags { script });
|
||||
}
|
||||
|
@ -3228,6 +3249,10 @@ fn cached_only_arg_parse(flags: &mut Flags, matches: &ArgMatches) {
|
|||
}
|
||||
}
|
||||
|
||||
fn ext_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||
flags.ext = matches.value_of("ext").map(String::from);
|
||||
}
|
||||
|
||||
fn location_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||
flags.location = matches
|
||||
.value_of("location")
|
||||
|
@ -3694,7 +3719,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![
|
||||
PathBuf::from("script_1.ts"),
|
||||
|
@ -3709,6 +3733,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: None,
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
@ -3719,7 +3744,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: true,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![],
|
||||
ignore: vec![],
|
||||
|
@ -3731,6 +3755,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: None,
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
@ -3741,7 +3766,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![],
|
||||
ignore: vec![],
|
||||
|
@ -3753,6 +3777,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: None,
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
@ -3763,7 +3788,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![],
|
||||
ignore: vec![],
|
||||
|
@ -3775,6 +3799,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: None,
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
watch: Some(vec![]),
|
||||
..Flags::default()
|
||||
}
|
||||
|
@ -3787,7 +3812,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![],
|
||||
ignore: vec![],
|
||||
|
@ -3799,6 +3823,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: None,
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
watch: Some(vec![]),
|
||||
no_clear_screen: true,
|
||||
..Flags::default()
|
||||
|
@ -3818,7 +3843,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: true,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![PathBuf::from("foo.ts")],
|
||||
ignore: vec![PathBuf::from("bar.js")],
|
||||
|
@ -3830,6 +3854,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: None,
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
watch: Some(vec![]),
|
||||
..Flags::default()
|
||||
}
|
||||
|
@ -3841,7 +3866,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![],
|
||||
ignore: vec![],
|
||||
|
@ -3853,6 +3877,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: None,
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
config_flag: ConfigFlag::Path("deno.jsonc".to_string()),
|
||||
..Flags::default()
|
||||
}
|
||||
|
@ -3871,7 +3896,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![PathBuf::from("foo.ts")],
|
||||
ignore: vec![],
|
||||
|
@ -3884,6 +3908,7 @@ mod tests {
|
|||
no_semicolons: None,
|
||||
}),
|
||||
config_flag: ConfigFlag::Path("deno.jsonc".to_string()),
|
||||
ext: Some("ts".to_string()),
|
||||
watch: Some(vec![]),
|
||||
..Flags::default()
|
||||
}
|
||||
|
@ -3907,7 +3932,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![],
|
||||
ignore: vec![],
|
||||
|
@ -3919,6 +3943,7 @@ mod tests {
|
|||
prose_wrap: Some("never".to_string()),
|
||||
no_semicolons: Some(true),
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
@ -3936,7 +3961,6 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||
check: false,
|
||||
ext: "ts".to_string(),
|
||||
files: FileFlags {
|
||||
include: vec![],
|
||||
ignore: vec![],
|
||||
|
@ -3948,6 +3972,7 @@ mod tests {
|
|||
prose_wrap: None,
|
||||
no_semicolons: Some(false),
|
||||
}),
|
||||
ext: Some("ts".to_string()),
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
@ -4362,7 +4387,6 @@ mod tests {
|
|||
subcommand: DenoSubcommand::Eval(EvalFlags {
|
||||
print: false,
|
||||
code: "'console.log(\"hello\")'".to_string(),
|
||||
ext: "js".to_string(),
|
||||
}),
|
||||
allow_net: Some(vec![]),
|
||||
allow_env: Some(vec![]),
|
||||
|
@ -4386,7 +4410,6 @@ mod tests {
|
|||
subcommand: DenoSubcommand::Eval(EvalFlags {
|
||||
print: true,
|
||||
code: "1+2".to_string(),
|
||||
ext: "js".to_string(),
|
||||
}),
|
||||
allow_net: Some(vec![]),
|
||||
allow_env: Some(vec![]),
|
||||
|
@ -4411,7 +4434,6 @@ mod tests {
|
|||
subcommand: DenoSubcommand::Eval(EvalFlags {
|
||||
print: false,
|
||||
code: "'console.log(\"hello\")'".to_string(),
|
||||
ext: "ts".to_string(),
|
||||
}),
|
||||
allow_net: Some(vec![]),
|
||||
allow_env: Some(vec![]),
|
||||
|
@ -4421,6 +4443,7 @@ mod tests {
|
|||
allow_write: Some(vec![]),
|
||||
allow_ffi: Some(vec![]),
|
||||
allow_hrtime: true,
|
||||
ext: Some("ts".to_string()),
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
@ -4436,7 +4459,6 @@ mod tests {
|
|||
subcommand: DenoSubcommand::Eval(EvalFlags {
|
||||
print: false,
|
||||
code: "42".to_string(),
|
||||
ext: "js".to_string(),
|
||||
}),
|
||||
import_map_path: Some("import_map.json".to_string()),
|
||||
no_remote: true,
|
||||
|
@ -4479,7 +4501,6 @@ mod tests {
|
|||
subcommand: DenoSubcommand::Eval(EvalFlags {
|
||||
print: false,
|
||||
code: "console.log(Deno.args)".to_string(),
|
||||
ext: "js".to_string(),
|
||||
}),
|
||||
argv: svec!["arg1", "arg2"],
|
||||
allow_net: Some(vec![]),
|
||||
|
|
|
@ -10,6 +10,8 @@ pub mod package_json;
|
|||
pub use self::import_map::resolve_import_map_from_specifier;
|
||||
use self::package_json::PackageJsonDeps;
|
||||
use ::import_map::ImportMap;
|
||||
use deno_core::resolve_url_or_path;
|
||||
use deno_graph::npm::NpmPackageReqReference;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use crate::npm::NpmRegistryApi;
|
||||
|
@ -50,6 +52,7 @@ use deno_runtime::deno_tls::webpki_roots;
|
|||
use deno_runtime::inspector_server::InspectorServer;
|
||||
use deno_runtime::permissions::PermissionsOptions;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::io::BufReader;
|
||||
use std::io::Cursor;
|
||||
|
@ -139,7 +142,6 @@ impl BenchOptions {
|
|||
pub struct FmtOptions {
|
||||
pub is_stdin: bool,
|
||||
pub check: bool,
|
||||
pub ext: String,
|
||||
pub options: FmtOptionsConfig,
|
||||
pub files: FilesConfig,
|
||||
}
|
||||
|
@ -166,10 +168,6 @@ impl FmtOptions {
|
|||
Ok(Self {
|
||||
is_stdin,
|
||||
check: maybe_fmt_flags.as_ref().map(|f| f.check).unwrap_or(false),
|
||||
ext: maybe_fmt_flags
|
||||
.as_ref()
|
||||
.map(|f| f.ext.to_string())
|
||||
.unwrap_or_else(|| "ts".to_string()),
|
||||
options: resolve_fmt_options(
|
||||
maybe_fmt_flags.as_ref(),
|
||||
maybe_config_options,
|
||||
|
@ -675,6 +673,73 @@ impl CliOptions {
|
|||
.map(Some)
|
||||
}
|
||||
|
||||
pub fn resolve_main_module(&self) -> Result<ModuleSpecifier, AnyError> {
|
||||
match &self.flags.subcommand {
|
||||
DenoSubcommand::Bundle(bundle_flags) => {
|
||||
resolve_url_or_path(&bundle_flags.source_file, self.initial_cwd())
|
||||
.map_err(AnyError::from)
|
||||
}
|
||||
DenoSubcommand::Compile(compile_flags) => {
|
||||
resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())
|
||||
.map_err(AnyError::from)
|
||||
}
|
||||
DenoSubcommand::Eval(_) => {
|
||||
resolve_url_or_path("./$deno$eval", self.initial_cwd())
|
||||
.map_err(AnyError::from)
|
||||
}
|
||||
DenoSubcommand::Repl(_) => {
|
||||
resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())
|
||||
.map_err(AnyError::from)
|
||||
}
|
||||
DenoSubcommand::Run(run_flags) => {
|
||||
if run_flags.is_stdin() {
|
||||
std::env::current_dir()
|
||||
.context("Unable to get CWD")
|
||||
.and_then(|cwd| {
|
||||
resolve_url_or_path("./$deno$stdin", &cwd).map_err(AnyError::from)
|
||||
})
|
||||
} else if self.flags.watch.is_some() {
|
||||
resolve_url_or_path(&run_flags.script, self.initial_cwd())
|
||||
.map_err(AnyError::from)
|
||||
} else if NpmPackageReqReference::from_str(&run_flags.script).is_ok() {
|
||||
ModuleSpecifier::parse(&run_flags.script).map_err(AnyError::from)
|
||||
} else {
|
||||
resolve_url_or_path(&run_flags.script, self.initial_cwd())
|
||||
.map_err(AnyError::from)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
bail!("No main module.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_file_header_overrides(
|
||||
&self,
|
||||
) -> HashMap<ModuleSpecifier, HashMap<String, String>> {
|
||||
let maybe_main_specifier = self.resolve_main_module().ok();
|
||||
// TODO(Cre3per): This mapping moved to deno_ast with https://github.com/denoland/deno_ast/issues/133 and should be available in deno_ast >= 0.25.0 via `MediaType::from_path(...).as_media_type()`
|
||||
let maybe_content_type =
|
||||
self.flags.ext.as_ref().and_then(|el| match el.as_str() {
|
||||
"ts" => Some("text/typescript"),
|
||||
"tsx" => Some("text/tsx"),
|
||||
"js" => Some("text/javascript"),
|
||||
"jsx" => Some("text/jsx"),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
if let (Some(main_specifier), Some(content_type)) =
|
||||
(maybe_main_specifier, maybe_content_type)
|
||||
{
|
||||
HashMap::from([(
|
||||
main_specifier,
|
||||
HashMap::from([("content-type".to_string(), content_type.to_string())]),
|
||||
)])
|
||||
} else {
|
||||
HashMap::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn resolve_npm_resolution_snapshot(
|
||||
&self,
|
||||
api: &NpmRegistryApi,
|
||||
|
@ -936,6 +1001,10 @@ impl CliOptions {
|
|||
self.flags.enable_testing_features
|
||||
}
|
||||
|
||||
pub fn ext_flag(&self) -> &Option<String> {
|
||||
&self.flags.ext
|
||||
}
|
||||
|
||||
/// If the --inspect or --inspect-brk flags are used.
|
||||
pub fn is_inspecting(&self) -> bool {
|
||||
self.flags.inspect.is_some()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue