vertigo_cli/serve/
mount_path.rs1#![allow(clippy::question_mark)]
2use std::{collections::HashMap, path::Path, sync::Arc};
3use vertigo::dev::VERTIGO_PUBLIC_BUILD_PATH_PLACEHOLDER;
4
5use crate::commons::{ErrorCode, models::IndexModel};
6
7pub struct MountConfigBuilder {
8 pub mount_point: String,
9 pub dest_dir: String,
10 pub env: Vec<(String, String)>,
11 pub wasm_preload: bool,
12 pub disable_hydration: bool,
13}
14
15impl MountConfigBuilder {
16 pub fn new(mount_point: impl Into<String>, dest_dir: impl Into<String>) -> MountConfigBuilder {
17 MountConfigBuilder {
18 mount_point: mount_point.into(),
19 dest_dir: dest_dir.into(),
20 env: vec![],
21 wasm_preload: false,
22 disable_hydration: false,
23 }
24 }
25
26 pub fn envs(mut self, envs: Vec<(String, String)>) -> Self {
27 self.env = envs;
28 self
29 }
30
31 pub fn env(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
32 self.env.push((key.into(), value.into()));
33 self
34 }
35
36 pub fn wasm_preload(mut self, wasm_preload: bool) -> Self {
37 self.wasm_preload = wasm_preload;
38 self
39 }
40
41 pub fn disable_hydration(mut self, disable_hydration: bool) -> Self {
42 self.disable_hydration = disable_hydration;
43 self
44 }
45
46 pub fn build(self) -> Result<MountConfig, ErrorCode> {
47 MountConfig::new(
48 self.mount_point,
49 self.dest_dir,
50 self.env,
51 self.wasm_preload,
52 self.disable_hydration,
53 )
54 }
55}
56
57#[derive(Clone, Debug)]
58pub struct MountConfig {
59 mount_point: String,
61 dest_dir: String,
63 run_js: String,
65 wasm_path: String,
67 pub env: Arc<HashMap<String, String>>,
69 pub wasm_preload: bool,
71 pub disable_hydration: bool,
73}
74
75impl MountConfig {
76 pub fn new(
77 public_mount_point: impl Into<String>,
78 dest_dir: impl Into<String>,
79 env: Vec<(String, String)>,
80 wasm_preload: bool,
81 disable_hydration: bool,
82 ) -> Result<MountConfig, ErrorCode> {
83 let dest_dir = dest_dir.into();
84 let index_model = read_index(&dest_dir)?;
85
86 Ok(MountConfig {
87 dest_dir,
88 mount_point: public_mount_point.into(),
89 run_js: index_model.run_js,
90 wasm_path: index_model.wasm,
91 env: Arc::new(env.into_iter().collect()),
92 wasm_preload,
93 disable_hydration,
94 })
95 }
96
97 pub fn mount_point(&self) -> &str {
98 self.mount_point.as_str()
99 }
100
101 pub fn dest_dir(&self) -> &str {
102 self.dest_dir.trim_start_matches("./")
103 }
104
105 pub fn dest_http_root(&self) -> String {
106 Path::new(&self.mount_point)
107 .join(self.dest_dir())
108 .components()
109 .as_path()
110 .to_string_lossy()
111 .into_owned()
112 }
113
114 pub fn get_wasm_http_path(&self) -> String {
115 self.translate_to_http(&self.wasm_path)
116 }
117
118 pub fn get_run_js_http_path(&self) -> String {
119 self.translate_to_http(&self.run_js)
120 }
121
122 pub fn get_wasm_fs_path(&self) -> String {
123 self.translate_to_fs(&self.wasm_path)
124 }
125
126 fn translate_to_http(&self, fs_path: impl Into<String>) -> String {
127 let fs_path = fs_path.into();
128 fs_path.replace(
129 VERTIGO_PUBLIC_BUILD_PATH_PLACEHOLDER,
130 &self.dest_http_root(),
131 )
132 }
133
134 fn translate_to_fs(&self, http_path: impl Into<String>) -> String {
135 let http_path = http_path.into();
136 replace_prefix(&self.dest_dir, &http_path)
137 }
138}
139
140fn read_index(dest_dir: &str) -> Result<IndexModel, ErrorCode> {
141 let index_path = Path::new(dest_dir).join("index.json");
142 let index_html = match std::fs::read_to_string(&index_path) {
143 Ok(data) => data,
144 Err(err) => {
145 log::error!("File read error: file={index_path:?}, error={err}, dest_dir={dest_dir}");
146 return Err(ErrorCode::ServeCantReadIndexFile);
147 }
148 };
149
150 serde_json::from_str::<IndexModel>(&index_html).map_err(|err| {
151 log::error!("File read error 2: file={index_path:?}, error={err}, dest_dir={dest_dir}");
152 ErrorCode::ServeCantReadIndexFile
153 })
154}
155
156fn replace_prefix(dest_dir: &str, path: &str) -> String {
157 if path.starts_with(VERTIGO_PUBLIC_BUILD_PATH_PLACEHOLDER) {
158 path.replace(VERTIGO_PUBLIC_BUILD_PATH_PLACEHOLDER, dest_dir)
160 } else {
161 path.to_string()
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use vertigo::dev::VERTIGO_PUBLIC_BUILD_PATH_PLACEHOLDER;
169
170 use super::replace_prefix;
171
172 #[test]
173 fn test_replace_prefix() {
174 assert_eq!(
175 replace_prefix("demo_build", "build/vertigo_demo.33.wasm"),
176 "build/vertigo_demo.33.wasm".to_string()
177 );
178
179 assert_eq!(
180 replace_prefix("demo_build", "build/vertigo_demo.33.wasm"),
181 "build/vertigo_demo.33.wasm".to_string()
182 );
183
184 assert_eq!(
185 replace_prefix(
186 "demo_build",
187 &format!("{VERTIGO_PUBLIC_BUILD_PATH_PLACEHOLDER}/vertigo_demo.33.wasm")
188 ),
189 "demo_build/vertigo_demo.33.wasm".to_string()
190 );
191 }
192}