Skip to main content

turbopack_cli/
arguments.rs

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 turbopack_core::issue::IssueSeverity;
11
12#[derive(Debug, Parser)]
13#[clap(author, version, about, long_about = None)]
14pub enum Arguments {
15    Build(BuildArguments),
16    Dev(DevArguments),
17}
18
19impl Arguments {
20    /// The directory of the application. see [CommonArguments]::dir
21    pub fn dir(&self) -> Option<&Path> {
22        match self {
23            Arguments::Build(args) => args.common.dir.as_deref(),
24            Arguments::Dev(args) => args.common.dir.as_deref(),
25        }
26    }
27
28    /// The number of worker threads to use. see [CommonArguments]::worker_threads
29    pub fn worker_threads(&self) -> Option<usize> {
30        match self {
31            Arguments::Build(args) => args.common.worker_threads,
32            Arguments::Dev(args) => args.common.worker_threads,
33        }
34    }
35}
36
37#[turbo_tasks::task_input]
38#[derive(Copy, Clone, Debug, ValueEnum, PartialEq, Eq, Hash, Encode, Decode)]
39pub enum Target {
40    Browser,
41    Node,
42}
43
44#[derive(Debug, Args, Clone)]
45pub struct CommonArguments {
46    /// The entrypoints of the project. Resolved relative to the project's
47    /// directory (`--dir`).
48    #[clap(value_parser)]
49    pub entries: Option<Vec<String>>,
50
51    /// The directory of the application.
52    /// If no directory is provided, the current directory will be used.
53    #[clap(short, long, value_parser)]
54    pub dir: Option<PathBuf>,
55
56    /// The root directory of the project. Nothing outside of this directory can
57    /// be accessed. e. g. the monorepo root.
58    /// If no directory is provided, `dir` will be used.
59    #[clap(long, value_parser)]
60    pub root: Option<PathBuf>,
61
62    /// Filter by issue severity.
63    #[clap(short, long)]
64    pub log_level: Option<IssueSeverityCliOption>,
65
66    /// Show all log messages without limit.
67    #[clap(long)]
68    pub show_all: bool,
69
70    /// Expand the log details.
71    #[clap(long)]
72    pub log_detail: bool,
73
74    /// Whether to enable full task stats recording in Turbo Engine.
75    #[clap(long)]
76    pub full_stats: bool,
77
78    /// Whether to build for the `browser` or `node`
79    #[clap(long)]
80    pub target: Option<Target>,
81
82    /// Number of worker threads to use for parallel processing
83    #[clap(long)]
84    pub worker_threads: Option<usize>,
85
86    /// Enable filesystem-backed persistent caching.
87    /// Cache is stored at `<cache-dir>/<git-version>`.
88    #[clap(long)]
89    pub persistent_caching: bool,
90
91    /// Directory to store the persistent cache.
92    /// Defaults to `.turbopack/cache` relative to the project directory.
93    #[clap(long)]
94    pub cache_dir: Option<PathBuf>,
95    // Enable experimental garbage collection with the provided memory limit in
96    // MB.
97    // #[clap(long)]
98    // pub memory_limit: Option<usize>,
99}
100
101#[derive(Debug, Args)]
102#[clap(author, version, about, long_about = None)]
103pub struct DevArguments {
104    #[clap(flatten)]
105    pub common: CommonArguments,
106
107    /// The port number on which to start the application
108    /// Note: setting env PORT allows to configure port without explicit cli
109    /// args. However, this is temporary measure to conform with existing
110    /// next.js devserver and can be removed in the future.
111    #[clap(short, long, value_parser, default_value_t = 3000, env = "PORT")]
112    pub port: u16,
113
114    /// Hostname on which to start the application
115    #[clap(short = 'H', long, value_parser, default_value = "0.0.0.0")]
116    pub hostname: IpAddr,
117
118    /// Compile all, instead of only compiling referenced assets when their
119    /// parent asset is requested
120    #[clap(long)]
121    pub eager_compile: bool,
122
123    /// Don't open the browser automatically when the dev server has started.
124    #[clap(long)]
125    pub no_open: bool,
126
127    // ==
128    // = Inherited options from next-dev, need revisit later.
129    // ==
130    /// If port is not explicitly specified, use different port if it's already
131    /// in use.
132    #[clap(long)]
133    pub allow_retry: bool,
134}
135
136#[derive(Debug, Args)]
137#[clap(author, version, about, long_about = None)]
138pub struct BuildArguments {
139    #[clap(flatten)]
140    pub common: CommonArguments,
141
142    /// Don't generate sourcemaps.
143    #[clap(long)]
144    pub no_sourcemap: bool,
145
146    /// Don't minify build output.
147    #[clap(long)]
148    pub no_minify: bool,
149
150    /// Don't perform scope hoisting.
151    #[clap(long)]
152    pub no_scope_hoist: bool,
153
154    /// Drop the `TurboTasks` object upon exit. By default we intentionally leak this memory, as
155    /// we're about to exit the process anyways, but that can cause issues with valgrind or other
156    /// leak detectors.
157    #[clap(long, hide = true)]
158    pub force_memory_cleanup: bool,
159}
160
161#[derive(Clone, Copy, PartialEq, Eq, Debug)]
162pub struct IssueSeverityCliOption(pub IssueSeverity);
163
164impl ValueEnum for IssueSeverityCliOption {
165    fn value_variants<'a>() -> &'a [Self] {
166        const VARIANTS: [IssueSeverityCliOption; 8] = [
167            IssueSeverityCliOption(IssueSeverity::Bug),
168            IssueSeverityCliOption(IssueSeverity::Fatal),
169            IssueSeverityCliOption(IssueSeverity::Error),
170            IssueSeverityCliOption(IssueSeverity::Warning),
171            IssueSeverityCliOption(IssueSeverity::Hint),
172            IssueSeverityCliOption(IssueSeverity::Note),
173            IssueSeverityCliOption(IssueSeverity::Suggestion),
174            IssueSeverityCliOption(IssueSeverity::Info),
175        ];
176        &VARIANTS
177    }
178
179    fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
180        Some(clap::builder::PossibleValue::new(self.0.as_str()).help(self.0.as_help_str()))
181    }
182}
183
184impl FromStr for IssueSeverityCliOption {
185    type Err = anyhow::Error;
186
187    fn from_str(s: &str) -> Result<Self, Self::Err> {
188        <IssueSeverityCliOption as clap::ValueEnum>::from_str(s, true).map_err(|s| anyhow!("{}", s))
189    }
190}