deeb_core/entity/
mod.rs

1use crate::database::index::{Index, IndexOptions};
2use anyhow::anyhow;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)]
6pub struct EntityName(pub String);
7impl From<&str> for EntityName {
8    fn from(s: &str) -> Self {
9        Self(s.to_string())
10    }
11}
12impl Into<EntityName> for String {
13    fn into(self) -> EntityName {
14        EntityName(self)
15    }
16}
17impl std::fmt::Display for EntityName {
18    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
19        write!(f, "{}", self.0)
20    }
21}
22
23#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)]
24pub struct EntityAssociation {
25    pub entity_name: EntityName,
26    pub from: String,
27    pub to: String,
28    /// Uses the entity name as the alias if not provided.
29    pub alias: EntityName,
30}
31
32#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)]
33pub struct PrimaryKey(pub String);
34
35#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)]
36pub struct Entity {
37    pub name: EntityName,
38    pub primary_key: PrimaryKey,
39    pub associations: Vec<EntityAssociation>,
40    pub indexes: Vec<Index>,
41}
42
43impl Entity {
44    /// Create a new entity.
45    /// # Example
46    /// ```rust
47    /// use deeb_core::entity::Entity;
48    /// let user = Entity::new("user");
49    /// ```
50    pub fn new(s: &str) -> Self {
51        Entity {
52            name: EntityName::from(s),
53            primary_key: PrimaryKey("_id".to_string()),
54            associations: vec![],
55            indexes: vec![],
56        }
57    }
58
59    pub fn primary_key(&mut self, key: &str) -> Self {
60        self.primary_key = PrimaryKey(key.to_string());
61        self.clone()
62    }
63
64    pub fn add_index(
65        &mut self,
66        name: &str,
67        keys: Vec<&str>,
68        options: Option<IndexOptions>,
69    ) -> Result<Self, anyhow::Error> {
70        if self.indexes.iter().any(|i| i.name == name) {
71            return Err(anyhow!("An index with the name '{}' already exists.", name));
72        }
73        self.indexes.push(Index {
74            name: name.to_string(),
75            keys: keys.iter().map(|c| c.to_string()).collect(),
76            options,
77        });
78        Ok(self.clone())
79    }
80
81    pub fn associate<'a, N>(
82        &mut self,
83        entity_name: N,
84        from: &str,
85        to: &str,
86        alias: Option<&str>,
87    ) -> Result<Self, String>
88    where
89        N: Into<EntityName> + Clone,
90    {
91        let alias = alias.map_or_else(|| entity_name.clone().into(), |a| a.into());
92
93        self.associations.push(EntityAssociation {
94            entity_name: entity_name.clone().into(),
95            from: from.to_string(),
96            to: to.to_string(),
97            alias,
98        });
99
100        Ok(self.clone())
101    }
102}