@equinor/fusion-framework-module-app 8.1.0 → 8.1.1
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.
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +12 -9
- package/CHANGELOG.md +0 -1469
- package/src/AppClient.ts +0 -409
- package/src/AppConfig.ts +0 -99
- package/src/AppConfigSelector.ts +0 -25
- package/src/AppConfigurator.ts +0 -145
- package/src/AppModuleProvider.ts +0 -283
- package/src/__tests__/AppModuleProvider.test.ts +0 -47
- package/src/__tests__/MockAppClient.test.ts +0 -97
- package/src/app/App.ts +0 -984
- package/src/app/actions.ts +0 -112
- package/src/app/create-reducer.ts +0 -62
- package/src/app/create-state.ts +0 -52
- package/src/app/events.ts +0 -108
- package/src/app/filter-empty.ts +0 -11
- package/src/app/flows/handle-fetch-config.ts +0 -48
- package/src/app/flows/handle-fetch-manifest.ts +0 -53
- package/src/app/flows/handle-fetch-settings.ts +0 -50
- package/src/app/flows/handle-import-application.ts +0 -37
- package/src/app/flows/handle-update-settings.ts +0 -39
- package/src/app/flows/index.ts +0 -5
- package/src/app/index.ts +0 -10
- package/src/app/types.ts +0 -51
- package/src/enable-app-module.ts +0 -40
- package/src/errors/AppBuildError.ts +0 -47
- package/src/errors/AppConfigError.ts +0 -47
- package/src/errors/AppManifestError.ts +0 -47
- package/src/errors/AppScriptModuleError.ts +0 -20
- package/src/errors/AppSettingsError.ts +0 -47
- package/src/errors/app-error-type.ts +0 -9
- package/src/errors.ts +0 -6
- package/src/events.ts +0 -18
- package/src/index.ts +0 -40
- package/src/mock/MockAppClient.ts +0 -77
- package/src/mock/index.ts +0 -13
- package/src/module.ts +0 -59
- package/src/schemas.ts +0 -181
- package/src/types.ts +0 -263
- package/src/version.ts +0 -2
- package/tsconfig.json +0 -30
- package/vitest.config.ts +0 -11
package/src/app/actions.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ActionInstanceMap,
|
|
3
|
-
type ActionTypes,
|
|
4
|
-
createAction,
|
|
5
|
-
createAsyncAction,
|
|
6
|
-
} from '@equinor/fusion-observable';
|
|
7
|
-
import type {
|
|
8
|
-
AppConfig,
|
|
9
|
-
AppManifest,
|
|
10
|
-
AppModulesInstance,
|
|
11
|
-
AppScriptModule,
|
|
12
|
-
AppSettings,
|
|
13
|
-
} from '../types';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Factory function that creates all action creators used by the {@link App}
|
|
17
|
-
* state machine.
|
|
18
|
-
*
|
|
19
|
-
* Actions are grouped by domain:
|
|
20
|
-
* - **Manifest** – `setManifest`, `fetchManifest` (async)
|
|
21
|
-
* - **Config** – `setConfig`, `fetchConfig` (async)
|
|
22
|
-
* - **Settings** – `setSettings`, `fetchSettings` (async), `updateSettings` (async)
|
|
23
|
-
* - **Script module** – `setModule`, `importApp` (async)
|
|
24
|
-
* - **Instance** – `setInstance`
|
|
25
|
-
* - **Lifecycle** – `initialize` (async)
|
|
26
|
-
*/
|
|
27
|
-
const createActions = () => ({
|
|
28
|
-
/** Manifest loading */
|
|
29
|
-
setManifest: createAction('set_manifest', (manifest: AppManifest, update?: boolean) => ({
|
|
30
|
-
payload: manifest,
|
|
31
|
-
meta: {
|
|
32
|
-
// TODO(#5129) when updating
|
|
33
|
-
created: Date.now(),
|
|
34
|
-
update,
|
|
35
|
-
},
|
|
36
|
-
})),
|
|
37
|
-
|
|
38
|
-
fetchManifest: createAsyncAction(
|
|
39
|
-
'fetch_manifest',
|
|
40
|
-
(key: string, tag?: string, update?: boolean) => ({ payload: { key, tag }, meta: { update } }),
|
|
41
|
-
(manifest: AppManifest) => ({ payload: manifest }),
|
|
42
|
-
(error: unknown) => ({ payload: error }),
|
|
43
|
-
),
|
|
44
|
-
/** Config loading */
|
|
45
|
-
setConfig: createAction('set_config', (config: AppConfig) => ({ payload: config })),
|
|
46
|
-
fetchConfig: createAsyncAction(
|
|
47
|
-
'fetch_config',
|
|
48
|
-
(manifest: AppManifest) => ({ payload: manifest }),
|
|
49
|
-
(config: AppConfig) => ({ payload: config }),
|
|
50
|
-
(error: unknown) => ({ payload: error }),
|
|
51
|
-
),
|
|
52
|
-
/** Settings loading */
|
|
53
|
-
setSettings: createAction('set_settings', (settings?: AppSettings) => ({
|
|
54
|
-
payload: settings,
|
|
55
|
-
})),
|
|
56
|
-
/** Fetching settings */
|
|
57
|
-
fetchSettings: createAsyncAction(
|
|
58
|
-
'fetch_settings',
|
|
59
|
-
(appKey: string) => ({ payload: { appKey } }),
|
|
60
|
-
(settings: AppSettings) => ({ payload: settings }),
|
|
61
|
-
(error: unknown) => ({ payload: error }),
|
|
62
|
-
),
|
|
63
|
-
/** Updating settings */
|
|
64
|
-
updateSettings: createAsyncAction(
|
|
65
|
-
'update_settings',
|
|
66
|
-
(appKey: string, settings: AppSettings) => ({
|
|
67
|
-
payload: { appKey, settings },
|
|
68
|
-
}),
|
|
69
|
-
(settings: AppSettings) => ({
|
|
70
|
-
payload: settings,
|
|
71
|
-
}),
|
|
72
|
-
(error: unknown) => ({
|
|
73
|
-
payload: error,
|
|
74
|
-
}),
|
|
75
|
-
),
|
|
76
|
-
updateSettingsAbort: createAction('update_settings::abort', (id: string) => ({
|
|
77
|
-
payload: id,
|
|
78
|
-
})),
|
|
79
|
-
/** App loading */
|
|
80
|
-
// biome-ignore lint/suspicious/noExplicitAny: module payload widens to accept any script module shape when set
|
|
81
|
-
setModule: createAction('set_module', (module: any) => ({ payload: module })),
|
|
82
|
-
importApp: createAsyncAction(
|
|
83
|
-
'import_app',
|
|
84
|
-
(entrypoint: string) => ({ payload: entrypoint }),
|
|
85
|
-
(module: AppScriptModule) => ({ payload: module }),
|
|
86
|
-
(error: unknown) => ({ payload: error }),
|
|
87
|
-
),
|
|
88
|
-
|
|
89
|
-
// App Instance
|
|
90
|
-
setInstance: createAction('set_instance', (instance: AppModulesInstance) => ({
|
|
91
|
-
payload: instance,
|
|
92
|
-
})),
|
|
93
|
-
|
|
94
|
-
initialize: createAsyncAction(
|
|
95
|
-
'initialize_app',
|
|
96
|
-
() => ({ payload: null }),
|
|
97
|
-
() => ({ payload: null }),
|
|
98
|
-
(error: unknown) => ({ payload: error }),
|
|
99
|
-
),
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
/** Singleton action creator map used by the app state machine. */
|
|
103
|
-
export const actions = createActions();
|
|
104
|
-
|
|
105
|
-
/** Record mapping action names to their creator functions. */
|
|
106
|
-
export type ActionBuilder = ReturnType<typeof createActions>;
|
|
107
|
-
|
|
108
|
-
/** Map of action names to their instantiated action shapes. */
|
|
109
|
-
export type ActionMap = ActionInstanceMap<ActionBuilder>;
|
|
110
|
-
|
|
111
|
-
/** Union of all action types dispatched by the app state machine. */
|
|
112
|
-
export type Actions = ActionTypes<typeof actions>;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getBaseType,
|
|
3
|
-
createReducer as makeReducer,
|
|
4
|
-
isCompleteAction,
|
|
5
|
-
isRequestAction,
|
|
6
|
-
} from '@equinor/fusion-observable';
|
|
7
|
-
|
|
8
|
-
import { enableMapSet } from 'immer';
|
|
9
|
-
|
|
10
|
-
enableMapSet();
|
|
11
|
-
|
|
12
|
-
import { type Actions, actions } from './actions';
|
|
13
|
-
|
|
14
|
-
import type { AppBundleState, AppBundleStateInitial } from './types';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Creates the Immer-powered reducer for the {@link App} state machine.
|
|
18
|
-
*
|
|
19
|
-
* Handles synchronous state updates (set manifest, config, settings, module, instance)
|
|
20
|
-
* and tracks in-progress async operations via a `status` set.
|
|
21
|
-
*
|
|
22
|
-
* @param value - Initial state values (appKey, tag, and any pre-loaded data).
|
|
23
|
-
* @returns A reducer function compatible with {@link FlowSubject}.
|
|
24
|
-
*/
|
|
25
|
-
export const createReducer = (value: AppBundleStateInitial) =>
|
|
26
|
-
makeReducer<AppBundleState, Actions>(
|
|
27
|
-
{ ...value, status: new Set() } as AppBundleState,
|
|
28
|
-
(builder) =>
|
|
29
|
-
builder
|
|
30
|
-
// update or set manifest
|
|
31
|
-
.addCase(actions.setManifest, (state, action) => {
|
|
32
|
-
// TODO(#5131): after legacy is removed, remove the update flag
|
|
33
|
-
if (action.meta.update) {
|
|
34
|
-
// Merge onto the existing manifest so partial updates don't clobber other fields.
|
|
35
|
-
state.manifest = Object.assign(state.manifest ?? {}, action.payload);
|
|
36
|
-
} else {
|
|
37
|
-
state.manifest = action.payload;
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
.addCase(actions.setConfig, (state, action) => {
|
|
41
|
-
state.config = action.payload;
|
|
42
|
-
})
|
|
43
|
-
.addCase(actions.setSettings, (state, action) => {
|
|
44
|
-
state.settings = action.payload;
|
|
45
|
-
})
|
|
46
|
-
.addCase(actions.setModule, (state, action) => {
|
|
47
|
-
state.modules = action.payload;
|
|
48
|
-
})
|
|
49
|
-
.addCase(actions.setInstance, (state, action) => {
|
|
50
|
-
state.instance = action.payload;
|
|
51
|
-
})
|
|
52
|
-
// add status which indicates that a request is in progress
|
|
53
|
-
.addMatcher(isRequestAction, (state, action) => {
|
|
54
|
-
state.status.add(getBaseType(action.type));
|
|
55
|
-
})
|
|
56
|
-
// remove status when a request is complete
|
|
57
|
-
.addMatcher(isCompleteAction, (state, action) => {
|
|
58
|
-
state.status.delete(getBaseType(action.type));
|
|
59
|
-
}),
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
export default createReducer;
|
package/src/app/create-state.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { FlowSubject } from '@equinor/fusion-observable';
|
|
2
|
-
|
|
3
|
-
import { createReducer } from './create-reducer';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
handleFetchManifest,
|
|
7
|
-
handleFetchConfig,
|
|
8
|
-
handleFetchSettings,
|
|
9
|
-
handleUpdateSettings,
|
|
10
|
-
handleImportApplication,
|
|
11
|
-
} from './flows';
|
|
12
|
-
|
|
13
|
-
import type { Actions } from './actions';
|
|
14
|
-
import type { AppBundleState, AppBundleStateInitial } from './types';
|
|
15
|
-
import type { AppModuleProvider } from '../AppModuleProvider';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Creates and configures the reactive state machine ({@link FlowSubject}) for
|
|
19
|
-
* an {@link App} instance.
|
|
20
|
-
*
|
|
21
|
-
* Registers flows for fetching manifests, configs, settings, and importing
|
|
22
|
-
* the application script module.
|
|
23
|
-
*
|
|
24
|
-
* @param value - Initial state values (appKey, tag, and any pre-loaded data).
|
|
25
|
-
* @param provider - The {@link AppModuleProvider} used by flows to fetch data.
|
|
26
|
-
* @returns A configured `FlowSubject` ready for use by the App class.
|
|
27
|
-
*/
|
|
28
|
-
export const createState = (
|
|
29
|
-
value: AppBundleStateInitial,
|
|
30
|
-
provider: AppModuleProvider,
|
|
31
|
-
): FlowSubject<AppBundleState, Actions> => {
|
|
32
|
-
const reducer = createReducer(value);
|
|
33
|
-
|
|
34
|
-
// create state
|
|
35
|
-
const state = new FlowSubject<AppBundleState, Actions>(reducer);
|
|
36
|
-
|
|
37
|
-
// add handler for fetching manifest
|
|
38
|
-
state.addFlow(handleFetchManifest(provider));
|
|
39
|
-
|
|
40
|
-
// add handler for fetching config
|
|
41
|
-
state.addFlow(handleFetchConfig(provider));
|
|
42
|
-
|
|
43
|
-
// add handler for fetching settings
|
|
44
|
-
state.addFlow(handleFetchSettings(provider));
|
|
45
|
-
|
|
46
|
-
state.addFlow(handleUpdateSettings(provider));
|
|
47
|
-
|
|
48
|
-
// add handler for loading application script
|
|
49
|
-
state.addFlow(handleImportApplication(provider));
|
|
50
|
-
|
|
51
|
-
return state;
|
|
52
|
-
};
|
package/src/app/events.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import type { FrameworkEvent, FrameworkEventInit } from '@equinor/fusion-framework-module-event';
|
|
2
|
-
|
|
3
|
-
import type { App } from './App';
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
AppConfig,
|
|
7
|
-
AppManifest,
|
|
8
|
-
AppModulesInstance,
|
|
9
|
-
AppScriptModule,
|
|
10
|
-
AppSettings,
|
|
11
|
-
} from '../types';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Base event initialization type for application lifecycle events.
|
|
15
|
-
*
|
|
16
|
-
* Extends {@link FrameworkEventInit} with a mandatory `appKey` field and
|
|
17
|
-
* the {@link App} as the event source.
|
|
18
|
-
*
|
|
19
|
-
* @template TDetail - Additional detail properties carried by the event.
|
|
20
|
-
*/
|
|
21
|
-
export type AppEventEventInit<TDetail extends Record<string, unknown> | unknown = unknown> =
|
|
22
|
-
FrameworkEventInit<
|
|
23
|
-
/** additional event details and key of target event */
|
|
24
|
-
TDetail & { appKey: string },
|
|
25
|
-
/** source of the event */
|
|
26
|
-
App
|
|
27
|
-
>;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Framework event carrying application-scoped detail and an {@link App} source.
|
|
31
|
-
*
|
|
32
|
-
* @template TDetail - Additional detail properties carried by the event.
|
|
33
|
-
*/
|
|
34
|
-
export type AppEvent<TDetail extends Record<string, unknown> | unknown = unknown> = FrameworkEvent<
|
|
35
|
-
AppEventEventInit<TDetail>
|
|
36
|
-
>;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Framework event emitted when an application lifecycle operation fails.
|
|
40
|
-
* The `error` detail carries the underlying failure.
|
|
41
|
-
*/
|
|
42
|
-
export type AppEventFailure = FrameworkEvent<
|
|
43
|
-
AppEventEventInit<{
|
|
44
|
-
error: AppConfig;
|
|
45
|
-
}>
|
|
46
|
-
>;
|
|
47
|
-
|
|
48
|
-
declare module '@equinor/fusion-framework-module-event' {
|
|
49
|
-
interface FrameworkEventMap {
|
|
50
|
-
/** fired when the application has initiated its modules */
|
|
51
|
-
onAppModulesLoaded: AppEvent<{
|
|
52
|
-
/** initiated modules for application */
|
|
53
|
-
appKey: string;
|
|
54
|
-
manifest: AppManifest;
|
|
55
|
-
modules: AppModulesInstance;
|
|
56
|
-
}>;
|
|
57
|
-
|
|
58
|
-
onAppManifestLoad: AppEvent;
|
|
59
|
-
/** fired when the application has loaded corresponding manifest */
|
|
60
|
-
onAppManifestLoaded: AppEvent<{
|
|
61
|
-
manifest: AppManifest;
|
|
62
|
-
}>;
|
|
63
|
-
onAppManifestFailure: AppEventFailure;
|
|
64
|
-
|
|
65
|
-
onAppConfigLoad: AppEvent;
|
|
66
|
-
/** fired when the application has loaded corresponding config */
|
|
67
|
-
onAppConfigLoaded: AppEvent<{
|
|
68
|
-
config: AppConfig;
|
|
69
|
-
}>;
|
|
70
|
-
onAppConfigFailure: AppEventFailure;
|
|
71
|
-
|
|
72
|
-
onAppSettingsLoad: AppEvent;
|
|
73
|
-
/** fired when the application has loaded corresponding settings */
|
|
74
|
-
onAppSettingsLoaded: AppEvent<{
|
|
75
|
-
settings: AppSettings;
|
|
76
|
-
}>;
|
|
77
|
-
onAppSettingsFailure: AppEventFailure;
|
|
78
|
-
|
|
79
|
-
onAppSettingsUpdate: AppEvent;
|
|
80
|
-
onAppSettingsUpdated: AppEvent<{
|
|
81
|
-
settings: AppSettings;
|
|
82
|
-
}>;
|
|
83
|
-
onAppSettingsUpdateFailure: AppEventFailure;
|
|
84
|
-
|
|
85
|
-
/** fired when the application has loaded corresponding javascript module */
|
|
86
|
-
onAppScriptLoad: AppEvent;
|
|
87
|
-
onAppScriptLoaded: AppEvent<{
|
|
88
|
-
script: AppScriptModule;
|
|
89
|
-
}>;
|
|
90
|
-
onAppScriptFailure: AppEventFailure;
|
|
91
|
-
|
|
92
|
-
/** fired before application loads manifest, config and script */
|
|
93
|
-
onAppInitialize: AppEvent;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* fired after application has loaded manifest, config and script
|
|
97
|
-
*
|
|
98
|
-
* __note:__ not fired until all loaders has settled (last emit)
|
|
99
|
-
*/
|
|
100
|
-
onAppInitialized: AppEvent;
|
|
101
|
-
|
|
102
|
-
/** fired when application fails to load either manifest, config and script */
|
|
103
|
-
onAppInitializeFailure: AppEventFailure;
|
|
104
|
-
|
|
105
|
-
/** fired when the application is disposed (unmounts) */
|
|
106
|
-
onAppDispose: FrameworkEvent<AppEventEventInit>;
|
|
107
|
-
}
|
|
108
|
-
}
|
package/src/app/filter-empty.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { filter, type OperatorFunction } from 'rxjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* RxJS operator that filters out `null` and `undefined` emissions.
|
|
5
|
-
*
|
|
6
|
-
* @template T - The non-nullable value type.
|
|
7
|
-
* @returns An operator that only passes through non-nullable values.
|
|
8
|
-
*/
|
|
9
|
-
export function filterEmpty<T>(): OperatorFunction<T | null | undefined, T> {
|
|
10
|
-
return filter((value): value is T => value !== undefined && value !== null);
|
|
11
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { from, of, concat } from 'rxjs';
|
|
2
|
-
import { catchError, filter, last, map, share, switchMap } from 'rxjs/operators';
|
|
3
|
-
|
|
4
|
-
import { actions } from '../actions';
|
|
5
|
-
|
|
6
|
-
import type { Flow } from '@equinor/fusion-observable';
|
|
7
|
-
import type { AppModuleProvider } from '../../AppModuleProvider';
|
|
8
|
-
import type { Actions } from '../actions';
|
|
9
|
-
import type { AppBundleState } from '../types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Handles the fetch config action by fetching the app configuration from the provider,
|
|
13
|
-
* filtering out null values, and dispatching success or failure actions accordingly.
|
|
14
|
-
*
|
|
15
|
-
* @param provider The AppModuleProvider used to fetch the app configuration.
|
|
16
|
-
* @returns A Flow function that takes an Observable of actions and returns an Observable of actions.
|
|
17
|
-
*/
|
|
18
|
-
export const handleFetchConfig =
|
|
19
|
-
(provider: AppModuleProvider): Flow<Actions, AppBundleState> =>
|
|
20
|
-
(action$) =>
|
|
21
|
-
// only handle fetch config request actions
|
|
22
|
-
action$.pipe(
|
|
23
|
-
filter(actions.fetchConfig.match),
|
|
24
|
-
// when request is received, abort any ongoing request and start new
|
|
25
|
-
switchMap(({ payload }) => {
|
|
26
|
-
// TODO(#5127) - use the configUrl directly from the manifest
|
|
27
|
-
// fetch config from provider
|
|
28
|
-
const subject = from(provider.getAppConfig(payload.appKey, payload.build?.version)).pipe(
|
|
29
|
-
// filter out null values
|
|
30
|
-
filter((x) => !!x),
|
|
31
|
-
// allow multiple subscriptions
|
|
32
|
-
share(),
|
|
33
|
-
);
|
|
34
|
-
// first load config and then dispatch success action
|
|
35
|
-
return concat(
|
|
36
|
-
subject.pipe(map((config) => actions.setConfig(config))),
|
|
37
|
-
subject.pipe(
|
|
38
|
-
last(),
|
|
39
|
-
map((config) => actions.fetchConfig.success(config)),
|
|
40
|
-
),
|
|
41
|
-
).pipe(
|
|
42
|
-
// catch any error and dispatch failure action
|
|
43
|
-
catchError((err) => {
|
|
44
|
-
return of(actions.fetchConfig.failure(err));
|
|
45
|
-
}),
|
|
46
|
-
);
|
|
47
|
-
}),
|
|
48
|
-
);
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { from, of, concat } from 'rxjs';
|
|
2
|
-
import { catchError, filter, last, map, share, switchMap } from 'rxjs/operators';
|
|
3
|
-
|
|
4
|
-
import { actions } from '../actions';
|
|
5
|
-
|
|
6
|
-
import type { Flow } from '@equinor/fusion-observable';
|
|
7
|
-
import type { AppModuleProvider } from '../../AppModuleProvider';
|
|
8
|
-
import type { Actions } from '../actions';
|
|
9
|
-
import type { AppBundleState } from '../types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Handles the fetch manifest action by fetching the app manifest from the provider,
|
|
13
|
-
* dispatching success or failure actions based on the result.
|
|
14
|
-
*
|
|
15
|
-
* @param provider The AppModuleProvider used to fetch the app manifest.
|
|
16
|
-
* @returns A Flow function that takes an Observable of actions and returns an Observable of actions.
|
|
17
|
-
*/
|
|
18
|
-
export const handleFetchManifest =
|
|
19
|
-
(provider: AppModuleProvider): Flow<Actions, AppBundleState> =>
|
|
20
|
-
(action$) =>
|
|
21
|
-
// only handle fetch manifest request actions
|
|
22
|
-
action$.pipe(
|
|
23
|
-
filter(actions.fetchManifest.match),
|
|
24
|
-
// when request is received, abort any ongoing request and start new
|
|
25
|
-
switchMap((action) => {
|
|
26
|
-
const {
|
|
27
|
-
payload: { key, tag },
|
|
28
|
-
meta: { update },
|
|
29
|
-
} = action;
|
|
30
|
-
|
|
31
|
-
// fetch manifest from provider
|
|
32
|
-
const subject = from(provider.getAppManifest(key, tag)).pipe(
|
|
33
|
-
// filter out null values
|
|
34
|
-
filter((x) => !!x),
|
|
35
|
-
// allow multiple subscriptions
|
|
36
|
-
share(),
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
// first load manifest and then dispatch success action
|
|
40
|
-
return concat(
|
|
41
|
-
subject.pipe(map((manifest) => actions.setManifest(manifest, update))),
|
|
42
|
-
subject.pipe(
|
|
43
|
-
last(),
|
|
44
|
-
map((manifest) => actions.fetchManifest.success(manifest)),
|
|
45
|
-
),
|
|
46
|
-
).pipe(
|
|
47
|
-
// catch any error and dispatch failure action
|
|
48
|
-
catchError((err) => {
|
|
49
|
-
return of(actions.fetchManifest.failure(err));
|
|
50
|
-
}),
|
|
51
|
-
);
|
|
52
|
-
}),
|
|
53
|
-
);
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { from, of, concat } from 'rxjs';
|
|
2
|
-
import { catchError, filter, last, map, share, switchMap } from 'rxjs/operators';
|
|
3
|
-
|
|
4
|
-
import { actions } from '../actions';
|
|
5
|
-
|
|
6
|
-
import type { Flow } from '@equinor/fusion-observable';
|
|
7
|
-
import type { AppModuleProvider } from '../../AppModuleProvider';
|
|
8
|
-
import type { Actions } from '../actions';
|
|
9
|
-
import type { AppBundleState } from '../types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Handles the fetch settings action by fetching the app settings from the provider,
|
|
13
|
-
* filtering out null values, and dispatching success or failure actions accordingly.
|
|
14
|
-
*
|
|
15
|
-
* @param provider The AppModuleProvider used to fetch the app settings.
|
|
16
|
-
* @returns A Flow function that takes an Observable of actions and returns an Observable of actions.
|
|
17
|
-
*/
|
|
18
|
-
export const handleFetchSettings =
|
|
19
|
-
(provider: AppModuleProvider): Flow<Actions, AppBundleState> =>
|
|
20
|
-
(action$) =>
|
|
21
|
-
// only handle fetch settings request actions
|
|
22
|
-
action$.pipe(
|
|
23
|
-
filter(actions.fetchSettings.match),
|
|
24
|
-
// when request is received, abort any ongoing request and start new
|
|
25
|
-
switchMap(({ payload }) => {
|
|
26
|
-
const { appKey } = payload;
|
|
27
|
-
|
|
28
|
-
// fetch settings from provider
|
|
29
|
-
const subject = from(provider.getAppSettings(appKey)).pipe(
|
|
30
|
-
// filter out null values
|
|
31
|
-
filter((x) => !!x),
|
|
32
|
-
// allow multiple subscriptions
|
|
33
|
-
share(),
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
// first load settings and then dispatch success action
|
|
37
|
-
return concat(
|
|
38
|
-
subject.pipe(map((settings) => actions.setSettings(settings))),
|
|
39
|
-
subject.pipe(
|
|
40
|
-
last(),
|
|
41
|
-
map((settings) => actions.fetchSettings.success(settings)),
|
|
42
|
-
),
|
|
43
|
-
).pipe(
|
|
44
|
-
// catch any error and dispatch failure action
|
|
45
|
-
catchError((err) => {
|
|
46
|
-
return of(actions.fetchSettings.failure(err));
|
|
47
|
-
}),
|
|
48
|
-
);
|
|
49
|
-
}),
|
|
50
|
-
);
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { from, of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, map, switchMap } from 'rxjs/operators';
|
|
3
|
-
|
|
4
|
-
import { actions } from '../actions';
|
|
5
|
-
|
|
6
|
-
import type { Flow } from '@equinor/fusion-observable';
|
|
7
|
-
import type { AppModuleProvider } from '../../AppModuleProvider';
|
|
8
|
-
import type { Actions } from '../actions';
|
|
9
|
-
import type { AppBundleState } from '../types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Handles the import application flow.
|
|
13
|
-
* @param provider The AppModuleProvider used to resolve the application asset URI.
|
|
14
|
-
* @returns A flow that takes in actions and returns an observable of AppBundleState.
|
|
15
|
-
*/
|
|
16
|
-
export const handleImportApplication =
|
|
17
|
-
(provider: AppModuleProvider): Flow<Actions, AppBundleState> =>
|
|
18
|
-
(action$) =>
|
|
19
|
-
// only handle import script request actions
|
|
20
|
-
action$.pipe(
|
|
21
|
-
filter(actions.importApp.match),
|
|
22
|
-
// when request is received, abort any ongoing request and start new
|
|
23
|
-
switchMap(({ payload }) => {
|
|
24
|
-
// dynamically import the application script
|
|
25
|
-
return from(
|
|
26
|
-
import(
|
|
27
|
-
/* @vite-ignore */ /* webpackIgnore: true */
|
|
28
|
-
[provider.assetUri, payload].join('/').replace(/\/{2,}/g, '/')
|
|
29
|
-
),
|
|
30
|
-
).pipe(
|
|
31
|
-
// dispatch success action
|
|
32
|
-
map(actions.importApp.success),
|
|
33
|
-
// catch any error and dispatch failure action
|
|
34
|
-
catchError((err) => of(actions.importApp.failure(err))),
|
|
35
|
-
);
|
|
36
|
-
}),
|
|
37
|
-
);
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { from, of } from 'rxjs';
|
|
2
|
-
import { catchError, concatMap, filter, last, switchMap } from 'rxjs/operators';
|
|
3
|
-
|
|
4
|
-
import { actions } from '../actions';
|
|
5
|
-
|
|
6
|
-
import type { Flow } from '@equinor/fusion-observable';
|
|
7
|
-
import type { AppModuleProvider } from '../../AppModuleProvider';
|
|
8
|
-
import type { Actions } from '../actions';
|
|
9
|
-
import type { AppBundleState } from '../types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Handles the set settings action by setting the app settings from the provider,
|
|
13
|
-
* filtering out null values, and dispatching success or failure actions accordingly.
|
|
14
|
-
*
|
|
15
|
-
* @param provider The AppModuleProvider used to fetch the app settings.
|
|
16
|
-
* @returns A Flow function that takes an Observable of actions and returns an Observable of actions.
|
|
17
|
-
*/
|
|
18
|
-
export const handleUpdateSettings =
|
|
19
|
-
(provider: AppModuleProvider): Flow<Actions, AppBundleState> =>
|
|
20
|
-
(action$) => {
|
|
21
|
-
// only handle update settings request actions
|
|
22
|
-
return action$.pipe(
|
|
23
|
-
filter(actions.updateSettings.match),
|
|
24
|
-
switchMap(({ payload }) => {
|
|
25
|
-
const { appKey, settings } = payload;
|
|
26
|
-
// take the last value, then request updating of settings and dispatch success or failure
|
|
27
|
-
return provider.updateAppSettings(appKey, settings).pipe(
|
|
28
|
-
last(),
|
|
29
|
-
concatMap((updatedSettings) =>
|
|
30
|
-
from([
|
|
31
|
-
actions.setSettings(updatedSettings),
|
|
32
|
-
actions.updateSettings.success(updatedSettings),
|
|
33
|
-
]),
|
|
34
|
-
),
|
|
35
|
-
catchError((err) => of(actions.updateSettings.failure(err))),
|
|
36
|
-
);
|
|
37
|
-
}),
|
|
38
|
-
);
|
|
39
|
-
};
|
package/src/app/flows/index.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { handleFetchManifest } from './handle-fetch-manifest';
|
|
2
|
-
export { handleFetchConfig } from './handle-fetch-config';
|
|
3
|
-
export { handleFetchSettings } from './handle-fetch-settings';
|
|
4
|
-
export { handleUpdateSettings } from './handle-update-settings';
|
|
5
|
-
export { handleImportApplication } from './handle-import-application';
|
package/src/app/index.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Re-exports for the app sub-module.
|
|
3
|
-
*
|
|
4
|
-
* - {@link App} – Concrete application class managing reactive state.
|
|
5
|
-
* - {@link IApp} – Public interface for an application instance.
|
|
6
|
-
* - {@link AppInitializeResult} – Shape emitted by `App.initialize()`.
|
|
7
|
-
*/
|
|
8
|
-
export { App, IApp, type AppInitializeResult } from './App';
|
|
9
|
-
|
|
10
|
-
export { default } from './App';
|
package/src/app/types.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { ActionBaseType } from '@equinor/fusion-observable';
|
|
2
|
-
import type {
|
|
3
|
-
AppManifest,
|
|
4
|
-
AppConfig,
|
|
5
|
-
AppModulesInstance,
|
|
6
|
-
AppScriptModule,
|
|
7
|
-
ConfigEnvironment,
|
|
8
|
-
AppSettings,
|
|
9
|
-
} from '../types';
|
|
10
|
-
import type { Actions } from './actions';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Represents the state of an application bundle.
|
|
14
|
-
*
|
|
15
|
-
* @template TConfig - The type of the configuration environment, defaults to `ConfigEnvironment`.
|
|
16
|
-
* @template TModules - The type of the modules, defaults to `any`.
|
|
17
|
-
*
|
|
18
|
-
* @property {string} appKey - A unique key identifying the application.
|
|
19
|
-
* @property {Set<string>} status - A set of strings representing the status of the application.
|
|
20
|
-
* @property {AppManifest} [manifest] - An optional manifest describing the application.
|
|
21
|
-
* @property {AppConfig<TConfig>} [config] - An optional configuration object for the application.
|
|
22
|
-
* @property {AppSettings} [settings] - An optional application settings object.
|
|
23
|
-
* @property {AppScriptModule} [modules] - An optional script module for the application.
|
|
24
|
-
* @property {AppModulesInstance<TModules>} [instance] - An optional instance of the application modules.
|
|
25
|
-
*/
|
|
26
|
-
export type AppBundleState<
|
|
27
|
-
TConfig extends ConfigEnvironment = ConfigEnvironment,
|
|
28
|
-
// biome-ignore lint/suspicious/noExplicitAny: default must be bivariant `any`, not `unknown` — `unknown` breaks assignability when a concrete `AppBundleState<TConfig, TModules>` is used where the default-typed generic is expected
|
|
29
|
-
TModules = any,
|
|
30
|
-
> = {
|
|
31
|
-
appKey: string;
|
|
32
|
-
tag?: string;
|
|
33
|
-
status: Set<ActionBaseType<Actions>>;
|
|
34
|
-
manifest?: AppManifest;
|
|
35
|
-
config?: AppConfig<TConfig>;
|
|
36
|
-
settings?: AppSettings;
|
|
37
|
-
modules?: AppScriptModule;
|
|
38
|
-
instance?: AppModulesInstance<TModules>;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Represents the initial state of an application bundle, excluding the 'status' property.
|
|
43
|
-
*
|
|
44
|
-
* @template TConfig - The configuration environment type, defaults to `ConfigEnvironment`.
|
|
45
|
-
* @template TModules - The type of modules included in the application bundle, defaults to `any`.
|
|
46
|
-
*/
|
|
47
|
-
export type AppBundleStateInitial<
|
|
48
|
-
TConfig extends ConfigEnvironment = ConfigEnvironment,
|
|
49
|
-
// biome-ignore lint/suspicious/noExplicitAny: see AppBundleState above — default must be bivariant `any`
|
|
50
|
-
TModules = any,
|
|
51
|
-
> = Omit<AppBundleState<TConfig, TModules>, 'status'>;
|