1use std::{
2 net::IpAddr,
3 path::{Path, PathBuf},
4 str::FromStr,
5};
6
7use anyhow::anyhow;
8use clap::{Args, Parser, ValueEnum};
9use serde::{Deserialize, Serialize};
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 Serialize,
46 Deserialize,
47 Hash,
48 TaskInput,
49 NonLocalValue,
50 TraceRawVcs,
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 serde::Serialize for IssueSeverityCliOption {
168 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
169 serializer.serialize_str(&self.0.to_string())
170 }
171}
172
173impl<'de> serde::Deserialize<'de> for IssueSeverityCliOption {
174 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
175 let s = String::deserialize(deserializer)?;
176 <IssueSeverityCliOption as std::str::FromStr>::from_str(&s)
177 .map_err(serde::de::Error::custom)
178 }
179}
180
181impl ValueEnum for IssueSeverityCliOption {
182 fn value_variants<'a>() -> &'a [Self] {
183 const VARIANTS: [IssueSeverityCliOption; 8] = [
184 IssueSeverityCliOption(IssueSeverity::Bug),
185 IssueSeverityCliOption(IssueSeverity::Fatal),
186 IssueSeverityCliOption(IssueSeverity::Error),
187 IssueSeverityCliOption(IssueSeverity::Warning),
188 IssueSeverityCliOption(IssueSeverity::Hint),
189 IssueSeverityCliOption(IssueSeverity::Note),
190 IssueSeverityCliOption(IssueSeverity::Suggestion),
191 IssueSeverityCliOption(IssueSeverity::Info),
192 ];
193 &VARIANTS
194 }
195
196 fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
197 Some(clap::builder::PossibleValue::new(self.0.as_str()).help(self.0.as_help_str()))
198 }
199}
200
201impl FromStr for IssueSeverityCliOption {
202 type Err = anyhow::Error;
203
204 fn from_str(s: &str) -> Result<Self, Self::Err> {
205 <IssueSeverityCliOption as clap::ValueEnum>::from_str(s, true).map_err(|s| anyhow!("{}", s))
206 }
207}