trinja 0.7.1

HTML templating / SSG for RDF(S) resources
Documentation
use std::sync::Arc;

use minijinja::{State, Value, value::Object};
use taganak_core::graphs::Graph;
use taganak_framework::prelude::TryStreamExt;
use taganak_orm::re::{GraphView, Term};
use tokio::runtime::Handle;
use tracing::trace;

use crate::{
    ParamsWithEnv,
    res::{object::TermList, str_to_term},
};

#[derive(Debug, Clone)]
pub struct GraphFn<'e, G> {
    params: ParamsWithEnv<'e, G>,
}

impl<'e, G> GraphFn<'e, G>
where
    G: Graph + std::fmt::Debug + Sync + 'static,
{
    pub fn new(params: ParamsWithEnv<'e, G>) -> Self {
        Self { params }
    }
}

impl<G> Object for GraphFn<'_, G>
where
    G: Graph + std::fmt::Debug + Sync + 'static,
    Self: 'static,
{
    fn call(
        self: &Arc<Self>,
        _state: &State<'_, '_>,
        args: &[Value],
    ) -> Result<Value, minijinja::Error> {
        if args.len() < 2 {
            return Err(minijinja::Error::new(
                minijinja::ErrorKind::MissingArgument,
                "needs predicate and object",
            ));
        }

        if args.len() > 2 {
            return Err(minijinja::Error::new(
                minijinja::ErrorKind::TooManyArguments,
                "too many arguments",
            ));
        }

        let handle = Handle::current();

        handle.block_on(async {
            let subject = if args[0].is_none() {
                None
            } else {
                Some(str_to_term(self.params.clone().to_params(), &args[0].to_string()).unwrap())
            };

            let predicate = if args[1].is_none() {
                None
            } else {
                Some(str_to_term(self.params.clone().to_params(), &args[1].to_string()).unwrap())
            };

            trace!(?subject, ?predicate, "finding matching subjects");

            let graph = self.params.graph.read().unwrap();
            let view = graph.view().await;
            static LIMIT: usize = 256;
            let objects = view
                .objects(subject.as_ref(), predicate.as_ref(), Some(LIMIT))
                .await
                .unwrap()
                .try_collect::<Vec<Arc<Term>>>()
                .await
                .unwrap();

            Ok(Value::from_object(TermList::new(
                self.params.clone(),
                objects,
            )))
        })
    }
}