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 lenso_contracts::{ModuleManifest, ModuleSource};
7use platform_core::{RuntimeConfigDescriptor, RuntimeConfigGroupDescriptor};
8use std::sync::Arc;
9
10/// One loaded module. `manifest` is serializable data; `binding` is behavior;
11/// `runtime_config` is internal `&'static` config NOT in the manifest (the
12/// registry needs the real `RuntimeConfigType` enum to validate). Cross-source
13/// config wire form is deferred to a later spec.
14#[derive(Debug)]
15pub struct Module {
16    pub manifest: ModuleManifest,
17    pub binding: Arc<dyn ModuleBinding>,
18    pub source: ModuleSource,
19    pub load_status: ModuleLoadStatus,
20    pub linked_http: Option<LinkedHttpContribution>,
21    pub runtime_config: &'static [RuntimeConfigDescriptor],
22    pub runtime_config_groups: &'static [RuntimeConfigGroupDescriptor],
23    /// Optional schema-admin data source. `None` for modules without an admin
24    /// surface (e.g. notifications). Set via [`Module::with_admin_data`].
25    pub admin_data: Option<Arc<dyn AdminDataSource>>,
26    /// Optional executable admin actions. Set via [`Module::with_admin_actions`].
27    pub admin_actions: Option<Arc<dyn AdminActionSource>>,
28    /// Optional read-only declarative queries. Set via [`Module::with_admin_queries`].
29    pub admin_queries: Option<Arc<dyn AdminQuerySource>>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub enum ModuleLoadStatus {
34    Loaded,
35    Error { message: String },
36}
37
38impl Module {
39    /// Build a compile-time (Linked) module from a manifest + linked behavior.
40    /// Config defaults to empty; attach it with [`Module::with_runtime_config`].
41    #[must_use]
42    pub fn linked(manifest: ModuleManifest, binding: LinkedBinding) -> Self {
43        let linked_http = binding.http;
44        Self {
45            manifest,
46            binding: Arc::new(binding),
47            source: ModuleSource::Linked,
48            load_status: ModuleLoadStatus::Loaded,
49            linked_http,
50            runtime_config: &[],
51            runtime_config_groups: &[],
52            admin_data: None,
53            admin_actions: None,
54            admin_queries: None,
55        }
56    }
57
58    /// Build a remote module from a manifest + transport-backed behavior.
59    /// Remote behavior is intentionally narrow in the first slice.
60    #[must_use]
61    pub fn remote(manifest: ModuleManifest, binding: Arc<dyn ModuleBinding>) -> Self {
62        Self {
63            manifest,
64            binding,
65            source: ModuleSource::Remote,
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}