sirius-framework-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +160 -0
  3. package/dist/grammars/tree-sitter-java.wasm +0 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +247 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/java-parser.d.ts +25 -0
  8. package/dist/java-parser.js +281 -0
  9. package/dist/java-parser.js.map +1 -0
  10. package/dist/prompts/index.d.ts +9 -0
  11. package/dist/prompts/index.js +15 -0
  12. package/dist/prompts/index.js.map +1 -0
  13. package/dist/prompts/workflows.d.ts +27 -0
  14. package/dist/prompts/workflows.js +317 -0
  15. package/dist/prompts/workflows.js.map +1 -0
  16. package/dist/resources/biz/analytics.md +157 -0
  17. package/dist/resources/biz/biz-controller.md +151 -0
  18. package/dist/resources/biz/codelists.md +154 -0
  19. package/dist/resources/biz/entity-triple.md +142 -0
  20. package/dist/resources/biz/importer.md +153 -0
  21. package/dist/resources/biz/isenguard.md +156 -0
  22. package/dist/resources/biz/jobs.md +145 -0
  23. package/dist/resources/biz/processes.md +155 -0
  24. package/dist/resources/biz/storage.md +149 -0
  25. package/dist/resources/biz/tenants.md +159 -0
  26. package/dist/resources/biz/testing.md +127 -0
  27. package/dist/resources/db/composites.md +145 -0
  28. package/dist/resources/db/entities.md +156 -0
  29. package/dist/resources/db/mixing.md +176 -0
  30. package/dist/resources/db/queries.md +178 -0
  31. package/dist/resources/db/refs.md +135 -0
  32. package/dist/resources/index.d.ts +27 -0
  33. package/dist/resources/index.js +68 -0
  34. package/dist/resources/index.js.map +1 -0
  35. package/dist/resources/kernel/async.md +189 -0
  36. package/dist/resources/kernel/commons.md +203 -0
  37. package/dist/resources/kernel/config.md +155 -0
  38. package/dist/resources/kernel/di.md +138 -0
  39. package/dist/resources/kernel/lifecycle.md +146 -0
  40. package/dist/resources/loader.d.ts +9 -0
  41. package/dist/resources/loader.js +17 -0
  42. package/dist/resources/loader.js.map +1 -0
  43. package/dist/resources/web/controllers.md +151 -0
  44. package/dist/resources/web/services.md +136 -0
  45. package/dist/resources/web/templates.md +162 -0
  46. package/dist/tools/index.d.ts +4 -0
  47. package/dist/tools/index.js +3 -0
  48. package/dist/tools/index.js.map +1 -0
  49. package/dist/tools/introspection.d.ts +55 -0
  50. package/dist/tools/introspection.js +233 -0
  51. package/dist/tools/introspection.js.map +1 -0
  52. package/dist/tools/scaffold.d.ts +64 -0
  53. package/dist/tools/scaffold.js +505 -0
  54. package/dist/tools/scaffold.js.map +1 -0
  55. package/dist/workspace.d.ts +37 -0
  56. package/dist/workspace.js +185 -0
  57. package/dist/workspace.js.map +1 -0
  58. package/package.json +41 -0
