1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! Template framework for quickly scaffolding hexser components.
//!
//! This module provides lightweight helpers and macros that REGISTER your components
//! without relying on derive macros: each one emits the `Registrable` impl AND the
//! `inventory::submit!` that puts the type in `HexGraph::current()`. It complements
//! proc-macro derives by offering simple, explicit building blocks you can use in any
//! context (including no-macros builds).
//!
//! ⚠ BOTH HALVES ARE THE REGISTRATION. `HexGraph::current()` is built by iterating the
//! `inventory` registry, so a `Registrable` impl on its own yields a type that answers
//! `node_info()` correctly and is in NO graph. These macros emitted only the impl until
//! 2026-09-04: the crate had no non-derive door into the graph at all, while naming these
//! `hex_register_*`.
//!
//! Registration is an ITEM-scope act — the submission is a static discovered at link time —
//! so invoke these macros at module scope, next to the type, not inside a function body.
//!
//! # Quick examples
//!
//! ```rust
//! use hexser::prelude::*;
//!
//! struct MyEntity { id: u64 }
//!
//! // Register a domain Entity using a template macro (module scope, next to the type).
//! hexser::hex_register_domain!(MyEntity, Role::Entity);
//!
//! fn main() {
//! // The type answers node_info() AND is in the process-wide graph.
//! let info = <MyEntity as Registrable>::node_info();
//! assert_eq!(info.layer, Layer::Domain);
//! assert_eq!(info.role, Role::Entity);
//! assert!(
//! hexser::HexGraph::current()
//! .nodes()
//! .any(|n| n.type_name().ends_with("MyEntity"))
//! );
//! }
//! ```
//!
//! ```rust
//! use hexser::prelude::*;
//!
//! struct PgUserRepo;
//!
//! // Register as an Adapter implementing a Repository.
//! hexser::hex_register_adapter!(PgUserRepo, Role::Adapter);
//!
//! fn main() {
//! assert_eq!(
//! <PgUserRepo as Registrable>::node_info().layer,
//! Layer::Adapter
//! );
//! }
//! ```
//!
//! These helpers are intended as templates: copy, adapt, and extend as needed.
//!
//! Revision History
//! - 2026-09-11T00:00:00Z @AI: Allow needless_doctest_main — the explicit `fn main` is what keeps the macro invocations at module scope, which is the whole subject of these examples.
//! - 2026-09-04T00:00:00Z @AI: The hex_register_* macros now emit the inventory submission they
//! are named for. They implemented `Registrable` and never submitted, so every type
//! "registered" through hexser's own explicit path answered node_info() correctly and was
//! absent from every graph query — the same end state as the silently-omitted generic
//! submission, reached through the door the crate advertises.
// The `fn main` in the examples above is load-bearing, not boilerplate: rustdoc only skips its
// implicit wrapper when the snippet declares `main` itself, and skipping it is the only way to
// invoke `hex_register_*!` at MODULE scope — which is exactly the constraint these examples
// exist to demonstrate (registration is an item-scope act, see the preamble). Removing the
// `fn main` to satisfy the lint would move the macro into a function body and teach the misuse.
/// Split a fully-qualified Rust type path into (module_path, type_name).
///
/// For example: "my_crate::module::Type" -> ("my_crate::module", "Type").
/// If the input has no module qualifiers, module_path is an empty string.
/// Core macro that REGISTERS a type: it implements `Registrable` with the given layer and
/// role AND submits the component to the inventory registry, so the type is in
/// `HexGraph::current()`.
///
/// ⚠ Both halves are the registration, and this macro emitted only the first until
/// 2026-09-04 — the type answered `node_info()` correctly and no graph query could find it.
/// That is the same silent end state as a derive dropping its submission, reached through
/// the macro the crate itself names `register`.
///
/// The type must be CONCRETE: it is used as `ComponentEntry::new::<T>()` at item scope, where
/// a generic parameter is not in scope, so a generic target is a compile error — the same
/// polarity `#[derive(HexDomain)]` and its siblings now have. Register a non-generic marker
/// struct that stands for the component instead.
///
/// Invoke at MODULE scope, next to the type: the submission is a link-time static.
/// Convenience macro for Domain-layer components.
/// Convenience macro for Port-layer components.
/// Convenience macro for Adapter-layer components.
/// Convenience macro for Application-layer components.
/// Convenience macro for Infrastructure-layer components.