use crate::ast::{DefaultValue, ReferentialAction};
use crate::types::{DatabaseProvider, ScalarType};
macro_rules! serde_derive {
($(#[$meta:meta])* $vis:vis struct $name:ident { $($body:tt)* }) => {
$(#[$meta])*
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
$vis struct $name { $($body)* }
};
($(#[$meta:meta])* $vis:vis enum $name:ident { $($body:tt)* }) => {
$(#[$meta])*
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
$vis enum $name { $($body)* }
};
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct Schema {
pub datasource: DatasourceConfig,
pub generators: Vec<GeneratorConfig>,
pub enums: Vec<Enum>,
pub models: Vec<Model>,
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct DatasourceConfig {
pub name: String,
pub provider: DatabaseProvider,
pub url: String,
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct GeneratorConfig {
pub name: String,
pub output: String,
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct Enum {
pub name: String,
pub db_name: String,
pub variants: Vec<String>,
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct Model {
pub name: String,
pub db_name: String,
pub fields: Vec<Field>,
pub primary_key: PrimaryKey,
pub indexes: Vec<Index>,
pub unique_constraints: Vec<UniqueConstraint>,
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct Field {
pub name: String,
pub db_name: String,
pub field_type: FieldKind,
pub is_optional: bool,
pub is_list: bool,
pub is_id: bool,
pub is_unique: bool,
pub is_updated_at: bool,
pub default: Option<DefaultValue>,
pub relation: Option<ResolvedRelation>,
}
}
impl Field {
pub fn is_scalar(&self) -> bool {
!matches!(self.field_type, FieldKind::Model(_)) && !self.is_list
}
pub fn has_default(&self) -> bool {
self.default.is_some() || self.is_updated_at
}
}
serde_derive! {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FieldKind {
Scalar(ScalarType),
Enum(String),
Model(String),
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct ResolvedRelation {
pub related_model: String,
pub relation_type: RelationType,
pub fields: Vec<String>,
pub references: Vec<String>,
pub on_delete: ReferentialAction,
pub on_update: ReferentialAction,
}
}
serde_derive! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelationType {
OneToOne,
OneToMany,
ManyToOne,
ManyToMany,
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct PrimaryKey {
pub fields: Vec<String>,
}
}
impl PrimaryKey {
pub fn is_composite(&self) -> bool {
self.fields.len() > 1
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct Index {
pub fields: Vec<String>,
}
}
serde_derive! {
#[derive(Debug, Clone)]
pub struct UniqueConstraint {
pub fields: Vec<String>,
}
}