@ama-mfe/ng-utils 13.3.0-prerelease.6 → 13.3.0-rc.3

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.
@@ -1,13 +1,76 @@
1
1
  import { MessagePeerService, MESSAGE_PEER_CONFIG, MESSAGE_PEER_CONNECT_OPTIONS } from '@amadeus-it-group/microfrontends-angular';
2
2
  export { MessagePeerService as ConnectionService } from '@amadeus-it-group/microfrontends-angular';
3
3
  import * as i0 from '@angular/core';
4
- import { Injectable, inject, signal, effect, DestroyRef, afterNextRender, input, computed, ElementRef, Renderer2, Directive, SecurityContext, Pipe, untracked, HostBinding, provideAppInitializer, makeEnvironmentProviders } from '@angular/core';
5
- import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
4
+ import { input, inject, ElementRef, computed, SecurityContext, effect, HostBinding, Directive, Injectable, signal, DestroyRef, provideAppInitializer, Pipe, makeEnvironmentProviders, untracked, afterNextRender, Renderer2 } from '@angular/core';
5
+ import { DomSanitizer } from '@angular/platform-browser';
6
6
  import { LoggerService } from '@o3r/logger';
7
- import { RESIZE_MESSAGE_TYPE, NAVIGATION_MESSAGE_TYPE, THEME_MESSAGE_TYPE } from '@ama-mfe/messages';
7
+ import { HISTORY_MESSAGE_TYPE, NAVIGATION_MESSAGE_TYPE, RESIZE_MESSAGE_TYPE, THEME_MESSAGE_TYPE } from '@ama-mfe/messages';
8
+ import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
8
9
  import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
9
10
  import { Subject, filter, map } from 'rxjs';
10
- import { DomSanitizer } from '@angular/platform-browser';
11
+
12
+ class ConnectDirective {
13
+ /**
14
+ * Binds the `src` attribute of the iframe to the sanitized source URL.
15
+ */
16
+ get srcAttr() {
17
+ return this.src();
18
+ }
19
+ constructor() {
20
+ /**
21
+ * The connection ID required for the message peer service.
22
+ */
23
+ this.connect = input.required(...(ngDevMode ? [{ debugName: "connect" }] : []));
24
+ /**
25
+ * The sanitized source URL for the iframe.
26
+ */
27
+ this.src = input(...(ngDevMode ? [undefined, { debugName: "src" }] : []));
28
+ this.messageService = inject(MessagePeerService);
29
+ this.domSanitizer = inject(DomSanitizer);
30
+ this.iframeElement = inject(ElementRef).nativeElement;
31
+ this.clientOrigin = computed(() => {
32
+ const src = this.src();
33
+ const srcString = src && this.domSanitizer.sanitize(SecurityContext.RESOURCE_URL, src);
34
+ return srcString && new URL(srcString).origin;
35
+ }, ...(ngDevMode ? [{ debugName: "clientOrigin" }] : []));
36
+ const logger = inject(LoggerService);
37
+ // When the origin or connection ID change - reconnect the message service
38
+ effect((onCleanup) => {
39
+ let stopHandshakeListening = () => { };
40
+ const origin = this.clientOrigin();
41
+ const id = this.connect();
42
+ const source = this.iframeElement.contentWindow;
43
+ // listen for handshakes only if we know the origin and were given a connection ID
44
+ if (origin && source && id) {
45
+ try {
46
+ stopHandshakeListening = this.messageService.listen({ id, source, origin });
47
+ }
48
+ catch (e) {
49
+ logger.error(`Failed to start listening for (connection ID: ${id})`, e);
50
+ }
51
+ }
52
+ // stop listening for handshakes and disconnect previous connection when:
53
+ // - origin/connection ID change
54
+ // - the directive is destroyed
55
+ onCleanup(() => {
56
+ stopHandshakeListening();
57
+ this.messageService.disconnect();
58
+ });
59
+ });
60
+ }
61
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ConnectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
62
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.7", type: ConnectDirective, isStandalone: true, selector: "iframe[connect]", inputs: { connect: { classPropertyName: "connect", publicName: "connect", isSignal: true, isRequired: true, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "src": "this.srcAttr" } }, ngImport: i0 }); }
63
+ }
64
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ConnectDirective, decorators: [{
65
+ type: Directive,
66
+ args: [{
67
+ selector: 'iframe[connect]',
68
+ standalone: true
69
+ }]
70
+ }], ctorParameters: () => [], propDecorators: { connect: [{ type: i0.Input, args: [{ isSignal: true, alias: "connect", required: true }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], srcAttr: [{
71
+ type: HostBinding,
72
+ args: ['src']
73
+ }] } });
11
74
 
