dbschema 0.1.0

Define database schema's as HCL files, and generate idempotent SQL migrations
Documentation
use std::fmt;

use internment::Intern;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Identifier(Intern<String>);

impl Identifier {
    pub fn new<S: Into<String>>(value: S) -> Self {
        Self(Intern::new(value.into()))
    }

    pub fn as_str(&self) -> &str {
        self.0.as_ref()
    }
}

impl Default for Identifier {
    fn default() -> Self {
        Identifier::new("")
    }
}

impl fmt::Display for Identifier {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl From<&str> for Identifier {
    fn from(value: &str) -> Self {
        Identifier::new(value)
    }
}

impl From<String> for Identifier {
    fn from(value: String) -> Self {
        Identifier::new(value)
    }
}

impl From<&Identifier> for String {
    fn from(value: &Identifier) -> Self {
        value.as_str().to_owned()
    }
}

#[derive(Debug, Default, Clone)]
pub struct Schema {
    pub enums: Vec<Enum>,
    pub models: Vec<Model>,
    pub views: Vec<View>,
    pub composite_types: Vec<CompositeType>,
    pub type_aliases: Vec<TypeAlias>,
    pub custom_blocks: Vec<CustomBlock>,
    pub datasources: Vec<ConfigBlock>,
    pub generators: Vec<ConfigBlock>,
}

#[derive(Debug, Clone)]
pub struct Model {
    pub name: Identifier,
    pub fields: Vec<Field>,
    pub attributes: Vec<BlockAttribute>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct View {
    pub name: Identifier,
    pub fields: Vec<Field>,
    pub attributes: Vec<BlockAttribute>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct CompositeType {
    pub name: Identifier,
    pub fields: Vec<Field>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct TypeAlias {
    pub name: Identifier,
    pub target: Type,
    pub attributes: Vec<FieldAttribute>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct CustomBlock {
    pub name: Identifier,
    pub contents: String,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfigBlockKind {
    Datasource,
    Generator,
}

#[derive(Debug, Clone)]
pub struct ConfigBlock {
    pub kind: ConfigBlockKind,
    pub name: Identifier,
    pub properties: Vec<ConfigProperty>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct ConfigProperty {
    pub name: Identifier,
    pub value: Option<String>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct Enum {
    pub name: Identifier,
    pub values: Vec<EnumValue>,
    pub attributes: Vec<BlockAttribute>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct EnumValue {
    pub name: Identifier,
    pub mapped_name: Option<String>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct Field {
    pub name: Identifier,
    pub r#type: Type,
    pub attributes: Vec<FieldAttribute>,
    pub documentation: Option<String>,
}

#[derive(Debug, Clone)]
pub struct Type {
    pub name: String,
    pub optional: bool,
    pub list: bool,
}

#[derive(Debug, Clone)]
pub enum FieldAttribute {
    Id,
    Unique,
    Default(DefaultValue),
    Relation(RelationAttribute),
    Map(String),
    DbNative(String),
    Raw(String),
}

#[derive(Debug, Clone)]
pub enum BlockAttribute {
    Id(Vec<Identifier>),
    Unique(Vec<Identifier>),
    Index(Vec<Identifier>),
    Map(String),
    Raw(String),
}

#[derive(Debug, Clone)]
pub enum DefaultValue {
    Now,
    Uuid,
    AutoIncrement,
    DbGenerated(String),
    Expression(String),
}

#[derive(Debug, Clone)]
pub struct RelationAttribute {
    pub name: Option<String>,
    pub fields: Vec<Identifier>,
    pub references: Vec<Identifier>,
    pub map: Option<String>,
    pub on_delete: Option<String>,
    pub on_update: Option<String>,
}