Skip to main content

mako_engine/
profile.rs

1//! Profile requirements — decouple domain crates from `edi-energy`.
2//!
3//! Domain crates (`mako-gpke`, `mako-wim`, …) declare which EDIFACT message
4//! types they depend on by implementing
5//! [`EngineModule::profile_requirements`].  The engine builder validates these
6//! requirements against the injected `ReleaseRegistry` at startup — without
7//! requiring domain crates to import `edi-energy` in their production
8//! `[dependencies]`.
9//!
10//! # Example (domain crate)
11//!
12//! ```rust,ignore
13//! use mako_engine::builder::EngineModule;
14//! use mako_engine::profile::ProfileRequirement;
15//!
16//! pub struct GpkeModule;
17//!
18//! impl EngineModule for GpkeModule {
19//!     fn name(&self) -> &'static str { "gpke" }
20//!
21//!     fn profile_requirements(&self) -> &'static [ProfileRequirement] {
22//!         &[
23//!             ProfileRequirement { message_type: "UTILMD", label: "UTILMD Strom" },
24//!             ProfileRequirement { message_type: "INVOIC", label: "INVOIC Abrechnung" },
25//!         ]
26//!     }
27//! }
28//! ```
29//!
30//! # Validation
31//!
32//! [`EngineBuilder::build`] calls every registered module's
33//! [`EngineModule::profile_requirements`] method.  For each requirement it checks that the
34//! caller-supplied validation function (see
35//! [`EngineBuilder::with_profile_validator`]) confirms at least one active
36//! profile exists.  If not, `build` panics with an actionable error message —
37//! exactly like `configure()` used to, but without the `edi-energy` import.
38//!
39//! [`EngineModule::profile_requirements`]: crate::builder::EngineModule::profile_requirements
40//! [`EngineBuilder::build`]: crate::builder::EngineBuilder::build
41//! [`EngineBuilder::with_profile_validator`]: crate::builder::EngineBuilder::with_profile_validator
42
43/// A single profile requirement declared by a domain module.
44///
45/// The engine builder validates that at least one active profile satisfying
46/// this requirement exists in the `edi-energy` registry.
47///
48/// Domain crates return a `&'static [ProfileRequirement]` slice from
49/// [`EngineModule::profile_requirements`] — no `edi-energy` import required.
50///
51/// [`EngineModule::profile_requirements`]: crate::builder::EngineModule::profile_requirements
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53pub struct ProfileRequirement {
54    /// EDIFACT message type identifier, e.g. `"UTILMD"`, `"APERAK"`, `"MSCONS"`.
55    ///
56    /// Must match the value that `edi_energy::MessageType::as_str()` (or
57    /// equivalent) returns for the relevant profile.
58    pub message_type: &'static str,
59
60    /// Human-readable label used in error messages.
61    ///
62    /// Example: `"UTILMD Strom (GPKE)"`.
63    pub label: &'static str,
64}