1use std::{
2 net::IpAddr,
3 path::{Path, PathBuf},
4 str::FromStr,
5};
6
7use anyhow::anyhow;
8use bincode::{Decode, Encode};
9use clap::{Args, Parser, ValueEnum};
10use turbo_tasks::{NonLocalValue, TaskInput, trace::TraceRawVcs};
11use turbopack_core::issue::IssueSeverity;
12
13#[derive(Debug, Parser)]
14#[clap(author, version, about, long_about = None)]
15pub enum Arguments {
16 Build(BuildArguments),
17 Dev(DevArguments),
18}
19
20impl Arguments {
21 pub fn dir(&self) -> Option<&Path> {
23 match self {
24 Arguments::Build(args) => args.common.dir.as_deref(),
25 Arguments::Dev(args) => args.common.dir.as_deref(),
26 }
27 }
28
29 pub fn worker_threads(&self) -> Option<usize> {
31 match self {
32 Arguments::Build(args) => args.common.worker_threads,
33 Arguments::Dev(args) => args.common.worker_threads,
34 }
35 }
36}
37
38#[derive(
39 Copy,
40 Clone,
41 Debug,
42 ValueEnum,
43 PartialEq,
44 Eq,
45 Hash,
46 TaskInput,
47 NonLocalValue,
48 TraceRawVcs,
49 Encode,
50 Decode,
51)]
52pub enum Target {
53 Browser,
54 Node,
55}
56
57#[derive(Debug, Args, Clone)]
58pub struct CommonArguments {
59 #[clap(value_parser)]
62 pub entries: Option<Vec<String>>,
63
64 #[clap(short, long, value_parser)]
67 pub dir: Option<PathBuf>,
68
69 #[clap(long, value_parser)]
73 pub root: Option<PathBuf>,
74
75 #[clap(short, long)]
77 pub log_level: Option<IssueSeverityCliOption>,
78
79 #[clap(long)]
81 pub show_all: bool,
82
83 #[clap(long)]
85 pub log_detail: bool,
86
87 #[clap(long)]
89 pub full_stats: bool,
90
91 #[clap(long)]
93 pub target: Option<Target>,
94
95 #[clap(long)]
97 pub worker_threads: Option<usize>,
98 }
103
104#[derive(Debug, Args)]
105#[clap(author, version, about, long_about = None)]
106pub struct DevArguments {
107 #[clap(flatten)]
108 pub common: CommonArguments,
109
110 #[clap(short, long, value_parser, default_value_t = 3000, env = "PORT")]
115 pub port: u16,
116
117 #[clap(short = 'H', long, value_parser, default_value = "0.0.0.0")]
119 pub hostname: IpAddr,
120
121 #[clap(long)]
124 pub eager_compile: bool,
125
126 #[clap(long)]
128 pub no_open: bool,
129
130 #[clap(long)]
136 pub allow_retry: bool,
137}
138
139#[derive(Debug, Args)]
140#[clap(author, version, about, long_about = None)]
141pub struct BuildArguments {
142 #[clap(flatten)]
143 pub common: CommonArguments,
144
145 #[clap(long)]
147 pub no_sourcemap: bool,
148
149 #[clap(long)]
151 pub no_minify: bool,
152
153 #[clap(long)]
155 pub no_scope_hoist: bool,
156
157 #[clap(long, hide = true)]
161 pub force_memory_cleanup: bool,
162}
163
164#[derive(Clone, Copy, PartialEq, Eq, Debug)]
165pub struct IssueSeverityCliOption(pub IssueSeverity);
166
167impl ValueEnum for IssueSeverityCliOption {
168 fn value_variants<'a>() -> &'a [Self] {
169 const VARIANTS: [IssueSeverityCliOption; 8] = [
170 IssueSeverityCliOption(IssueSeverity::Bug),
171 IssueSeverityCliOption(IssueSeverity::Fatal),
172 IssueSeverityCliOption(IssueSeverity::Error),
173 IssueSeverityCliOption(IssueSeverity::Warning),
174 IssueSeverityCliOption(IssueSeverity::Hint),
175 IssueSeverityCliOption(IssueSeverity::Note),
176 IssueSeverityCliOption(IssueSeverity::Suggestion),
177 IssueSeverityCliOption(IssueSeverity::Info),
178 ];
179 &VARIANTS
180 }
181
182 fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
183 Some(clap::builder::PossibleValue::new(self.0.as_str()).help(self.0.as_help_str()))
184 }
185}
186
187impl FromStr for IssueSeverityCliOption {
188 type Err = anyhow::Error;
189
190 fn from_str(s: &str) -> Result<Self, Self::Err> {
191 <IssueSeverityCliOption as clap::ValueEnum>::from_str(s, true).map_err(|s| anyhow!("{}", s))
192 }
193}