@equinor/fusion-framework-app 11.0.12 → 12.0.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 (41) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +38 -1
  3. package/dist/esm/AppConfigurator.js +28 -3
  4. package/dist/esm/AppConfigurator.js.map +1 -1
  5. package/dist/esm/AppConfiguratorError.js +32 -0
  6. package/dist/esm/AppConfiguratorError.js.map +1 -0
  7. package/dist/esm/AppModulesConfiguredEvent.js +18 -0
  8. package/dist/esm/AppModulesConfiguredEvent.js.map +1 -0
  9. package/dist/esm/AppModulesInitializedEvent.js +23 -0
  10. package/dist/esm/AppModulesInitializedEvent.js.map +1 -0
  11. package/dist/esm/configure-modules.js +6 -0
  12. package/dist/esm/configure-modules.js.map +1 -1
  13. package/dist/esm/enable-state.js +42 -0
  14. package/dist/esm/enable-state.js.map +1 -0
  15. package/dist/esm/index.js +3 -0
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/utils.js +41 -0
  18. package/dist/esm/utils.js.map +1 -0
  19. package/dist/esm/version.js +1 -1
  20. package/dist/esm/version.js.map +1 -1
  21. package/dist/tsconfig.tsbuildinfo +1 -1
  22. package/dist/types/AppConfigurator.d.ts +20 -2
  23. package/dist/types/AppConfiguratorError.d.ts +26 -0
  24. package/dist/types/AppModulesConfiguredEvent.d.ts +37 -0
  25. package/dist/types/AppModulesInitializedEvent.d.ts +34 -0
  26. package/dist/types/configure-modules.d.ts +6 -0
  27. package/dist/types/enable-state.d.ts +39 -0
  28. package/dist/types/index.d.ts +4 -1
  29. package/dist/types/utils.d.ts +22 -0
  30. package/dist/types/version.d.ts +1 -1
  31. package/package.json +21 -7
  32. package/src/AppConfigurator.ts +50 -4
  33. package/src/AppConfiguratorError.ts +34 -0
  34. package/src/AppModulesConfiguredEvent.ts +43 -0
  35. package/src/AppModulesInitializedEvent.ts +40 -0
  36. package/src/configure-modules.ts +8 -0
  37. package/src/enable-state.ts +49 -0
  38. package/src/index.ts +7 -1
  39. package/src/utils.ts +50 -0
  40. package/src/version.ts +1 -1
  41. package/tsconfig.json +3 -0
@@ -2,6 +2,13 @@ import type { FusionModulesInstance } from '@equinor/fusion-framework';
2
2
  import { type AnyModule, type IModulesConfigurator, ModulesConfigurator } from '@equinor/fusion-framework-module';
3
3
  import { configureHttpClient, configureHttp, type HttpClientOptions } from '@equinor/fusion-framework-module-http';
4
4
  import type { AppEnv, AppModules } from './types';
5
+ import { type DeepImmutable } from './utils';
6
+ /**
7
+ * Type definition for AppConfigurator constructor
8
+ */
9
+ export type AppConfiguratorConstructor<TModules extends readonly AnyModule[] = [], TRef extends FusionModulesInstance = FusionModulesInstance, TEnv extends AppEnv = AppEnv> = {
10
+ new (env: TEnv, ref?: TRef): IAppConfigurator<TModules, TRef>;
11
+ };
5
12
  /**
6
13
  * Contract for configuring Fusion application modules.
7
14
  *
@@ -25,6 +32,7 @@ import type { AppEnv, AppModules } from './types';
25
32
  * ```
26
33
  */
