@equinor/fusion-framework-module-widget 2.0.10 → 3.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 (66) hide show
  1. package/CHANGELOG.md +82 -70
  2. package/dist/esm/Widget.js +255 -0
  3. package/dist/esm/Widget.js.map +1 -0
  4. package/dist/esm/WidgetModuleConfigurator.js +39 -73
  5. package/dist/esm/WidgetModuleConfigurator.js.map +1 -1
  6. package/dist/esm/WidgetModuleProvider.js +85 -17
  7. package/dist/esm/WidgetModuleProvider.js.map +1 -1
  8. package/dist/esm/enable-widget-module.js +8 -2
  9. package/dist/esm/enable-widget-module.js.map +1 -1
  10. package/dist/esm/errors.js +22 -4
  11. package/dist/esm/errors.js.map +1 -1
  12. package/dist/esm/events.js +2 -0
  13. package/dist/esm/events.js.map +1 -0
  14. package/dist/esm/index.js +1 -1
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/module.js +5 -2
  17. package/dist/esm/module.js.map +1 -1
  18. package/dist/esm/state/actions.js +31 -0
  19. package/dist/esm/state/actions.js.map +1 -0
  20. package/dist/esm/state/create-reducer.js +32 -0
  21. package/dist/esm/state/create-reducer.js.map +1 -0
  22. package/dist/esm/state/create-state.js +12 -0
  23. package/dist/esm/state/create-state.js.map +1 -0
  24. package/dist/esm/state/flows.js +21 -0
  25. package/dist/esm/state/flows.js.map +1 -0
  26. package/dist/esm/utils.js +43 -0
  27. package/dist/esm/utils.js.map +1 -0
  28. package/dist/esm/version.js +2 -1
  29. package/dist/esm/version.js.map +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/dist/types/Widget.d.ts +78 -0
  32. package/dist/types/WidgetModuleConfigurator.d.ts +27 -27
  33. package/dist/types/WidgetModuleProvider.d.ts +44 -5
  34. package/dist/types/enable-widget-module.d.ts +5 -1
  35. package/dist/types/errors.d.ts +7 -2
  36. package/dist/types/events.d.ts +54 -0
  37. package/dist/types/index.d.ts +1 -1
  38. package/dist/types/module.d.ts +3 -3
  39. package/dist/types/state/actions.d.ts +92 -0
  40. package/dist/types/state/create-reducer.d.ts +3 -0
  41. package/dist/types/state/create-state.d.ts +5 -0
  42. package/dist/types/state/flows.d.ts +7 -0
  43. package/dist/types/types.d.ts +81 -5
  44. package/dist/types/utils.d.ts +5 -0
  45. package/dist/types/version.d.ts +1 -1
  46. package/package.json +4 -1
  47. package/src/Widget.ts +324 -0
  48. package/src/WidgetModuleConfigurator.ts +48 -118
  49. package/src/WidgetModuleProvider.ts +110 -22
  50. package/src/enable-widget-module.ts +2 -2
  51. package/src/errors.ts +38 -4
  52. package/src/events.ts +75 -0
  53. package/src/index.ts +1 -5
  54. package/src/module.ts +8 -5
  55. package/src/state/actions.ts +70 -0
  56. package/src/state/create-reducer.ts +44 -0
  57. package/src/state/create-state.ts +21 -0
  58. package/src/state/flows.ts +75 -0
  59. package/src/types.ts +89 -9
  60. package/src/utils.ts +51 -0
  61. package/src/version.ts +1 -1
  62. package/tsconfig.json +1 -3
  63. package/dist/esm/WidgetModuleConfigBuilder.js +0 -42
  64. package/dist/esm/WidgetModuleConfigBuilder.js.map +0 -1
  65. package/dist/types/WidgetModuleConfigBuilder.d.ts +0 -19
  66. package/src/WidgetModuleConfigBuilder.ts +0 -70
@@ -6,68 +6,156 @@ import { EventModule } from '@equinor/fusion-framework-module-event';
6
6
 
7
7
  import { Query } from '@equinor/fusion-query';
