use std::borrow::Cow;
use std::marker::PhantomData;
use std::path::Path;
use std::pin::Pin;
use std::sync::{Arc, OnceLock};
use std::time::Duration;
use crate::opt::auth::{Credentials, Token};
use crate::opt::{IntoEndpoint, IntoExportDestination, WaitFor, auth};
use crate::types::{SurrealValue, Value, Variables};
use crate::{Connect, Connection, OnceLockExt, SessionClone, Surreal};
pub(crate) mod live;
pub(crate) mod query;
mod authenticate;
mod begin;
mod cancel;
mod commit;
mod content;
mod create;
mod delete;
mod export;
mod health;
mod import;
mod insert;
mod insert_relation;
mod invalidate;
mod merge;
mod patch;
mod run;
mod select;
mod set;
mod signin;
mod signup;
mod transaction;
mod unset;
mod update;
mod upsert;
mod use_db;
mod use_defaults;
mod use_ns;
mod version;
#[cfg(test)]
mod tests;
pub use authenticate::Authenticate;
pub use begin::Begin;
pub use cancel::Cancel;
pub use commit::Commit;
pub use content::Content;
pub use create::Create;
pub use delete::Delete;
pub use export::{Backup, Export};
use futures::Future;
pub use health::Health;
pub use import::Import;
pub use insert::Insert;
pub use invalidate::Invalidate;
pub use live::Stream;
pub use merge::Merge;
pub use patch::Patch;
pub use query::{IntoVariables, Query, QueryStream};
pub use run::{IntoFn, Run};
pub use select::Select;
pub use set::Set;
pub use signin::Signin;
pub use signup::Signup;
use tokio::sync::watch;
pub use transaction::Transaction;
pub use unset::Unset;
pub use update::Update;
pub use upsert::Upsert;
pub use use_db::UseDb;
pub use use_defaults::UseDefaults;
pub use use_ns::UseNs;
pub use version::Version;
use super::opt::{CreateResource, IntoResource};
pub(crate) type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>;
pub struct Model;
pub struct ExportConfig;
pub struct Live;
pub struct Relation;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct Stats {
pub execution_time: Option<Duration>,
}
#[derive(Debug)]
pub struct WithStats<T>(pub T);
impl<C> Surreal<C>
where
C: Connection,
{
pub fn init() -> Self {
Arc::new(super::Inner {
router: OnceLock::new(),
waiter: watch::channel(None),
session_clone: SessionClone::new(),
})
.into()
}
pub fn new<P>(address: impl IntoEndpoint<P, Client = C>) -> Connect<C, Self> {
Connect {
surreal: Surreal::init(),
address: address.into_endpoint(),
capacity: 0,
response_type: PhantomData,
}
}
pub fn begin(self) -> Begin<C> {
Begin {
client: self,
}
}
pub fn use_defaults(&self) -> UseDefaults<'_, C> {
UseDefaults {
client: Cow::Borrowed(self),
}
}
pub fn use_ns(&self, ns: impl Into<String>) -> UseNs<'_, C> {
UseNs {
client: Cow::Borrowed(self),
ns: ns.into(),
}
}
pub fn use_db(&self, db: impl Into<String>) -> UseDb<'_, C> {
UseDb {
client: Cow::Borrowed(self),
ns: None,
db: db.into(),
}
}
pub fn set(&self, key: impl Into<String>, value: impl SurrealValue) -> Set<'_, C> {
Set {
client: Cow::Borrowed(self),
key: key.into(),
value: value.into_value(),
}
}
pub fn unset(&'_ self, key: impl Into<String>) -> Unset<'_, C> {
Unset {
client: Cow::Borrowed(self),
key: key.into(),
}
}
pub fn signup(&'_ self, credentials: impl Credentials<auth::Signup>) -> Signup<'_, C> {
Signup {
client: Cow::Borrowed(self),
credentials: credentials.into_value(),
}
}
pub fn signin(&'_ self, credentials: impl Credentials<auth::Signin>) -> Signin<'_, C> {
Signin {
client: Cow::Borrowed(self),
credentials: credentials.into_value(),
}
}
pub fn invalidate(&'_ self) -> Invalidate<'_, C> {
Invalidate {
client: Cow::Borrowed(self),
token: Value::None,
typ: PhantomData,
}
}
pub fn authenticate(&'_ self, token: impl Into<Token>) -> Authenticate<'_, C> {
Authenticate {
client: Cow::Borrowed(self),
token: token.into(),
token_type: PhantomData,
}
}
#[must_use = "queries do nothing unless you `.await` or poll them"]
pub fn query<'client>(&'client self, query: impl Into<Cow<'client, str>>) -> Query<'client, C> {
Query {
txn: None,
client: Cow::Borrowed(self),
query: query.into(),
variables: Ok(Variables::new()),
}
}
pub fn select<O>(&'_ self, resource: impl IntoResource<O>) -> Select<'_, C, O> {
Select {
txn: None,
client: Cow::Borrowed(self),
resource: resource.into_resource(),
response_type: PhantomData,
query_type: PhantomData,
}
}
pub fn create<R>(&'_ self, resource: impl CreateResource<R>) -> Create<'_, C, R> {
Create {
txn: None,
client: Cow::Borrowed(self),
resource: resource.into_resource(),
response_type: PhantomData,
}
}
pub fn insert<O>(&self, resource: impl IntoResource<O>) -> Insert<'_, C, O> {
Insert {
txn: None,
client: Cow::Borrowed(self),
resource: resource.into_resource(),
response_type: PhantomData,
}
}
pub fn upsert<O>(&'_ self, resource: impl IntoResource<O>) -> Upsert<'_, C, O> {
Upsert {
txn: None,
client: Cow::Borrowed(self),
resource: resource.into_resource(),
response_type: PhantomData,
}
}
pub fn update<O>(&'_ self, resource: impl IntoResource<O>) -> Update<'_, C, O> {
Update {
txn: None,
client: Cow::Borrowed(self),
resource: resource.into_resource(),
response_type: PhantomData,
}
}
pub fn delete<O>(&'_ self, resource: impl IntoResource<O>) -> Delete<'_, C, O> {
Delete {
txn: None,
client: Cow::Borrowed(self),
resource: resource.into_resource(),
response_type: PhantomData,
}
}
pub fn version(&'_ self) -> Version<'_, C> {
Version {
client: Cow::Borrowed(self),
}
}
pub fn run<R>(&'_ self, function: impl IntoFn) -> Run<'_, C, R> {
Run {
client: Cow::Borrowed(self),
function: function.into_fn(),
args: Value::None,
response_type: PhantomData,
}
}
pub fn health(&'_ self) -> Health<'_, C> {
Health {
client: Cow::Borrowed(self),
}
}
pub async fn wait_for(&'_ self, event: WaitFor) {
let mut rx = self.inner.waiter.0.subscribe();
rx.wait_for(|current| match current {
None => false,
Some(WaitFor::Connection) => matches!(event, WaitFor::Connection),
Some(WaitFor::Database) => matches!(event, WaitFor::Connection | WaitFor::Database),
})
.await
.ok();
}
pub fn export<R>(&'_ self, target: impl IntoExportDestination<R>) -> Export<'_, C, R> {
Export {
client: Cow::Borrowed(self),
target: target.into_export_destination(),
ml_config: None,
db_config: None,
response: PhantomData,
export_type: PhantomData,
}
}
pub fn import<P>(&'_ self, file: P) -> Import<'_, C>
where
P: AsRef<Path>,
{
Import {
client: Cow::Borrowed(self),
file: file.as_ref().to_owned(),
is_ml: false,
import_type: PhantomData,
}
}
}
fn validate_data(data: &Value, error_message: &str) -> crate::Result<()> {
match data {
Value::Object(_) => Ok(()),
Value::Array(v) if v.iter().all(Value::is_object) => Ok(()),
_ => Err(crate::Error::validation(error_message.to_owned(), None)),
}
}