27
34
  export interface IAppConfigurator<TModules extends Array<AnyModule> | unknown = unknown, TRef extends FusionModulesInstance = FusionModulesInstance> extends IModulesConfigurator<AppModules<TModules>, TRef> {
35
+ readonly manifest: DeepImmutable<AppEnv['manifest']>;
28
36
  /**
29
37
  * Configure the HTTP module with custom settings.
30
38
  *
@@ -73,7 +81,7 @@ export interface IAppConfigurator<TModules extends Array<AnyModule> | unknown =
73
81
  *
74
82
  * `AppConfigurator` is created internally by {@link configureModules}. It registers
75
83
  * the `event`, `http`, and `msal` (auth) modules by default and reads any HTTP
76
- * endpoints declared in the applications environment config.
84
+ * endpoints declared in the application's environment config.
77
85
  *
78
86
  * @template TModules - Additional application-specific modules beyond the defaults.
79
87
  * @template TRef - The resolved Fusion modules instance used as an initialization reference.
@@ -90,6 +98,7 @@ export interface IAppConfigurator<TModules extends Array<AnyModule> | unknown =
90
98
  * ```
91
99
  */
92
100
  export declare class AppConfigurator<TModules extends Array<AnyModule> | unknown = unknown, TRef extends FusionModulesInstance = FusionModulesInstance, TEnv extends AppEnv = AppEnv> extends ModulesConfigurator<AppModules<TModules>, TRef> implements IAppConfigurator<TModules, TRef> {
101
+ #private;
93
102
  readonly env: TEnv;
94
103
  /**
95
104
  * The class name used for event naming. This static property ensures
@@ -103,8 +112,17 @@ export declare class AppConfigurator<TModules extends Array<AnyModule> | unknown
103
112
  * HTTP clients declared in `env.config.endpoints`.
104
113
  *
105
114
  * @param env - The application environment containing manifest, config, and optional basename.
115
+ * @param ref - Optional reference to the Fusion modules instance, used for event dispatching.
116
+ */
117
+ constructor(env: TEnv, ref?: TRef);
118
+ /**
119
+ * The immutable application manifest.
120
+ *
121
+ * Deeply frozen at construction time to prevent accidental mutations.
122
+ *
123
+ * @returns The deeply immutable application manifest.
106
124
  */
107
- constructor(env: TEnv);
125
+ get manifest(): DeepImmutable<AppEnv['manifest']>;
108
126
  /**
109
127
  * Read HTTP endpoint definitions from the application config and register each
110
128
  * one as a named HTTP client.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Custom error class for application configurator errors.
3
+ *
4
+ * Provides error context to help developers debug configuration and initialization issues.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * try {
9
+ * const modules = await initialize({ fusion, env });
10
+ * } catch (error) {
11
+ * if (error instanceof AppConfiguratorError) {
12
+ * console.log(`Error in ${error.phase}: ${error.message}`);
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export declare class AppConfiguratorError extends Error {
18
+ readonly phase: 'configuration' | 'initialization';
19
+ /**
20
+ * @param message - Human-readable error description
21
+ * @param phase - The phase where the error occurred
22
+ * @param cause - The underlying error that caused this failure
23
+ */
24
+ constructor(message: string, phase: 'configuration' | 'initialization', cause?: unknown);
25
+ }
26
+ export default AppConfiguratorError;
@@ -0,0 +1,37 @@
1
+ import type { ModulesConfigType, AnyModule } from '@equinor/fusion-framework-module';
2
+ import type { AppModules } from '@equinor/fusion-framework-module-app';
3
+ import { FrameworkEvent, type FrameworkEventInit } from '@equinor/fusion-framework-module-event';
4
+ import type { AppModulesInitializedEvent } from './AppModulesInitializedEvent';
5
+ /**
6
+ * Represents the initialization data for an event indicating that application modules have been configured.
7
+ *
8
+ * @template T - Array of additional modules configured in the application.
9
+ * @extends FrameworkEventInit
10
+ * @property {string} appKey - The unique key identifying the application.
11
+ * @property {ModulesConfigType<AppModules<T>>} configs - The configuration objects for the specified application modules.
12
+ */
13
+ type AppModulesConfiguredEventInit<T extends AnyModule[] | unknown = unknown> = FrameworkEventInit<{
14
+ appKey: string;
15
+ configs: ModulesConfigType<AppModules<T>>;
16
+ }>;
17
+ /**
18
+ * Event emitted when application modules have been configured.
19
+ *
20
+ * @template T - An array of additional modules configured in the application.
21
+ * @extends FrameworkEvent<AppModulesConfiguredEventInit<T>>
22
+ */
23
+ export declare class AppModulesConfiguredEvent<T extends AnyModule[] | unknown = unknown> extends FrameworkEvent<AppModulesConfiguredEventInit<T>> {
24
+ /**
25
+ * Create an event describing configured application modules.
26
+ *
27
+ * @param init - Event initialization data containing the application key and module configs.
28
+ */
29
+ constructor(init: AppModulesConfiguredEventInit<T>);
30
+ }
31
+ declare module '@equinor/fusion-framework-module-event' {
32
+ interface FrameworkEventMap {
33
+ onAppModulesConfigured: AppModulesConfiguredEvent;
34
+ onAppModulesInitialized: AppModulesInitializedEvent;
35
+ }
36
+ }
37
+ export {};
@@ -0,0 +1,34 @@
1
+ import type { AnyModule } from '@equinor/fusion-framework-module';
2
+ import type { AppModulesInstance } from '@equinor/fusion-framework-module-app';
3
+ import { FrameworkEvent, type FrameworkEventInit } from '@equinor/fusion-framework-module-event';
4
+ /**
5
+ * Event initialization type for the "AppModulesInitialized" event.
6
+ *
7
+ * @template T - An array of module types extending `AnyModule`. Defaults to an empty array.
8
+ * @property appKey - The unique key identifying the application.
9
+ * @property modules - The instance containing all initialized application modules.
10
+ */
11
+ type AppModulesInitializedEventInit<T extends AnyModule[] | unknown = unknown> = FrameworkEventInit<{
12
+ appKey: string;
13
+ modules: AppModulesInstance<T>;
14
+ }>;
15
+ /**
16
+ * Event triggered when application modules have been initialized.
17
+ *
18
+ * @template T - An array of modules extending `AnyModule`. Defaults to an empty array.
19
+ * @extends FrameworkEvent<AppModulesInitializedEventInit<T>>
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const event = new AppModulesInitializedEvent({ modules: [...] });
24
+ * ```
25
+ */
26
+ export declare class AppModulesInitializedEvent<T extends AnyModule[] | unknown = unknown> extends FrameworkEvent<AppModulesInitializedEventInit<T>> {
27
+ /**
28
+ * Create an event describing initialized application modules.
29
+ *
30
+ * @param init - Event initialization data containing the application key and module instance.
31
+ */
32
+ constructor(init: AppModulesInitializedEventInit<T>);
33
+ }
34
+ export {};
@@ -1,3 +1,9 @@
1
+ /**
2
+ * @fileoverview Application module configuration factory
3
+ *
4
+ * Provides the core factory function for configuring and initializing
5
+ * application-specific modules in the Fusion framework.
6
+ */
1
7
  import type { Fusion } from '@equinor/fusion-framework';
2
8
  import type { AnyModule } from '@equinor/fusion-framework-module';
3
9
  import type { AppModulesInstance, AppModuleInitiator, AppEnv } from './types';
@@ -0,0 +1,39 @@
1
+ import type { IStateModuleConfigurator } from '@equinor/fusion-framework-module-state';
2
+ import type { IAppConfigurator } from './AppConfigurator';
3
+ import type { AnyModule } from '@equinor/fusion-framework-module';
4
+ import type { FusionModulesInstance } from '@equinor/fusion-framework';
5
+ /**
6
+ * Enables state management for the application with persistent storage.
7
+ *
8
+ * This is a thin, app-scoped convenience wrapper around `enableStateModule` — it registers
9
+ * the state module on the app's configurator so app code can reach it via the app namespace,
10
+ * and scopes the module's default storage to this app's own `manifest.appKey` (so unrelated
11
+ * apps or widgets hosted alongside it never share its state). The state module resolves a
12
+ * local PouchDB database, optionally synced with the Fusion App State backend when service
13
+ * discovery and auth are configured; call `setStorage` on the configurator to override it.
14
+ *
15
+ * @warning Local storage is NOT encrypted. Do not store sensitive data such as passwords,
16
+ * tokens, personal information, or any data that requires security protection.
17
+ *
18
+ * @see {@link https://github.com/equinor/fusion-framework/blob/main/packages/modules/state/README.md | State Module Documentation} for comprehensive usage examples and API reference.
19
+ *
20
+ * @template M - Array of modules to be configured.
21
+ * @template R - The fusion modules instance type.
22
+ * @param configurator - The application configurator to enable state management on.
23
+ * @param configure - Optional config callback, receiving the module's `IStateModuleConfigurator`.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * import { enableState } from '@equinor/fusion-framework-app';
28
+ *
29
+ * export const configure = (configurator) => {
30
+ * enableState(configurator);
31
+ * };
32
+ *
33
+ * // Later in your app, access the state provider
34
+ * const stateProvider = modules.state;
35
+ * await stateProvider.storeItem({ key: 'user-preference', value: { theme: 'dark' } });
36
+ * const item = await stateProvider.getItem('user-preference');
37
+ * ```
38
+ */
39
+ export declare function enableState<M extends AnyModule[], R extends FusionModulesInstance>(configurator: IAppConfigurator<M, R>, configure?: (builder: IStateModuleConfigurator) => void | Promise<void>): void;
@@ -15,9 +15,12 @@
15
15
  * Bookmark support is available via the `@equinor/fusion-framework-app/enable-bookmark`
16
16
  * sub-path export.
17
17
  */
18
- export { AppConfigurator, IAppConfigurator } from './AppConfigurator';
18
+ export { AppConfigurator, IAppConfigurator, AppConfiguratorConstructor } from './AppConfigurator';
19
19
  export * from './types';
20
20
  export { configureModules, default } from './configure-modules';
21
+ export { AppConfiguratorError } from './AppConfiguratorError';
22
+ export { AppModulesConfiguredEvent } from './AppModulesConfiguredEvent';
23
+ export { AppModulesInitializedEvent } from './AppModulesInitializedEvent';
21
24
  /**
22
25
  * @deprecated Use {@link configureModules} instead. This alias will be removed in a future major version.
23
26
  */
@@ -0,0 +1,22 @@
1
+ export { default as deepClone } from 'lodash.clonedeep';
2
+ /**
3
+ * Utility type that makes all properties of an object deeply readonly.
4
+ *
5
+ * @typeParam T - The type to make deeply readonly.
6
+ */
7
+ export type DeepImmutable<T> = {
8
+ readonly [P in keyof T]: T[P] extends object ? DeepImmutable<T[P]> : T[P];
9
+ };
10
+ /**
11
+ * Recursively applies Object.freeze to an object and all nested properties, making them immutable.
12
+ *
13
+ * @remarks
14
+ * - Plain objects and arrays are deeply frozen.
15
+ * - Does not handle circular references. Use with caution on complex object graphs.
16
+ * - Symbol properties are not frozen.
17
+ *
18
+ * @template T - The type of the object to freeze.
19
+ * @param obj - The object to deeply freeze.
20
+ * @returns The deeply frozen (read-only) object.
21
+ */
22
+ export declare function deepFreeze<T>(source: T): DeepImmutable<T>;
@@ -1 +1 @@
1
- export declare const version = "11.0.12";
1
+ export declare const version = "12.0.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-app",
3
- "version": "11.0.12",
3
+ "version": "12.0.0",
4
4
  "description": "",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -9,6 +9,10 @@
9
9
  "types": "./dist/types/index.d.ts",
10
10
  "import": "./dist/esm/index.js"
11
11
  },