12
75
  /**
13
76
  * Gets the available consumers and formats them into a {@see DeclareMessages} object.
@@ -80,10 +143,10 @@ class ProducerManagerService {
80
143
  }
81
144
  return handlersPresent;
82
145
  }
83
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ProducerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
84
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ProducerManagerService, providedIn: 'root' }); }
146
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ProducerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
147
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ProducerManagerService, providedIn: 'root' }); }
85
148
  }
86
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ProducerManagerService, decorators: [{
149
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ProducerManagerService, decorators: [{
87
150
  type: Injectable,
88
151
  args: [{
89
152
  providedIn: 'root'
@@ -175,10 +238,10 @@ class ConsumerManagerService {
175
238
  return consumers.filter((c) => c !== consumer);
176
239
  });
177
240
  }
178
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConsumerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
179
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConsumerManagerService, providedIn: 'root' }); }
241
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ConsumerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
242
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ConsumerManagerService, providedIn: 'root' }); }
180
243
  }
181
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConsumerManagerService, decorators: [{
244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ConsumerManagerService, decorators: [{
182
245
  type: Injectable,
183
246
  args: [{
184
247
  providedIn: 'root'
@@ -210,53 +273,49 @@ const registerConsumer = (consumer) => {
210
273
  });
211
274
  };
212
275
 
213
- /** the error message type */
214
- const ERROR_MESSAGE_TYPE = 'error';
215
-
216
276
  /**
217
- * This service listens for resize messages and updates the height of elements based on the received messages.
277
+ * A service that handles history messages.
278
+ *
279
+ * This service listens for history messages and navigates accordingly.
218
280
  */
219
- class ResizeConsumerService {
281
+ class HistoryConsumerService {
220
282
  constructor() {
221
- this.newHeight = signal(undefined, ...(ngDevMode ? [{ debugName: "newHeight" }] : []));
222
- /**
223
- * A readonly signal that provides the new height information from the channel.
224
- */
225
- this.newHeightFromChannel = this.newHeight.asReadonly();
226
283
  /**
227
- * The type of messages this service handles ('resize').
284
+ * The type of messages this service handles.
228
285
  */
229
- this.type = RESIZE_MESSAGE_TYPE;
286
+ this.type = HISTORY_MESSAGE_TYPE;
230
287
  /**
231
- * The supported versions of resize messages and their handlers.
288
+ * @inheritdoc
232
289
  */
233
290
  this.supportedVersions = {
234
291
  /**
235
- * Use the message paylod to compute a new height and emit it via the public signal
292
+ * Use the message payload to navigate in the history
236
293
  * @param message message to consume
237
294
  */
238
- '1.0': (message) => this.newHeight.set({ height: message.payload.height, channelId: message.from })
295
+ '1.0': (message) => {
296
+ history.go(message.payload.delta);
297
+ }
239
298
  };
240
299
  this.consumerManagerService = inject(ConsumerManagerService);
241
300
  this.start();
242
301
  inject(DestroyRef).onDestroy(() => this.stop());
243
302
  }
244
303
  /**
245
- * Starts the resize handler service by registering it into the consumer manager service.
304
+ * @inheritdoc
246
305
  */
247
306
  start() {
248
307
  this.consumerManagerService.register(this);
249
308
  }
250
309
  /**
251
- * Stops the resize handler service by unregistering it from the consumer manager service.
310
+ * @inheritdoc
252
311
  */
253
312
  stop() {
254
313
  this.consumerManagerService.unregister(this);
255
314
  }
256
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ResizeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
257
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ResizeConsumerService, providedIn: 'root' }); }
315
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: HistoryConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
316
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: HistoryConsumerService, providedIn: 'root' }); }
258
317
  }
