Skip to main content

mocra_core/common/model/
meta.rs

1use crate::common::model::ModuleConfig;
2use crate::common::model::login_info::LoginInfo;
3
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7#[derive(Default, Debug, Clone, Serialize, Deserialize)]
8pub struct MetaData {
9    /// Task metadata. Provenance: Task definition → ParserModel/ErrorModel processing →
10    /// TaskFactory merge → Module.generate() → Request.meta
11    /// Stored by serializing the task config into a Value via `add_task_config()`.
12    #[serde(with = "crate::common::model::serde_value::value")]
13    pub task: Value,
14    /// Login information. Provenance: the LoginInfo.extra field → user authentication/authorization
15    /// system → Module.generate() → Request.meta
16    /// Extracted from LoginInfo's extra field and serialized via `add_login_info()`.
17    #[serde(with = "crate::common::model::serde_value::value")]
18    pub login_info: Value,
19    /// Module configuration. Provenance: database (account/platform/middleware relation tables) →
20    /// ModuleConfig instance → module initialization → Module.generate() → Request.meta
21    /// Includes: account table config, platform table config, the module's own config,
22    /// rel_module_account config, rel_module_platform config, middleware config, and so on.
23    /// Stored by serializing the whole ModuleConfig struct via `add_module_config()`.
24    #[serde(with = "crate::common::model::serde_value::value")]
25    pub module_config: Value,
26    /// Trait metadata. Provenance: individual trait implementations → trait type definitions →
27    /// business code calls → add_trait_config() → Request.meta
28    /// Stores trait-level custom configuration and extension data via `add_trait_config()`.
29    #[serde(with = "crate::common::model::serde_value::value")]
30    pub trait_meta: Value,
31}
32
33/// Type-safe selector for MetaData storage slots.
34#[derive(Debug, Clone, Copy)]
35pub enum MetaSource {
36    Task,
37    LoginInfo,
38    ModuleConfig,
39    TraitMeta,
40}
41
42impl MetaData {
43    pub fn add(
44        mut self,
45        key: impl AsRef<str>,
46        value: serde_json::Value,
47        source: MetaSource,
48    ) -> Self {
49        let target = match source {
50            MetaSource::Task => &mut self.task,
51            MetaSource::LoginInfo => &mut self.login_info,
52            MetaSource::ModuleConfig => &mut self.module_config,
53            MetaSource::TraitMeta => &mut self.trait_meta,
54        };
55
56        if !target.is_object() {
57            *target = Value::Object(serde_json::Map::new());
58        }
59
60        if let Some(map) = target.as_object_mut() {
61            map.insert(key.as_ref().into(), value);
62        }
63        self
64    }
65    pub fn add_task_config<T>(mut self, task_meta: T) -> Self
66    where
67        T: Serialize,
68    {
69        if let Ok(value) = serde_json::to_value(task_meta) {
70            self.task = value;
71        }
72        self
73    }
74    pub fn add_login_info(mut self, login_info: &LoginInfo) -> Self {
75        if let Ok(value) = serde_json::to_value(&login_info.extra) {
76            self.login_info = value;
77        }
78        self
79    }
80    pub fn add_module_config(mut self, module_config: &ModuleConfig) -> Self {
81        if let Ok(value) = serde_json::to_value(module_config) {
82            self.module_config = value;
83        };
84
85        self
86    }
87    pub fn add_trait_config<T>(mut self, key: impl AsRef<str>, value: T) -> Self
88    where
89        T: Serialize,
90    {
91        if !self.trait_meta.is_object() {
92            self.trait_meta = Value::Object(serde_json::Map::new());
93        }
94
95        if let Some(map) = self.trait_meta.as_object_mut() {
96            if let Ok(value) = serde_json::to_value(value) {
97                map.insert(key.as_ref().into(), value);
98            }
99        }
100
101        self
102    }
103    pub fn get_trait_config<T>(&self, key: &str) -> Option<T>
104    where
105        T: for<'de> Deserialize<'de>,
106    {
107        self.trait_meta
108            .get(key)
109            .cloned()
110            .and_then(|v| serde_json::from_value(v).ok())
111    }
112    pub fn get_login_config<T>(&self, key: &str) -> Option<T>
113    where
114        T: for<'de> Deserialize<'de>,
115    {
116        self.login_info
117            .get(key)
118            .cloned()
119            .and_then(|v| serde_json::from_value(v).ok())
120    }
121    pub fn get_module_config<T>(&self, key: &str) -> Option<T>
122    where
123        T: for<'de> Deserialize<'de>,
124    {
125        self.module_config
126            .get(key)
127            .cloned()
128            .and_then(|v| serde_json::from_value(v).ok())
129    }
130    pub fn get_task_config<T>(&self, key: &str) -> Option<T>
131    where
132        T: for<'de> Deserialize<'de>,
133    {
134        self.task
135            .get(key)
136            .cloned()
137            .and_then(|v| serde_json::from_value(v).ok())
138    }
139}
140
141impl From<MetaData> for Value {
142    fn from(value: MetaData) -> Self {
143        serde_json::to_value(value).unwrap_or_default()
144    }
145}