12
+ "./enable-state": {
13
+ "types": "./dist/types/enable-state.d.ts",
14
+ "import": "./dist/esm/enable-state.js"
15
+ },
12
16
  "./enable-bookmark": {
13
17
  "types": "./dist/types/enable-bookmark.d.ts",
14
18
  "import": "./dist/esm/enable-bookmark.js"
@@ -19,6 +23,9 @@
19
23
  ".": [
20
24
  "dist/types/index.d.ts"
21
25
  ],
26
+ "enable-state": [
27
+ "dist/types/enable-state.d.ts"
28
+ ],
22
29
  "enable-bookmark": [
23
30
  "dist/types/enable-bookmark.d.ts"
24
31
  ]
@@ -45,25 +52,32 @@
45
52
  "directory": "packages/app"
46
53
  },
47
54
  "dependencies": {
55
+ "lodash.clonedeep": "^4.5.0",
48
56
  "rxjs": "^7.8.1",
49
- "@equinor/fusion-framework": "8.0.12",
50
- "@equinor/fusion-framework-module": "6.1.1",
57
+ "@equinor/fusion-framework": "8.0.13",
51
58
  "@equinor/fusion-framework-module-app": "8.0.4",
52
59
  "@equinor/fusion-framework-module-event": "6.0.1",
53
- "@equinor/fusion-framework-module-msal": "10.0.2",
54
60
  "@equinor/fusion-framework-module-http": "8.0.5",
55
- "@equinor/fusion-framework-module-telemetry": "7.0.1"
61
+ "@equinor/fusion-framework-module": "6.1.2",
62
+ "@equinor/fusion-framework-module-msal": "10.0.2",
63
+ "@equinor/fusion-framework-module-telemetry": "7.0.2"
56
64
  },