259
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ResizeConsumerService, decorators: [{
318
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: HistoryConsumerService, decorators: [{
260
319
  type: Injectable,
261
320
  args: [{
262
321
  providedIn: 'root'
@@ -264,102 +323,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
264
323
  }], ctorParameters: () => [] });
265
324
 
266
325
  /**
267
- * This service observe changes in the document's body height.
268
- * When the height changes, it sends a resize message with the new height, to the connected peers
326
+ * Provides necessary overrides to make the module navigation in history work in an embedded context :
327
+ * - Prevent pushing states to history, replace state instead
328
+ * - Handle history navigation via History messages to let the host manage the states
269
329
  */
270
- class ResizeService {
271
- constructor() {
272
- this.messageService = inject((MessagePeerService));
273
- /**
274
- * @inheritdoc
275
- */
276
- this.types = RESIZE_MESSAGE_TYPE;
277
- registerProducer(this);
278
- }
279
- /**
280
- * @inheritdoc
281
- */
282
- handleError(message) {
283
- // eslint-disable-next-line no-console -- error handling placeholder
284
- console.error('Error in resize service message', message);
285
- }
286
- /**
287
- * This method sets up a `ResizeObserver` to observe changes in the document's body height.
288
- * When the height changes, it sends a resize message with the new height, to the connected peers
289
- */
290
- startResizeObserver() {
291
- this.resizeObserver = new ResizeObserver(() => {
292
- const newHeight = document.body.getBoundingClientRect().height;
293
- if (!this.actualHeight || newHeight !== this.actualHeight) {
294
- this.actualHeight = newHeight;
295
- const messageV10 = {
296
- type: 'resize',
297
- version: '1.0',
298
- height: this.actualHeight
299
- };
300
- // TODO: sendBest() is not implemented -- https://github.com/AmadeusITGroup/microfrontends/issues/11
301
- this.messageService.send(messageV10);
302
- }
330
+ function provideHistoryOverrides() {
331
+ return provideAppInitializer(() => {
332
+ const messageService = inject((MessagePeerService));
333
+ const navigate = (delta) => {
334
+ messageService.send({
335
+ type: 'history',
336
+ version: '1.0',
337
+ delta
338
+ });
339
+ };
340
+ Object.defineProperty(history, 'pushState', {
341
+ value: (data, unused, url) => {
342
+ history.replaceState(data, unused, url);
343
+ },
344
+ writable: false,
345
+ configurable: false
303
346
  });
304
- afterNextRender(() => this.resizeObserver?.observe(document.body));
305
- }
306
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ResizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
307
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ResizeService, providedIn: 'root' }); }
308
- }
309
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ResizeService, decorators: [{
310
- type: Injectable,
311
- args: [{
312
- providedIn: 'root'
313
- }]
314
- }], ctorParameters: () => [] });
315
-
316
- /**
317
- * A directive that adjusts the height of an element based on resize messages from a specified channel.
318
- */
319
- class ScalableDirective {
320
- constructor() {
321
- /**
322
- * The connection ID for the element, used as channel id backup
323
- */
324
- this.connect = input(...(ngDevMode ? [undefined, { debugName: "connect" }] : []));
325
- /**
326
- * The channel id
327
- */
328
- this.scalable = input(...(ngDevMode ? [undefined, { debugName: "scalable" }] : []));
329
- this.resizeHandler = inject(ResizeConsumerService);
330
- /**
331
- * This signal checks if the current channel requesting the resize matches the channel ID from the resize handler.
332
- * If they match, it returns the new height information; otherwise, it returns undefined.
333
- */
334
- this.newHeightFromChannel = computed(() => {
335
- const channelAskingResize = this.scalable() || this.connect();
336
- const newHeightFromChannel = this.resizeHandler.newHeightFromChannel();
337
- if (channelAskingResize && newHeightFromChannel?.channelId === channelAskingResize) {
338
- return newHeightFromChannel;
339
- }
340
- return undefined;
341
- }, ...(ngDevMode ? [{ debugName: "newHeightFromChannel" }] : []));
342
- const elem = inject(ElementRef);
343
- const renderer = inject(Renderer2);
344
- this.resizeHandler.start();
345
- /** When a new height value is received set the height of the host element (in pixels) */
346
- effect(() => {
347
- const newHeightFromChannel = this.newHeightFromChannel();
348
- if (newHeightFromChannel) {
349
- renderer.setStyle(elem.nativeElement, 'height', `${newHeightFromChannel.height}px`);
350
- }
347
+ Object.defineProperty(history, 'back', {
348
+ value: () => navigate(-1),
349
+ writable: false,
350
+ configurable: false
351
351
  });
352
- }
353
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ScalableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
354
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.4", type: ScalableDirective, isStandalone: true, selector: "[scalable]", inputs: { connect: { classPropertyName: "connect", publicName: "connect", isSignal: true, isRequired: false, transformFunction: null }, scalable: { classPropertyName: "scalable", publicName: "scalable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
352
+ Object.defineProperty(history, 'forward', {
353
+ value: () => navigate(1),
354
+ writable: false,
355
+ configurable: false
356
+ });
357
+ Object.defineProperty(history, 'go', {
358
+ value: (delta) => navigate(delta),
359
+ writable: false,
360
+ configurable: false
361
+ });
362
+ });
355
363
  }
356
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ScalableDirective, decorators: [{
357
- type: Directive,
358
- args: [{
359
- selector: '[scalable]',
360
- standalone: true
361
- }]
362
- }], ctorParameters: () => [] });
363
364
 
364
365
  const SESSION_STORAGE_KEY = 'ama-mfe-host-info';
