1use serde::Deserialize;
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum RenderMode {
7 Phase1ClientMount,
9 Phase2SsrReconcile,
11}
12
13pub struct PageConfig<'a> {
15 pub title: &'a str,
16 pub route_pattern: &'a str,
17 pub manifest: &'a AssetManifest,
18 pub config_script: Option<&'a str>,
20 pub body_class: Option<&'a str>,
21 pub personality_css: Option<&'a str>,
23 pub body_prefix: Option<&'a str>,
25 pub render_mode: RenderMode,
26 pub ir_module: Option<&'a forma_ir::parser::IrModule>,
28 pub slots: Option<&'a forma_ir::slot::SlotData>,
30}
31
32pub struct PageOutput {
34 pub html: String,
35 pub csp: String,
36}
37
38#[derive(Debug, Clone, Deserialize)]
40pub struct AssetManifest {
41 pub version: u32,
42 pub build_hash: String,
43 pub assets: HashMap<String, String>,
44 pub routes: HashMap<String, RouteAssets>,
45 #[serde(default)]
46 pub wasm: Option<WasmAssets>,
47}
48
49#[derive(Debug, Clone, Deserialize)]
51pub struct RouteAssets {
52 pub js: Vec<String>,
53 pub css: Vec<String>,
54 pub fonts: Vec<String>,
55 pub total_size_br: u64,
56 pub budget_warn_threshold: u64,
57 #[serde(default)]
58 pub ir: Option<String>,
59}
60
61#[derive(Debug, Clone, Deserialize)]
63pub struct WasmAssets {
64 pub loader: String,
65 pub binary: String,
66}
67
68impl AssetManifest {
69 pub fn resolve<'a>(&'a self, logical_name: &'a str) -> &'a str {
71 self.assets
72 .get(logical_name)
73 .map(|s| s.as_str())
74 .unwrap_or(logical_name)
75 }
76
77 pub fn route(&self, pattern: &str) -> Option<&RouteAssets> {
79 self.routes.get(pattern)
80 }
81}