use crate::prelude::*;
#[_impls]
use chrono::{DateTime, Utc};
use cido_macros::_impls;
#[derive(Clone)]
pub struct TableDescriptor<T: Transformer> {
pub base_table_name: &'static str,
pub fields: &'static [ColDescription],
pub id_field: &'static ColDescription,
pub event_order_field: &'static ColDescription,
pub constraints: &'static [TableConstraint],
pub record_kind: RecordType,
pub max_table_rows: u64,
pub max_table_bytes: u64,
pub table_resolver: fn() -> &'static std::sync::OnceLock<TableResolver<T>>,
}
impl<T: Transformer> TableDescriptor<T> {
pub fn table_resolver(&self) -> &'static TableResolver<T> {
(self.table_resolver)().get().unwrap_or_else(|| {
panic!(
"TableResolver for {} has already been initialized",
std::any::type_name::<T>()
)
})
}
pub(crate) fn fields_list(&self) -> impl Iterator<Item = &'static str> {
self.fields.iter().map(|c| c.name)
}
pub(crate) const fn event_order_field(&self) -> &'static str {
&self.event_order_field.name
}
}
#[derive(Clone)]
pub struct ColDescription {
pub name: &'static str,
pub type_fn: fn() -> sqlx::postgres::PgTypeInfo,
pub constraints: &'static [ColConstraint],
pub is_static: bool,
pub indexed: bool,
}
pub struct TableConstraint {
pub(crate) name: Option<&'static str>,
pub(crate) apply_only_current: bool,
pub(crate) apply_not_current: bool,
pub(crate) constraint_type: TableConstraintType,
}
impl TableConstraint {
pub const fn new(constraint_type: TableConstraintType, name: Option<&'static str>) -> Self {
Self {
name,
apply_only_current: false,
apply_not_current: false,
constraint_type,
}
}
pub const fn apply_to_current(mut self) -> Self {
assert!(!self.apply_not_current);
self.apply_only_current = true;
self
}
pub const fn apply_to_non_current(mut self) -> Self {
assert!(!self.apply_only_current);
self.apply_not_current = true;
self
}
}
#[non_exhaustive]
pub enum TableConstraintType {
Exclude { method: &'static str },
Unique { columns: &'static [&'static str] },
PrimaryKey { columns: &'static [&'static str] },
Check { check: &'static str },
Raw { raw_sql: &'static str },
}
#[derive(Clone, Copy)]
pub enum ColConstraint {
PrimaryKey,
NotNull,
Check { check: &'static str },
}
pub trait LoadLocator: core::fmt::Display {}
#[_impls]
impl LoadLocator for &str {}
#[_impls]
pub struct TableResolver<T: Transformer> {
inner: std::marker::PhantomData<fn() -> T>,
}
#[_impls]
impl<T: Transformer> TableResolver<T> {
pub fn get_table_for_block_number(
&self,
number: <<T::Cidomap as Cidomap>::Network as Network>::BlockNumber,
) -> impl LoadLocator {
"unknown"
}
pub fn get_tables_for_range(
&self,
range: &<<T::Cidomap as Cidomap>::Network as Network>::BlockNumberRange,
) -> impl LoadLocator {
"unknown"
}
}
#[_impls]
pub struct MetaInfo<N: Network> {
sync_block: N::BlockNumber,
chain_head: N::BlockNumber,
last_synced: DateTime<Utc>,
initialized_at: DateTime<Utc>,
}
#[_impls]
impl<N: Network> MetaInfo<N> {
pub async fn get<'a, 'c: 'a, C>(conn: C) -> sqlx::Result<Self>
where
C: sqlx::Executor<'c, Database = sqlx::Postgres> + 'a + Send,
{
unimplemented!()
}
pub fn get_sync_block(&self) -> N::BlockNumber {
self.sync_block
}
}
#[_impls]
#[async_graphql::Object]
impl<N: Network> MetaInfo<N> {
#[graphql(name = "lastSynced")]
pub async fn graphql_last_synced(&self) -> DateTime<Utc> {
self.last_synced
}
#[graphql(name = "syncBlock")]
pub async fn graphql_sync_block(&self) -> N::BlockNumber {
self.get_sync_block()
}
#[graphql(name = "initializedAt")]
pub async fn graphql_initialized_at(&self) -> DateTime<Utc> {
self.initialized_at
}
#[graphql(name = "synced")]
pub async fn graphql_synced(
&self,
ctx: &async_graphql::Context<'_>,
) -> async_graphql::Result<bool> {
let _ = ctx;
Ok(self.chain_head <= self.sync_block)
}
#[graphql(name = "chainHead")]
pub async fn graphql_chain_head(&self) -> N::BlockNumber {
self.chain_head
}
}