use cratestack_core::ModelEventKind;
use cratestack_policy::ReadPolicy;
use super::{CreateDefault, ModelColumn};
pub trait ReadSource<M, PK>: Send + Sync {
fn schema_name(&self) -> &'static str;
fn table_name(&self) -> &'static str;
fn columns(&self) -> &'static [ModelColumn];
fn primary_key(&self) -> &'static str;
fn allowed_fields(&self) -> &'static [&'static str];
fn allowed_includes(&self) -> &'static [&'static str];
fn allowed_sorts(&self) -> &'static [&'static str];
fn read_allow_policies(&self) -> &'static [ReadPolicy];
fn read_deny_policies(&self) -> &'static [ReadPolicy];
fn detail_allow_policies(&self) -> &'static [ReadPolicy];
fn detail_deny_policies(&self) -> &'static [ReadPolicy];
fn soft_delete_column(&self) -> Option<&'static str>;
fn select_projection(&self) -> String {
use std::fmt::Write;
let mut sql = String::new();
for (index, column) in self.columns().iter().enumerate() {
if index > 0 {
sql.push_str(", ");
}
let _ = write!(sql, "{} AS \"{}\"", column.sql_name, column.rust_name);
}
sql
}
fn select_projection_subset(&self, columns: &[&str]) -> String {
use std::fmt::Write;
let mut sql = String::new();
let mut emitted = false;
for column in self.columns().iter() {
if columns.iter().any(|name| *name == column.sql_name) {
if emitted {
sql.push_str(", ");
}
let _ = write!(sql, "{} AS \"{}\"", column.sql_name, column.rust_name);
emitted = true;
}
}
if !emitted {
if let Some(pk_column) = self
.columns()
.iter()
.find(|column| column.sql_name == self.primary_key())
{
let _ = write!(sql, "{} AS \"{}\"", pk_column.sql_name, pk_column.rust_name);
}
}
sql
}
}
pub trait WriteSource<M, PK>: ReadSource<M, PK> {
fn create_allow_policies(&self) -> &'static [ReadPolicy];
fn create_deny_policies(&self) -> &'static [ReadPolicy];
fn update_allow_policies(&self) -> &'static [ReadPolicy];
fn update_deny_policies(&self) -> &'static [ReadPolicy];
fn delete_allow_policies(&self) -> &'static [ReadPolicy];
fn delete_deny_policies(&self) -> &'static [ReadPolicy];
fn create_defaults(&self) -> &'static [CreateDefault];
fn emitted_events(&self) -> &'static [ModelEventKind];
fn version_column(&self) -> Option<&'static str>;
fn audit_enabled(&self) -> bool;
fn pii_columns(&self) -> &'static [&'static str];
fn sensitive_columns(&self) -> &'static [&'static str];
fn retention_days(&self) -> Option<u32>;
fn upsert_update_columns(&self) -> &'static [&'static str];
}