perseus_cli/
parse.rs

1#![allow(missing_docs)] // Prevents double-documenting some things
2
3use crate::PERSEUS_VERSION;
4use clap::Parser;
5
6// The documentation for the `Opts` struct will appear in the help page, hence
7// the lack of punctuation and the lowercasing in places
8
9/// The command-line interface for Perseus, a super-fast WebAssembly frontend
10/// development framework!
11#[derive(Parser, Clone)]
12#[clap(version = PERSEUS_VERSION)]
13// #[clap(setting = AppSettings::ColoredHelp)]
14pub struct Opts {
15    #[clap(subcommand)]
16    pub subcmd: Subcommand,
17    // All the following arguments are global, and can provided to any subcommand
18    /// The path to `cargo` when used for engine builds
19    #[clap(long, default_value = "cargo", global = true)]
20    pub cargo_engine_path: String,
21    /// The path to `cargo` when used for browser builds
22    #[clap(long, default_value = "cargo", global = true)]
23    pub cargo_browser_path: String,
24    /// A path to `wasm-bindgen`, if you want to use a local installation (note
25    /// that the CLI will install it locally for you by default)
26    #[clap(long, global = true)]
27    pub wasm_bindgen_path: Option<String>,
28    /// A path to `wasm-opt`, if you want to use a local installation (note that
29    /// the CLI will install it locally for you by default)
30    #[clap(long, global = true)]
31    pub wasm_opt_path: Option<String>,
32    /// The path to `rustup`
33    #[clap(long, default_value = "rustup", global = true)]
34    pub rustup_path: String,
35    /// The value of `RUSTFLAGS` when building for Wasm in release mode (this
36    /// will not impact internal target-gating)
37    #[clap(
38        long,
39        default_value = "-C opt-level=z -C codegen-units=1",
40        global = true
41    )]
42    pub wasm_release_rustflags: String,
43    /// Any arguments to `cargo` when building for the engine-side
44    #[clap(long, default_value = "", global = true)]
45    pub cargo_engine_args: String,
46    /// Any arguments to `cargo` when building for the browser-side
47    #[clap(long, default_value = "", global = true)]
48    pub cargo_browser_args: String,
49    /// Any arguments to `wasm-bindgen`
50    #[clap(long, default_value = "", global = true)]
51    pub wasm_bindgen_args: String,
52    /// Any arguments to `wasm-opt` (only run in release builds)
53    #[clap(long, default_value = "-Oz", global = true)]
54    pub wasm_opt_args: String,
55    /// The path to `git` (for downloading custom templates for `perseus new`)
56    #[clap(long, default_value = "git", global = true)]
57    pub git_path: String,
58    /// The host for the reload server (you should almost never change this)
59    #[clap(long, default_value = "localhost", global = true)]
60    pub reload_server_host: String,
61    /// The port for the reload server (you should almost never change this)
62    #[clap(long, default_value = "3100", global = true)]
63    pub reload_server_port: u16,
64    /// If this is set, commands will be run sequentially rather than in
65    /// parallel (slows down operations, but reduces memory usage)
66    #[clap(long, global = true)]
67    pub sequential: bool,
68    /// Disable automatic browser reloading
69    #[clap(long, global = true)]
70    pub no_browser_reload: bool,
71    /// A custom version of `wasm-bindgen` to use (defaults to the latest
72    /// installed version, and after that the latest available from GitHub;
73    /// update to latest can be forced with `latest`)
74    #[clap(long, global = true)]
75    pub wasm_bindgen_version: Option<String>,
76    /// A custom version of `wasm-opt` to use (defaults to the latest installed
77    /// version, and after that the latest available from GitHub; update to
78    /// latest can be forced with `latest`)
79    #[clap(long, global = true)]
80    pub wasm_opt_version: Option<String>,
81    /// Disables the system-wide tools cache in `~/.cargo/perseus_tools/` (you
82    /// should set this for CI)
83    #[clap(long, global = true)]
84    pub no_system_tools_cache: bool,
85    /// Shows the logs from building and serving your app no matter what (the
86    /// default is to only show them on a compilation/build failure); this
87    /// is intended mainly for end-to-end debugging, although the `snoop`
88    /// commands are more useful for targeted debugging
89    #[clap(long, global = true)]
90    pub verbose: bool,
91}
92
93#[derive(Parser, Clone)]
94pub enum Subcommand {
95    Build(BuildOpts),
96    ExportErrorPage(ExportErrorPageOpts),
97    Export(ExportOpts),
98    Serve(ServeOpts),
99    Test(TestOpts),
100    /// Removes build artifacts in the `dist/` directory
101    Clean,
102    Deploy(DeployOpts),
103    Tinker(TinkerOpts),
104    /// Runs one of the underlying commands that builds your app, allowing you
105    /// to see more detailed logs
106    #[clap(subcommand)]
107    Snoop(SnoopSubcommand),
108    New(NewOpts),
109    Init(InitOpts),
110    /// Checks if your app builds properly for both the engine-side and the
111    /// browser-side
112    Check(CheckOpts),
113}
114/// Builds your app
115#[derive(Parser, Clone)]
116pub struct BuildOpts {
117    /// Build for production
118    #[clap(long)]
119    pub release: bool,
120    /// Watch the files in your working directory for changes (excluding
121    /// `target/` and `dist/`)
122    #[clap(short, long)]
123    pub watch: bool,
124    /// Marks a specific file/directory to be watched (directories will be
125    /// recursively watched)
126    #[clap(long)]
127    pub custom_watch: Vec<String>,
128}
129/// Exports your app to purely static files
130#[derive(Parser, Clone)]
131pub struct ExportOpts {
132    /// Export for production
133    #[clap(long)]
134    pub release: bool,
135    /// Serve the generated static files locally
136    #[clap(short, long)]
137    pub serve: bool,
138    /// Where to host your exported app
139    #[clap(long, default_value = "127.0.0.1")]
140    pub host: String,
141    /// The port to host your exported app on
142    #[clap(long, default_value = "8080")]
143    pub port: u16,
144    /// Watch the files in your working directory for changes (excluding
145    /// `target/` and `dist/`)
146    #[clap(short, long)]
147    pub watch: bool,
148    /// Marks a specific file/directory to be watched (directories will be
149    /// recursively watched)
150    #[clap(long)]
151    pub custom_watch: Vec<String>,
152}
153/// Exports an error page for the given HTTP status code
154#[derive(Parser, Clone)]
155pub struct ExportErrorPageOpts {
156    #[clap(short, long)]
157    pub code: String,
158    #[clap(short, long)]
159    pub output: String,
160}
161/// Serves your app
162#[derive(Parser, Clone)]
163pub struct ServeOpts {
164    /// Don't run the final binary, but print its location instead as the last
165    /// line of output
166    #[clap(long)]
167    pub no_run: bool,
168    /// Only build the server, and use the results of a previous `perseus build`
169    #[clap(long)]
170    pub no_build: bool,
171    /// Build and serve for production
172    #[clap(long)]
173    pub release: bool,
174    /// Make the final binary standalone (this is used in `perseus deploy` only,
175    /// don't manually invoke it unless you have a good reason!)
176    #[clap(long)]
177    pub standalone: bool,
178    /// Watch the files in your working directory for changes (excluding
179    /// `target/` and `dist/`)
180    #[clap(short, long)]
181    pub watch: bool,
182    /// Marks a specific file/directory to be watched (directories will be
183    /// recursively watched)
184    #[clap(long)]
185    pub custom_watch: Vec<String>,
186    /// Where to host your exported app
187    #[clap(long, default_value = "127.0.0.1")]
188    pub host: String,
189    /// The port to host your exported app on
190    #[clap(long, default_value = "8080")]
191    pub port: u16,
192}
193/// Serves your app as `perseus serve` does, but puts it in testing mode
194#[derive(Parser, Clone)]
195pub struct TestOpts {
196    /// Only build the testing server, and use the results of a previous
197    /// `perseus build`
198    #[clap(long)]
199    pub no_build: bool,
200    /// Show the browser window when testing (by default, the browser is used in
201    /// 'headless' mode); this can be useful for debugging failing tests in
202    /// some cases
203    #[clap(long)]
204    pub show_browser: bool,
205    /// Watch the files in your working directory for changes (excluding
206    /// `target/` and `dist/`)
207    #[clap(short, long)]
208    pub watch: bool,
209    /// Marks a specific file/directory to be watched (directories will be
210    /// recursively watched)
211    #[clap(long)]
212    pub custom_watch: Vec<String>,
213    /// Where to host your exported app
214    #[clap(long, default_value = "127.0.0.1")]
215    pub host: String,
216    /// The port to host your exported app on
217    #[clap(long, default_value = "8080")]
218    pub port: u16,
219}
220/// Packages your app for deployment
221#[derive(Parser, Clone)]
222pub struct DeployOpts {
223    /// Change the output from `pkg/` to somewhere else
224    #[clap(short, long, default_value = "pkg")]
225    pub output: String,
226    /// Export your app to purely static files (see `export`)
227    #[clap(short, long)]
228    pub export_static: bool,
229    /// Don't minify JavaScript (this will decrease performance)
230    #[clap(long)]
231    pub no_minify_js: bool,
232}
233/// Runs the `tinker` action of plugins, which lets them modify the Perseus
234/// engine
235#[derive(Parser, Clone)]
236pub struct TinkerOpts {
237    /// Don't remove and recreate the `dist/` directory
238    #[clap(long)]
239    pub no_clean: bool,
240}
241/// Creates a new Perseus project in a directory of the given name, which will
242/// be created in the current path
243#[derive(Parser, Clone)]
244pub struct NewOpts {
245    /// The name of the new project, which will also be used for the directory
246    #[clap(value_parser)]
247    pub name: String,
248    /// An optional custom URL to a Git repository to be used as a custom
249    /// template (note that custom templates will not respect your project's
250    /// name). This can be followed with `@branch` to fetch from `branch`
251    /// rather than the default
252    #[clap(short, long)]
253    pub template: Option<String>,
254    /// The path to a custom directory to create (if this is not provided, the
255    /// project name will be used by default)
256    #[clap(long)]
257    pub dir: Option<String>,
258}
259/// Initializes a new Perseus project in the current directory
260#[derive(Parser, Clone)]
261pub struct InitOpts {
262    /// The name of the new project
263    #[clap(value_parser)]
264    pub name: String,
265}
266
267#[derive(Parser, Clone)]
268pub enum SnoopSubcommand {
269    /// Snoops on the static generation process (this will let you see `dbg!`
270    /// calls and the like)
271    Build {
272        /// Watch the files in your working directory for changes (excluding
273        /// `target/` and `dist/`)
274        #[clap(short, long)]
275        watch: bool,
276        /// Marks a specific file/directory to be watched (directories will be
277        /// recursively watched)
278        #[clap(long)]
279        custom_watch: Vec<String>,
280    },
281    /// Snoops on the Wasm building process (mostly for debugging errors)
282    WasmBuild {
283        /// Watch the files in your working directory for changes (excluding
284        /// `target/` and `dist/`)
285        #[clap(short, long)]
286        watch: bool,
287        /// Marks a specific file/directory to be watched (directories will be
288        /// recursively watched)
289        #[clap(long)]
290        custom_watch: Vec<String>,
291    },
292    /// Snoops on the server process (run `perseus build` before this)
293    Serve(SnoopServeOpts),
294}
295
296#[derive(Parser, Clone)]
297pub struct SnoopServeOpts {
298    /// Where to host your exported app
299    #[clap(long, default_value = "127.0.0.1")]
300    pub host: String,
301    /// The port to host your exported app on
302    #[clap(long, default_value = "8080")]
303    pub port: u16,
304    /// Watch the files in your working directory for changes (excluding
305    /// `target/` and `dist/`)
306    #[clap(short, long)]
307    pub watch: bool,
308    /// Marks a specific file/directory to be watched (directories will be
309    /// recursively watched)
310    #[clap(long)]
311    pub custom_watch: Vec<String>,
312}
313
314#[derive(Parser, Clone)]
315pub struct CheckOpts {
316    /// Watch the files in your working directory for changes (excluding
317    /// `target/` and `dist/`)
318    #[clap(short, long)]
319    pub watch: bool,
320    /// Marks a specific file/directory to be watched (directories will be
321    /// recursively watched)
322    #[clap(long)]
323    pub custom_watch: Vec<String>,
324    /// Make sure the app's page generation works properly (this will take much
325    /// longer, but almost guarantees that your app will actually build);
326    /// use this to catch errors in build state and the like
327    #[clap(short, long)]
328    pub generate: bool,
329}