Skip to main content

euv_cli/build/
struct.rs

1use super::*;
2
3/// euv CLI for real-time WASM compilation and hot-reload development server.
4///
5/// Defines the command-line interface with three sub-commands
6/// (`run` / `build` / `fmt`). All arguments after `--` are transparently
7/// forwarded to `wasm-pack build` without interpretation.
8#[derive(Clone, Data, Debug, New, Parser)]
9#[command(name = "euv")]
10#[command(about = "euv development server with live WASM compilation")]
11pub struct Cli {
12    /// The mode to run in: run (build + server), build (build only), or fmt (format)
13    #[command(subcommand)]
14    ///
15    /// Public: `cli/src/main.rs` is the `--bin euv` crate root, a
16    /// different crate from the `euv_cli` library, so its
17    /// `cli.get_command()` call cannot see a `pub(crate)` accessor. The
18    /// field is public to match that getter rather than the getter
19    /// narrowed to `pub(crate)`, which would fail with E0624 at the bin
20    /// call site. `get_mut` / `set` stay crate-internal — clap's derive
21    /// is the only writer and nothing mutates the mode in place.
22    #[get_mut(pub(crate))]
23    #[set(pub(crate))]
24    pub command: Mode,
25}
26
27/// euv-specific arguments combined with wasm-pack passthrough.
28///
29/// Only `--crate-path`, `--port`, `--www-dir`, `--index-html`, `--no-gitignore`, and `--dev`/`--release`/`--profiling`
30/// belong to euv; everything in `wasm_pack_args` is forwarded to `wasm-pack build` as-is.
31#[derive(Clone, Data, Debug, Parser)]
32pub struct ModeArgs {
33    /// Path to the Rust crate containing the WASM application
34    #[arg(short, long, default_value = ".")]
35    #[get(pub(crate))]
36    #[get_mut(pub(crate))]
37    #[set(pub(crate))]
38    pub(crate) crate_path: PathBuf,
39    /// Port for the development server
40    #[arg(short, long, default_value_t = 80)]
41    #[get(pub(crate), type(copy))]
42    #[get_mut(pub(crate))]
43    #[set(pub(crate))]
44    pub(crate) port: u16,
45    /// Directory name for static assets and generated HTML (relative to crate-path)
46    #[arg(long, default_value = "www")]
47    #[get(pub(crate))]
48    #[get_mut(pub(crate))]
49    #[set(pub(crate))]
50    pub(crate) www_dir: String,
51    /// Path to a custom index.html template file.
52    /// When specified, uses this file instead of the built-in template.
53    /// The placeholders `__IMPORT_PATH__` and `__RELOAD_ROUTE__` will be replaced.
54    #[arg(long)]
55    #[get(pub(crate))]
56    #[get_mut(pub(crate))]
57    #[set(pub(crate))]
58    pub(crate) index_html: Option<PathBuf>,
59    /// Create a development build. Enable debug info, and disable optimizations
60    #[arg(long)]
61    #[get(pub(crate), type(copy))]
62    #[get_mut(pub(crate))]
63    #[set(pub(crate))]
64    pub(crate) dev: bool,
65    /// Create a release build. Enable optimizations and disable debug info
66    #[arg(long)]
67    #[get(pub(crate), type(copy))]
68    #[get_mut(pub(crate))]
69    #[set(pub(crate))]
70    pub(crate) release: bool,
71    /// Create a profiling build. Enable optimizations and debug info
72    #[arg(long)]
73    #[get(pub(crate), type(copy))]
74    #[get_mut(pub(crate))]
75    #[set(pub(crate))]
76    pub(crate) profiling: bool,
77    /// Remove the .gitignore file from the output directory after building
78    #[arg(long)]
79    #[get(pub(crate), type(copy))]
80    #[get_mut(pub(crate))]
81    #[set(pub(crate))]
82    pub(crate) no_gitignore: bool,
83    /// Arguments transparently forwarded to `wasm-pack build`
84    #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
85    #[get(pub(crate))]
86    #[get_mut(pub(crate))]
87    #[set(pub(crate))]
88    pub(crate) wasm_pack_args: Vec<String>,
89}
90
91/// Arguments for the `fmt` subcommand.
92///
93/// Formats euv macro invocations (`html!`, `class!`, `vars!`, `watch!`)
94/// in Rust source files.
95#[derive(Clone, Debug, Getter, New, Parser)]
96pub struct FmtArgs {
97    /// Path to the directory or file to format
98    #[arg(short, long, default_value = ".")]
99    ///
100    /// Narrowed to `pub(crate)`: the only getter call sites are in
101    /// `cli/src/mode/fn.rs`, which is inside this crate. The integration
102    /// test constructs a `FmtArgs` through `FmtArgs::new` /
103    /// `FmtArgs::parse_from` but never reads the field, so no public
104    /// accessor is required. `Getter` does not generate mutators — no
105    /// caller anywhere mutates the path after parsing.
106    #[get(pub(crate))]
107    pub(crate) path: PathBuf,
108    /// Check if formatting is needed without modifying files
109    #[arg(long, default_value_t = false)]
110    ///
111    /// Narrowed for the same reason as [`FmtArgs::path`]: the flag is read
112    /// only by `cli/src/mode/fn.rs`, and clap's derive is what writes it,
113    /// so `Getter` is the right derive — it generates no mutators.
114    #[get(pub(crate), type(copy))]
115    pub(crate) check: bool,
116}
117
118/// Configuration for server URL display.
119///
120/// Groups all parameters needed by `print_server_urls` into a single struct.
121#[derive(Clone, Data, Debug, New)]
122pub(crate) struct ServerUrlConfig {
123    /// The port number the server is listening on.
124    #[get(pub(crate), type(copy))]
125    #[get_mut(pub(crate))]
126    #[set(pub(crate))]
127    pub(crate) port: u16,
128    /// The serving route prefix (e.g. "www" or "wwws").
129    #[get(pub(crate))]
130    #[get_mut(pub(crate))]
131    #[set(pub(crate))]
132    pub(crate) route_prefix: String,
133    /// The index HTML file name (e.g. "index.html").
134    #[get(pub(crate))]
135    #[get_mut(pub(crate))]
136    #[set(pub(crate))]
137    pub(crate) index_html_file_name: String,
138}
139
140/// One static `import` clause of the wasm-bindgen bridge, parsed into the
141/// bindings a self-contained bootstrap can reproduce.
142///
143/// A single clause carries at most one of the three binding forms: a
144/// namespace alias (`* as alias`), a list of named bindings (`{ a, b }`),
145/// or a default binding. The borrowed lifetimes tie every binding and the
146/// module specifier to the bridge source line they were sliced from.
147#[derive(Debug)]
148pub struct ImportClause<'a> {
149    /// The module specifier, with its quotes and trailing semicolon removed.
150    pub spec: &'a str,
151    /// The local binding of a `* as alias` namespace import.
152    pub namespace: Option<&'a str>,
153    /// The local binding of a default import.
154    pub default_binding: Option<&'a str>,
155    /// The bindings of a `{ a, b }` named import, in source order.
156    pub named: Vec<&'a str>,
157}
158
159/// A namespace import clause found in the bridge: `import * as alias from
160/// "spec"`.
161///
162/// Collected while scanning the bridge's imports so the inlined bootstrap
163/// can rebuild the alias as a plain object once the module graph is gone.
164/// The owned form exists so a namespace binding survives the async read of
165/// the snippet module it points at.
166#[derive(Debug)]
167pub(crate) struct NamespaceImport {
168    /// The local binding the clause introduces.
169    pub(crate) alias: String,
170    /// The module specifier, verbatim with its quotes.
171    pub(crate) spec: String,
172}