Skip to content

Commit 8e82081

Browse files
authored
docs(module): document configurator lifecycle and module system (#4738)
* docs(module): document configurator lifecycle and module system closes equinor/fusion-core-tasks#1258 ref equinor/fusion-core-tasks#1256 * docs(module): add sidebar entry and README doc links for module system * feat(module): document configurator plugins * fix(docs): quote module lifecycle frontmatter
1 parent 052cdab commit 8e82081

36 files changed

Lines changed: 2111 additions & 68 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@equinor/fusion-framework-docs": patch
3+
---
4+
5+
Document module configurator plugins, including `registerPlugin`, `createPlugin`, plugin teardown behavior, lifecycle ordering, and VuePress navigation updates.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
"@equinor/fusion-framework-module": patch
3+
"@equinor/fusion-framework-docs": patch
4+
---
5+
6+
Document the `@equinor/fusion-framework-module` configurator and lifecycle.
7+
8+
Adds structured `docs/` pages covering:
9+
10+
- **concepts** — module system overview, roles, and mental model
11+
- **lifecycle** — configure → initialize → post-initialize → dispose phase sequence
12+
- **configuration** — how to register modules and use `addConfig` / `configure`
13+
- **cross-module deps**`requireInstance` pattern for inter-module dependencies
14+
- **events**`event$` observable and event naming conventions
15+
- **authoring modules** — step-by-step guide for creating a custom module
16+
- **common mistakes** — FAQ-style pitfalls and how to avoid them
17+
18+
All pages are structured for retrieval (chunked sections, import paths, copy-pasteable examples) to improve Fusion Knowledge / Azure AI Search answer quality.
19+
20+
Closes: equinor/fusion-core-tasks#1258

.changeset/fusion-framework-module_register-plugin.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
Add `registerPlugin` to `IModulesConfigurator` and `ModulesConfigurator` for application-level side effects that run after modules are initialized and before application render.
77

8-
Plugins receive the initialized module map through `FrameworkPluginArgs` and may return a teardown callback that runs during `dispose`. Plugin-related types and the `createPlugin(name, callback)` helper are available from the dedicated `@equinor/fusion-framework-module/plugins` entrypoint. Plugin registration and teardown failures are isolated so one failing plugin does not block other plugins or module disposal.
8+
Plugins receive the initialized module map through `FrameworkPluginArgs` and may return a teardown callback that runs during `dispose`. Plugin-related types and the `createPlugin(name, callback)` helper are available from the dedicated `@equinor/fusion-framework-module/plugins` entrypoint. Plugin registration and teardown failures are isolated so one failing plugin does not block other plugins or module disposal. `ModuleConfiguratorEventName` and `ModuleConfiguratorEventBaseName` are available from the `@equinor/fusion-framework-module/configurator` entrypoint for filtering `ModuleConfigurator.{name}.{state}` lifecycle events without hard-coded strings.
99

1010
```typescript
1111
import { createPlugin } from '@equinor/fusion-framework-module/plugins';

packages/modules/module/README.md

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ A `Module` is a plain object that declares a name, an optional configuration fac
1717
1. **Configure** – each module's `configure()` factory creates a config builder; registered callbacks mutate it; `postConfigure()` hooks run.
1818
2. **Initialize** – modules are initialized concurrently; cross-module dependencies are resolved through `requireInstance()`.
1919
3. **Post-initialize**`postInitialize()` hooks and `onInitialized` callbacks run.
20+
4. **Plugins** – registered plugins connect host-level side effects after every module is ready.
2021

2122
The result is a sealed `ModulesInstance` whose property names match the module keys and whose values are the initialized providers.
2223

@@ -28,6 +29,19 @@ An abstract class for building module configuration declaratively. Subclasses ex
2829

2930
Abstract base class for module providers (the runtime instances returned by `initialize()`). It manages a `Subscription` container for automatic teardown and exposes a `SemanticVersion` for compatibility checks.
3031

32+
## Documentation
33+
34+
| Topic | Description |
35+
|---|---|
36+
| [Concepts](./docs/concepts.md) | Module system overview, roles, and mental model |
37+
| [Lifecycle](./docs/lifecycle.md) | Configure → initialize → post-initialize → dispose phase sequence |
38+
| [Configuration](./docs/configuration.md) | How to register modules and use `addConfig` / `configure` |
39+
| [Cross-Module Dependencies](./docs/cross-module-deps.md) | `requireInstance` pattern for inter-module dependencies |
40+
| [Plugins](./docs/plugins.md) | `registerPlugin`, `createPlugin`, plugin teardown, and host-level side effects |
41+
| [Events](./docs/events.md) | `event$` observable and event naming conventions |
42+
| [Authoring Modules](./docs/authoring-modules.md) | Step-by-step guide for creating a custom module |
43+
| [Common Mistakes](./docs/common-mistakes.md) | FAQ-style pitfalls and how to avoid them |
44+
3145
## Installation
3246

3347
```sh
@@ -92,7 +106,7 @@ export const greeterModule: Module<'greeter', GreeterProvider, GreeterConfigurat
92106
| Export | Kind | Description |
93107
|---|---|---|
94108
| `Module` | type | Interface describing a module's structure and lifecycle hooks |
95-
| `ModulesConfigurator` | class | Orchestrates configure → initialize → dispose for a set of modules |
109+
| `ModulesConfigurator` | class | Orchestrates configure → initialize → plugin → dispose for a set of modules |
96110
| `IModulesConfigurator` | interface | Public contract for the modules configurator |
97111
| `IModuleConfigurator` | interface | Descriptor for registering a single module with lifecycle hooks |
98112
| `BaseConfigBuilder` | class | Abstract config builder with dot-path targeting and observable pipelines |
@@ -105,6 +119,25 @@ export const greeterModule: Module<'greeter', GreeterProvider, GreeterConfigurat
105119
| `IModuleConsoleLogger` | interface | Logger interface with `formatModuleName` |
106120
| `DotPath`, `DotPathType`, `DotPathUnion` | types | Recursive dot-notation path utilities |
107121

122+
### Configurator Sub-path (`@equinor/fusion-framework-module/configurator`)
123+
124+
| Export | Kind | Description |
125+
|---|---|---|
126+
| `ModuleConfiguratorEventBaseName` | const | Shared `ModuleConfigurator` base segment for configurator lifecycle event names |
127+
| `ModuleConfiguratorEventName` | object | Map of `ModuleConfigurator.{name}.{state}` event names for filtering `event$` without hard-coded strings |
128+
129+
### Plugins Sub-path (`@equinor/fusion-framework-module/plugins`)
130+
131+
| Export | Kind | Description |
132+
|---|---|---|
133+
| `createPlugin` | function | Creates a named plugin callback for stable lifecycle diagnostics |
134+
| `FrameworkPluginArgs` | type | Arguments passed to inline plugin callbacks: initialized modules and optional ref |
135+
| `FrameworkPluginCallback` | type | Callback accepted by `IModulesConfigurator.registerPlugin` |
136+
| `FrameworkPluginTeardown` | type | Cleanup callback or disposable object returned by a plugin |
137+
| `FrameworkPluginRegistration` | type | Plugin return type: teardown or `undefined` |
138+
| `FrameworkPlugin` | interface | Named plugin callback returned by `createPlugin` |
139+
| `FrameworkPluginInitializer` | type | Developer-facing callback signature used by `createPlugin` |
140+
108141
### Provider Sub-path (`@equinor/fusion-framework-module/provider`)
109142

110143
| Export | Kind | Description |
@@ -127,6 +160,8 @@ export const greeterModule: Module<'greeter', GreeterProvider, GreeterConfigurat
127160
│ Init │ module.initialize() │ │
128161
│ │ module.postInitialize() │ onInitialized()│
129162
├──────────┼──────────────────────────┼────────────────┤
163+
│ Plugin │ │ registerPlugin │
164+
├──────────┼──────────────────────────┼────────────────┤
130165
│ Dispose │ module.dispose() │ instance. │
131166
│ │ │ dispose() │
132167
└──────────┴──────────────────────────┴────────────────┘
@@ -161,6 +196,25 @@ postInitialize: async ({ instance, modules }) => {
161196

162197
`configure` and `initialize` are the two required hooks. `postConfigure`, `postInitialize`, and `dispose` are optional.
163198

199+
### Plugins and host-level side effects
200+
201+
Use `registerPlugin` for application-owned wiring that needs the complete module instance before render. Plugins run after `postInitialize` and `onInitialized`, but before `initialize()` resolves. Return a teardown callback to clean up subscriptions, global listeners, timers, or telemetry bindings during dispose.
202+
203+
```typescript
204+
import { createPlugin } from '@equinor/fusion-framework-module/plugins';
205+
206+
const contextTelemetryPlugin = createPlugin<[typeof eventModule, typeof telemetryModule]>(
207+
'contextTelemetry',
208+
(modules) => modules.event.addEventListener('context:changed', (event) => {
209+
modules.telemetry.track('context.changed', event.detail);
210+
}),
211+
);
212+
213+
configurator.registerPlugin(contextTelemetryPlugin);
214+
```
215+
216+
See [Plugins](./docs/plugins.md) for teardown rules, failure behavior, and API reference.
217+
164218
Events are emitted on `configurator.event$` throughout the lifecycle for telemetry and debugging.
165219

166220
## Related Packages

0 commit comments

Comments
 (0)