8
8
 
9
- import type { GetWidgetParameters, WidgetManifest } from './types';
9
+ import type { GetWidgetParameters, WidgetConfig, WidgetManifest } from './types';
10
10
 
11
11
  import { WidgetModuleConfig } from './WidgetModuleConfigurator';
12
- import { GetWidgetError } from './errors';
12
+ import { WidgetManifestLoadError, WidgetConfigLoadError } from './errors';
13
+ import { Widget } from './Widget';
13
14
 
14
15
  export interface IWidgetModuleProvider {
15
16
  getWidget(
16
17
  widgetKey: GetWidgetParameters['widgetKey'],
17
- args: GetWidgetParameters['args'],
18
+ args?: GetWidgetParameters['args'],
19
+ ): Widget;
20
+ getWidgetManifest(
21
+ widgetKey: GetWidgetParameters['widgetKey'],
22
+ args?: GetWidgetParameters['args'],
18
23
  ): Observable<WidgetManifest>;
24
+ getWidgetConfig(
25
+ widgetKey: GetWidgetParameters['widgetKey'],
26
+ args?: GetWidgetParameters['args'],
27
+ ): Observable<WidgetConfig>;
19
28
  }
20
29
 
30
+ /**
31
+ * The `WidgetModuleProvider` class implements the `IWidgetModuleProvider` interface and serves as a provider for managing widgets.
32
+ */
21
33
  export class WidgetModuleProvider implements IWidgetModuleProvider {
22
- #widgetClient: Query<WidgetManifest, GetWidgetParameters>;
34
+ // Private fields
23
35
  #subscription = new Subscription();
36
+ #config: WidgetModuleConfig;
37
+ #event?: ModuleType<EventModule>;
24
38
 
39
+ /**
40
+ * Constructs a new `WidgetModuleProvider` instance.
41
+ * @param args - An object containing configuration and optional event module for the widget provider.
42
+ */
25
43
  constructor(args: { config: WidgetModuleConfig; event?: ModuleType<EventModule> }) {
26
- const { config } = args;
27
-
28
- this.#widgetClient = new Query(config.client.getWidget);
44
+ const { config, event } = args;
45
+ this.#event = event;
46
+ this.#config = config;
47
+ }
29
48
 
30
- this.#subscription.add(() => this.#widgetClient.complete());
49
+ /**
50
+ * Retrieves a widget instance based on the provided name and optional parameters.
51
+ * @param name - The name of the widget.
52
+ * @param widgetParams - Optional parameters for the widget.
53
+ * @returns A new `Widget` instance.
54
+ */
55
+ public getWidget(name: string, widgetPrams?: GetWidgetParameters['args']): Widget {
56
+ return new Widget(
57
+ { name },
58
+ { provider: this, event: this.#event, widgetPrams, config: this.#config },
59
+ );
31
60
  }
32
61
 
33
- public getWidget(name: string): Observable<WidgetManifest> {
34
- return this._getWidget(name);
62
+ /**
63
+ * Retrieves the manifest of a widget as an observable stream.
64
+ * @param name - The name of the widget.
65
+ * @param widgetParams - Optional parameters for the widget.
66
+ * @returns An observable stream of the widget manifest.
67
+ */
68
+ public getWidgetManifest(
69
+ name: string,
70
+ widgetPrams?: GetWidgetParameters['args'],
71
+ ): Observable<WidgetManifest> {
72
+ return this._getWidget(name, widgetPrams);
35
73
  }
36
74
 
37
- public getWidgetByVersion(name: string, version: string): Observable<WidgetManifest> {
38
- return this._getWidget(name, { type: 'version', value: version });
75
+ /**
76
+ * Retrieves the config of a widget as an observable stream.
77
+ * @param name - The name of the widget.
78
+ * @param widgetParams - Optional parameters for the widget.
79
+ * @returns An observable stream of the widget config.
80
+ */
81
+ public getWidgetConfig(
82
+ name: string,
83
+ widgetPrams?: GetWidgetParameters['args'],
84
+ ): Observable<WidgetConfig> {
85
+ return this._getWidgetConfig(name, widgetPrams);
39
86
  }
40
87
 
41
- public getWidgetByTag(name: string, tag: string): Observable<WidgetManifest> {
42
- return this._getWidget(name, { type: 'tag', value: tag });
88
+ protected _getWidgetConfig(
89
+ widgetKey: GetWidgetParameters['widgetKey'],
90
+ args?: GetWidgetParameters['args'],
91
+ ): Observable<WidgetConfig> {
92
+ const client = new Query(this.#config.client.getWidgetConfig);
93
+ this.#subscription.add(() => client.complete());
94
+ return Query.extractQueryValue(
95
+ client.query({ widgetKey, args }).pipe(
96
+ catchError((err) => {
97
+ // Extract the cause since the error will be a `QueryError`
98
+ const { cause } = err;
99
+
100
+ // Handle specific errors and throw a `GetWidgetManifestError` if applicable
101
+ if (cause instanceof WidgetManifestLoadError) {
102
+ throw cause;
103
+ }
104
+ if (cause instanceof HttpResponseError) {
105
+ throw WidgetManifestLoadError.fromHttpResponse(cause.response, {
106
+ cause,
107
+ });
108
+ }
109
+ // Throw a generic `GetWidgetManifestError` for unknown errors
110
+ throw new WidgetManifestLoadError('unknown', 'failed to load config', {
111
+ cause,
112
+ });
113
+ }),
114
+ ),
115
+ );
43
116
  }
44
117
 
45
118
  /**
46
- * fetch configuration for a widget
47
- * @param widgetKey - widget key
48
- * @param version - version of widget to use
119
+ * Fetches the configuration for a widget using a query.
120
+ * @param widgetKey - The key identifying the widget.
121
+ * @param args - Optional arguments for the widget.
122
+ * @returns An observable stream of the widget manifest.
123
+ * @protected
49
124
  */
50
125
  protected _getWidget(
51
126
  widgetKey: GetWidgetParameters['widgetKey'],
52
127
  args?: GetWidgetParameters['args'],
53
128
  ): Observable<WidgetManifest> {
129
+ // Create a new query using the configured client
130
+ const client = new Query(this.#config.client.getWidgetManifest);
131
+ this.#subscription.add(() => client.complete());
132
+
133
+ // Execute the query and handle errors
54
134
  return Query.extractQueryValue(
55
- this.#widgetClient.query({ widgetKey, args }).pipe(
135
+ client.query({ widgetKey, args }).pipe(
56
136
  catchError((err) => {
57
- /** extract cause, since error will be a `QueryError` */
137
+ // Extract the cause since the error will be a `QueryError`
58
138
  const { cause } = err;
59
- if (cause instanceof GetWidgetError) {
139
+
140
+ // Handle specific errors and throw a `GetWidgetConfigError` if applicable
141
+ if (cause instanceof WidgetConfigLoadError) {
60
142
  throw cause;
61
143
  }
62
144
  if (cause instanceof HttpResponseError) {
63
- throw GetWidgetError.fromHttpResponse(cause.response, { cause });
145
+ throw WidgetConfigLoadError.fromHttpResponse(cause.response, { cause });
64
146
  }
65
- throw new GetWidgetError('unknown', 'failed to load config', { cause });
147
+ // Throw a generic `GetWidgetManifestError` for unknown errors
148
+ throw new WidgetConfigLoadError('unknown', 'failed to load config', {
149
+ cause,
150
+ });
66
151
  }),
67
152
  ),
68
153
  );
69
154
  }
70
155
 
156
+ /**
157
+ * Disposes of the widget provider by unsubscribing from any active subscriptions.
158
+ */
71
159
  public dispose() {
72
160
  this.#subscription.unsubscribe();
73
161
  }
@@ -1,7 +1,7 @@
1
1
  import type { IModulesConfigurator } from '@equinor/fusion-framework-module';
2
- import type { WidgetModuleConfigBuilderCallback } from './WidgetModuleConfigBuilder';
3
2
 
4
3
  import { module } from './module';
4
+ import { WidgetModuleConfigBuilderCallback } from './WidgetModuleConfigurator';
5
5
 
6
6
  /**
7
7
  * Method for enabling the widget module
@@ -15,7 +15,7 @@ export const enableWidgetModule = (
15
15
  configurator.addConfig({
16
16
  module,
17
17
  configure: (widgetConfigurator) => {
18
- builder && widgetConfigurator.addConfigBuilder(builder);
18
+ builder && builder(widgetConfigurator);
19
19
  },
20
20
  });
21
21
  };
package/src/errors.ts CHANGED
@@ -1,18 +1,22 @@
1
1
  type WidgetErrorType = 'not_found' | 'unauthorized' | 'unknown';
2
2
 
3
- export class GetWidgetError extends Error {
3
+ export class WidgetManifestLoadError extends Error {
4
4
  static fromHttpResponse(response: Response, options?: ErrorOptions) {
5
5
  switch (response.status) {
6
6
  case 401:
7
- return new GetWidgetError(
7
+ return new WidgetManifestLoadError(
8
8
  'unauthorized',
9
9
  'failed to load widget manifest, request not authorized',
10
10
  options,
11
11
  );
12
12
  case 404:
13
- return new GetWidgetError('not_found', 'widget manifest not found', options);
13
+ return new WidgetManifestLoadError(
14
+ 'not_found',
15
+ 'widget manifest not found',
16
+ options,
17
+ );
14
18
  }
15
- return new GetWidgetError(
19
+ return new WidgetManifestLoadError(
16
20
  'unknown',
17
21
  `failed to load widget manifest, status code ${response.status}`,
18
22
  options,
@@ -24,6 +28,35 @@ export class GetWidgetError extends Error {
24
28
  options?: ErrorOptions,
25
29
  ) {
26
30
  super(message, options);
31
+ this.name = 'GetWidgetLoadManifestErrors';
32
+ }
33
+ }
34
+
35
+ export class WidgetConfigLoadError extends Error {
36
+ static fromHttpResponse(response: Response, options?: ErrorOptions) {
37
+ switch (response.status) {
38
+ case 401:
39
+ return new WidgetConfigLoadError(
40
+ 'unauthorized',
41
+ 'failed to load widget config, request not authorized',
42
+ options,
43
+ );
44
+ case 404:
45
+ return new WidgetConfigLoadError('not_found', 'widget config not found', options);
46
+ }
47
+ return new WidgetConfigLoadError(
48
+ 'unknown',
49
+ `failed to load widget config, status code ${response.status}`,
50
+ options,
51
+ );
52
+ }
53
+ constructor(
54
+ public readonly type: WidgetErrorType,
55
+ message?: string,
56
+ options?: ErrorOptions,
57
+ ) {
58
+ super(message, options);
59
+ this.name = 'GetWidgetLoadConfigError';
27
60
  }
28
61
  }
29
62
 
@@ -34,5 +67,6 @@ export class WidgetScriptModuleError extends Error {
34
67
  options?: ErrorOptions,
35
68
  ) {
36
69
  super(message, options);
70
+ this.name = 'WidgetScriptModuleError';
37
71
  }
38
72
  }
package/src/events.ts ADDED
@@ -0,0 +1,75 @@
1
+ import type { FrameworkEvent, FrameworkEventInit } from '@equinor/fusion-framework-module-event';
2
+
3
+ import type { Widget } from './Widget';
4
+
5
+ import type {
6
+ WidgetConfig,
7
+ WidgetManifest,
8
+ WidgetModulesInstance,
9
+ WidgetScriptModule,
10
+ } from './types';
11
+
12
+ /** base event type for applications */
13
+ export type WidgetEventInit<TDetail extends Record<string, unknown> | unknown = unknown> =
14
+ FrameworkEventInit<
15
+ /** additional event details and key of target event */
16
+ TDetail & { name: string },
17
+ /** source of the event */
18
+ Widget
19
+ >;
20
+
21
+ export type WidgetEvent<TDetail extends Record<string, unknown> | unknown = unknown> =
22
+ FrameworkEvent<WidgetEventInit<TDetail>>;
23
+
24
+ export type WidgetEventFailure = FrameworkEvent<
25
+ WidgetEventInit<{
26
+ error: WidgetConfig;
27
+ }>
28
+ >;
29
+
30
+ declare module '@equinor/fusion-framework-module-event' {
31
+ interface FrameworkEventMap {
32
+ /** fired when the application has initiated its modules */
33
+ onWidgetModulesLoaded: WidgetEvent<{
34
+ /** initiated modules for application */
35
+ modules: WidgetModulesInstance;
36
+ }>;
37
+
38
+ onWidgetManifestLoad: WidgetEvent;
39
+ /** fired when the application has loaded corresponding manifest */
40
+ onWidgetManifestLoaded: WidgetEvent<{
41
+ manifest: WidgetManifest;
42
+ }>;
43
+ onWidgetManifestFailure: WidgetEventFailure;
44
+
45
+ onWidgetConfigLoad: WidgetEvent;
46
+ /** fired when the application has loaded corresponding config */
47
+ onWidgetConfigLoaded: WidgetEvent<{
48
+ config: WidgetConfig;
49
+ }>;
50
+ onWidgetConfigFailure: WidgetEventFailure;
51
+
52
+ /** fired when the application has loaded corresponding javascript module */
53
+ onAWidgetScriptLoad: WidgetEvent;
54
+ onWidgetScriptLoaded: WidgetEvent<{
55
+ script: WidgetScriptModule;
56
+ }>;
57
+ onWidgetScriptFailure: WidgetEventFailure;
58
+
59
+ /** fired before application loads manifest, config and script */
60
+ onWidgetInitialize: WidgetEvent;
61
+
62
+ /**
63
+ * fired after application has loaded manifest, config and script
64
+ *
65
+ * __note:__ not fired until all loaders has settled (last emit)
66
+ */
67
+ onWidgetInitialized: WidgetEvent;
68
+
69
+ /** fired when application fails to load either manifest, config and script */
70
+ onWidgetInitializeFailure: WidgetEventFailure;
71
+
72
+ /** fired when the application is disposed (unmounts) */
73
+ onWidgetDispose: FrameworkEvent<WidgetEventInit>;
74
+ }
75
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,4 @@
1
- export {
2
- WidgetModuleConfigurator,
3
- IWidgetModuleConfigurator,
4
- WidgetModuleConfig,
5
- } from './WidgetModuleConfigurator';
1
+ export { WidgetModuleConfigurator, WidgetModuleConfig } from './WidgetModuleConfigurator';
6
2
 
7
3
  export { WidgetModuleProvider } from './WidgetModuleProvider';
8
4
 
package/src/module.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Module } from '@equinor/fusion-framework-module';
2
2
  import { ModuleDeps } from './types';
3
3
 
4
- import { IWidgetModuleConfigurator, WidgetModuleConfigurator } from './WidgetModuleConfigurator';
4
+ import { WidgetModuleConfigurator } from './WidgetModuleConfigurator';
5
5
  import { IWidgetModuleProvider, WidgetModuleProvider } from './WidgetModuleProvider';
6
6
 
7
7
  export const moduleKey = 'widget';
@@ -9,15 +9,18 @@ export const moduleKey = 'widget';
9
9
  export type WidgetModule = Module<
10
10
  typeof moduleKey,
11
11
  IWidgetModuleProvider,
12
- IWidgetModuleConfigurator,
12
+ WidgetModuleConfigurator,
13
13
  ModuleDeps
14
14
  >;
15
15
 
16
16
  export const module: WidgetModule = {
17
17
  name: moduleKey,
18
- configure: () => new WidgetModuleConfigurator('1.0-preview'),
18
+ configure() {
19
+ const config = new WidgetModuleConfigurator();
20
+ return config;
21
+ },
19
22
  initialize: async (args) => {
20
- const config = await (args.config as WidgetModuleConfigurator).createConfig(args);
23
+ const config = await args.config.createConfigAsync(args);
21
24
  const event = await args.requireInstance('event').catch(() => undefined);
22
25
  return new WidgetModuleProvider({ config, event });
23
26
  },
@@ -30,6 +33,6 @@ export default module;
30
33
 
31
34
  declare module '@equinor/fusion-framework-module' {
32
35
  interface Modules {
33
- widget: WidgetModule;
36
+ [moduleKey]: WidgetModule;
34
37
  }
35
38
  }
@@ -0,0 +1,70 @@
1
+ import {
2
+ ActionInstanceMap,
3
+ ActionTypes,
4
+ createAction,
5
+ createAsyncAction,
6
+ } from '@equinor/fusion-observable';
7
+ import {
8
+ GetWidgetParameters,
9
+ WidgetConfig,
10
+ WidgetManifest,
11
+ WidgetModulesInstance,
12
+ WidgetScriptModule,
13
+ } from '../types';
14
+
15
+ const createActions = () => ({
16
+ /** Manifest loading */
17
+ setManifest: createAction('set_manifest', (manifest: WidgetManifest, update?: boolean) => ({
18
+ payload: manifest,
19
+ meta: {
20
+ created: Date.now(),
21
+ update,
22
+ },
23
+ })),
24
+ fetchManifest: createAsyncAction(
25
+ 'fetch_manifest',
26
+ (payload: { key: string; args?: GetWidgetParameters['args'] }, update?: boolean) => ({
27
+ payload,
28
+ meta: { update },
29
+ }),
30
+ (manifest: WidgetManifest) => ({ payload: manifest }),
31
+ (error: unknown) => ({ payload: error }),
32
+ ),
33
+ /** Config loading */
34
+ setConfig: createAction('set_config', (config: WidgetConfig) => ({ payload: config })),
35
+ fetchConfig: createAsyncAction(
36
+ 'fetch_config',
37
+ (payload: { key: string; args?: GetWidgetParameters['args'] }, update?: boolean) => ({
38
+ payload,
39
+ meta: { update },
40
+ }),
41
+ (config: WidgetConfig) => ({ payload: config }),
42
+ (error: unknown) => ({ payload: error }),
43
+ ),
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ setModule: createAction('set_module', (module: any) => ({ payload: module })),
46
+ importWidget: createAsyncAction(
47
+ 'import_widget',
48
+ (entrypoint: string) => ({ payload: entrypoint }),
49
+ (module: WidgetScriptModule) => ({ payload: module }),
50
+ (error: unknown) => ({ payload: error }),
51
+ ),
52
+ // widget Instance
53
+ setInstance: createAction('set_instance', (instance: WidgetModulesInstance) => ({
54
+ payload: instance,
55
+ })),
56
+ initialize: createAsyncAction(
57
+ 'initialize_widget',
58
+ () => ({ payload: null }),
59
+ () => ({ payload: null }),
60
+ (error: unknown) => ({ payload: error }),
61
+ ),
62
+ });
63
+
64
+ export const actions = createActions();
65
+
66
+ export type ActionBuilder = ReturnType<typeof createActions>;
67
+
68
+ export type ActionMap = ActionInstanceMap<ActionBuilder>;
69
+
70
+ export type Actions = ActionTypes<typeof actions>;
@@ -0,0 +1,44 @@
1
+ import {
2
+ actionBaseType,
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 { actions } from './actions';
13
+ import { WidgetStateInitial, WidgetState } from '../types';
14
+
15
+ export const createReducer = (value: WidgetStateInitial) =>
16
+ makeReducer({ ...value, status: new Set() } as WidgetState, (builder) =>
17
+ builder
18
+ .addCase(actions.setManifest, (state, action) => {
19
+ if (action.meta.update) {
20
+ state.manifest = { ...state.manifest, ...action.payload };
21
+ } else {
22
+ state.manifest = action.payload;
23
+ }
24
+ })
25
+ .addCase(actions.setConfig, (state, action) => {
26
+ state.config = action.payload;
27
+ })
28
+ .addCase(actions.setModule, (state, action) => {
29
+ state.modules = action.payload;
30
+ })
31
+ .addCase(actions.setInstance, (state, action) => {
32
+ state.instance = action.payload;
33
+ })
34
+ /** mark status as loading {{type}} */
35
+ .addMatcher(isRequestAction, (state, action) => {
36
+ state.status.add(actionBaseType(action));
37
+ })
38
+ /** clear status {{type}} */
39
+ .addMatcher(isCompleteAction, (state, action) => {
40
+ state.status.delete(actionBaseType(action));
41
+ }),
42
+ );
43
+
44
+ export default createReducer;
@@ -0,0 +1,21 @@
1
+ import { FlowSubject } from '@equinor/fusion-observable';
2
+
3
+ import { createReducer } from './create-reducer';
4
+
5
+ import { handleFetchManifest, handleImportWidget, handleFetchConfig } from './flows';
6
+
7
+ import type { Actions } from './actions';
8
+ import { WidgetState, WidgetStateInitial } from '../types';
9
+ import WidgetModuleProvider from '../WidgetModuleProvider';
10
+
11
+ export const createState = (
12
+ value: WidgetStateInitial,
13
+ provider: WidgetModuleProvider,
14
+ ): FlowSubject<WidgetState, Actions> => {
15
+ const reducer = createReducer(value);
16
+ const state = new FlowSubject<WidgetState, Actions>(reducer);
17
+ state.addFlow(handleFetchManifest(provider));
18
+ state.addFlow(handleImportWidget());
19
+ state.addFlow(handleFetchConfig(provider));
20
+ return state;
21
+ };
@@ -0,0 +1,75 @@
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
+
8
+ import type { Actions } from './actions';
9
+ import { WidgetState } from '../types';
10
+ import type WidgetModuleProvider from '../WidgetModuleProvider';
11
+
12
+ export const handleFetchManifest =
13
+ (provider: WidgetModuleProvider): Flow<Actions, WidgetState> =>
14
+ (action$) =>
15
+ action$.pipe(
16
+ filter(actions.fetchManifest.match),
17
+ switchMap((action) => {
18
+ const {
19
+ payload: { key, args },
20
+ meta: { update },
21
+ } = action;
22
+
23
+ const subject = from(provider.getWidgetManifest(key, args)).pipe(
24
+ filter((x) => !!x),
25
+ share(),
26
+ );
27
+ return concat(
28
+ subject.pipe(map((manifest) => actions.setManifest(manifest, update))),
29
+ subject.pipe(
30
+ last(),
31
+ map((manifest) => actions.fetchManifest.success(manifest)),
32
+ ),
33
+ ).pipe(
34
+ catchError((err) => {
35
+ console.log(err, action.payload);
36
+ return of(actions.fetchManifest.failure(err));
37
+ }),
38
+ );
39
+ }),
40
+ );
41
+
42
+ export const handleFetchConfig =
43
+ (provider: WidgetModuleProvider): Flow<Actions, WidgetState> =>
44
+ (action$) =>
45
+ action$.pipe(
46
+ filter(actions.fetchConfig.match),
47
+ switchMap(({ payload: { key, args } }) => {
48
+ const subject = from(provider.getWidgetConfig(key, args)).pipe(
49
+ filter((x) => !!x),
50
+ share(),
51
+ );
52
+ return concat(
53
+ subject.pipe(map((manifest) => actions.setConfig(manifest))),
54
+ subject.pipe(
55
+ last(),
56
+ map((manifest) => actions.fetchConfig.success(manifest)),
57
+ ),
58
+ ).pipe(
59
+ catchError((err) => {
60
+ return of(actions.fetchConfig.failure(err));
61
+ }),
62
+ );
63
+ }),
64
+ );
65
+
66
+ export const handleImportWidget = (): Flow<Actions, WidgetState> => (action$) =>
67
+ action$.pipe(
68
+ filter(actions.importWidget.match),
69
+ switchMap(({ payload }) => {
70
+ return from(import(/* @vite-ignore */ payload)).pipe(
71
+ map(actions.importWidget.success),
72
+ catchError((err) => of(actions.importWidget.failure(err))),
73
+ );
74
+ }),
75
+ );