57
65
  "devDependencies": {
66
+ "@types/lodash.clonedeep": "^4.5.9",
58
67
  "typescript": "^7.0.2",
59
- "@equinor/fusion-framework-module-bookmark": "^4.0.4"
68
+ "@equinor/fusion-framework-module-bookmark": "^4.0.4",
69
+ "@equinor/fusion-framework-module-state": "^1.0.0"
60
70
  },
61
71
  "peerDependencies": {
62
- "@equinor/fusion-framework-module-bookmark": "^4.0.4"
72
+ "@equinor/fusion-framework-module-bookmark": "^4.0.4",
73
+ "@equinor/fusion-framework-module-state": "^1.0.0"
63
74
  },
64
75
  "peerDependenciesMeta": {
65
76
  "@equinor/fusion-framework-module-bookmark": {
66
77
  "optional": true
78
+ },
79
+ "@equinor/fusion-framework-module-state": {
80
+ "optional": true
67
81
  }
68
82
  },
69
83
  "scripts": {
@@ -17,6 +17,20 @@ import http, {
17
17
  import auth from '@equinor/fusion-framework-module-msal';
18
18
 
19
19
  import type { AppEnv, AppModules } from './types';
20
+ import { AppModulesConfiguredEvent } from './AppModulesConfiguredEvent';
21
+ import { AppConfiguratorError } from './AppConfiguratorError';
22
+ import { deepClone, deepFreeze, type DeepImmutable } from './utils';
23
+
24
+ /**
25
+ * Type definition for AppConfigurator constructor
26
+ */
27
+ export type AppConfiguratorConstructor<
28
+ TModules extends readonly AnyModule[] = [],
29
+ TRef extends FusionModulesInstance = FusionModulesInstance,
30
+ TEnv extends AppEnv = AppEnv,
31
+ > = {
32
+ new (env: TEnv, ref?: TRef): IAppConfigurator<TModules, TRef>;
33
+ };
20
34
 
21
35
  /**
22
36
  * Contract for configuring Fusion application modules.
@@ -44,6 +58,8 @@ export interface IAppConfigurator<
44
58
  TModules extends Array<AnyModule> | unknown = unknown,
45
59
  TRef extends FusionModulesInstance = FusionModulesInstance,
46
60
  > extends IModulesConfigurator<AppModules<TModules>, TRef> {
61
+ readonly manifest: DeepImmutable<AppEnv['manifest']>;
62
+
47
63
  /**
48
64
  * Configure the HTTP module with custom settings.
49
65
  *
@@ -100,7 +116,7 @@ export interface IAppConfigurator<
100
116
  *
101
117
  * `AppConfigurator` is created internally by {@link configureModules}. It registers
102
118
  * the `event`, `http`, and `msal` (auth) modules by default and reads any HTTP
103
- * endpoints declared in the applications environment config.
119
+ * endpoints declared in the application's environment config.
104
120
  *
105
121
  * @template TModules - Additional application-specific modules beyond the defaults.
106
122
  * @template TRef - The resolved Fusion modules instance used as an initialization reference.
@@ -130,6 +146,8 @@ export class AppConfigurator<
130
146
  */
131
147
  static readonly className: string = 'AppConfigurator';
132
148
 
149
+ #manifest: DeepImmutable<AppEnv['manifest']>;
150
+
133
151
  /**
134
152
  * Create an application configurator with default modules and environment.
135
153
  *
@@ -137,11 +155,36 @@ export class AppConfigurator<
137
155
  * HTTP clients declared in `env.config.endpoints`.
138
156
  *
139
157
  * @param env - The application environment containing manifest, config, and optional basename.
158
+ * @param ref - Optional reference to the Fusion modules instance, used for event dispatching.
140
159
  */
141
- constructor(public readonly env: TEnv) {
160
+ constructor(
161
+ public readonly env: TEnv,
162
+ ref?: TRef,
163
+ ) {
142
164
  super([event, http, auth]);
143
-
165
+ this.#manifest = deepFreeze(deepClone(env.manifest));
144
166
  this._configureHttpClientsFromAppConfig();
167
+
168
+ this.onConfigured((configs) => {
169
+ const configuredEvent = new AppModulesConfiguredEvent<TModules>({
170
+ detail: {
171
+ appKey: this.#manifest.appKey,
172
+ configs,
173
+ },
174
+ });
175
+ ref?.event.dispatchEvent(configuredEvent);
176
+ });
177
+ }
178
+
179
+ /**
180
+ * The immutable application manifest.
181
+ *
182
+ * Deeply frozen at construction time to prevent accidental mutations.
183
+ *
184
+ * @returns The deeply immutable application manifest.
185
+ */
186
+ get manifest(): DeepImmutable<AppEnv['manifest']> {
187
+ return this.#manifest;
145
188
  }
146
189
 
147
190
  /**
@@ -207,7 +250,10 @@ export class AppConfigurator<
207
250
  const service = await ref?.serviceDiscovery.resolveService(serviceName);
208
251
  // Guard: service must resolve before the HTTP client can be configured.
209
252
  if (!service) {
210
- throw Error(`failed to configure service [${serviceName}]`);
253
+ throw new AppConfiguratorError(
254
+ `Unable to resolve service [${serviceName}] during configuration.`,
255
+ 'configuration',
256
+ );
211
257
  }
212
258
 
213
259
  // Check if serviceName is already configured (potentially with app-config)
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Custom error class for application configurator errors.
3
+ *
4
+ * Provides error context to help developers debug configuration and initialization issues.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * try {
9
+ * const modules = await initialize({ fusion, env });
10
+ * } catch (error) {
11
+ * if (error instanceof AppConfiguratorError) {
12
+ * console.log(`Error in ${error.phase}: ${error.message}`);
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export class AppConfiguratorError extends Error {
18
+ /**
19
+ * @param message - Human-readable error description
20
+ * @param phase - The phase where the error occurred
21
+ * @param cause - The underlying error that caused this failure
22
+ */
23
+ constructor(
24
+ message: string,
25
+ public readonly phase: 'configuration' | 'initialization',
26
+ cause?: unknown,
27
+ ) {
28
+ super(message);
29
+ this.name = 'AppConfiguratorError';
30
+ this.cause = cause;
31
+ }
32
+ }
33
+
34
+ export default AppConfiguratorError;
@@ -0,0 +1,43 @@
1
+ import type { ModulesConfigType, AnyModule } from '@equinor/fusion-framework-module';
2
+ import type { AppModules } from '@equinor/fusion-framework-module-app';
3
+ import { FrameworkEvent, type FrameworkEventInit } from '@equinor/fusion-framework-module-event';
4
+ import type { AppModulesInitializedEvent } from './AppModulesInitializedEvent';
5
+
6
+ /**
7
+ * Represents the initialization data for an event indicating that application modules have been configured.
8
+ *
9
+ * @template T - Array of additional modules configured in the application.
10
+ * @extends FrameworkEventInit
11
+ * @property {string} appKey - The unique key identifying the application.
12
+ * @property {ModulesConfigType<AppModules<T>>} configs - The configuration objects for the specified application modules.
13
+ */
14
+ type AppModulesConfiguredEventInit<T extends AnyModule[] | unknown = unknown> = FrameworkEventInit<{
15
+ appKey: string;
16
+ configs: ModulesConfigType<AppModules<T>>;
17
+ }>;
18
+
19
+ /**
20
+ * Event emitted when application modules have been configured.
21
+ *
22
+ * @template T - An array of additional modules configured in the application.
23
+ * @extends FrameworkEvent<AppModulesConfiguredEventInit<T>>
24
+ */
25
+ export class AppModulesConfiguredEvent<
26
+ T extends AnyModule[] | unknown = unknown,
27
+ > extends FrameworkEvent<AppModulesConfiguredEventInit<T>> {
28
+ /**
29
+ * Create an event describing configured application modules.
30
+ *
31
+ * @param init - Event initialization data containing the application key and module configs.
32
+ */
33
+ constructor(init: AppModulesConfiguredEventInit<T>) {
34
+ super('onAppModulesConfigured', init);
35
+ }
36
+ }
37
+
38
+ declare module '@equinor/fusion-framework-module-event' {
39
+ interface FrameworkEventMap {
40
+ onAppModulesConfigured: AppModulesConfiguredEvent;
41
+ onAppModulesInitialized: AppModulesInitializedEvent;
42
+ }
43
+ }
@@ -0,0 +1,40 @@
1
+ import type { AnyModule } from '@equinor/fusion-framework-module';
2
+ import type { AppModulesInstance } from '@equinor/fusion-framework-module-app';
3
+ import { FrameworkEvent, type FrameworkEventInit } from '@equinor/fusion-framework-module-event';
4
+
5
+ /**
6
+ * Event initialization type for the "AppModulesInitialized" event.
7
+ *
8
+ * @template T - An array of module types extending `AnyModule`. Defaults to an empty array.
9
+ * @property appKey - The unique key identifying the application.
10
+ * @property modules - The instance containing all initialized application modules.
11
+ */
12
+ type AppModulesInitializedEventInit<T extends AnyModule[] | unknown = unknown> =
13
+ FrameworkEventInit<{
14
+ appKey: string;
15
+ modules: AppModulesInstance<T>;
16
+ }>;
17
+
18
+ /**
19
+ * Event triggered when application modules have been initialized.
20
+ *
21
+ * @template T - An array of modules extending `AnyModule`. Defaults to an empty array.
22
+ * @extends FrameworkEvent<AppModulesInitializedEventInit<T>>
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const event = new AppModulesInitializedEvent({ modules: [...] });
27
+ * ```
28
+ */
29
+ export class AppModulesInitializedEvent<
30
+ T extends AnyModule[] | unknown = unknown,
31
+ > extends FrameworkEvent<AppModulesInitializedEventInit<T>> {
32
+ /**
33
+ * Create an event describing initialized application modules.
34
+ *
35
+ * @param init - Event initialization data containing the application key and module instance.
36
+ */
37
+ constructor(init: AppModulesInitializedEventInit<T>) {
38
+ super('onAppModulesInitialized', init);
39
+ }
40
+ }
@@ -1,3 +1,10 @@
1
+ /**
2
+ * @fileoverview Application module configuration factory
3
+ *
4
+ * Provides the core factory function for configuring and initializing
5
+ * application-specific modules in the Fusion framework.
6
+ */
7
+
1
8
  import type { Fusion } from '@equinor/fusion-framework';
2
9
  import type { AnyModule } from '@equinor/fusion-framework-module';
3
10
  import {
@@ -6,6 +13,7 @@ import {
6
13
  } from '@equinor/fusion-framework-module-telemetry';
7
14
 
8
15
  import { AppConfigurator } from './AppConfigurator';
16
+
9
17
  import type { AppModulesInstance, AppModuleInitiator, AppEnv } from './types';
10
18
 
11
19
  /**
@@ -0,0 +1,49 @@
1
+ import { enableStateModule } from '@equinor/fusion-framework-module-state';
2
+ import type { IStateModuleConfigurator } from '@equinor/fusion-framework-module-state';
3
+ import type { IAppConfigurator } from './AppConfigurator';
4
+ import type { AnyModule } from '@equinor/fusion-framework-module';
5
+ import type { FusionModulesInstance } from '@equinor/fusion-framework';
6
+
7
+ /**
8
+ * Enables state management for the application with persistent storage.
9
+ *
10
+ * This is a thin, app-scoped convenience wrapper around `enableStateModule` — it registers
11
+ * the state module on the app's configurator so app code can reach it via the app namespace,
12
+ * and scopes the module's default storage to this app's own `manifest.appKey` (so unrelated
13
+ * apps or widgets hosted alongside it never share its state). The state module resolves a
14
+ * local PouchDB database, optionally synced with the Fusion App State backend when service
15
+ * discovery and auth are configured; call `setStorage` on the configurator to override it.
16
+ *
17
+ * @warning Local storage is NOT encrypted. Do not store sensitive data such as passwords,
18
+ * tokens, personal information, or any data that requires security protection.
19
+ *
20
+ * @see {@link https://github.com/equinor/fusion-framework/blob/main/packages/modules/state/README.md | State Module Documentation} for comprehensive usage examples and API reference.
21
+ *
22
+ * @template M - Array of modules to be configured.
23
+ * @template R - The fusion modules instance type.
24
+ * @param configurator - The application configurator to enable state management on.
25
+ * @param configure - Optional config callback, receiving the module's `IStateModuleConfigurator`.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * import { enableState } from '@equinor/fusion-framework-app';
30
+ *
31
+ * export const configure = (configurator) => {
32
+ * enableState(configurator);
33
+ * };
34
+ *
35
+ * // Later in your app, access the state provider
36
+ * const stateProvider = modules.state;
37
+ * await stateProvider.storeItem({ key: 'user-preference', value: { theme: 'dark' } });
38
+ * const item = await stateProvider.getItem('user-preference');
39
+ * ```
40
+ */
41
+ export function enableState<M extends AnyModule[], R extends FusionModulesInstance>(
42
+ configurator: IAppConfigurator<M, R>,
43
+ configure?: (builder: IStateModuleConfigurator) => void | Promise<void>,
44
+ ): void {
45
+ enableStateModule(configurator, async (builder) => {
46
+ builder.setName(configurator.manifest.appKey);
47
+ await configure?.(builder);
48
+ });
49
+ }
package/src/index.ts CHANGED
@@ -16,12 +16,18 @@
16
16
  * sub-path export.
17
17
  */
18
18
 
19
- export { AppConfigurator, IAppConfigurator } from './AppConfigurator';
19
+ export { AppConfigurator, IAppConfigurator, AppConfiguratorConstructor } from './AppConfigurator';
20
20
 
21
21
  export * from './types';
22
22
 
23
23
  export { configureModules, default } from './configure-modules';
24
24
 
25
+ export { AppConfiguratorError } from './AppConfiguratorError';
26
+
27
+ export { AppModulesConfiguredEvent } from './AppModulesConfiguredEvent';
28
+
29
+ export { AppModulesInitializedEvent } from './AppModulesInitializedEvent';
30
+
25
31
  /**
26
32
  * @deprecated Use {@link configureModules} instead. This alias will be removed in a future major version.
27
33
  */