1use super::*;
2
3pub async fn build_mode(mut args: ModeArgs) -> Result<(), EuvError> {
13 reconcile_args(&mut args);
14 args.set_crate_path(
15 sync_canonicalize(args.get_crate_path()).map_err(|error: io::Error| EuvError::IoPath {
16 message: ERROR_INVALID_CRATE_PATH.to_string(),
17 path: args.get_crate_path().clone(),
18 error,
19 })?,
20 );
21 let crate_path_str: String = args.get_crate_path().to_string_lossy().to_string();
22 if crate_path_str.starts_with(WINDOWS_UNC_PREFIX) {
23 args.set_crate_path(PathBuf::from(
24 crate_path_str
25 .strip_prefix(WINDOWS_UNC_PREFIX)
26 .unwrap_or(&crate_path_str),
27 ));
28 }
29 print_banner(Action::Build);
30 run_build_only_pipeline(&args).await?;
31 log::info!("Build completed. Exiting (build-only mode).");
32 Ok(())
33}
34
35pub async fn fmt_mode(args: FmtArgs) -> Result<(), EuvError> {
45 let fmt_path: PathBuf = if args.get_path().is_absolute() {
46 args.get_path().clone()
47 } else {
48 current_dir()
49 .map_err(|error: io::Error| EuvError::Io {
50 message: ERROR_CURRENT_DIRECTORY.to_string(),
51 error,
52 })?
53 .join(args.get_path())
54 };
55 let mode: FmtMode = if args.get_check() {
56 FmtMode::Check
57 } else {
58 FmtMode::Write
59 };
60 format_dir(&fmt_path, mode).await
61}
62
63#[hyperlane(server: Server)]
73pub async fn run_mode(mut args: ModeArgs) -> Result<(), EuvError> {
74 reconcile_args(&mut args);
75 args.set_crate_path(
76 sync_canonicalize(args.get_crate_path()).map_err(|error: io::Error| EuvError::IoPath {
77 message: ERROR_INVALID_CRATE_PATH.to_string(),
78 path: args.get_crate_path().clone(),
79 error,
80 })?,
81 );
82 let crate_path_str: String = args.get_crate_path().to_string_lossy().to_string();
83 if crate_path_str.starts_with(WINDOWS_UNC_PREFIX) {
84 args.set_crate_path(PathBuf::from(
85 crate_path_str
86 .strip_prefix(WINDOWS_UNC_PREFIX)
87 .unwrap_or(&crate_path_str),
88 ));
89 }
90 let serving_route_prefix: String = resolve_serving_route_prefix(&args);
91 let initial_html: String = match run_build_pipeline(&args, None).await {
92 Ok(html) => html,
93 Err(error) => {
94 log::error!("Initial build pipeline failed: {error}");
95 let html_config: HtmlConfig = HtmlConfig::new(
96 resolve_serving_root(&args).await,
97 resolve_import_path(&args),
98 resolve_build_mode(&args) == BuildMode::Release,
99 args.try_get_index_html().clone(),
100 true,
101 );
102 generate_html(&html_config).await?
103 }
104 };
105 print_banner(Action::Run);
106 let (reload_tx, _): (
107 broadcast::Sender<ReloadEvent>,
108 broadcast::Receiver<ReloadEvent>,
109 ) = broadcast::channel(16);
110 let state: Arc<AppState> = Arc::new(AppState::new(
111 RwLock::new(initial_html),
112 reload_tx.clone(),
113 RwLock::new(false),
114 args.clone(),
115 ));
116 let state_for_watch: Arc<AppState> = Arc::clone(&state);
117 tokio::spawn(async move {
118 if let Err(error) = watch_and_build(state_for_watch).await {
119 log::error!("Watch error: {error}");
120 }
121 });
122 let pkg_dir: PathBuf = resolve_pkg_dir(&args);
123 log::info!("Serving pkg from: {}", pkg_dir.display());
124 let mut server_config: ServerConfig = ServerConfig::default();
125 server_config.set_nodelay(Some(false));
126 server_config.set_address(Server::format_bind_address(DEFAULT_HOST, args.get_port()));
127 server.server_config(server_config);
128 server.route::<IndexRoute>(format!("{serving_route_prefix}/{{path:.*}}"));
129 if let Err(error) = set_global_state(Arc::clone(&state)) {
130 log::error!("Failed to set global state: {error}");
131 }
132 print_server_urls(&ServerUrlConfig::new(
133 args.get_port(),
134 serving_route_prefix.clone(),
135 INDEX_HTML_FILE_NAME.to_string(),
136 ));
137 let server_control_hook: ServerControlHook = server
138 .run()
139 .await
140 .map_err(|error: Box<ServerError>| EuvError::Server(error.to_string()))?;
141 server_control_hook.wait().await;
142 Ok(())
143}