|
2 | 2 | outline: deep |
3 | 3 | --- |
4 | 4 |
|
5 | | -# Ui5Registry |
| 5 | +# Ui5Registry — Central Coordination and Introspection Service |
6 | 6 |
|
7 | | -The `Ui5Registry` is the central runtime lookup system for resolving all UI5 modules and artifacts within the LaravelUi5 ecosystem. It powers routing, rendering, manifest generation, and backend integration for all registered UI5 entities. |
| 7 | +> **Since v1.1.0** |
| 8 | +> The `Ui5Registry` provides full introspection support (Roles, Abilities, Settings, SemanticObjects) |
| 9 | +> and hybrid semantic link discovery between Eloquent models. |
8 | 10 |
|
9 | | -LaravelUi5 uses a hybrid approach of *code-first registration*, *runtime caching*, and *database synchronization* to deliver fast and predictable artifact resolution across environments. |
| 11 | +The `Ui5Registry` is the central coordination and introspection service of the LaravelUi5 ecosystem. |
| 12 | +It provides a unified API to discover, inspect, and resolve all UI5-related modules, artifacts, and metadata within a Laravel application. |
10 | 13 |
|
11 | | -## Purpose |
| 14 | +It serves as the **semantic backbone** of the system, connecting static configuration, runtime reflection, and UI5 resource resolution into a single coherent model. |
12 | 15 |
|
13 | | -The `Ui5Registry` acts as a *read-only service locator* that: |
| 16 | +## Responsibilities |
14 | 17 |
|
15 | | -* Resolves UI5 modules by slug (e.g., `users`, `offers`) |
16 | | -* Resolves artifacts (e.g., cards, dashboards, actions) by their UI5 namespace |
17 | | -* Supports routing, UI5 tag rendering, and metadata generation |
18 | | -* Enforces system-wide constraints like uniqueness and slug mapping |
| 18 | +* Configuration-based declaration of UI5 modules and their artifacts |
| 19 | +* Metadata introspection for Roles, Abilities, Settings, and SemanticObjects |
| 20 | +* Semantic link discovery between models (explicit and inferred) |
| 21 | +* Fast runtime resolution of modules and artifacts |
| 22 | +* Central service for manifest generation, routing, and navigation |
19 | 23 |
|
20 | | -## Artifacts & Modules |
| 24 | +## System Rules |
21 | 25 |
|
22 | | -Each UI5-related PHP class in LaravelUi5 implements either: |
| 26 | +* Every module must have a **unique slug** |
| 27 | +* Every artifact must have a **globally unique namespace** |
| 28 | +* Artifacts are only accessible via their registered module or full namespace |
| 29 | +* Semantic links may only target models that are registered as SemanticObjects |
23 | 30 |
|
24 | | -* `Ui5ModuleInterface`: Represents a reusable module |
25 | | -* `Ui5ArtifactInterface`: Represents an artifact (e.g. card, tile, dashboard, report, action) |
| 31 | +## Layer Overview |
26 | 32 |
|
27 | | -Artifacts may optionally implement `SluggableInterface` to allow addressable routing via `getSlug()`. |
| 33 | +The `Ui5Registry` operates in three logical layers. |
28 | 34 |
|
29 | | -## Runtime Registry |
| 35 | +| Layer | Description | Example Methods | |
| 36 | +|:------------------------|:----------------------------------------------------------------------------|:----------------------------------------------------| |
| 37 | +| **Lookup Layer** | Provides lookup and resolution of modules and artifacts | `getModule()`, `get()`, `all()` | |
| 38 | +| **Introspection Layer** | Reflects and collects metadata from PHP attributes | `roles()`, `abilities()`, `settings()`, `objects()` | |
| 39 | +| **Runtime Layer** | Provides runtime path and intent resolution for UI5 and manifest generation | `slugFor()`, `resolve()`, `resolveIntents()` | |
30 | 40 |
|
31 | | -The default implementation (`Ui5Registry`) performs *live resolution* on each request: |
32 | | - |
33 | | -* Modules are loaded from `config/ui5.php` under the `modules` key |
34 | | -* Dashboards are loaded from the `dashboards` key |
35 | | -* Each module may provide: |
36 | | - |
37 | | - * App |
38 | | - * Library |
39 | | - * Cards |
40 | | - * Tiles |
41 | | - * KPIs |
42 | | - * Actions |
43 | | - * Reports |
44 | | - |
45 | | -On construction, all artifacts are instantiated and registered into lookup maps by: |
46 | | - |
47 | | -* Namespace (e.g., `io.pragmatiqu.users.cards.summary`) |
48 | | -* Slug (e.g., `users`) and URL key (e.g., `card/users/summary`) |
49 | | - |
50 | | -This is ideal for development, but less performant in production. |
| 41 | +### Lookup Layer |
51 | 42 |
|
52 | | -## API Overview |
| 43 | +Handles registration and retrieval of modules and artifacts at runtime. |
| 44 | +Modules are indexed by slug, artifacts by namespace. |
53 | 45 |
|
54 | | -The `Ui5RegistryInterface` defines a robust contract for artifact resolution: |
| 46 | +Example usage: |
55 | 47 |
|
56 | 48 | ```php |
57 | | -public function getModule(string $slug): ?Ui5ModuleInterface; |
58 | | -public function get(string $namespace): ?Ui5ArtifactInterface; |
59 | | -public function fromSlug(string $slug): ?Ui5ArtifactInterface; |
60 | | -public function slugFor(Ui5ArtifactInterface $artifact): ?string; |
61 | | -public function resolve(string $namespace): ?string; |
62 | | -public function resolveRoots(array $namespaces): array; |
| 49 | +$module = $registry->getModule('users'); |
| 50 | +$artifact = $registry->get('com.laravelui5.users'); |
63 | 51 | ``` |
64 | 52 |
|
65 | | -## System Rules Enforced |
66 | | - |
67 | | -* Every module must have a *unique slug* |
68 | | -* Every artifact must have a *globally unique namespace* |
69 | | -* All routing-safe artifacts must implement `SluggableInterface` |
70 | | - |
71 | | -## Best Practices |
| 53 | +### Introspection Layer |
72 | 54 |
|
73 | | -* Use `Ui5Registry::get()` when rendering components by namespace |
74 | | -* Use `fromSlug()` and `slugFor()` when working with routes or URLs |
75 | | -* Always run `ui5:cache` before deployment |
76 | | -* Use `ui5:sync` to persist artifact metadata for dashboards or admin UIs |
| 55 | +The introspection layer discovers metadata via PHP attributes declared on modules and artifacts. |
| 56 | +It collects the following categories. |
77 | 57 |
|
78 | | -## Example Use Cases |
| 58 | +| Category | Attribute | Description | |
| 59 | +|:---------------------|:--------------------|:------------------------------------------------------------| |
| 60 | +| **Roles** | `#[Role]` | Declares roles within a module | |
| 61 | +| **Abilities** | `#[Ability]` | Declares abilities on backend actions | |
| 62 | +| **Settings** | `#[Setting]` | Declares configurable module settings | |
| 63 | +| **Semantic Objects** | `#[SemanticObject]` | Declares the semantic model and available navigation routes | |
79 | 64 |
|
80 | | -* *Resolve module from URL*: `/ui5/app/users/overview` → `users` |
81 | | -* *Render dynamic tag*: `<x-ui5-element id="io.pragmatiqu.users.cards.summary" />` |
82 | | -* *Dispatch backend action*: Call `Ui5Registry::get('io.pragmatiqu.users.actions.toggle-lock')` |
| 65 | +Since v1.1.0, Abilities and Settings are discovered dynamically for every artifact registered within a module. |
| 66 | +The data is cached internally for fast lookup and later used in manifest.json generation. |
83 | 67 |
|
84 | | ---- |
85 | | ---- |
| 68 | +### Runtime Layer |
86 | 69 |
|
87 | | -## Understanding the Ui5Registry Layers |
| 70 | +The runtime layer is responsible for path resolution, intent discovery, and runtime linking of UI5 resources. |
| 71 | +It bridges the reflection-based metadata with actual runtime routes and assets. |
88 | 72 |
|
89 | | -The **Ui5Registry** is the central lookup and introspection service |
90 | | -in the LaravelUi5 Core. It represents the *semantic heart* of the entire system — |
91 | | -bridging PHP metadata, Laravel runtime, and UI5 manifest output. |
| 73 | +**Responsibilities** |
92 | 74 |
|
93 | | -To keep things maintainable and predictable, the Registry operates across **three distinct layers** that are summarized in the following sections. |
| 75 | +* Resolving artifacts and resource paths by slug |
| 76 | +* Mapping namespaces to modules |
| 77 | +* Exposing semantic navigation routes for manifest.json |
| 78 | +* Generating UI5 resource roots for bootstrap configuration |
| 79 | +* Providing reverse-intent resolution between linked SemanticObjects |
94 | 80 |
|
95 | | -### Lookup Layer |
| 81 | +## Semantic Links |
96 | 82 |
|
97 | | -> “What exists, and how can I find it?” |
| 83 | +*Starting with v1.1.0*, the Registry supports **hybrid semantic link discovery**. |
| 84 | +Links between SemanticObjects can be declared explicitly via |
| 85 | +`#[SemanticLink(model: Target::class)]` |
| 86 | +or inferred automatically from Eloquent relations (`belongsTo`, `hasOne`). |
98 | 87 |
|
99 | | -This layer provides **fast, structural access** to all registered modules and artifacts. |
100 | | -It doesn’t use Reflection — it simply exposes already-known objects (from cache or boot discovery). |
| 88 | +This hybrid approach keeps the system ORM-agnostic yet fully aware of semantic relationships, |
| 89 | +allowing cross-module navigation without database constraints. |
101 | 90 |
|
102 | | -#### Responsibilities |
103 | | -- Fast lookup of modules and artifacts |
104 | | -- Routing-safe and rendering-safe resolution |
105 | | -- Base for all higher-level layers |
| 91 | +Example: |
106 | 92 |
|
107 | | -#### Typical Methods |
108 | 93 | ```php |
109 | | -$module = $registry->getModule('users'); |
110 | | -$artifact = $registry->get('io.pragmatiqu.users.cards.summary'); |
111 | | -$allModules = $registry->modules(); |
112 | | -```` |
113 | | - |
114 | | -| Method | Purpose | |
115 | | -|:----------------------|:---------------------------| |
116 | | -| `get()` | Find artifact by namespace | |
117 | | -| `getModule()` | Find module by slug | |
118 | | -| `has()` | Check if artifact exists | |
119 | | -| `fromSlug()` | Reverse-lookup by slug | |
120 | | -| `slugFor()` | Get full route slug | |
121 | | -| `all()` / `modules()` | List everything | |
122 | | - |
123 | | -### Introspection Layer |
124 | | - |
125 | | -> “Which metadata is defined through PHP Attributes?” |
126 | | - |
127 | | -This layer performs **deep reflection** over all LaravelUi5 modules, |
128 | | -collecting metadata such as roles, abilities, semantic objects, and settings. |
129 | | -It’s the **source of truth** for the SDK, manifest generation, and permission systems. |
| 94 | +#[SemanticLink] |
| 95 | +public function user(): BelongsTo |
| 96 | +{ |
| 97 | + return $this->belongsTo(User::class); |
| 98 | +} |
| 99 | +``` |
130 | 100 |
|
131 | | -#### Responsibilities |
| 101 | +## Semantic Intents |
132 | 102 |
|
133 | | -* Parse PHP attributes (e.g. `#[Role]`, `#[Ability]`, `#[SemanticObject]`) |
134 | | -* Structure semantic metadata for all modules |
135 | | -* Provide a unified view of backend capabilities |
| 103 | +The `resolveIntents()` method provides navigation intents based on registered SemanticObjects |
| 104 | +and discovered SemanticLinks. It reverses the direction of declared links and returns |
| 105 | +all routes that *point to* the given module. |
136 | 106 |
|
137 | | -#### Typical Methods |
| 107 | +Example: |
138 | 108 |
|
139 | 109 | ```php |
140 | | -$roles = $registry->roles(); |
141 | | -$abilities = $registry->abilities(); |
142 | | -$settings = $registry->settings(); |
143 | | -$objects = $registry->objects(); |
| 110 | +$intents = $registry->resolveIntents('users'); |
144 | 111 | ``` |
145 | 112 |
|
146 | | -| Method | Returns | Source | |
147 | | -|:--------------|:--------------------------------------|:--------------------| |
148 | | -| `roles()` | Declared roles across all modules | `#[Role]` | |
149 | | -| `abilities()` | Declared abilities | `#[Ability]` | |
150 | | -| `settings()` | Configurable or tenant-level settings | `#[Setting]` | |
151 | | -| `objects()` | Semantic business objects and routes | `#[SemanticObject]` | |
152 | | - |
153 | | -Example structure for `objects()`: |
| 113 | +Output: |
154 | 114 |
|
155 | 115 | ```php |
156 | 116 | [ |
157 | | - "User" => [ |
158 | | - "name" => "User", |
159 | | - "module" => "users", |
160 | | - "routes" => [ |
161 | | - "display" => ["label" => "Show", "icon" => "sap-icon://display"], |
162 | | - "edit" => ["label" => "Edit", "icon" => "sap-icon://edit"] |
| 117 | + "Order" => [ |
| 118 | + "details" => [ |
| 119 | + "label" => "Order Details", |
| 120 | + "icon" => null |
163 | 121 | ] |
164 | 122 | ] |
165 | 123 | ] |
166 | 124 | ``` |
167 | 125 |
|
168 | | -### Runtime Layer |
169 | | - |
170 | | -> “How do these elements work together at runtime?” |
171 | | -
|
172 | | -This layer derives **contextual information** during runtime — |
173 | | -for example, navigation intents, resource roots, or semantic relations between objects. |
| 126 | +This result indicates that **Orders** link to **Users**, |
| 127 | +and exposes their navigable intents (e.g., “Order Details” in the UI). |
174 | 128 |
|
175 | | -It depends on the Lookup and Introspection data but provides runtime-ready results |
176 | | -for routers, manifest generators, and UI5 frontends. |
| 129 | +## Resource Resolution |
177 | 130 |
|
178 | | -#### Responsibilities |
179 | | - |
180 | | -* Derive semantic intents from object graph |
181 | | -* Generate `resourceroots` and manifest paths |
182 | | -* Connect backend and frontend semantics |
183 | | - |
184 | | -#### Typical Methods |
| 131 | +The registry also resolves resource roots and versioned UI5 paths for module assets. |
185 | 132 |
|
186 | 133 | ```php |
187 | | -$roots = $registry->resolveRoots(['io.pragmatiqu.users']); |
188 | | -$intents = $registry->resolveIntents('users'); |
| 134 | +$path = $registry->resolve('com.laravelui5.users'); |
| 135 | +// => /ui5/app/users/1.0.0 |
| 136 | + |
| 137 | +$roots = $registry->resolveRoots(['com.laravelui5.users', 'com.laravelui5.offers']); |
| 138 | +/* |
| 139 | +[ |
| 140 | + "com.laravelui5.users" => "/ui5/app/users/1.0.0", |
| 141 | + "com.laravelui5.offers" => "/ui5/app/offers/1.0.0" |
| 142 | +] |
| 143 | +*/ |
189 | 144 | ``` |
190 | 145 |
|
191 | | -| Method | Description | |
192 | | -|:----------------------------|:--------------------------------------------------| |
193 | | -| `resolveIntents($module)` | Returns UI5 navigation intents for a given module | |
194 | | -| `resolveRoots($namespaces)` | Builds resource root map for manifest.json | |
195 | | -| `artifactToModuleSlug()` | Maps an artifact class to its module | |
196 | | -| `namespaceToModuleSlug()` | Maps a namespace to its owning module | |
| 146 | +## Introspection Summary |
197 | 147 |
|
198 | | -### Conceptual Overview |
| 148 | +The `introspect()` method returns a snapshot of the registry’s internal state: |
199 | 149 |
|
200 | | -``` |
201 | | - ┌──────────────────────────────────────────┐ |
202 | | - │ Runtime Layer │ |
203 | | - │ resolveIntents() • resolveRoots() │ |
204 | | - │ namespaceToModuleSlug() • artifactTo… │ |
205 | | - └──────────────────────────────────────────┘ |
206 | | - ▲ |
207 | | - │ uses data from |
208 | | - │ |
209 | | - ┌──────────────────────────────────────────┐ |
210 | | - │ Reflection / Introspection Layer │ |
211 | | - │ roles() • abilities() • settings() • │ |
212 | | - │ objects() (SemanticObject) │ |
213 | | - └──────────────────────────────────────────┘ |
214 | | - ▲ |
215 | | - │ builds on |
216 | | - │ |
217 | | - ┌──────────────────────────────────────────┐ |
218 | | - │ POPO / Lookup Layer │ |
219 | | - │ get() • getModule() • fromSlug() • all() │ |
220 | | - │ (cached or live registry view) │ |
221 | | - └──────────────────────────────────────────┘ |
| 150 | +```php |
| 151 | +$data = $registry->introspect(); |
222 | 152 | ``` |
223 | 153 |
|
224 | | -### Summary |
| 154 | +Structure: |
225 | 155 |
|
226 | | -| Layer | Responsibility | Typical Consumer | |
227 | | -|:-------------------------------|:-----------------------------------|:---------------------------------| |
228 | | -| **Lookup (POPO)** | Structural access, no reflection | Core runtime, routing | |
229 | | -| **Introspection (Reflection)** | Semantic metadata via attributes | SDK, Manifest generator | |
230 | | -| **Runtime (Resolution)** | Derived navigation & resource data | Frontend, routers, UI5 manifests | |
| 156 | +* `modules` |
| 157 | +* `artifacts` |
| 158 | +* `namespaceToModule` |
| 159 | +* `slugs` |
| 160 | +* `roles` |
| 161 | +* `abilities` |
| 162 | +* `objects` |
| 163 | +* `links` |
231 | 164 |
|
232 | | -**In short:** |
| 165 | +## Final Notes |
233 | 166 |
|
234 | | -> The `Ui5Registry` is not just a lookup service — it’s a *semantic runtime system* |
235 | | -> bridging your Laravel backend and OpenUI5 frontend through a unified data model. |
| 167 | +Since v1.1.0, the `Ui5Registry` forms the introspective backbone of the LaravelUi5 Core, |
| 168 | +bridging static metadata, runtime reflection, and UI5 integration |
| 169 | +through a unified semantic graph. |
0 commit comments