365
366
  /**
@@ -429,16 +430,80 @@ class HostInfoPipe {
429
430
  return typeof url === 'string' ? moduleUrlStringyfied : this.domSanitizer.bypassSecurityTrustResourceUrl(moduleUrlStringyfied);
430
431
  }
431
432
  }
432
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: HostInfoPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
433
- /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.4", ngImport: i0, type: HostInfoPipe, isStandalone: true, name: "hostInfo" }); }
433
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: HostInfoPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
434
+ /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.7", ngImport: i0, type: HostInfoPipe, isStandalone: true, name: "hostInfo" }); }
434
435
  }
435
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: HostInfoPipe, decorators: [{
436
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: HostInfoPipe, decorators: [{
436
437
  type: Pipe,
437
438
  args: [{
438
439
  name: 'hostInfo'
439
440
  }]
440
441
  }] });
441
442
 
443
+ /** the error message type */
444
+ const ERROR_MESSAGE_TYPE = 'error';
445
+
446
+ /**
447
+ * A constant array of known message types and their versions.
448
+ */
449
+ const KNOWN_MESSAGES = [
450
+ {
451
+ type: ERROR_MESSAGE_TYPE,
452
+ version: '1.0'
453
+ }
454
+ ];
455
+ /**
456
+ * Returns the default options for starting a client endpoint peer connection.
457
+ * As `origin`, it will take the hostURL from {@link getHostInfo} and the `window` will be the parent window.
458
+ */
459
+ function getDefaultClientEndpointStartOptions() {
460
+ const hostInfo = getHostInfo();
461
+ if (hostInfo.hostURL) {
462
+ return {
463
+ origin: new URL(hostInfo.hostURL).origin,
464
+ window: window.parent
465
+ };
466
+ }
467
+ return {};
468
+ }
469
+ /**
470
+ * Return `true` if embedded inside an iframe, `false` otherwise
471
+ */
472
+ function isEmbedded() {
473
+ return window.top !== window.self;
474
+ }
475
+
476
+ /**
477
+ * Provide the communication protocol connection configuration
478
+ * @param connectionConfigOptions The identifier of the application in the communication protocol ecosystem plus the types of messages able to exchange and a logger object
479
+ */
480
+ function provideConnection(connectionConfigOptions) {
481
+ persistHostInfo();
482
+ const connectionId = (isEmbedded() && getHostInfo().moduleApplicationId) || connectionConfigOptions?.id;
483
+ if (!connectionId) {
484
+ (connectionConfigOptions?.logger || console).error('An id (moduleId) needs to be provided for the application in order to establish a connection inside the communication protocol');
485
+ return makeEnvironmentProviders([]);
486
+ }
487
+ const config = {
488
+ id: connectionId,
489
+ messageCheckStrategy: 'version',
490
+ knownMessages: [...KNOWN_MESSAGES, ...(connectionConfigOptions?.knownMessages || [])]
491
+ };
492
+ return makeEnvironmentProviders([
493
+ {
494
+ provide: MESSAGE_PEER_CONFIG, useValue: config
495
+ },
496
+ {
497
+ provide: MESSAGE_PEER_CONNECT_OPTIONS, useValue: getDefaultClientEndpointStartOptions()
498
+ },
499
+ {
500
+ // in the case of the ConnectionService will extend the base service 'useExisting' should be used
501
+ provide: MessagePeerService, useClass: MessagePeerService, deps: [MESSAGE_PEER_CONFIG]
502
+ },
503
+ ...isEmbedded() ? [provideHistoryOverrides()] : []
504
+ ]);
505
+ }
506
+
442
507
  /**
443
508
  * A service that handles navigation messages and routing.
444
509
  *
@@ -509,10 +574,10 @@ class NavigationConsumerService {
509
574
  stop() {
510
575
  this.consumerManagerService.unregister(this);
511
576
  }
512
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: NavigationConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
513
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: NavigationConsumerService, providedIn: 'root' }); }
577
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: NavigationConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
578
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: NavigationConsumerService, providedIn: 'root' }); }
514
579
  }
515
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: NavigationConsumerService, decorators: [{
580
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: NavigationConsumerService, decorators: [{
516
581
  type: Injectable,
517
582
  args: [{
518
583
  providedIn: 'root'
@@ -555,10 +620,10 @@ class RouteMemorizeService {
555
620
  getRoute(channelId) {
556
621
  return this.routeStack[channelId];
557
622
  }
558
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RouteMemorizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
559
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RouteMemorizeService, providedIn: 'root' }); }
623
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RouteMemorizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
624
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RouteMemorizeService, providedIn: 'root' }); }
560
625
  }
561
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RouteMemorizeService, decorators: [{
626
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RouteMemorizeService, decorators: [{
562
627
  type: Injectable,
563
628
  args: [{
564
629
  providedIn: 'root'
@@ -605,52 +670,23 @@ class RouteMemorizeDirective {
605
670
  return;
606
671
  }
607
672
  const requested = requestedUrlSignal();
608
- const id = this.memorizeRouteId() || this.connect();
609
- if (requested && id && requested.channelId === id) {
673
+ const channelId = this.connect();
674
+ const id = this.memorizeRouteId() || channelId;
675
+ if (requested && id && requested.channelId === channelId) {
610
676
  memory.memorizeRoute(id, requested.url, untracked(this.maxAge));
611
677
  }
612
678
  });
613
679
  }
614
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RouteMemorizeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
615
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.4", type: RouteMemorizeDirective, isStandalone: true, selector: "iframe[memorizeRoute]", inputs: { memorizeRoute: { classPropertyName: "memorizeRoute", publicName: "memorizeRoute", isSignal: true, isRequired: false, transformFunction: null }, memorizeRouteId: { classPropertyName: "memorizeRouteId", publicName: "memorizeRouteId", isSignal: true, isRequired: false, transformFunction: null }, memorizeMaxAge: { classPropertyName: "memorizeMaxAge", publicName: "memorizeMaxAge", isSignal: true, isRequired: false, transformFunction: null }, memorizeRouteMaxAge: { classPropertyName: "memorizeRouteMaxAge", publicName: "memorizeRouteMaxAge", isSignal: true, isRequired: false, transformFunction: null }, connect: { classPropertyName: "connect", publicName: "connect", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
680
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RouteMemorizeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
681
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.7", type: RouteMemorizeDirective, isStandalone: true, selector: "iframe[memorizeRoute]", inputs: { memorizeRoute: { classPropertyName: "memorizeRoute", publicName: "memorizeRoute", isSignal: true, isRequired: false, transformFunction: null }, memorizeRouteId: { classPropertyName: "memorizeRouteId", publicName: "memorizeRouteId", isSignal: true, isRequired: false, transformFunction: null }, memorizeMaxAge: { classPropertyName: "memorizeMaxAge", publicName: "memorizeMaxAge", isSignal: true, isRequired: false, transformFunction: null }, memorizeRouteMaxAge: { classPropertyName: "memorizeRouteMaxAge", publicName: "memorizeRouteMaxAge", isSignal: true, isRequired: false, transformFunction: null }, connect: { classPropertyName: "connect", publicName: "connect", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
616
682
  }
617
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RouteMemorizeDirective, decorators: [{
683
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RouteMemorizeDirective, decorators: [{
618
684
  type: Directive,
619
685
  args: [{
620
686
  selector: 'iframe[memorizeRoute]',
621
687
  standalone: true
622
688
  }]
623
- }], ctorParameters: () => [] });
624
-
625
- /**
626
- * A constant array of known message types and their versions.
627
- */
628
- const KNOWN_MESSAGES = [
629
- {
630
- type: ERROR_MESSAGE_TYPE,
631
- version: '1.0'
632
- }
633
- ];
634
- /**
635
- * Returns the default options for starting a client endpoint peer connection.
636
- * As `origin`, it will take the hostURL from {@link getHostInfo} and the `window` will be the parent window.
637
- */
638
- function getDefaultClientEndpointStartOptions() {
639
- const hostInfo = getHostInfo();
640
- if (hostInfo.hostURL) {
641
- return {
642
- origin: new URL(hostInfo.hostURL).origin,
643
- window: window.parent
644
- };
645
- }
646
- return {};
647
- }
648
- /**
649
- * Return `true` if embedded inside an iframe, `false` otherwise
650
- */
651
- function isEmbedded() {
652
- return window.top !== window.self;
653
- }
689
+ }], ctorParameters: () => [], propDecorators: { memorizeRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "memorizeRoute", required: false }] }], memorizeRouteId: [{ type: i0.Input, args: [{ isSignal: true, alias: "memorizeRouteId", required: false }] }], memorizeMaxAge: [{ type: i0.Input, args: [{ isSignal: true, alias: "memorizeMaxAge", required: false }] }], memorizeRouteMaxAge: [{ type: i0.Input, args: [{ isSignal: true, alias: "memorizeRouteMaxAge", required: false }] }], connect: [{ type: i0.Input, args: [{ isSignal: true, alias: "connect", required: false }] }] } });
654
690
 