@@ -0,0 +1,203 @@
1
+ # Commons Utilities
2
+
3
+ Sirius-kernel provides a set of utility classes in `sirius.kernel.commons` for
4
+ everyday programming tasks: internationalization, string handling, type-safe
5
+ value wrapping, and decimal arithmetic.
6
+
7
+ ## NLS — Internationalization
8
+
9
+ `NLS` (Native Language Support) is the central class for i18n. Translations
10
+ are stored in `.properties` files and accessed via keys.
11
+
12
+ ### Simple Lookup
13
+
14
+ ```java
15
+ // Looks up key "MyEntity.name" in the current language
16
+ String label = NLS.get("MyEntity.name");
17
+ ```
18
+
19
+ ### Formatted Messages
20
+
21
+ `NLS.fmtr()` provides named-parameter formatting:
22
+
23
+ ```java
24
+ // Given property: "welcome = Welcome, {{name}}! You have {{count}} items."
25
+ String msg = NLS.fmtr("welcome")
26
+ .set("name", userName)
27
+ .set("count", itemCount)
28
+ .format();
29
+ ```
30
+
31
+ The `{{param}}` syntax is Sirius-specific — it uses named parameters rather
32
+ than positional ones, making translations much easier to maintain.
33
+
34
+ ### Smart Formatting
35
+
36
+ `NLS.toUserString(Object)` converts any value to a locale-appropriate string:
37
+ - Numbers are formatted with locale-specific grouping and decimals.
38
+ - Dates/times use the locale's standard format.
39
+ - `Amount` values respect precision and locale.
40
+
41
+ ### Property Files
42
+
43
+ Translation files follow the pattern `basename_lang.properties`:
44
+ - `biz_en.properties` — English
45
+ - `biz_de.properties` — German
46
+
47
+ They are loaded from the classpath under `resources/`.
48
+
49
+ ## Strings
50
+
51
+ `Strings` provides null-safe string operations:
52
+
53
+ ```java
54
+ // Null-safe emptiness checks
55
+ Strings.isEmpty(null); // true
56
+ Strings.isEmpty(""); // true
57
+ Strings.isEmpty(" "); // true (trims first)
58
+ Strings.isFilled(value); // opposite of isEmpty
59
+
60
+ // Null-safe equality
61
+ Strings.areEqual(a, b); // null == null is true
62
+ Strings.equalIgnoreCase(a, b);
63
+
64
+ // Join with separator, skipping empty values
65
+ Strings.join(", ", firstName, lastName); // Skips nulls/empty
66
+
67
+ // Apply a string operation only if filled
68
+ Strings.apply("%s (%s)", name, code); // Returns "" if name is empty
69
+ ```
70
+
71
+ ### Strings.join
72
+
73
+ A commonly used pattern for building display strings:
74
+
75
+ ```java
76
+ // Produces "John, Doe" — skips empty parts
77
+ String fullName = Strings.join(" ", title, firstName, lastName);
78
+ ```
79
+
80
+ ## Value
81
+
82
+ `Value` is a type-safe wrapper around an arbitrary object, providing fluent
83
+ conversion and null-safe access:
84
+
85
+ ```java
86
+ Value val = Value.of(someObject);
87
+
88
+ // Type conversions with defaults
89
+ String s = val.asString(); // "" if null
90
+ int n = val.asInt(0); // 0 if not convertible
91
+ boolean b = val.asBoolean(); // false if null
92
+ LocalDate d = val.asLocalDate(fallback);
93
+
94
+ // Check state
95
+ val.isNull();
96
+ val.isFilled();
97
+ val.isEmpty();
98
+
99
+ // Conditional execution
100
+ val.ifFilled(v -> process(v));
101
+ ```
102
+
103
+ `Value` is used extensively in the web layer for request parameters and in the
104
+ import framework for cell values.
105
+
106
+ ## Amount
107
+
108
+ `Amount` provides precise decimal arithmetic, replacing `BigDecimal` with a
109
+ more ergonomic API. It is the standard type for monetary values and quantities.
110
+
111
+ ```java
112
+ Amount price = Amount.of(19.99);
113
+ Amount quantity = Amount.of(3);
114
+
115
+ // Arithmetic
116
+ Amount total = price.times(quantity); // 59.97
117
+ Amount discounted = total.subtract(Amount.of(5));
118
+
119
+ // Rounding
120
+ Amount rounded = total.round(RoundingMode.HALF_UP, 2);
121
+
122
+ // Comparison
123
+ total.isGreaterThan(Amount.of(50)); // true
124
+ total.isZeroOrNull(); // false
125
+
126
+ // Safe null handling — Amount.NOTHING represents "no value"
127
+ Amount.NOTHING.add(Amount.of(10)); // Amount.of(10)
128
+ ```
129
+
130
+ ### Amount vs BigDecimal
131
+
132
+ `Amount` wraps `BigDecimal` but adds:
133
+ - Null safety via `Amount.NOTHING` (acts as identity in arithmetic).
134
+ - Fluent API: `a.add(b).times(c)` reads naturally.
135
+ - Built-in formatting: `amount.toSmartRoundedString()`.
136
+
137
+ ## Formatter (Strings.apply)
138
+
139
+ `Strings.apply()` provides printf-like formatting but with Sirius conventions:
140
+
141
+ ```java
142
+ Strings.apply("User %s logged in from %s", username, ip);
143
+ ```
144
+
145
+ For more complex cases, use `NLS.fmtr()` with named parameters.
146
+
147
+ ## @Explain Annotation
148
+
149
+ `@Explain` is a documentation annotation used to justify code decisions that
150
+ might otherwise trigger review comments or static analysis warnings:
151
+
152
+ ```java
153
+ @Explain("We use a constant here because the interface pattern is intentional")
154
+ public interface Permissions {
155
+ String PERMISSION_MANAGE_USERS = "permission-manage-users";
156
+ }
157
+ ```
158
+
159
+ It has no runtime effect — it serves purely as inline documentation for
160
+ reviewers and maintainers. Common uses:
161
+ - Constants in interfaces (a Sirius convention).
162
+ - Intentional fallthrough in switch statements.
163
+ - Suppressed warnings that need justification.
164
+
165
+ ## Tuple and MultiLanguageString
166
+
167
+ ### Tuple
168
+
169
+ A simple pair container:
170
+
171
+ ```java
172
+ Tuple<String, Integer> pair = Tuple.create("key", 42);
173
+ pair.getFirst(); // "key"
174
+ pair.getSecond(); // 42
175
+ ```
176
+
177
+ ### MultiLanguageString
178
+
179
+ Stores text in multiple languages:
180
+
181
+ ```java
182
+ MultiLanguageString mls = new MultiLanguageString();
183
+ mls.addText("en", "Hello");
184
+ mls.addText("de", "Hallo");
185
+
186
+ // Gets text for current language, falls back to default
187
+ String text = mls.getText();
188
+ ```
189
+
190
+ Used in entities that need multi-language content (product names, descriptions).
191
+
192
+ ## Best Practices
193
+
194
+ 1. **Use `Strings.isFilled()`** instead of `str != null && !str.isEmpty()`.
195
+
196
+ 2. **Use `Amount`** for all monetary and quantity values — never `double`.
197
+
198
+ 3. **Use `NLS.fmtr()`** with named parameters for user-facing messages. Positional
199
+ parameters break when translations reorder words.
200
+
201
+ 4. **Use `Value`** when dealing with loosely typed data (web params, imports).
202
+
203
+ 5. **Use `@Explain`** to document non-obvious code choices proactively.
@@ -0,0 +1,155 @@
1
+ # Configuration System
2
+
3
+ Sirius uses Typesafe Config (HOCON format) for all configuration. The system
4
+ supports layered config files with well-defined precedence and a framework
5
+ flag mechanism for enabling/disabling modules.
6
+
7
+ ## HOCON Format
8
+
9
+ HOCON (Human-Optimized Config Object Notation) is a superset of JSON:
10
+
11
+ ```hocon
12
+ http {
13
+ port = 9000
14
+ sessionTimeout = 30 minutes
15
+ ssl.enabled = false
16
+ }
17
+
18
+ # Lists
19
+ allowed.hosts = ["localhost", "example.com"]
20
+
21
+ # Substitutions
22
+ app.url = "http://"${http.host}":"${http.port}
23
+ ```
24
+
25
+ Key features: comments with `#`, duration/size literals (`30 minutes`, `512MB`),
26
+ path expressions with dots, and variable substitution.
27
+
28
+ ## File Precedence
29
+
30
+ Config files are loaded in this order, with later files overriding earlier ones:
31
+
32
+ 1. **`component-NNN-name.conf`** — Framework defaults, loaded by classpath scan.
33
+ The numeric prefix controls load order (e.g., `component-050-kernel.conf`
34
+ loads before `component-070-biz.conf`).
35
+
36
+ 2. **`application.conf`** — Application-level defaults. This is where a Sirius
37
+ application defines its own configuration.
38
+
39
+ 3. **`develop.conf`** — Development overrides. Loaded only when the system
40
+ property `sirius.debug` is set (automatically set in dev mode). Use this
41
+ for local database URLs, debug flags, etc.
42
+
43
+ 4. **`instance.conf`** — Instance-specific configuration. Loaded last, used
44
+ for production secrets, deployment-specific URLs, and other environment
45
+ settings. Typically not checked into version control.
46
+
47
+ ### Merge Behavior
48
+
49
+ Later files **merge** with earlier ones — they do not replace the entire tree.
50
+ A key in `instance.conf` overrides only that specific key; everything else
51
+ from earlier files remains.
52
+
53
+ ## Framework Flags
54
+
55
+ The `sirius.frameworks` config section controls which modules are active:
56
+
57
+ ```hocon
58
+ sirius.frameworks {
59
+ biz.tenants = true
60
+ biz.tenants-jdbc = true
61
+ biz.tenants-mongo = false
62
+ biz.storage = true
63
+ biz.jobs = true
64
+ biz.processes = true
65
+ biz.analytics = false
66
+ }
67
+ ```
68
+
69
+ **All flags default to `false`.** A module must be explicitly enabled by the
70
+ application or it will not be loaded.
71
+
72
+ Framework flags affect two things:
73
+
74
+ 1. **Entity loading** — Entities annotated with `@Framework("flag.name")` are
75
+ only registered in the ORM when the flag is `true`.
76
+
77
+ 2. **Service loading** — Services annotated with `@Register(framework = "flag.name")`
78
+ are only instantiated and registered when the flag is `true`.
79
+
80
+ ### Naming Convention
81
+
82
+ Framework flags follow the pattern `module.feature` or `module.feature-variant`:
83
+ - `biz.tenants` — The tenants module
84
+ - `biz.tenants-jdbc` — JDBC variant of tenants
85
+ - `biz.tenants-mongo` — MongoDB variant of tenants
86
+
87
+ ## @ConfigValue Injection
88
+
89
+ Configuration values can be injected directly into fields:
90
+
91
+ ```java
92
+ @ConfigValue("http.port")
93
+ private int port;
94
+
95
+ @ConfigValue("product.name")
96
+ private String productName;
97
+
98
+ @ConfigValue("feature.enabled")
99
+ private boolean enabled;
100
+
101
+ @ConfigValue("http.sessionTimeout")
102
+ private Duration sessionTimeout;
103
+
104
+ @ConfigValue("allowed.hosts")
105
+ private List<String> hosts;
106
+ ```
107
+
108
+ The injection happens at startup time and values are immutable after that.
109
+
110
+ ## Accessing Config Programmatically
111
+
112
+ For dynamic access, use the `Sirius` class:
113
+
114
+ ```java
115
+ // Get a config value
116
+ String value = Sirius.getSettings().getString("my.config.key");
117
+
118
+ // Check if a framework is enabled
119
+ boolean enabled = Sirius.isFrameworkEnabled("biz.tenants");
120
+ ```
121
+
122
+ ## Extension Configs
123
+
124
+ Libraries can provide default configuration by including a
125
+ `component-NNN-name.conf` file in their JAR's classpath root. The naming
126
+ convention:
127
+
128
+ - `component-050-kernel.conf` — sirius-kernel defaults
129
+ - `component-060-web.conf` — sirius-web defaults
130
+ - `component-060-db.conf` — sirius-db defaults
131
+ - `component-070-biz.conf` — sirius-biz defaults
132
+
133
+ The numbering ensures correct load order: kernel before web, web before biz.
134
+
135
+ ## System Properties
136
+
137
+ Some settings can be overridden via JVM system properties:
138
+
139
+ - `-Dsirius.debug=true` — Enables development mode (loads `develop.conf`)
140
+ - `-Dport=9000` — Override HTTP port
141
+ - `-Dsirius.nodeName=node1` — Set the cluster node name
142
+
143
+ ## Best Practices
144
+
145
+ 1. **Never hardcode values** that might vary between environments. Use config.
146
+
147
+ 2. **Put secrets in `instance.conf`** and exclude it from version control.
148
+
149
+ 3. **Use `develop.conf`** for local database URLs and debug settings.
150
+
151
+ 4. **Document config keys** in your `component-*.conf` with comments — these
152
+ serve as the default values and documentation for downstream users.
153
+
154
+ 5. **Check framework flags** before depending on a module's services. If your
155
+ code is optional, guard it with a framework flag on your own `@Register`.
@@ -0,0 +1,138 @@
1
+ # Dependency Injection
2
+
3
+ Sirius uses its own lightweight DI system built into sirius-kernel. All injection
4
+ happens at startup time — there is no runtime resolution or request-scoped injection.
5
+
6
+ ## @Register — Publishing a Service
7
+
8
+ Every class that should participate in DI must be annotated with `@Register`:
9
+
10
+ ```java
11
+ @Register(classes = {MyService.class, Startable.class})
12
+ public class MyServiceImpl implements MyService, Startable {
13
+ // ...
14
+ }
15
+ ```
16
+
17
+ **Critical rule:** The `classes` parameter must list **every interface and superclass**
18
+ the component should be discoverable as. If you implement `Startable` but omit it
19
+ from `classes`, the framework will never call `started()`.
20
+
21
+ Parameters:
22
+ - `classes` — Array of types this component registers as (required when implementing interfaces).
23
+ - `framework` — The framework flag that must be enabled for this component to load
24
+ (e.g., `@Register(framework = "biz.tenants")`).
25
+ - `name` — Optional name for named lookups.
26
+
27
+ If a class has no interfaces and no special lifecycle, a bare `@Register` suffices.
28
+
29
+ ## @Framework — For Entities
30
+
31
+ Entities (database-mapped classes) use `@Framework` instead of `@Register(framework = ...)`:
32
+
33
+ ```java
34
+ @Framework("biz.tenants-jdbc")
35
+ public class SQLTenant extends SQLTenantAware<SQLTenant, SQLUserAccount>
36
+ implements Tenant<Long> {
37
+ }
38
+ ```
39
+
40
+ The distinction: `@Register(framework = ...)` controls service loading;
41
+ `@Framework` controls entity registration in the schema and ORM layer.
42
+
43
+ ## @Part — Injecting a Singleton
44
+
45
+ `@Part` injects a single implementation of a type:
46
+
47
+ ```java
48
+ @Part
49
+ private OMA oma;
50
+
51
+ @Part
52
+ private Tasks tasks;
53
+ ```
54
+
55
+ The field is populated after the object is constructed, before `started()` is called.
56
+
57
+ If no implementation is registered, the field remains `null` — no error is thrown.
58
+ Guard against this in optional dependencies.
59
+
60
+ ### configPath
61
+
62
+ For interfaces with multiple named implementations, use `configPath`:
63
+
64
+ ```java
65
+ @Part(configPath = "storage.layer1.engine")
66
+ private ObjectStorageEngine engine;
67
+ ```
68
+
69
+ This reads the implementation class name from the config file, allowing runtime
70
+ selection of the concrete implementation.
71
+
72
+ ## @Parts — Injecting All Implementations
73
+
74
+ `@Parts` injects every registered implementation of a given interface as a
75
+ `PartCollection`:
76
+
77
+ ```java
78
+ @Parts(SidebarProvider.class)
79
+ private PartCollection<SidebarProvider> providers;
80
+ ```
81
+
82
+ `PartCollection` is iterable and provides `getAll()` returning a list. The
83
+ implementations are returned in no guaranteed order.
84
+
85
+ ## @PriorityParts — Ordered Injection
86
+
87
+ Like `@Parts`, but returns implementations sorted by their `Priorized.getPriority()`
88
+ value (lower values first):
89
+
90
+ ```java
91
+ @PriorityParts(LinkTarget.class)
92
+ private List<LinkTarget> targets;
93
+ ```
94
+
95
+ Use this when execution order matters — e.g., filter chains, interceptors, or
96
+ fallback strategies.
97
+
98
+ ## @ConfigValue — Injecting Configuration
99
+
100
+ `@ConfigValue` injects values from the Typesafe Config system:
101
+
102
+ ```java
103
+ @ConfigValue("product.baseUrl")
104
+ private String baseUrl;
105
+
106
+ @ConfigValue("http.sessionTimeout")
107
+ private Duration sessionTimeout;
108
+
109
+ @ConfigValue("security.enabled")
110
+ private boolean securityEnabled;
111
+
112
+ @ConfigValue("cache.maxSize")
113
+ private int maxSize;
114
+
115
+ @ConfigValue("allowed.hosts")
116
+ private List<String> allowedHosts;
117
+ ```
118
+
119
+ Supported types: `String`, `int`, `long`, `boolean`, `Duration`, `List<String>`.
120
+ The config path refers to a key in the HOCON configuration (see config resource).
121
+
122
+ ## Common Mistakes
123
+
124
+ 1. **Missing `classes` in @Register** — The most frequent DI bug. If your class
125
+ implements `Startable` or `Initializable` and you write `@Register` without
126
+ listing those interfaces in `classes`, the lifecycle methods will never be called.
127
+
128
+ 2. **Circular dependencies** — Sirius does not support circular `@Part` injection.
129
+ Use `Injector.context().findPart(...)` for lazy resolution when needed.
130
+
131
+ 3. **Using DI in constructors** — `@Part` fields are not yet populated during
132
+ construction. Use `Startable.started()` or `Initializable.initialize()` for
133
+ init logic that depends on injected parts.
134
+
135
+ 4. **Forgetting the framework flag** — If your service only makes sense when a
136
+ specific framework is active, always set `@Register(framework = "...")`.
137
+ Otherwise the class loads unconditionally and may fail if its dependencies
138
+ are not present.
@@ -0,0 +1,146 @@
1
+ # Lifecycle Interfaces
2
+
3
+ Sirius-kernel defines three lifecycle interfaces that components can implement to
4
+ hook into the application startup and shutdown process. All three extend `Priorized`,
5
+ which controls execution order.
6
+
7
+ ## Startable
8
+
9
+ `Startable` is called once after dependency injection is complete. This is the
10
+ primary hook for initialization logic that depends on injected `@Part` fields.
11
+
12
+ ```java
13
+ @Register(classes = {MyService.class, Startable.class})
14
+ public class MyServiceImpl implements MyService, Startable {
15
+
16
+ @Part
17
+ private OMA oma;
18
+
19
+ @Override
20
+ public int getPriority() {
21
+ return PriorityCollector.DEFAULT_PRIORITY;
22
+ }
23
+
24
+ @Override
25
+ public void started() {
26
+ // All @Part fields are populated at this point.
27
+ // Initialize caches, start background work, etc.
28
+ }
29
+ }
30
+ ```
31
+
32
+ **Key points:**
33
+ - `started()` is called exactly once, during framework boot.
34
+ - All `@Part` fields are guaranteed to be injected before `started()` runs.
35
+ - Components are started in priority order (lower `getPriority()` values first).
36
+ - The `started()` method should not block indefinitely — long-running work should
37
+ be dispatched to an executor via the `Tasks` service.
38
+
39
+ ## Stoppable
40
+
41
+ `Stoppable` is called during graceful shutdown. It **must not block** for extended
42
+ periods — it should signal threads to stop, release non-critical resources, and
43
+ return quickly.
44
+
45
+ ```java
46
+ @Register(classes = {CacheManager.class, Startable.class, Stoppable.class})
47
+ public class CacheManager implements Startable, Stoppable {
48
+
49
+ @Override
50
+ public void started() {
51
+ // Initialize caches
52
+ }
53
+
54
+ @Override
55
+ public void stopped() {
56
+ // Signal cache eviction threads to stop.
57
+ // Must return quickly — do NOT block here.
58
+ }
59
+ }
60
+ ```
61
+
62
+ **Key points:**
63
+ - `stopped()` is called in reverse priority order (highest priority stopped first).
64
+ - Must not block. If you need to wait for cleanup, implement `Killable` instead.
65
+ - Called before `Killable.killed()`, so resources may still be partially available.
66
+
67
+ ## Killable
68
+
69
+ `Killable` is the final shutdown hook. Unlike `Stoppable`, it **may block** to
70
+ perform thorough cleanup — closing database connections, flushing buffers,
71
+ writing final state.
72
+
73
+ ```java
74
+ @Register(classes = {ConnectionPool.class, Startable.class, Killable.class})
75
+ public class ConnectionPool implements Startable, Killable {
76
+
77
+ @Override
78
+ public void started() {
79
+ // Open connection pool
80
+ }
81
+
82
+ @Override
83
+ public void killed() {
84
+ // Close all connections, wait for pending queries.
85
+ // Blocking is acceptable here.
86
+ }
87
+ }
88
+ ```
89
+
90
+ **Key points:**
91
+ - `killed()` is called after all `Stoppable` instances have been stopped.
92
+ - May block for cleanup — this is the last chance before the JVM exits.
93
+ - Called in reverse priority order.
94
+
95
+ ## Priorized
96
+
97
+ All lifecycle interfaces extend `Priorized`:
98
+
99
+ ```java
100
+ public interface Priorized {
101
+ int getPriority();
102
+ }
103
+ ```
104
+
105
+ Priority values control execution order:
106
+ - **Startup**: lower values start first (priority 10 starts before priority 100).
107
+ - **Shutdown**: higher values stop/kill first (reverse order).
108
+
109
+ Common priority constants from `PriorityCollector`:
110
+ - `DEFAULT_PRIORITY` (100) — Use unless you have a specific ordering need.
111
+
112
+ ## Registration Pattern
113
+
114
+ The most important pattern: always list lifecycle interfaces in `@Register(classes = ...)`:
115
+
116
+ ```java
117
+ // CORRECT
118
+ @Register(classes = {MyService.class, Startable.class, Stoppable.class})
119
+ public class MyServiceImpl implements MyService, Startable, Stoppable { ... }
120
+
121
+ // WRONG — lifecycle methods will never be called!
122
+ @Register
123
+ public class MyServiceImpl implements MyService, Startable, Stoppable { ... }
124
+ ```
125
+
126
+ This is a common mistake. The framework discovers lifecycle participants by
127
+ looking up registered classes — if `Startable.class` is not in the `classes`
128
+ list, the framework does not know the component is startable.
129
+
130
+ ## Initialization Order Summary
131
+
132
+ 1. All `@Register` components are instantiated.
133
+ 2. All `@Part` fields are injected.
134
+ 3. `Startable.started()` is called in priority order (ascending).
135
+ 4. Application runs.
136
+ 5. Shutdown signal received.
137
+ 6. `Stoppable.stopped()` is called in reverse priority order (non-blocking).
138
+ 7. `Killable.killed()` is called in reverse priority order (may block).
139
+ 8. JVM exits.
140
+
141
+ ## Initializable
142
+
143
+ A less common alternative: `Initializable` provides an `initialize()` method
144
+ that is called even earlier than `started()`, during the injection phase itself.
145
+ Use this only when your component must be ready before other `@Part` injections
146
+ complete. In most cases, prefer `Startable`.
@@ -0,0 +1,9 @@
1
+ export interface ResourceDefinition {
2
+ uri: string;
3
+ name: string;
4
+ description: string;
5
+ layer: string;
6
+ mimeType: string;
7
+ content: string;
8
+ }
9
+ export declare function loadResource(layer: string, name: string, description: string): ResourceDefinition;
@@ -0,0 +1,17 @@
1
+ import { readFileSync } from "fs";
2
+ import { join, dirname } from "path";
3
+ import { fileURLToPath } from "url";
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ export function loadResource(layer, name, description) {
6
+ const filePath = join(__dirname, layer, `${name}.md`);
7
+ const content = readFileSync(filePath, "utf-8");
8
+ return {
9
+ uri: `sirius://${layer}/${name}`,
10
+ name: `${layer}/${name}`,
11
+ description,
12
+ layer,
13
+ mimeType: "text/markdown",
14
+ content,
15
+ };
16
+ }
17
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/resources/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAW1D,MAAM,UAAU,YAAY,CAC1B,KAAa,EACb,IAAY,EACZ,WAAmB;IAEnB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO;QACL,GAAG,EAAE,YAAY,KAAK,IAAI,IAAI,EAAE;QAChC,IAAI,EAAE,GAAG,KAAK,IAAI,IAAI,EAAE;QACxB,WAAW;QACX,KAAK;QACL,QAAQ,EAAE,eAAe;QACzB,OAAO;KACR,CAAC;AACJ,CAAC"}