use std::collections::BTreeMap;
use std::fmt::{Display, Formatter};
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::language::CompiledProgram;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateSource {
pub id: String,
pub source_path: Option<PathBuf>,
pub markup: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct ReactiveWebOptions {
pub minify_html: bool,
pub strict_mode: bool,
pub style_engine: StyleEngineMode,
pub runtime_mode: RuntimeMode,
pub reactive_mode: ReactiveMode,
pub allow_list: ResourceAllowList,
pub load_scripts: Vec<String>,
pub components: ComponentOptions,
pub language: LanguageOptions,
#[serde(default)]
pub templates: TemplateOptions,
#[serde(default)]
pub processors: Vec<String>,
}
impl Default for ReactiveWebOptions {
fn default() -> Self {
Self {
minify_html: false,
strict_mode: false,
style_engine: StyleEngineMode::TailwindLike,
runtime_mode: RuntimeMode::Prod,
reactive_mode: ReactiveMode::Bindings,
allow_list: ResourceAllowList::default(),
load_scripts: Vec::new(),
components: ComponentOptions::default(),
language: LanguageOptions::default(),
templates: TemplateOptions::default(),
processors: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TemplateOptions {
#[serde(default)]
pub template_root: Option<PathBuf>,
#[serde(default)]
pub library_roots: std::collections::BTreeMap<String, PathBuf>,
#[serde(default)]
pub style_entries: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ComponentOptions {
#[serde(default)]
pub registry: BTreeMap<String, String>,
#[serde(default)]
pub strict: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "kebab-case")]
pub enum RuntimeMode {
Dev,
#[default]
Prod,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "kebab-case")]
pub enum StyleEngineMode {
Off,
#[default]
TailwindLike,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "kebab-case")]
pub enum ReactiveMode {
Off,
#[default]
Bindings,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ResourceAllowList {
#[serde(default)]
pub css: Vec<String>,
#[serde(default)]
pub scripts: Vec<String>,
#[serde(default)]
pub urls: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LanguageOptions {
#[serde(default)]
pub run_patch: Option<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeBundle {
pub name: String,
pub source: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompiledScript {
pub id: String,
pub scope: CompiledScriptScope,
pub content_type: String,
pub content: String,
pub content_hash: String,
pub suggested_file_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum CompiledScriptScope {
Shared,
Page,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReactiveBinding {
pub kind: String,
pub key: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReactiveWebDiagnostic {
pub code: String,
pub message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompiledTemplate {
pub engine_id: String,
pub template_id: String,
pub html_ir: String,
#[serde(default)]
pub control_script_source: Option<String>,
pub compiled_logic: Option<CompiledProgram>,
pub runtime_bundle: RuntimeBundle,
#[serde(default)]
pub reactive_bindings: Vec<ReactiveBinding>,
#[serde(default)]
pub diagnostics: Vec<ReactiveWebDiagnostic>,
#[serde(default)]
pub needs_runtime_tailwind_rebuild: bool,
#[serde(default)]
pub tailwind_variant_exact_tokens: Vec<String>,
#[serde(default)]
pub tailwind_variant_patterns: Vec<String>,
pub options: ReactiveWebOptions,
#[serde(default)]
pub engine_payload: Option<Value>,
#[serde(default)]
pub dependency_paths: std::collections::HashSet<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RenderContext {
pub route: String,
pub request_id: String,
pub metadata: Value,
#[serde(default)]
pub enabled_libraries: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RenderOutput {
pub html: String,
#[serde(default)]
pub compiled_scripts: Vec<CompiledScript>,
pub hydration_payload: Value,
pub trace: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReactiveWebError {
pub code: &'static str,
pub message: String,
}
impl ReactiveWebError {
pub fn new(code: &'static str, message: impl Into<String>) -> Self {
Self {
code,
message: message.into(),
}
}
}
impl Display for ReactiveWebError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.code, self.message)
}
}
impl std::error::Error for ReactiveWebError {}