655
691
  /**
656
692
  * A service that keeps in sync Router navigation and navigation messages.
@@ -735,10 +771,10 @@ class RoutingService {
735
771
  }
736
772
  });
737
773
  }
738
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RoutingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
739
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RoutingService, providedIn: 'root' }); }
774
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RoutingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
775
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RoutingService, providedIn: 'root' }); }
740
776
  }
741
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RoutingService, decorators: [{
777
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RoutingService, decorators: [{
742
778
  type: Injectable,
743
779
  args: [{
744
780
  providedIn: 'root'
@@ -785,16 +821,164 @@ class RestoreRoute {
785
821
  return typeof url === 'string' ? moduleUrlStringyfied : this.domSanitizer.bypassSecurityTrustResourceUrl(moduleUrlStringyfied);
786
822
  }
787
823
  }
788
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RestoreRoute, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
789
- /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.4", ngImport: i0, type: RestoreRoute, isStandalone: true, name: "restoreRoute" }); }
824
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RestoreRoute, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
825
+ /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.7", ngImport: i0, type: RestoreRoute, isStandalone: true, name: "restoreRoute" }); }
790
826
  }
791
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RestoreRoute, decorators: [{
827
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: RestoreRoute, decorators: [{
792
828
  type: Pipe,
793
829
  args: [{
794
830
  name: 'restoreRoute'
795
831
  }]
796
832
  }] });
797
833
 
834
+ /**
835
+ * This service listens for resize messages and updates the height of elements based on the received messages.
836
+ */
837
+ class ResizeConsumerService {
838
+ constructor() {
839
+ this.newHeight = signal(undefined, ...(ngDevMode ? [{ debugName: "newHeight" }] : []));
840
+ /**
841
+ * A readonly signal that provides the new height information from the channel.
842
+ */
843
+ this.newHeightFromChannel = this.newHeight.asReadonly();
844
+ /**
845
+ * The type of messages this service handles ('resize').
846
+ */
847
+ this.type = RESIZE_MESSAGE_TYPE;
848
+ /**
849
+ * The supported versions of resize messages and their handlers.
850
+ */
851
+ this.supportedVersions = {
852
+ /**
853
+ * Use the message paylod to compute a new height and emit it via the public signal
854
+ * @param message message to consume
855
+ */
856
+ '1.0': (message) => this.newHeight.set({ height: message.payload.height, channelId: message.from })
857
+ };
858
+ this.consumerManagerService = inject(ConsumerManagerService);
859
+ this.start();
860
+ inject(DestroyRef).onDestroy(() => this.stop());
861
+ }
862
+ /**
863
+ * Starts the resize handler service by registering it into the consumer manager service.
864
+ */
865
+ start() {
866
+ this.consumerManagerService.register(this);
867
+ }
868
+ /**
869
+ * Stops the resize handler service by unregistering it from the consumer manager service.
870
+ */
871
+ stop() {
872
+ this.consumerManagerService.unregister(this);
873
+ }
874
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ResizeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
875
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ResizeConsumerService, providedIn: 'root' }); }
876
+ }
877
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ResizeConsumerService, decorators: [{
878
+ type: Injectable,
879
+ args: [{
880
+ providedIn: 'root'
881
+ }]
882
+ }], ctorParameters: () => [] });
883
+
884
+ /**
885
+ * This service observe changes in the document's body height.
886
+ * When the height changes, it sends a resize message with the new height, to the connected peers
887
+ */
888
+ class ResizeService {
889
+ constructor() {
890
+ this.messageService = inject((MessagePeerService));
891
+ /**
892
+ * @inheritdoc
893
+ */
894
+ this.types = RESIZE_MESSAGE_TYPE;
895
+ registerProducer(this);
896
+ }
897
+ /**
898
+ * @inheritdoc
899
+ */
900
+ handleError(message) {
901
+ // eslint-disable-next-line no-console -- error handling placeholder
902
+ console.error('Error in resize service message', message);
903
+ }
904
+ /**
905
+ * This method sets up a `ResizeObserver` to observe changes in the document's body height.
906
+ * When the height changes, it sends a resize message with the new height, to the connected peers
907
+ */
908
+ startResizeObserver() {
909
+ this.resizeObserver = new ResizeObserver(() => {
910
+ const newHeight = document.body.getBoundingClientRect().height;
911
+ if (!this.actualHeight || newHeight !== this.actualHeight) {
912
+ this.actualHeight = newHeight;
913
+ const messageV10 = {
914
+ type: 'resize',
915
+ version: '1.0',
916
+ height: this.actualHeight
917
+ };
918
+ // TODO: sendBest() is not implemented -- https://github.com/AmadeusITGroup/microfrontends/issues/11
919
+ this.messageService.send(messageV10);
920
+ }
921
+ });
922
+ afterNextRender(() => this.resizeObserver?.observe(document.body));
923
+ }
924
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ResizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
925
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ResizeService, providedIn: 'root' }); }
926
+ }
927
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ResizeService, decorators: [{
928
+ type: Injectable,
929
+ args: [{
930
+ providedIn: 'root'
931
+ }]
932
+ }], ctorParameters: () => [] });
933
+
934
+ /**
935
+ * A directive that adjusts the height of an element based on resize messages from a specified channel.
936
+ */
937
+ class ScalableDirective {
938
+ constructor() {
939
+ /**
940
+ * The connection ID for the element, used as channel id backup
941
+ */
942
+ this.connect = input(...(ngDevMode ? [undefined, { debugName: "connect" }] : []));
943
+ /**
944
+ * The channel id
945
+ */
946
+ this.scalable = input(...(ngDevMode ? [undefined, { debugName: "scalable" }] : []));
947
+ this.resizeHandler = inject(ResizeConsumerService);
948
+ /**
949
+ * This signal checks if the current channel requesting the resize matches the channel ID from the resize handler.
950
+ * If they match, it returns the new height information; otherwise, it returns undefined.
951
+ */
952
+ this.newHeightFromChannel = computed(() => {
953
+ const channelAskingResize = this.scalable() || this.connect();
954
+ const newHeightFromChannel = this.resizeHandler.newHeightFromChannel();
955
+ if (channelAskingResize && newHeightFromChannel?.channelId === channelAskingResize) {
956
+ return newHeightFromChannel;
957
+ }
958
+ return undefined;
959
+ }, ...(ngDevMode ? [{ debugName: "newHeightFromChannel" }] : []));
960
+ const elem = inject(ElementRef);
961
+ const renderer = inject(Renderer2);
962
+ this.resizeHandler.start();
963
+ /** When a new height value is received set the height of the host element (in pixels) */
964
+ effect(() => {
965
+ const newHeightFromChannel = this.newHeightFromChannel();
966
+ if (newHeightFromChannel) {
967
+ renderer.setStyle(elem.nativeElement, 'height', `${newHeightFromChannel.height}px`);
968
+ }
969
+ });
970
+ }
971
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ScalableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
972
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.7", type: ScalableDirective, isStandalone: true, selector: "[scalable]", inputs: { connect: { classPropertyName: "connect", publicName: "connect", isSignal: true, isRequired: false, transformFunction: null }, scalable: { classPropertyName: "scalable", publicName: "scalable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
973
+ }
974
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ScalableDirective, decorators: [{
975
+ type: Directive,
976
+ args: [{
977
+ selector: '[scalable]',
978
+ standalone: true
979
+ }]
980
+ }], ctorParameters: () => [], propDecorators: { connect: [{ type: i0.Input, args: [{ isSignal: true, alias: "connect", required: false }] }], scalable: [{ type: i0.Input, args: [{ isSignal: true, alias: "scalable", required: false }] }] } });
981
+
798
982
  /** Default suffix for an url containing a theme css file */
