@equinor/fusion-framework-module-widget 16.0.7 → 16.0.8
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 +15 -12
- package/CHANGELOG.md +0 -907
- package/src/Widget.ts +0 -403
- package/src/WidgetManifestLoadError.ts +0 -61
- package/src/WidgetModuleConfigurator.ts +0 -96
- package/src/WidgetModuleProvider.ts +0 -233
- package/src/enable-widget-module.ts +0 -35
- package/src/errors/WidgetConfigLoadError.ts +0 -51
- package/src/errors/WidgetScriptModuleError.ts +0 -20
- package/src/events.ts +0 -94
- package/src/index.ts +0 -21
- package/src/module.ts +0 -61
- package/src/state/actions.ts +0 -88
- package/src/state/create-reducer.ts +0 -57
- package/src/state/create-state.ts +0 -33
- package/src/state/flows.ts +0 -123
- package/src/types.ts +0 -203
- package/src/utils.ts +0 -85
- package/src/version.ts +0 -2
- package/tsconfig.json +0 -25
package/src/Widget.ts
DELETED
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
import type { ModuleType } from '@equinor/fusion-framework-module';
|
|
2
|
-
import type {
|
|
3
|
-
GetWidgetParameters,
|
|
4
|
-
WidgetConfig,
|
|
5
|
-
WidgetManifest,
|
|
6
|
-
WidgetScriptModule,
|
|
7
|
-
WidgetState,
|
|
8
|
-
WidgetStateInitial,
|
|
9
|
-
} from './types';
|
|
10
|
-
import { type Actions, actions } from './state/actions';
|
|
11
|
-
import type { FlowSubject } from '@equinor/fusion-observable';
|
|
12
|
-
|
|
13
|
-
import { createState } from './state/create-state';
|
|
14
|
-
import type { EventModule } from '@equinor/fusion-framework-module-event';
|
|
15
|
-
import { Observable, Subscription, combineLatest, firstValueFrom, lastValueFrom, of } from 'rxjs';
|
|
16
|
-
import type WidgetModuleProvider from './WidgetModuleProvider';
|
|
17
|
-
import type { WidgetModuleConfig } from './WidgetModuleConfigurator';
|
|
18
|
-
|
|
19
|
-
import './events';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Manages the full lifecycle of a single Fusion widget.
|
|
23
|
-
*
|
|
24
|
-
* A `Widget` encapsulates fetching its manifest, dynamically importing its
|
|
25
|
-
* script entry point, loading configuration, and emitting lifecycle events.
|
|
26
|
-
* Internally it uses an RxJS-based `FlowSubject` state machine driven by
|
|
27
|
-
* actions and flows defined in the `state/` directory.
|
|
28
|
-
*
|
|
29
|
-
* Create instances via {@link WidgetModuleProvider.getWidget} rather than
|
|
30
|
-
* constructing directly.
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```typescript
|
|
34
|
-
* const widget = provider.getWidget('my-widget');
|
|
35
|
-
* widget.initialize().subscribe(({ manifest, script }) => {
|
|
36
|
-
* script.renderWidget(el, { fusion, env: { manifest } });
|
|
37
|
-
* });
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export class Widget {
|
|
41
|
-
#state: FlowSubject<WidgetState, Actions>;
|
|
42
|
-
|
|
43
|
-
/** Human-readable widget name used as the lookup key for manifest and config. */
|
|
44
|
-
name: string;
|
|
45
|
-
|
|
46
|
-
/** Module-level HTTP client configuration used to resolve asset URLs. */
|
|
47
|
-
config?: WidgetModuleConfig;
|
|
48
|
-
|
|
49
|
-
/** Optional version or tag parameters forwarded to manifest/config endpoints. */
|
|
50
|
-
widgetPrams?: GetWidgetParameters['args'];
|
|
51
|
-
|
|
52
|
-
#subscription = new Subscription();
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Current snapshot of the widget's internal state (manifest, config, modules, status).
|
|
56
|
-
*
|
|
57
|
-
* @returns The current {@link WidgetState}.
|
|
58
|
-
*/
|
|
59
|
-
get state(): WidgetState {
|
|
60
|
-
return this.#state.value;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Constructs a new `Widget` instance.
|
|
65
|
-
*
|
|
66
|
-
* Prefer using {@link WidgetModuleProvider.getWidget} instead of calling
|
|
67
|
-
* this constructor directly.
|
|
68
|
-
*
|
|
69
|
-
* @param value - Initial widget state (at minimum, the widget `name`).
|
|
70
|
-
* @param args - Dependencies required by the widget.
|
|
71
|
-
* @param args.provider - The owning {@link WidgetModuleProvider}.
|
|
72
|
-
* @param args.config - Optional module-level HTTP client configuration.
|
|
73
|
-
* @param args.event - Optional event module for dispatching lifecycle events.
|
|
74
|
-
* @param args.widgetPrams - Optional version/tag selector for the widget.
|
|
75
|
-
*/
|
|
76
|
-
constructor(
|
|
77
|
-
value: WidgetStateInitial,
|
|
78
|
-
args: {
|
|
79
|
-
provider: WidgetModuleProvider;
|
|
80
|
-
config?: WidgetModuleConfig;
|
|
81
|
-
event?: ModuleType<EventModule>;
|
|
82
|
-
widgetPrams?: GetWidgetParameters['args'];
|
|
83
|
-
},
|
|
84
|
-
) {
|
|
85
|
-
this.name = value.name;
|
|
86
|
-
this.widgetPrams = args.widgetPrams;
|
|
87
|
-
this.config = args.config;
|
|
88
|
-
this.#state = createState(value, args.provider);
|
|
89
|
-
args.event && this.#registerEvents(args.event);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Registers event listeners for various actions in the widget's state.
|
|
94
|
-
* @param event - The event module to dispatch events.
|
|
95
|
-
*/
|
|
96
|
-
#registerEvents(event: ModuleType<EventModule>): void {
|
|
97
|
-
const { name } = this;
|
|
98
|
-
|
|
99
|
-
this.#state.addEffect(actions.fetchManifest.type, () => {
|
|
100
|
-
event.dispatchEvent('onWidgetManifestLoad', {
|
|
101
|
-
detail: { name },
|
|
102
|
-
source: this,
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
this.#state.addEffect(actions.fetchManifest.success.type, (action) => {
|
|
106
|
-
event.dispatchEvent('onWidgetManifestLoaded', {
|
|
107
|
-
detail: { name, manifest: action.payload },
|
|
108
|
-
source: this,
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
this.#state.addEffect(actions.fetchManifest.failure.type, (action) => {
|
|
112
|
-
event.dispatchEvent('onWidgetManifestFailure', {
|
|
113
|
-
detail: { name, error: action.payload },
|
|
114
|
-
source: this,
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
this.#state.addEffect(actions.importWidget.type, () => {
|
|
119
|
-
event.dispatchEvent('onWidgetScriptLoad', {
|
|
120
|
-
detail: { name },
|
|
121
|
-
source: this,
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
this.#state.addEffect(actions.importWidget.success.type, (action) => {
|
|
125
|
-
event.dispatchEvent('onWidgetScriptLoaded', {
|
|
126
|
-
detail: { name, script: action.payload },
|
|
127
|
-
source: this,
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
this.#state.addEffect(actions.importWidget.failure.type, (action) => {
|
|
131
|
-
event.dispatchEvent('onWidgetScriptFailure', {
|
|
132
|
-
detail: { name, error: action.payload },
|
|
133
|
-
source: this,
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
this.#state.addEffect(actions.initialize.type, () => {
|
|
138
|
-
event.dispatchEvent('onWidgetInitialize', {
|
|
139
|
-
detail: { name },
|
|
140
|
-
source: this,
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
this.#state.addEffect(actions.initialize.success.type, () => {
|
|
145
|
-
event.dispatchEvent('onWidgetInitialized', {
|
|
146
|
-
detail: { name },
|
|
147
|
-
source: this,
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
this.#state.addEffect(actions.initialize.failure.type, ({ payload }) => {
|
|
152
|
-
event.dispatchEvent('onWidgetInitializeFailure', {
|
|
153
|
-
detail: { name, error: payload },
|
|
154
|
-
source: this,
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Retrieves the widget manifest as an observable stream.
|
|
161
|
-
*
|
|
162
|
-
* If the manifest is already cached in state it is emitted immediately.
|
|
163
|
-
* When `force_refresh` is `true`, a new fetch is dispatched regardless of
|
|
164
|
-
* cache status.
|
|
165
|
-
*
|
|
166
|
-
* @param force_refresh - When `true`, re-fetches the manifest even if cached.
|
|
167
|
-
* @returns Observable that emits the {@link WidgetManifest} and completes.
|
|
168
|
-
* @throws {Error} When the manifest fetch fails (wraps the underlying cause).
|
|
169
|
-
*/
|
|
170
|
-
public getManifest(force_refresh = false): Observable<WidgetManifest> {
|
|
171
|
-
return new Observable((subscriber) => {
|
|
172
|
-
// Emit the cached manifest immediately if one is already available
|
|
173
|
-
if (this.#state.value.manifest) {
|
|
174
|
-
subscriber.next(this.#state.value.manifest);
|
|
175
|
-
// Skip the fetch below unless the caller explicitly asked to refresh
|
|
176
|
-
if (!force_refresh) {
|
|
177
|
-
return subscriber.complete();
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
subscriber.add(
|
|
181
|
-
this.#state.addEffect('set_manifest', ({ payload }) => {
|
|
182
|
-
subscriber.next(payload);
|
|
183
|
-
}),
|
|
184
|
-
);
|
|
185
|
-
subscriber.add(
|
|
186
|
-
this.#state.addEffect('fetch_manifest::success', ({ payload }) => {
|
|
187
|
-
subscriber.next(payload);
|
|
188
|
-
subscriber.complete();
|
|
189
|
-
}),
|
|
190
|
-
);
|
|
191
|
-
subscriber.add(
|
|
192
|
-
this.#state.addEffect('fetch_manifest::failure', ({ payload }) => {
|
|
193
|
-
subscriber.error(
|
|
194
|
-
Error('failed to load widget manifest', {
|
|
195
|
-
cause: payload,
|
|
196
|
-
}),
|
|
197
|
-
);
|
|
198
|
-
}),
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
this.loadManifest();
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Retrieves the widget configuration as an observable stream.
|
|
207
|
-
*
|
|
208
|
-
* Returns the cached config immediately when available. Set `force_refresh`
|
|
209
|
-
* to `true` to force a new fetch from the backend API.
|
|
210
|
-
*
|
|
211
|
-
* @param force_refresh - When `true`, re-fetches the config even if cached.
|
|
212
|
-
* @returns Observable that emits the {@link WidgetConfig} and completes.
|
|
213
|
-
* @throws {Error} When the config fetch fails (wraps the underlying cause).
|
|
214
|
-
*/
|
|
215
|
-
public getConfig(force_refresh = false): Observable<WidgetConfig> {
|
|
216
|
-
return new Observable((subscriber) => {
|
|
217
|
-
const currentValue = this.#state.value;
|
|
218
|
-
// Emit the cached config immediately if the manifest and config are already available
|
|
219
|
-
if (currentValue.manifest && currentValue.config) {
|
|
220
|
-
subscriber.next(currentValue.config);
|
|
221
|
-
// Skip the fetch below unless the caller explicitly asked to refresh
|
|
222
|
-
if (!force_refresh) {
|
|
223
|
-
return subscriber.complete();
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
subscriber.add(
|
|
227
|
-
this.#state.addEffect('set_config', ({ payload }) => {
|
|
228
|
-
subscriber.next(payload);
|
|
229
|
-
}),
|
|
230
|
-
);
|
|
231
|
-
subscriber.add(
|
|
232
|
-
this.#state.addEffect('fetch_config::success', ({ payload }) => {
|
|
233
|
-
subscriber.next(payload);
|
|
234
|
-
subscriber.complete();
|
|
235
|
-
}),
|
|
236
|
-
);
|
|
237
|
-
subscriber.add(
|
|
238
|
-
this.#state.addEffect('fetch_config::failure', ({ payload }) => {
|
|
239
|
-
subscriber.error(
|
|
240
|
-
Error('failed to load widget manifest', {
|
|
241
|
-
cause: payload,
|
|
242
|
-
}),
|
|
243
|
-
);
|
|
244
|
-
}),
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
this.loadConfig();
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Dispatches a config fetch action into the state machine.
|
|
253
|
-
*
|
|
254
|
-
* @param update - When `true`, merges the fetched config with existing state
|
|
255
|
-
* instead of replacing it.
|
|
256
|
-
*/
|
|
257
|
-
public loadConfig(update?: boolean) {
|
|
258
|
-
this.#state.next(actions.fetchConfig({ key: this.name, ...this.widgetPrams }, update));
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Dispatches a manifest fetch action into the state machine.
|
|
263
|
-
*
|
|
264
|
-
* @param update - When `true`, merges the fetched manifest with existing
|
|
265
|
-
* state instead of replacing it.
|
|
266
|
-
*/
|
|
267
|
-
public loadManifest(update?: boolean) {
|
|
268
|
-
this.#state.next(actions.fetchManifest({ key: this.name, ...this.widgetPrams }, update));
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Retrieves the widget's script module as an observable stream.
|
|
273
|
-
*
|
|
274
|
-
* Resolves the manifest first, builds the full import URL from the asset
|
|
275
|
-
* path and entry point, then dynamically imports the script. The imported
|
|
276
|
-
* module is cached in state for subsequent calls.
|
|
277
|
-
*
|
|
278
|
-
* @param force_refresh - When `true`, re-imports the script even if cached.
|
|
279
|
-
* @returns Observable that emits the {@link WidgetScriptModule} and completes.
|
|
280
|
-
* @throws {Error} When the script import fails (wraps the underlying cause).
|
|
281
|
-
*/
|
|
282
|
-
public getWidgetModule(force_refresh = false): Observable<WidgetScriptModule> {
|
|
283
|
-
return new Observable((subscriber) => {
|
|
284
|
-
// Emit the cached script module immediately if one is already available
|
|
285
|
-
if (this.#state.value.modules) {
|
|
286
|
-
subscriber.next(this.#state.value.modules);
|
|
287
|
-
// Skip the import below unless the caller explicitly asked to refresh
|
|
288
|
-
if (!force_refresh) {
|
|
289
|
-
return subscriber.complete();
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
subscriber.add(
|
|
293
|
-
this.#state.addEffect('set_module', ({ payload }) => {
|
|
294
|
-
subscriber.next(payload);
|
|
295
|
-
}),
|
|
296
|
-
);
|
|
297
|
-
subscriber.add(
|
|
298
|
-
this.#state.addEffect('import_widget::success', ({ payload }) => {
|
|
299
|
-
subscriber.next(payload);
|
|
300
|
-
subscriber.complete();
|
|
301
|
-
}),
|
|
302
|
-
);
|
|
303
|
-
subscriber.add(
|
|
304
|
-
this.#state.addEffect('import_widget::failure', ({ payload }) => {
|
|
305
|
-
subscriber.error(
|
|
306
|
-
Error('failed to load widget modules from script', {
|
|
307
|
-
cause: payload,
|
|
308
|
-
}),
|
|
309
|
-
);
|
|
310
|
-
}),
|
|
311
|
-
);
|
|
312
|
-
|
|
313
|
-
subscriber.add(
|
|
314
|
-
this.getManifest().subscribe((manifest) => {
|
|
315
|
-
const path = manifest.assetPath
|
|
316
|
-
? `${manifest.assetPath}/${manifest.entryPoint}?api-version=${this.config?.client.apiVersion}`
|
|
317
|
-
: `${manifest.entryPoint}?api-version=${this.config?.client.apiVersion}`;
|
|
318
|
-
|
|
319
|
-
const url = new URL(path, this.config?.client.baseImportUrl);
|
|
320
|
-
|
|
321
|
-
return of(this.#state.next(actions.importWidget(url.href)));
|
|
322
|
-
}),
|
|
323
|
-
);
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Initializes the widget by loading the manifest, importing the script, and
|
|
328
|
-
* preparing configuration. Emits a combined result when all resources are ready.
|
|
329
|
-
*
|
|
330
|
-
* @returns Observable that emits `{ manifest, script, config }` and completes
|
|
331
|
-
* once all resources have been resolved.
|
|
332
|
-
* @throws {Error} When any initialization step fails.
|
|
333
|
-
*/
|
|
334
|
-
public initialize(): Observable<{
|
|
335
|
-
manifest: WidgetManifest;
|
|
336
|
-
script: WidgetScriptModule;
|
|
337
|
-
config?: WidgetConfig;
|
|
338
|
-
}> {
|
|
339
|
-
return new Observable((observer) => {
|
|
340
|
-
this.#state.next(actions.initialize());
|
|
341
|
-
observer.add(
|
|
342
|
-
combineLatest([
|
|
343
|
-
this.getManifest(),
|
|
344
|
-
this.getWidgetModule(),
|
|
345
|
-
// this.getConfig(),
|
|
346
|
-
]).subscribe({
|
|
347
|
-
next: ([manifest, script]) =>
|
|
348
|
-
observer.next({
|
|
349
|
-
manifest,
|
|
350
|
-
script,
|
|
351
|
-
//Todo: uncomment the getConfig on line #273 and replace config when backend support widget config.
|
|
352
|
-
config: {
|
|
353
|
-
environment: {},
|
|
354
|
-
endpoints: {},
|
|
355
|
-
},
|
|
356
|
-
}),
|
|
357
|
-
error: (err) => {
|
|
358
|
-
observer.error(err);
|
|
359
|
-
this.#state.next(actions.initialize.failure(err));
|
|
360
|
-
},
|
|
361
|
-
complete: () => {
|
|
362
|
-
this.#state.next(actions.initialize.success());
|
|
363
|
-
observer.complete();
|
|
364
|
-
},
|
|
365
|
-
}),
|
|
366
|
-
);
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* Retrieves the widget script module as a `Promise`.
|
|
371
|
-
*
|
|
372
|
-
* When `allow_cache` is `true` (default), resolves with the first emitted
|
|
373
|
-
* value (which may be cached). When `false`, waits for the last emission
|
|
374
|
-
* after a forced refresh.
|
|
375
|
-
*
|
|
376
|
-
* @param allow_cache - When `true`, uses `firstValueFrom`; when `false`,
|
|
377
|
-
* uses `lastValueFrom` after forcing a re-import.
|
|
378
|
-
* @returns Promise that resolves with the {@link WidgetScriptModule}.
|
|
379
|
-
*/
|
|
380
|
-
public getWidgetModuleAsync(allow_cache = true): Promise<WidgetScriptModule> {
|
|
381
|
-
const operator = allow_cache ? firstValueFrom : lastValueFrom;
|
|
382
|
-
return operator(this.getWidgetModule(!allow_cache));
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* Replaces or merges the widget manifest in state.
|
|
386
|
-
*
|
|
387
|
-
* @param manifest - The new or partial manifest to set.
|
|
388
|
-
* @param replace - When `false` (default), the new manifest is merged with
|
|
389
|
-
* the existing one. Pass explicit `false` to merge, or omit to merge.
|
|
390
|
-
*/
|
|
391
|
-
public updateManifest(manifest: WidgetManifest, replace?: false) {
|
|
392
|
-
this.#state.next(actions.setManifest(manifest, !replace));
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Disposes of the widget by unsubscribing from all internal subscriptions.
|
|
397
|
-
*
|
|
398
|
-
* After disposal the widget instance should not be reused.
|
|
399
|
-
*/
|
|
400
|
-
public dispose() {
|
|
401
|
-
this.#subscription.unsubscribe();
|
|
402
|
-
}
|
|
403
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Discriminator for categorizing widget HTTP errors.
|
|
3
|
-
*
|
|
4
|
-
* - `'not_found'` — HTTP 404
|
|
5
|
-
* - `'unauthorized'` — HTTP 401
|
|
6
|
-
* - `'unknown'` — any other error
|
|
7
|
-
*/
|
|
8
|
-
export type WidgetErrorType = 'not_found' | 'unauthorized' | 'unknown';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Error thrown when a widget manifest cannot be loaded from the backend API.
|
|
12
|
-
*
|
|
13
|
-
* Use the static {@link fromHttpResponse} factory to create instances from
|
|
14
|
-
* HTTP responses with appropriate type mapping.
|
|
15
|
-
*/
|
|
16
|
-
export class WidgetManifestLoadError extends Error {
|
|
17
|
-
/**
|
|
18
|
-
* Creates a `WidgetManifestLoadError` from an HTTP `Response`.
|
|
19
|
-
*
|
|
20
|
-
* Maps HTTP 401 to `'unauthorized'`, 404 to `'not_found'`, and all other
|
|
21
|
-
* status codes to `'unknown'`.
|
|
22
|
-
*
|
|
23
|
-
* @param response - The failing HTTP response.
|
|
24
|
-
* @param options - Standard `ErrorOptions` (e.g., `cause`).
|
|
25
|
-
* @returns A typed `WidgetManifestLoadError`.
|
|
26
|
-
*/
|
|
27
|
-
static fromHttpResponse(response: Response, options?: ErrorOptions) {
|
|
28
|
-
// Map known status codes to a specific error type, otherwise fall through to 'unknown'
|
|
29
|
-
switch (response.status) {
|
|
30
|
-
case 401:
|
|
31
|
-
return new WidgetManifestLoadError(
|
|
32
|
-
'unauthorized',
|
|
33
|
-
'failed to load widget manifest, request not authorized',
|
|
34
|
-
options,
|
|
35
|
-
);
|
|
36
|
-
case 404:
|
|
37
|
-
return new WidgetManifestLoadError('not_found', 'widget manifest not found', options);
|
|
38
|
-
}
|
|
39
|
-
return new WidgetManifestLoadError(
|
|
40
|
-
'unknown',
|
|
41
|
-
`failed to load widget manifest, status code ${response.status}`,
|
|
42
|
-
options,
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* @param type - Error category discriminator.
|
|
47
|
-
* @param message - Human-readable error description.
|
|
48
|
-
* @param options - Standard `ErrorOptions` (e.g., `cause`).
|
|
49
|
-
*/
|
|
50
|
-
constructor(
|
|
51
|
-
public readonly type: WidgetErrorType,
|
|
52
|
-
message?: string,
|
|
53
|
-
options?: ErrorOptions,
|
|
54
|
-
) {
|
|
55
|
-
super(message, options);
|
|
56
|
-
this.name = 'GetWidgetLoadManifestErrors';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export { WidgetConfigLoadError } from './errors/WidgetConfigLoadError.js';
|
|
61
|
-
export { WidgetScriptModuleError } from './errors/WidgetScriptModuleError.js';
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { BaseConfigBuilder, type ConfigBuilderCallback } from '@equinor/fusion-framework-module';
|
|
2
|
-
import type { ConfigBuilderCallbackArgs } from '@equinor/fusion-framework-module';
|
|
3
|
-
import { createDefaultClient } from './utils';
|
|
4
|
-
import type { IClient } from './types';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Resolved configuration produced by {@link WidgetModuleConfigurator}.
|
|
8
|
-
*
|
|
9
|
-
* Contains the {@link IClient} used to fetch widget manifests and configs
|
|
10
|
-
* from the backend API.
|
|
11
|
-
*/
|
|
12
|
-
export type WidgetModuleConfig = {
|
|
13
|
-
/** HTTP client abstraction for widget API calls. */
|
|
14
|
-
client: IClient;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Callback signature accepted by {@link enableWidgetModule} for customizing
|
|
19
|
-
* the widget module configuration.
|
|
20
|
-
*
|
|
21
|
-
* @param builder - The {@link WidgetModuleConfigurator} instance to configure.
|
|
22
|
-
*/
|
|
23
|
-
export type WidgetModuleConfigBuilderCallback = (
|
|
24
|
-
builder: WidgetModuleConfigurator,
|
|
25
|
-
) => void | Promise<void>;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Configuration builder for the widget module.
|
|
29
|
-
*
|
|
30
|
-
* Extends `BaseConfigBuilder` to produce a {@link WidgetModuleConfig}. If no
|
|
31
|
-
* custom client is provided via {@link setClient}, a default HTTP client is
|
|
32
|
-
* created from the `apps` service-discovery endpoint.
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```typescript
|
|
36
|
-
* enableWidgetModule(configurator, (builder) => {
|
|
37
|
-
* builder.setClient(async () => myCustomClient);
|
|
38
|
-
* });
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
export class WidgetModuleConfigurator extends BaseConfigBuilder<WidgetModuleConfig> {
|
|
42
|
-
/** Default cache expiration time in milliseconds (1 minute). */
|
|
43
|
-
defaultExpireTime = 1 * 60 * 1000;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Registers a custom {@link IClient} factory for the widget module.
|
|
47
|
-
*
|
|
48
|
-
* @param cb - Callback that receives config-builder args and returns an
|
|
49
|
-
* `IClient` instance (or a `Promise` thereof).
|
|
50
|
-
*/
|
|
51
|
-
public setClient(cb: ConfigBuilderCallback<IClient>) {
|
|
52
|
-
this._set('client', cb);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Creates an HTTP client by resolving the `apps` client from the HTTP module
|
|
57
|
-
* or falling back to service discovery.
|
|
58
|
-
*
|
|
59
|
-
* @param clientId - Registered HTTP client identifier (typically `'apps'`).
|
|
60
|
-
* @param init - Framework config-builder callback args providing module instances.
|
|
61
|
-
* @returns An `IHttpClient` instance for widget API calls.
|
|
62
|
-
*/
|
|
63
|
-
private async _createHttpClient(clientId: string, init: ConfigBuilderCallbackArgs) {
|
|
64
|
-
const http = await init.requireInstance('http');
|
|
65
|
-
|
|
66
|
-
// Reuse an already-registered client when one exists for this id
|
|
67
|
-
if (http.hasClient(clientId)) {
|
|
68
|
-
return http.createClient(clientId);
|
|
69
|
-
} else {
|
|
70
|
-
/** load service discovery module */
|
|
71
|
-
const serviceDiscovery = await init.requireInstance('serviceDiscovery');
|
|
72
|
-
return await serviceDiscovery.createClient(clientId);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Finalizes the configuration by creating the default HTTP client when no
|
|
78
|
-
* custom client has been set.
|
|
79
|
-
*
|
|
80
|
-
* @param config - Partial configuration accumulated by builder callbacks.
|
|
81
|
-
* @param _init - Framework config-builder callback args.
|
|
82
|
-
* @returns The fully resolved {@link WidgetModuleConfig}.
|
|
83
|
-
*/
|
|
84
|
-
protected async _processConfig(
|
|
85
|
-
config: Partial<WidgetModuleConfig>,
|
|
86
|
-
_init: ConfigBuilderCallbackArgs,
|
|
87
|
-
) {
|
|
88
|
-
const httpClient = await this._createHttpClient('apps', _init);
|
|
89
|
-
|
|
90
|
-
// Only fall back to the default client when the caller hasn't set one
|
|
91
|
-
if (!config.client) {
|
|
92
|
-
config.client = createDefaultClient(httpClient);
|
|
93
|
-
}
|
|
94
|
-
return config as WidgetModuleConfig;
|
|
95
|
-
}
|
|
96
|
-
}
|