use std::fmt;
use std::sync::Arc;
#[allow(unused_imports)]
use crate::error::{Error, Result};
use crate::schema::{Schema, SchemaPackage, Unbound};
#[derive(Clone, PartialEq, Eq)]
pub struct ConnectionOptions {
address: String,
database: String,
username: Option<String>,
password: Option<String>,
http_port: u16,
tls: bool,
}
impl fmt::Debug for ConnectionOptions {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("ConnectionOptions")
.field("address", &self.address)
.field("database", &self.database)
.field("username", &self.username)
.field("password", &self.password.as_ref().map(|_| "[REDACTED]"))
.field("http_port", &self.http_port)
.field("tls", &self.tls)
.finish()
}
}
impl ConnectionOptions {
#[must_use]
pub fn new(address: impl Into<String>, database: impl Into<String>) -> Self {
Self {
address: address.into(),
database: database.into(),
username: None,
password: None,
http_port: 8000,
tls: false,
}
}
#[must_use]
pub fn credentials(mut self, username: impl Into<String>, password: impl Into<String>) -> Self {
self.username = Some(username.into());
self.password = Some(password.into());
self
}
#[must_use]
pub fn http_port(mut self, port: u16) -> Self {
self.http_port = port;
self
}
#[must_use]
pub fn tls(mut self, enabled: bool) -> Self {
self.tls = enabled;
self
}
#[must_use]
pub fn address(&self) -> &str {
&self.address
}
#[must_use]
pub fn database(&self) -> &str {
&self.database
}
#[must_use]
pub fn get_http_port(&self) -> u16 {
self.http_port
}
#[must_use]
pub fn is_tls(&self) -> bool {
self.tls
}
}
impl From<(&str, &str)> for ConnectionOptions {
fn from((address, database): (&str, &str)) -> Self {
Self::new(address, database)
}
}
pub struct Database<S: Schema = Unbound> {
inner: type_bridge_orm::Database,
installed_schema: Option<Arc<type_bridge_orm::InstalledRuntimeProjection>>,
match_registry: Option<Arc<type_bridge_orm::DescriptorRegistry>>,
marker: std::marker::PhantomData<fn() -> S>,
}
fn build_match_registry(
installed: &type_bridge_orm::InstalledRuntimeProjection,
) -> Result<Arc<type_bridge_orm::DescriptorRegistry>> {
installed
.match_registry()
.map(Arc::new)
.map_err(Error::from_orm)
}
impl Database<Unbound> {
#[cfg(feature = "typedb")]
pub async fn connect(options: impl Into<ConnectionOptions>) -> Result<Database<Unbound>> {
let opts = options.into();
let username = opts.username.as_deref().unwrap_or("admin");
let password = opts.password.as_deref().unwrap_or("password");
let orm_opts = type_bridge_orm::ConnectOptions {
http_port: opts.http_port,
tls: opts.tls,
..type_bridge_orm::ConnectOptions::default()
};
let inner = type_bridge_orm::Database::connect_with_options(
&opts.address,
&opts.database,
username,
password,
orm_opts,
)
.await
.map_err(Error::from_orm)?;
Ok(Database {
inner,
installed_schema: None,
match_registry: None,
marker: std::marker::PhantomData,
})
}
#[allow(dead_code)]
pub(crate) fn from_orm_database(inner: type_bridge_orm::Database) -> Self {
Self {
inner,
installed_schema: None,
match_registry: None,
marker: std::marker::PhantomData,
}
}
pub fn with_schema<S: Schema>(self, schema: SchemaPackage<S>) -> Result<Database<S>> {
let installed = schema.verify_and_install()?;
let match_registry = build_match_registry(&installed)?;
Ok(Database {
inner: self.inner,
installed_schema: Some(installed),
match_registry: Some(match_registry),
marker: std::marker::PhantomData,
})
}
}
impl<S: Schema> Database<S> {
#[cfg(test)]
pub(crate) fn from_test_parts(
inner: type_bridge_orm::Database,
installed: type_bridge_orm::InstalledRuntimeProjection,
) -> Self {
let installed = Arc::new(installed);
let match_registry =
build_match_registry(&installed).expect("test projection descriptors register");
Self {
inner,
installed_schema: Some(installed),
match_registry: Some(match_registry),
marker: std::marker::PhantomData,
}
}
#[cfg(test)]
pub(crate) fn from_test_unbound_parts(inner: type_bridge_orm::Database) -> Self {
Self {
inner,
installed_schema: None,
match_registry: None,
marker: std::marker::PhantomData,
}
}
pub fn entities<M>(&self) -> crate::entity_manager::EntityManager<'_, S, M>
where
M: crate::__codegen::EntityModel<Schema = S>,
{
crate::entity_manager::EntityManager::new(self)
}
pub fn relations<M>(&self) -> crate::relation_manager::RelationManager<'_, S, M>
where
M: crate::__codegen::RelationModel<Schema = S>,
{
crate::relation_manager::RelationManager::new(self)
}
pub async fn write(&self) -> Result<crate::transaction::WriteTransaction<'_, S>> {
crate::transaction::WriteTransaction::open(self).await
}
pub async fn read(&self) -> Result<crate::transaction::ReadTransaction<'_, S>> {
crate::transaction::ReadTransaction::open(self).await
}
#[must_use]
pub fn database_name(&self) -> &str {
self.inner.database_name()
}
#[must_use]
pub fn is_schema_bound(&self) -> bool {
self.installed_schema.is_some()
}
#[allow(dead_code)]
pub(crate) fn inner_orm(&self) -> &type_bridge_orm::Database {
&self.inner
}
#[allow(dead_code)]
pub(crate) fn installed_schema(
&self,
) -> Option<&Arc<type_bridge_orm::InstalledRuntimeProjection>> {
self.installed_schema.as_ref()
}
#[allow(dead_code)]
pub(crate) fn match_registry(&self) -> Option<&Arc<type_bridge_orm::DescriptorRegistry>> {
self.match_registry.as_ref()
}
}