@ama-mfe/ng-utils 12.1.0-prerelease.80 → 12.1.0-prerelease.81

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 (2) hide show
  1. package/README.md +260 -2
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -1,3 +1,261 @@
1
- # Ama mfe angular utils
1
+ # Ama MFE Angular Utils
2
+ `@ama-mfe/ng-utils` is an Angular library designed to streamline communication within a micro-frontend architecture that
3
+ uses iframes.
4
+ This package is built on the [Amadeus Toolkit for Micro Frontends framework](https://www.npmjs.com/package/@amadeus-it-group/microfrontends-angular)
5
+ and offers a suite of tools - including helpers, wrappers, and services - to facilitate seamless integration and
6
+ interaction between host and embedded applications.
2
7
 
3
- This Angular project includes various helpers, wrappers, and services designed to facilitate communication within a microfrontend architecture based on iframes.
8
+ Key features include:
9
+ - [Connect](https://github.com/AmadeusITGroup/otter/blob/main/packages/%40ama-mfe/ng-utils/src/connect/): Connect to the communication protocol and send messages to registered applications.
10
+ - [Navigation](https://github.com/AmadeusITGroup/otter/blob/main/packages/%40ama-mfe/ng-utils/src/navigation/): Ensures the host application can update its navigation to reflect the embedded application's URL,
11
+ maintaining consistency even after a page refresh.
12
+ - [Theme](https://github.com/AmadeusITGroup/otter/blob/main/packages/%40ama-mfe/ng-utils/src/theme/): Allows the application of unified CSS variables and styles across embedded modules, ensuring a cohesive
13
+ look and feel.
14
+ - [Resize](https://github.com/AmadeusITGroup/otter/blob/main/packages/%40ama-mfe/ng-utils/src/resize/): Dynamically adjusts the iframe dimensions to fit the content of the embedded application, enhancing the
15
+ user experience.
16
+
17
+ ## Installation
18
+ To install the package, run:
19
+
20
+ ```bash
21
+ npm exec ng add @ama-mfe/ng-utils
22
+ ```
23
+
24
+ ## Consumer and Producer
25
+ In the communication protocol, a message is created by a `Producer` and sent to a `Consumer` which will read the message
26
+ and react according to its content.
27
+
28
+ The `@ama-mfe/ng-utils` package exposes a set of features based on messages exchanged between a host application and its
29
+ embedded module. For each feature, the package provides a `Producer`/`Consumer` pair.
30
+ The former service is in charge of delivering the messages based on triggers (resize event, call to a public function
31
+ etc.) while the latter implements the logic behind the feature (resizing of the iframe, application of a theme, etc.).
32
+
33
+ ## How to use
34
+ ### Connection to the communication service
35
+ #### Configure your application connection
36
+ Applications first need to provide and configure the `ConnectionService` to use the communication protocol.
37
+ The `provideConnection` method allows an application to register with a unique ID that others will use to
38
+ connect and target the application.
39
+
40
+ ```typescript
41
+ import {provideConnection} from '@ama-mfe/ng-utils';
42
+
43
+ export const appConfig: ApplicationConfig = {
44
+ providers: [
45
+ provideConnection({
46
+ id: 'applicationUniqueID'
47
+ })
48
+ ]
49
+ };
50
+ ```
51
+
52
+ #### Initiate the communication with the host application
53
+ An application embedded into another one can connect to its host using the [ConnectionService].
54
+ To establish the connection, the embedded application requires the host application id (set via the
55
+ [connection service's provider](#configure-your-application-connection)).
56
+
57
+ ```typescript
58
+ // main.ts
59
+ import {inject, runInInjectionContext} from '@angular/core';
60
+ import {bootstrapApplication} from '@angular/platform-browser';
61
+ import {ConnectionService, NavigationConsumerService} from '@ama-mfe/ng-utils';
62
+
63
+ bootstrapApplication(AppComponent, appConfig)
64
+ .then((m) => {
65
+ runInInjectionContext(m.injector, () => {
66
+ if (window.top !== window.self) {
67
+ // If embedded in an iframe, connect to the host
68
+ inject(ConnectionService).connect('hostUniqueID');
69
+ }
70
+ // Other injections
71
+ })
72
+ });
73
+ ```
74
+
75
+ #### Initiate the connection to your embedded module
76
+ Use the `connect` directive to initiate the communication between your application and the module in the iframe.
77
+ The communication pipe will be closed once the iframe is destroyed.
78
+
79
+ ```html
80
+ <iframe [src]='myModuleUrl'
81
+ [connect]='myModuleUniqueID'>
82
+ </iframe>
83
+ ```
84
+ In this example, `myModuleUniqueID` refers to the id provided in the `provideConnection` method.
85
+
86
+ ### Enable a message-based feature
87
+ To use a feature based on the message communication protocol, you need first to identify if your application will be a
88
+ user of the message (`Consumer`) or the one sending the message (`Producer`).
89
+ This may depend on the context and the type of message. For instance, an application can be the consumer of navigation
90
+ messages but the producer of theme messages.
91
+
92
+ #### Consumers
93
+ If you are a consumer of the message, call the `start` and `stop` methods to respectively enable and disable the feature.
94
+
95
+ ```typescript
96
+ import {Component, inject} from '@angular/core';
97
+ import {NavigationConsumerService} from '@ama-mfe/ng-utils';
98
+ import {ThemeConsumerService} from "./theme.consumer.service";
99
+
100
+ @Component({
101
+ selector: 'app-example-module',
102
+ template: './example-module.template.html',
103
+ styleUrl: './example-module.style.scss',
104
+ })
105
+ export class ExampleModuleComponent {
106
+ private readonly navigationConsumerService = inject(NavigationConsumerService);
107
+
108
+ constructor() {
109
+ this.navigationConsumerService.start();
110
+ }
111
+
112
+ ngOnDestroy() {
113
+ this.navigationConsumerService.stop()
114
+ }
115
+ }
116
+ ```
117
+
118
+ Depending on your use case, you might need to start the service as soon as your application start running.
119
+ In this case, you may inject it in the `main.ts`:
120
+
121
+ ```typescript
122
+ // main.ts
123
+ import {inject, runInInjectionContext} from '@angular/core';
124
+ import {bootstrapApplication} from '@angular/platform-browser';
125
+ import {ConnectionService, ThemeConsumerService} from '@ama-mfe/ng-utils';
126
+
127
+ bootstrapApplication(AppComponent, appConfig)
128
+ .then((m) => {
129
+ runInInjectionContext(m.injector, () => {
130
+ if (window.top !== window.self) {
131
+ // If embedded in an iframe, connect to the host
132
+ inject(ConnectionService).connect('hostUniqueID');
133
+ // Start the service to consume messages
134
+ inject(ThemeConsumerService).start();
135
+ }
136
+ // Other injections
137
+ })
138
+ });
139
+ ```
140
+
141
+ #### Producers
142
+ If your application is a producer, just inject the message producer service and call the trigger when needed.
143
+ There is no standardization on the name of the methods used to trigger a message. It will be different for each service.
144
+
145
+ #### Services provided in @ama-mfe/ng-utils
146
+ You will find more information for each service in their respective `README.md`:
147
+ - [Navigation](https://github.com/AmadeusITGroup/otter/tree/main/packages/%40ama-mfe/ng-utils/src/navigation/README.md)
148
+ - [Resize](https://github.com/AmadeusITGroup/otter/tree/main/packages/%40ama-mfe/ng-utils/src/resize/README.md)
149
+ - [Theme](https://github.com/AmadeusITGroup/otter/tree/main/packages/%40ama-mfe/ng-utils/src/theme/README.md)
150
+
151
+ ### Write your own producer and consumers.
152
+ Use the `ProducerManagerService` and the `ConsumerManagerService` to support your own custom messages.
153
+
154
+ A message should be identified by its type and a version to allow different message versions between the host and the
155
+ embedded applications (and avoid migration issues).
156
+
157
+ ```typescript
158
+ import type {Message} from '@amadeus-it-group/microfrontends';
159
+
160
+ export interface CustomMessageV1_0 extends Message {
161
+ type: 'custom',
162
+ version: '1.0',
163
+ // Custom properties
164
+ customPayload: any
165
+ }
166
+ // Use union type here to add all the future version
167
+ // For example CustomMessage = CustomMessageV1_0 | CustomMessagev2_0
168
+ export type CustomMessageVersions = CustomMessageV1_0;
169
+ ```
170
+
171
+ #### Consumer
172
+ A consumer should implement the `MessageConsumer` interface and inject the `ConsumeManagerService` which handles the
173
+ registration to the communication protocol.
174
+ It should list the supported versions and map its callback function in a `supportedVersions` public object.
175
+
176
+ ```typescript
177
+ import type {CustomMessageV1_0, CustomMessageVersions} from '@ama-mfe/messages';
178
+ import type {RoutedMessage} from '@amadeus-it-group/microfrontends';
179
+ import {DestroyRef, inject, Injectable} from '@angular/core';
180
+ import {ConsumerManagerService, type MessageConsumer} from '@ama-mfe/ng-utils';
181
+
182
+ @Injectable({
183
+ providedIn: 'root'
184
+ })
185
+ export class CustomConsumerService implements MessageConsumer<CustomMessageVersions> {
186
+ /**
187
+ * The type of messages this service handles ('custom').
188
+ */
189
+ public readonly type = 'custom';
190
+
191
+ /**
192
+ * The supported versions of theme messages and their handlers.
193
+ */
194
+ public readonly supportedVersions = {
195
+ '1.0': (message: RoutedMessage<CustomMessageV1_0>) => console.log('Do some stuff with this message version', message)
196
+ };
197
+
198
+ private readonly consumerManagerService = inject(ConsumerManagerService);
199
+
200
+ constructor() {
201
+ this.start();
202
+ inject(DestroyRef).onDestroy(() => this.stop());
203
+ }
204
+
205
+ /**
206
+ * Starts the theme handler service by registering it into the consumer manager service.
207
+ */
208
+ public start() {
209
+ this.consumerManagerService.register(this);
210
+ }
211
+
212
+ /**
213
+ * Stops the theme handler service by unregistering it from the consumer manager service.
214
+ */
215
+ public stop() {
216
+ this.consumerManagerService.unregister(this);
217
+ }
218
+ }
219
+ ```
220
+
221
+ #### Producer
222
+ A producer should implement the `MessageProducer` interface and inject the `ProducerManagerService` which handles the
223
+ registration to the communication protocol.
224
+ Once connected, it is able to send messages via the `MessagePeerService`.
225
+
226
+ ```typescript
227
+ import type {CustomMessageV1_0, CustomMessageVersions} from '../messages';
228
+ import {MessagePeerService} from '@amadeus-it-group/microfrontends-angular';
229
+ import {DestroyRef, inject, Injectable} from '@angular/core';
230
+ import {type MessageProducer, type ErrorContent, ProducerManagerService} from '@ama-mfe/ng-utils';
231
+
232
+ @Injectable({
233
+ providedIn: 'root'
234
+ })
235
+ export class CustomService implements MessageProducer<CustomMessageVersions> {
236
+ private readonly messageService = inject(MessagePeerService<CustomMessageVersions>);
237
+
238
+ constructor() {
239
+ const producerManagerService = inject(ProducerManagerService);
240
+ producerManagerService.register(this);
241
+
242
+ inject(DestroyRef).onDestroy(() => {
243
+ producerManagerService.unregister(this);
244
+ });
245
+ }
246
+
247
+ public handleError(message: ErrorContent<CustomMessage_V1_0>): void {
248
+ // If available, use your own logger
249
+ console.error('Error in custom service message', message);
250
+ }
251
+
252
+ public postMessageAction(payload: any): void {
253
+ const messageV10 = {
254
+ type: 'custom',
255
+ version: '1.0',
256
+ customPayload: 'test'
257
+ } satisfies CustomMessageV1_0;
258
+ this.messageService.send(messageV10);
259
+ }
260
+ }
261
+ ```
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@ama-mfe/ng-utils",
3
- "version": "12.1.0-prerelease.80",
3
+ "version": "12.1.0-prerelease.81",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
7
  "peerDependencies": {
8
- "@ama-mfe/messages": "^12.1.0-prerelease.80",
8
+ "@ama-mfe/messages": "^12.1.0-prerelease.81",
9
9
  "@amadeus-it-group/microfrontends": "0.x.x",
10
10
  "@amadeus-it-group/microfrontends-angular": "0.x.x",
11
11
  "@angular-devkit/core": "~19.2.0",
@@ -14,7 +14,7 @@
14
14
  "@angular/core": "^19.0.0",
15
15
  "@angular/platform-browser": "~19.2.0",
16
16
  "@angular/router": "~19.2.0",
17
- "@o3r/schematics": "^12.1.0-prerelease.80",
17
+ "@o3r/schematics": "^12.1.0-prerelease.81",
18
18
  "rxjs": "^7.8.1"
19
19
  },
20
20
  "dependencies": {