799
983
  const THEME_URL_SUFFIX = '-theme.css';
800
984
  /** Default name for the query parameter containing the theme name */
@@ -943,10 +1127,10 @@ class ThemeProducerService {
943
1127
  this.logger.error('Error in theme service message', message);
944
1128
  this.revertToPreviousTheme();
945
1129
  }
946
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ThemeProducerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
947
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ThemeProducerService, providedIn: 'root' }); }
1130
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ThemeProducerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1131
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ThemeProducerService, providedIn: 'root' }); }
948
1132
  }
949
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ThemeProducerService, decorators: [{
1133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ThemeProducerService, decorators: [{
950
1134
  type: Injectable,
951
1135
  args: [{
952
1136
  providedIn: 'root'
@@ -979,10 +1163,10 @@ class ApplyTheme {
979
1163
  }
980
1164
  return undefined;
981
1165
  }
982
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ApplyTheme, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
983
- /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.4", ngImport: i0, type: ApplyTheme, isStandalone: true, name: "applyTheme" }); }
1166
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ApplyTheme, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
1167
+ /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.7", ngImport: i0, type: ApplyTheme, isStandalone: true, name: "applyTheme" }); }
984
1168
  }
985
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ApplyTheme, decorators: [{
1169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ApplyTheme, decorators: [{
986
1170
  type: Pipe,
987
1171
  args: [{
988
1172
  name: 'applyTheme'
@@ -1038,132 +1222,19 @@ class ThemeConsumerService {
1038
1222
  stop() {
1039
1223
  this.consumerManagerService.unregister(this);
1040
1224
  }
1041
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ThemeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1042
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ThemeConsumerService, providedIn: 'root' }); }
1225
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ThemeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1226
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ThemeConsumerService, providedIn: 'root' }); }
1043
1227
  }
1044
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ThemeConsumerService, decorators: [{
1228
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ThemeConsumerService, decorators: [{
1045
1229
  type: Injectable,
1046
1230
  args: [{
1047
1231
  providedIn: 'root'
1048
1232
  }]
1049
1233
  }], ctorParameters: () => [] });
1050
1234
 
1051
- class ConnectDirective {
1052
- /**
1053
- * Binds the `src` attribute of the iframe to the sanitized source URL.
1054
- */
1055
- get srcAttr() {
1056
- return this.src();
1057
- }
1058
- constructor() {
1059
- /**
1060
- * The connection ID required for the message peer service.
1061
- */
1062
- this.connect = input.required(...(ngDevMode ? [{ debugName: "connect" }] : []));
1063
- /**
1064
- * The sanitized source URL for the iframe.
1065
- */
1066
- this.src = input(...(ngDevMode ? [undefined, { debugName: "src" }] : []));
1067
- this.messageService = inject(MessagePeerService);
1068
- this.domSanitizer = inject(DomSanitizer);
1069
- this.iframeElement = inject(ElementRef).nativeElement;
1070
- this.clientOrigin = computed(() => {
1071
- const src = this.src();
1072
- const srcString = src && this.domSanitizer.sanitize(SecurityContext.RESOURCE_URL, src);
1073
- return srcString && new URL(srcString).origin;
1074
- }, ...(ngDevMode ? [{ debugName: "clientOrigin" }] : []));
1075
- const logger = inject(LoggerService);
1076
- // When the origin or connection ID change - reconnect the message service
1077
- effect((onCleanup) => {
1078
- let stopHandshakeListening = () => { };
1079
- const origin = this.clientOrigin();
1080
- const id = this.connect();
1081
- const source = this.iframeElement.contentWindow;
1082
- // listen for handshakes only if we know the origin and were given a connection ID
1083
- if (origin && source && id) {
1084
- try {
1085
- stopHandshakeListening = this.messageService.listen({ id, source, origin });
1086
- }
1087
- catch (e) {
1088
- logger.error(`Failed to start listening for (connection ID: ${id})`, e);
1089
- }
1090
- }
1091
- // stop listening for handshakes and disconnect previous connection when:
1092
- // - origin/connection ID change
1093
- // - the directive is destroyed
1094
- onCleanup(() => {
1095
- stopHandshakeListening();
1096
- this.messageService.disconnect();
1097
- });
1098
- });
1099
- }
1100
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConnectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1101
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.4", type: ConnectDirective, isStandalone: true, selector: "iframe[connect]", inputs: { connect: { classPropertyName: "connect", publicName: "connect", isSignal: true, isRequired: true, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "src": "this.srcAttr" } }, ngImport: i0 }); }
1102
- }
1103
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: ConnectDirective, decorators: [{
1104
- type: Directive,
1105
- args: [{
1106
- selector: 'iframe[connect]',
1107
- standalone: true
1108
- }]
1109
- }], ctorParameters: () => [], propDecorators: { srcAttr: [{
1110
- type: HostBinding,
1111
- args: ['src']
1112
- }] } });
1113
-
1114
- /**
1115
- * No operation function used to override the history API methods.
1116
- */
1117
- function noop() { }
1118
- /**
1119
- * If an iframe is not sandboxed or is of the same origin, navigation inside it will mess up the main window history.
1120
- * This disables writing to and overriding history API from inside the iframe to prevent this.
1121
- * Theoretically, this might break applications that rely on reading history API from inside the iframe.
1122
- *
1123
- * This should also allow having `CustomPathLocationStrategy` in the iframe if necessary.
1124
- */
1125
- function provideDisableHistoryWrites() {
1126
- return provideAppInitializer(() => {
1127
- Object.defineProperty(history, 'pushState', { value: noop, writable: false, configurable: false });
1128
- Object.defineProperty(history, 'replaceState', { value: noop, writable: false, configurable: false });
1129
- });
1130
- }
1131
-
1132
- /**
1133
- * Provide the communication protocol connection configuration
1134
- * @param connectionConfigOptions The identifier of the application in the communication protocol ecosystem plus the types of messages able to exchange and a logger object
1135
- */
1136
- function provideConnection(connectionConfigOptions) {
1137
- persistHostInfo();
1138
- const connectionId = (isEmbedded() && getHostInfo().moduleApplicationId) || connectionConfigOptions?.id;
1139
- if (!connectionId) {
1140
- (connectionConfigOptions?.logger || console).error('An id (moduleId) needs to be provided for the application in order to establish a connection inside the communication protocol');
1141
- return makeEnvironmentProviders([]);
1142
- }
1143
- const config = {
1144
- id: connectionId,
1145
- messageCheckStrategy: 'version',
1146
- knownMessages: [...KNOWN_MESSAGES, ...(connectionConfigOptions?.knownMessages || [])]
1147
- };
1148
- return makeEnvironmentProviders([
1149
- {
1150
- provide: MESSAGE_PEER_CONFIG, useValue: config
1151
- },
1152
- {
1153
- provide: MESSAGE_PEER_CONNECT_OPTIONS, useValue: getDefaultClientEndpointStartOptions()
1154
- },
1155
- {
1156
- // in the case of the ConnectionService will extend the base service 'useExisting' should be used
1157
- provide: MessagePeerService, useClass: MessagePeerService, deps: [MESSAGE_PEER_CONFIG]
1158
- },
1159
- // deactivate history writes to avoid embedded app writing to the host history
1160
- ...isEmbedded() ? [provideDisableHistoryWrites()] : []
1161
- ]);
1162
- }
1163
-
1164
1235
  /**
1165
1236
  * Generated bundle index. Do not edit.
1166
1237
  */
1167
1238
 
1168
- export { ApplyTheme, ConnectDirective, ConsumerManagerService, ERROR_MESSAGE_TYPE, HostInfoPipe, KNOWN_MESSAGES, MFE_HOST_APPLICATION_ID_PARAM, MFE_HOST_URL_PARAM, MFE_MODULE_APPLICATION_ID_PARAM, NavigationConsumerService, ProducerManagerService, ResizeConsumerService, ResizeService, RestoreRoute, RouteMemorizeDirective, RouteMemorizeService, RoutingService, ScalableDirective, THEME_QUERY_PARAM_NAME, THEME_URL_SUFFIX, ThemeConsumerService, ThemeProducerService, applyInitialTheme, applyTheme, downloadApplicationThemeCss, getAvailableConsumers, getDefaultClientEndpointStartOptions, getHostInfo, getStyle, hostQueryParams, isEmbedded, isErrorMessage, persistHostInfo, provideConnection, registerConsumer, registerProducer, sendError };
1239
+ export { ApplyTheme, ConnectDirective, ConsumerManagerService, ERROR_MESSAGE_TYPE, HistoryConsumerService, HostInfoPipe, KNOWN_MESSAGES, MFE_HOST_APPLICATION_ID_PARAM, MFE_HOST_URL_PARAM, MFE_MODULE_APPLICATION_ID_PARAM, NavigationConsumerService, ProducerManagerService, ResizeConsumerService, ResizeService, RestoreRoute, RouteMemorizeDirective, RouteMemorizeService, RoutingService, ScalableDirective, THEME_QUERY_PARAM_NAME, THEME_URL_SUFFIX, ThemeConsumerService, ThemeProducerService, applyInitialTheme, applyTheme, downloadApplicationThemeCss, getAvailableConsumers, getDefaultClientEndpointStartOptions, getHostInfo, getStyle, hostQueryParams, isEmbedded, isErrorMessage, persistHostInfo, provideConnection, provideHistoryOverrides, registerConsumer, registerProducer, sendError };
1169
1240
  //# sourceMappingURL=ama-mfe-ng-utils.mjs.map