Files
tuono/crates/tuono_lib/src/payload.rs
T

174 lines
5.0 KiB
Rust
Raw Normal View History

use crate::config::GLOBAL_CONFIG;
2024-07-02 21:59:30 +02:00
use crate::manifest::MANIFEST;
2025-03-29 10:50:58 +01:00
use crate::mode::{GLOBAL_MODE, Mode};
use erased_serde::Serialize;
use serde::Serialize as SerdeSerialize;
use tuono_internal::config::ServerConfig;
2024-06-23 20:15:33 +02:00
use crate::request::{Location, Request};
#[derive(SerdeSerialize)]
2024-06-23 20:15:33 +02:00
/// This is the payload sent to the client for hydration
pub struct Payload<'a> {
2025-01-25 15:56:10 +01:00
location: Location,
data: &'a dyn Serialize,
2024-06-23 20:15:33 +02:00
mode: Mode,
#[serde(rename(serialize = "jsBundles"))]
2025-05-24 18:34:02 +02:00
js_bundles: Option<Vec<String>>,
2024-06-23 20:15:33 +02:00
#[serde(rename(serialize = "cssBundles"))]
2025-05-24 18:34:02 +02:00
css_bundles: Option<Vec<String>>,
#[serde(rename(serialize = "devServerConfig"))]
dev_server_config: Option<&'a ServerConfig>,
}
impl<'a> Payload<'a> {
2025-01-25 15:56:10 +01:00
pub fn new(req: &'a Request, data: &'a dyn Serialize) -> Payload<'a> {
let config = GLOBAL_CONFIG
.get()
.expect("Failed to load the current config");
let mode = *GLOBAL_MODE.get().expect("Failed to load the current mode");
let dev_server_config = if mode == Mode::Dev {
Some(&config.server)
} else {
None
};
Payload {
2025-01-25 15:56:10 +01:00
location: req.location(),
data,
mode,
2024-06-23 20:15:33 +02:00
js_bundles: None,
css_bundles: None,
dev_server_config,
}
}
2024-06-23 20:15:33 +02:00
pub fn client_payload(&mut self) -> Result<String, serde_json::Error> {
if self.mode == Mode::Prod {
self.add_bundle_sources();
}
serde_json::to_string(&self)
}
2024-06-23 20:15:33 +02:00
fn add_bundle_sources(&mut self) {
2025-05-24 18:34:02 +02:00
let manifest = MANIFEST.get().expect("Manifest not loaded");
let bundles = manifest.get_bundle_from_pathname(self.location.pathname());
self.js_bundles = Some(bundles.js_files);
self.css_bundles = Some(bundles.css_files);
2024-06-23 20:15:33 +02:00
}
}
#[cfg(test)]
mod tests {
use super::*;
2025-05-24 18:34:02 +02:00
use crate::manifest::ViteManifest;
2024-06-23 20:15:33 +02:00
use axum::http::Uri;
2025-05-24 18:34:02 +02:00
const MANIFEST_EXAMPLE: &str = r#"{
"../src/routes/index.tsx": {
"file": "assets/index-D-yFyCZo.js",
"name": "index",
"src": "../src/routes/index.tsx",
"isDynamicEntry": true,
"imports": [
"client-main.tsx"
],
"css": [
"assets/index-CynfArjF.css"
]
},
"../src/routes/pokemons/[pokemon].tsx": {
"file": "assets/_pokemon_-DlFInatQ.js",
"name": "_pokemon_",
"src": "../src/routes/pokemons/[pokemon].tsx",
"isDynamicEntry": true,
"imports": [
"client-main.tsx"
],
"css": [
"assets/_pokemon_-BcJZaQaO.css"
]
},
"../src/routes/pokemons/__layout.tsx": {
"file": "assets/__layout-BFnT3M7X.js",
"name": "__layout",
"src": "../src/routes/pokemons/__layout.tsx",
"isDynamicEntry": true,
"imports": [
"client-main.tsx"
],
"css": [
"assets/__layout-CXGGqNw5.css"
]
},
"client-main.tsx": {
"file": "assets/client-main-B9g1NVV7.js",
"name": "client-main",
"src": "client-main.tsx",
"isEntry": true,
"dynamicImports": [
"../src/routes/pokemons/__layout.tsx",
"../src/routes/index.tsx",
"../src/routes/pokemons/[pokemon].tsx"
],
"css": [
"assets/client-main-BS7N-NIa.css"
]
}
}"#;
2024-06-23 20:15:33 +02:00
fn prepare_payload(uri: Option<&str>, mode: Mode) -> Payload {
2025-05-24 18:34:02 +02:00
let manifest_mock = serde_json::from_str::<ViteManifest>(MANIFEST_EXAMPLE)
.expect("Failed to parse the manifest example");
MANIFEST.get_or_init(|| manifest_mock.into());
2024-07-11 21:43:38 +02:00
let uri = uri
.unwrap_or("http://localhost:3000/")
.parse::<Uri>()
.unwrap();
let location = Location::from(uri);
2024-06-23 20:15:33 +02:00
Payload {
2025-01-25 15:56:10 +01:00
location,
data: &None::<Option<()>>,
2024-06-23 20:15:33 +02:00
mode,
js_bundles: None,
css_bundles: None,
dev_server_config: None,
2024-06-23 20:15:33 +02:00
}
}
#[test]
fn should_load_the_bundles_on_mode_prod() {
let mut payload = prepare_payload(None, Mode::Prod);
let _ = payload.client_payload();
assert_eq!(
payload.js_bundles,
Some(vec![
2025-05-24 18:34:02 +02:00
"assets/index-D-yFyCZo.js".to_string(),
"assets/client-main-B9g1NVV7.js".to_string()
2024-06-23 20:15:33 +02:00
])
);
assert_eq!(
payload.css_bundles,
Some(vec![
2025-05-24 18:34:02 +02:00
"assets/index-CynfArjF.css".to_string(),
"assets/client-main-BS7N-NIa.css".to_string()
2024-06-23 20:15:33 +02:00
])
);
}
#[test]
fn should_not_load_the_bundles_on_mode_dev() {
let mut payload = prepare_payload(None, Mode::Dev);
let _ = payload.client_payload();
assert!(payload.js_bundles.is_none());
assert!(payload.css_bundles.is_none());
}
}