dinoco 0.0.1

A modern Rust ORM for schema-driven queries, migrations, and database operations.
Documentation
use dinoco_engine::{DinocoAdapter, DinocoClient, Expression};

use crate::{FindMany, IntoCountNode, IntoIncludeNode, Model, OrderBy, Projection};

#[derive(Debug, Clone)]
pub struct FindFirst<M, S = M> {
    pub inner: FindMany<M, S>,
}

pub fn find_first<M>() -> FindFirst<M>
where
    M: Model + Projection<M>,
{
    FindFirst { inner: crate::find_many::<M>().take(1) }
}

impl<M, S> FindFirst<M, S>
where
    M: Model,
    S: Projection<M>,
{
    pub fn select<NS>(self) -> FindFirst<M, NS>
    where
        NS: Projection<M>,
    {
        FindFirst { inner: self.inner.select::<NS>() }
    }

    pub fn cond<F>(self, closure: F) -> Self
    where
        F: FnOnce(M::Where) -> Expression,
    {
        Self { inner: self.inner.cond(closure) }
    }

    pub fn take(self, value: usize) -> Self {
        Self { inner: self.inner.take(value) }
    }

    pub fn skip(self, value: usize) -> Self {
        Self { inner: self.inner.skip(value) }
    }

    pub fn order_by<F>(self, closure: F) -> Self
    where
        F: FnOnce(M::Where) -> OrderBy,
    {
        Self { inner: self.inner.order_by(closure) }
    }

    pub fn includes<F, I>(self, closure: F) -> Self
    where
        F: FnOnce(M::Include) -> I,
        I: IntoIncludeNode,
    {
        Self { inner: self.inner.includes(closure) }
    }

    pub fn count<F, I>(self, closure: F) -> Self
    where
        F: FnOnce(M::Include) -> I,
        I: IntoCountNode,
    {
        Self { inner: self.inner.count(closure) }
    }

    pub fn read_in_primary(self) -> Self {
        Self { inner: self.inner.read_in_primary() }
    }

    pub fn execute<'a, A>(
        self,
        client: &'a DinocoClient<A>,
    ) -> impl std::future::Future<Output = dinoco_engine::DinocoResult<Option<S>>> + 'a
    where
        A: DinocoAdapter,
    {
        async move {
            let mut rows = crate::execute_many::<M, S, A>(
                self.inner.statement.limit(1),
                &self.inner.includes,
                &self.inner.counts,
                self.inner.read_mode,
                client,
            )
            .await?;

            Ok(rows.drain(..).next())
        }
    }
}