coil-runtime 0.1.1

HTTP runtime and request handling for the Coil framework.
Documentation
use super::*;
use coil_i18n::I18nError;
use coil_seo::SeoError;
use coil_template::{DocumentRenderRequest, TemplateKind, TemplateModelError};
use thiserror::Error;

mod model;
mod seo;
mod templates;

#[derive(Debug, Error)]
pub enum RuntimeRenderError {
    #[error(transparent)]
    Template(#[from] TemplateModelError),
    #[error(transparent)]
    I18n(#[from] I18nError),
    #[error(transparent)]
    Seo(#[from] SeoError),
    #[error(transparent)]
    RouteUrl(#[from] RouteUrlError),
}

impl RuntimePlan {
    pub fn render_page_response(
        &self,
        execution: &RequestExecution,
        page: &PageResponse,
        extra_metadata: Option<&TypedMetadata>,
    ) -> Result<String, RuntimeRenderError> {
        let selector = templates::template_selector(&page.template)?;
        let namespaces = self.template_namespaces_for_execution(execution);
        let model = self.render_model_for_execution(execution, &page.template, None)?;

        let html = match self.template.runtime.render_document(
            &namespaces,
            DocumentRenderRequest::new(selector.clone(), model.clone()),
        ) {
            Ok(output) => output.html,
            Err(TemplateModelError::TemplateNotFound { .. })
            | Err(TemplateModelError::TemplateKindMismatch {
                actual: TemplateKind::Fragment,
                ..
            }) => {
                let content =
                    self.render_fragment_content(execution, &namespaces, &selector, model, None)?;
                self.render_document_shell(execution, &page.template, content)?
            }
            Err(error) => return Err(error.into()),
        };

        self.decorate_page_document(execution, &page.template, html, extra_metadata)
    }

    pub fn render_fragment_response(
        &self,
        execution: &RequestExecution,
        fragment: &FragmentResponse,
    ) -> Result<String, RuntimeRenderError> {
        let selector = templates::template_selector(&fragment.template)?;
        let namespaces = self.template_namespaces_for_execution(execution);
        let model = self.render_model_for_execution(
            execution,
            &fragment.template,
            Some(fragment.fragment_id.as_str()),
        )?;

        self.render_fragment_content(
            execution,
            &namespaces,
            &selector,
            model,
            Some(fragment.fragment_id.as_str()),
        )
        .map_err(Into::into)
    }
}