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
99 #[clap(long)]
102 pub persistent_caching: bool,
103
104 #[clap(long)]
107 pub cache_dir: Option<PathBuf>,
108 }
113
114#[derive(Debug, Args)]
115#[clap(author, version, about, long_about = None)]
116pub struct DevArguments {
117 #[clap(flatten)]
118 pub common: CommonArguments,
119
120 #[clap(short, long, value_parser, default_value_t = 3000, env = "PORT")]
125 pub port: u16,
126
127 #[clap(short = 'H', long, value_parser, default_value = "0.0.0.0")]
129 pub hostname: IpAddr,
130
131 #[clap(long)]
134 pub eager_compile: bool,
135
136 #[clap(long)]
138 pub no_open: bool,
139
140 #[clap(long)]
146 pub allow_retry: bool,
147}
148
149#[derive(Debug, Args)]
150#[clap(author, version, about, long_about = None)]
151pub struct BuildArguments {
152 #[clap(flatten)]
153 pub common: CommonArguments,
154
155 #[clap(long)]
157 pub no_sourcemap: bool,
158
159 #[clap(long)]
161 pub no_minify: bool,
162
163 #[clap(long)]
165 pub no_scope_hoist: bool,
166
167 #[clap(long, hide = true)]
171 pub force_memory_cleanup: bool,
172}
173
174#[derive(Clone, Copy, PartialEq, Eq, Debug)]
175pub struct IssueSeverityCliOption(pub IssueSeverity);
176
177impl ValueEnum for IssueSeverityCliOption {
178 fn value_variants<'a>() -> &'a [Self] {
179 const VARIANTS: [IssueSeverityCliOption; 8] = [
180 IssueSeverityCliOption(IssueSeverity::Bug),
181 IssueSeverityCliOption(IssueSeverity::Fatal),
182 IssueSeverityCliOption(IssueSeverity::Error),
183 IssueSeverityCliOption(IssueSeverity::Warning),
184 IssueSeverityCliOption(IssueSeverity::Hint),
185 IssueSeverityCliOption(IssueSeverity::Note),
186 IssueSeverityCliOption(IssueSeverity::Suggestion),
187 IssueSeverityCliOption(IssueSeverity::Info),
188 ];
189 &VARIANTS
190 }
191
192 fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
193 Some(clap::builder::PossibleValue::new(self.0.as_str()).help(self.0.as_help_str()))
194 }
195}
196
197impl FromStr for IssueSeverityCliOption {
198 type Err = anyhow::Error;
199
200 fn from_str(s: &str) -> Result<Self, Self::Err> {
201 <IssueSeverityCliOption as clap::ValueEnum>::from_str(s, true).map_err(|s| anyhow!("{}", s))
202 }
203}