Skip to main content

platform_module/
module.rs

1//! A loaded module: serializable manifest + behavior binding + internal config.
2
3use crate::admin_data::{AdminActionSource, AdminDataSource, AdminQuerySource};
4use crate::binding::ModuleBinding;
5use crate::linked::{LinkedBinding, LinkedHttpContribution};
6use crate::source::ModuleSource;
7use lenso_contracts::ModuleManifest;
8use platform_core::{RuntimeConfigDescriptor, RuntimeConfigGroupDescriptor};
9use std::sync::Arc;
10
11/// One loaded module. `manifest` is serializable data; `binding` is behavior;
12/// `runtime_config` is internal `&'static` config NOT in the manifest (the
13/// registry needs the real `RuntimeConfigType` enum to validate). Cross-source
14/// config wire form is deferred to a later spec.
15#[derive(Debug)]
16pub struct Module {
17    pub manifest: ModuleManifest,
18    pub binding: Arc<dyn ModuleBinding>,
19    pub source: ModuleSource,
20    pub load_status: ModuleLoadStatus,
21    pub linked_http: Option<LinkedHttpContribution>,
22    pub runtime_config: &'static [RuntimeConfigDescriptor],
23    pub runtime_config_groups: &'static [RuntimeConfigGroupDescriptor],
24    /// Optional schema-admin data source. `None` for modules without an admin
25    /// surface (e.g. notifications). Set via [`Module::with_admin_data`].
26    pub admin_data: Option<Arc<dyn AdminDataSource>>,
27    /// Optional executable admin actions. Set via [`Module::with_admin_actions`].
28    pub admin_actions: Option<Arc<dyn AdminActionSource>>,
29    /// Optional read-only declarative queries. Set via [`Module::with_admin_queries`].
30    pub admin_queries: Option<Arc<dyn AdminQuerySource>>,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub enum ModuleLoadStatus {
35    Loaded,
36    Error { message: String },
37}
38
39impl Module {
40    /// Build a compile-time (Linked) module from a manifest + linked behavior.
41    /// Config defaults to empty; attach it with [`Module::with_runtime_config`].
42    #[must_use]
43    pub fn linked(manifest: ModuleManifest, binding: LinkedBinding) -> Self {
44        let linked_http = binding.http;
45        Self {
46            manifest,
47            binding: Arc::new(binding),
48            source: ModuleSource::Linked,
49            load_status: ModuleLoadStatus::Loaded,
50            linked_http,
51            runtime_config: &[],
52            runtime_config_groups: &[],
53            admin_data: None,
54            admin_actions: None,
55            admin_queries: None,
56        }
57    }
58
59    /// Build a Service-delivered Module from a manifest + Provider behavior.
60    #[must_use]
61    pub fn service(manifest: ModuleManifest, binding: Arc<dyn ModuleBinding>) -> Self {
62        Self {
63            manifest,
64            binding,
65            source: ModuleSource::Service,
66            load_status: ModuleLoadStatus::Loaded,
67            linked_http: None,
68            runtime_config: &[],
69            runtime_config_groups: &[],
70            admin_data: None,
71            admin_actions: None,
72            admin_queries: None,
73        }
74    }
75
76    /// Attach the module's editable configuration descriptors.
77    #[must_use]
78    pub fn with_runtime_config(
79        mut self,
80        runtime_config: &'static [RuntimeConfigDescriptor],
81    ) -> Self {
82        self.runtime_config = runtime_config;
83        self
84    }
85
86    /// Attach presentation groups for the module's editable configuration.
87    #[must_use]
88    pub fn with_runtime_config_groups(
89        mut self,
90        runtime_config_groups: &'static [RuntimeConfigGroupDescriptor],
91    ) -> Self {
92        self.runtime_config_groups = runtime_config_groups;
93        self
94    }
95
96    /// Attach a schema-admin data source (read access to admin entities).
97    #[must_use]
98    pub fn with_admin_data(mut self, data: Arc<dyn AdminDataSource>) -> Self {
99        self.admin_data = Some(data);
100        self
101    }
102
103    /// Attach admin action behavior for manifest-declared actions.
104    #[must_use]
105    pub fn with_admin_actions(mut self, actions: Arc<dyn AdminActionSource>) -> Self {
106        self.admin_actions = Some(actions);
107        self
108    }
109
110    /// Attach declarative query behavior for manifest-declared queries.
111    #[must_use]
112    pub fn with_admin_queries(mut self, queries: Arc<dyn AdminQuerySource>) -> Self {
113        self.admin_queries = Some(queries);
114        self
115    }
116}