-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathremote-module.service.ts
101 lines (86 loc) · 2.82 KB
/
remote-module.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import {
LoadRemoteModuleOptions,
loadRemoteModule,
} from '@angular-architects/module-federation';
import { Injectable, InjectionToken, inject } from '@angular/core';
import {
RemoteModuleEvent,
RemoteModuleFailed,
RemoteModuleLoaded,
RemoteModuleLoading,
} from './remote-module-events';
import { Observable, Subject } from 'rxjs';
// The REMOTE_MODULE_EVENTS InjectionToken was based on the idea explained in
// "The Hidden Power of InjectionToken Factory Functions in Angular":
// - https://netbasal.com/the-hidden-power-of-injectiontoken-factory-functions-in-angular-d42d5575859b
export type RemoteModuleEvents = Observable<RemoteModuleEvent>;
export const REMOTE_MODULE_EVENTS = new InjectionToken<RemoteModuleEvents>(
'Remote module events',
{
factory() {
const remoteModuleService = inject(RemoteModuleService);
return remoteModuleService.events$;
},
}
);
export const enum RemoteModuleResultTypes {
Loaded = 'Loaded',
Failed = 'Failed',
}
export type RemoteModuleResult = RemoteModuleLoadedResult | RemoteModuleFailedResult;
export class RemoteModuleLoadedResult {
public constructor(public readonly webpackModule: any) {}
public readonly type = RemoteModuleResultTypes.Loaded;
}
export class RemoteModuleFailedResult {
public constructor(public readonly error: Error) {}
public readonly type = RemoteModuleResultTypes.Failed;
}
export type LoadRemoteModuleOptionsExtended = LoadRemoteModuleOptions & {
id: string;
};
@Injectable({ providedIn: 'root' })
export class RemoteModuleService {
private readonly _events = new Subject<RemoteModuleEvent>();
public readonly events$ = this._events.asObservable();
public async loadAsync(options: LoadRemoteModuleOptionsExtended): Promise<RemoteModuleResult> {
try {
this.triggerLoading(options);
const webpackModule: any = await loadRemoteModule(options);
this.triggerLoaded(options, webpackModule);
return new RemoteModuleLoadedResult(webpackModule);
} catch (error: unknown) {
if (!(error instanceof Error)) {
throw error; //should always be of type Error but if not rethrow
}
this.triggerFailed(options, error);
return new RemoteModuleFailedResult(error);
}
}
private triggerLoading(options: LoadRemoteModuleOptionsExtended) {
const event = new RemoteModuleLoading(
options.id,
options);
this._events.next(event);
}
private triggerLoaded(
options: LoadRemoteModuleOptionsExtended,
webpackModule: any,
) {
const event = new RemoteModuleLoaded(
options.id,
options,
webpackModule);
this._events.next(event);
}
private triggerFailed(
options: LoadRemoteModuleOptionsExtended,
error: Error
) {
const event = new RemoteModuleFailed(
options.id,
options,
error);
this._events.next(event);
}
}