@ama-mfe/ng-utils 14.5.0-prerelease.9 → 14.5.0-rc.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.
@@ -1,10 +1,10 @@
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 { input, inject, ElementRef, computed, SecurityContext, effect, HostBinding, Directive, Injectable, signal, DestroyRef, provideAppInitializer, Pipe, makeEnvironmentProviders, Renderer2, afterNextRender, ChangeDetectionStrategy, ViewEncapsulation, Component, untracked } from '@angular/core';
4
+ import { input, inject, ElementRef, computed, SecurityContext, effect, HostBinding, Directive, Injectable, signal, DestroyRef, provideAppInitializer, Pipe, makeEnvironmentProviders, Renderer2, afterNextRender, ChangeDetectionStrategy, ViewEncapsulation, Component, untracked, InjectionToken } from '@angular/core';
5
5
  import { DomSanitizer } from '@angular/platform-browser';
6
6
  import { LoggerService } from '@o3r/logger';
7
- import { HISTORY_MESSAGE_TYPE, USER_ACTIVITY_MESSAGE_TYPE, RESIZE_MESSAGE_TYPE, THEME_MESSAGE_TYPE, NAVIGATION_MESSAGE_TYPE } from '@ama-mfe/messages';
7
+ import { HISTORY_MESSAGE_TYPE, USER_ACTIVITY_MESSAGE_TYPE, RESIZE_MESSAGE_TYPE, THEME_MESSAGE_TYPE, NAVIGATION_MESSAGE_TYPE, NAVIGATION_BLOCK_STATE_MESSAGE_TYPE, NAVIGATION_REQUEST_MESSAGE_TYPE, NAVIGATION_DECISION_MESSAGE_TYPE } from '@ama-mfe/messages';
8
8
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
9
9
  import { fromEvent, throttleTime, Subject, filter, map } from 'rxjs';
10
10
  import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
@@ -58,10 +58,10 @@ class ConnectDirective {
58
58
  });
59
59
  });
60
60
  }
61
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConnectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
62
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.15", 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 }); }
61
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ConnectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
62
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.17", 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
63
  }
64
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConnectDirective, decorators: [{
64
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ConnectDirective, decorators: [{
65
65
  type: Directive,
66
66
  args: [{
67
67
  selector: 'iframe[connect]',
@@ -143,10 +143,10 @@ class ProducerManagerService {
143
143
  }
144
144
  return handlersPresent;
145
145
  }
146
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ProducerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
147
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ProducerManagerService, providedIn: 'root' }); }
146
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProducerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
147
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProducerManagerService, providedIn: 'root' }); }
148
148
  }
149
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ProducerManagerService, decorators: [{
149
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProducerManagerService, decorators: [{
150
150
  type: Injectable,
151
151
  args: [{
152
152
  providedIn: 'root'
@@ -267,16 +267,47 @@ class ConsumerManagerService {
267
267
  return consumers.filter((c) => c !== consumer);
268
268
  });
269
269
  }
270
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConsumerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
271
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConsumerManagerService, providedIn: 'root' }); }
270
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ConsumerManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
271
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ConsumerManagerService, providedIn: 'root' }); }
272
272
  }
273
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConsumerManagerService, decorators: [{
273
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ConsumerManagerService, decorators: [{
274
274
  type: Injectable,
275
275
  args: [{
276
276
  providedIn: 'root'
277
277
  }]
278
278
  }], ctorParameters: () => [] });
279
279
 
280
+ /**
281
+ * An abstract base class for message consumers that provides common functionality for registering and unregistering with the ConsumerManagerService.
282
+ *
283
+ * This class implements the MessageConsumer interface and provides a default implementation for the start and stop methods.
284
+ * It also handles the automatic registration and unregistration of the consumer with the ConsumerManagerService when the service is created and destroyed.
285
+ *
286
+ * To use this class, simply extend it and implement the required properties (type and supportedVersions) and any additional logic needed to consume messages.
287
+ */
288
+ class AbstractMessageConsumer {
289
+ constructor() {
290
+ /** The service used to register the consumer */
291
+ this.consumerManagerService = inject(ConsumerManagerService);
292
+ /** The reference used to handle the destruction of the consumer */
293
+ this.destroyRef = inject(DestroyRef);
294
+ /** Logger shared with subclasses. */
295
+ this.logger = inject(LoggerService);
296
+ }
297
+ /** @inheritdoc */
298
+ start() {
299
+ this.consumerManagerService.register(this);
300
+ this.unregisterCallback?.();
301
+ this.unregisterCallback = this.destroyRef.onDestroy(() => this.stop());
302
+ }
303
+ /** @inheritdoc */
304
+ stop() {
305
+ this.consumerManagerService.unregister(this);
306
+ this.unregisterCallback?.();
307
+ this.unregisterCallback = undefined;
308
+ }
309
+ }
310
+
280
311
  /**
281
312
  * Method to call in the constructor of a producer
282
313
  * @note should be used in injection context
@@ -307,8 +338,9 @@ const registerConsumer = (consumer) => {
307
338
  *
308
339
  * This service listens for history messages and navigates accordingly.
309
340
  */
310
- class HistoryConsumerService {
341
+ class HistoryConsumerService extends AbstractMessageConsumer {
311
342
  constructor() {
343
+ super();
312
344
  /**
313
345
  * The type of messages this service handles.
314
346
  */
@@ -325,26 +357,16 @@ class HistoryConsumerService {
325
357
  history.go(message.payload.delta);
326
358
  }
327
359
  };
328
- this.consumerManagerService = inject(ConsumerManagerService);
360
+ /**
361
+ * Auto-starts the consumer on creation.
362
+ * @deprecated The constructor auto-starts the consumer for backwards compatibility. It will be removed in v15;
363
+ */
329
364
  this.start();
330
- inject(DestroyRef).onDestroy(() => this.stop());
331
365
  }
332
- /**
333
- * @inheritdoc
334
- */
335
- start() {
336
- this.consumerManagerService.register(this);
337
- }
338
- /**
339
- * @inheritdoc
340
- */
341
- stop() {
342
- this.consumerManagerService.unregister(this);
343
- }
344
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HistoryConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
345
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HistoryConsumerService, providedIn: 'root' }); }
366
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HistoryConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
367
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HistoryConsumerService, providedIn: 'root' }); }
346
368
  }
347
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HistoryConsumerService, decorators: [{
369
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HistoryConsumerService, decorators: [{
348
370
  type: Injectable,
349
371
  args: [{
350
372
  providedIn: 'root'
@@ -460,10 +482,10 @@ class HostInfoPipe {
460
482
  return typeof url === 'string' ? moduleUrlStringyfied : this.domSanitizer.bypassSecurityTrustResourceUrl(moduleUrlStringyfied);
461
483
  }
462
484
  }
463
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HostInfoPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
464
- /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: HostInfoPipe, isStandalone: true, name: "hostInfo" }); }
485
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HostInfoPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
486
+ /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: HostInfoPipe, isStandalone: true, name: "hostInfo" }); }
465
487
  }
466
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HostInfoPipe, decorators: [{
488
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HostInfoPipe, decorators: [{
467
489
  type: Pipe,
468
490
  args: [{
469
491
  name: 'hostInfo'
@@ -514,6 +536,17 @@ function getDefaultClientEndpointStartOptions() {
514
536
  function isEmbedded(windowParam = window) {
515
537
  return windowParam.top !== windowParam.self;
516
538
  }
539
+ /**
540
+ * Generate a string id suitable for correlating asynchronous request/reply messages across the micro-frontend bus.
541
+ * Uses `crypto.randomUUID` when the runtime supports it, otherwise falls back to a timestamp + random suffix.
542
+ * @param prefix Optional prefix used by the fallback path to make ids easier to identify in logs (ignored when `crypto.randomUUID` is available).
543
+ */
544
+ function generateCorrelationId(prefix = 'corr') {
545
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
546
+ return crypto.randomUUID();
547
+ }
548
+ return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
549
+ }
517
550
 
518
551
  /**
519
552
  * Provide the communication protocol connection configuration
@@ -549,8 +582,9 @@ function provideConnection(connectionConfigOptions) {
549
582
  /**
550
583
  * This service listens for resize messages and updates the height of elements based on the received messages.
551
584
  */
552
- class ResizeConsumerService {
585
+ class ResizeConsumerService extends AbstractMessageConsumer {
553
586
  constructor() {
587
+ super();
554
588
  this.newHeight = signal(undefined, ...(ngDevMode ? [{ debugName: "newHeight" }] : /* istanbul ignore next */ []));
555
589
  /**
556
590
  * A readonly signal that provides the new height information from the channel.
@@ -570,26 +604,16 @@ class ResizeConsumerService {
570
604
  */
571
605
  '1.0': (message) => this.newHeight.set({ height: message.payload.height, channelId: message.from })
572
606
  };
573
- this.consumerManagerService = inject(ConsumerManagerService);
607
+ /**
608
+ * Auto-starts the consumer on creation.
609
+ * @deprecated The constructor auto-starts the consumer for backwards compatibility. It will be removed in v15;
610
+ */
574
611
  this.start();
575
- inject(DestroyRef).onDestroy(() => this.stop());
576
- }
577
- /**
578
- * Starts the resize handler service by registering it into the consumer manager service.
579
- */
580
- start() {
581
- this.consumerManagerService.register(this);
582
612
  }
583
- /**
584
- * Stops the resize handler service by unregistering it from the consumer manager service.
585
- */
586
- stop() {
587
- this.consumerManagerService.unregister(this);
588
- }
589
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ResizeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
590
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ResizeConsumerService, providedIn: 'root' }); }
613
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ResizeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
614
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ResizeConsumerService, providedIn: 'root' }); }
591
615
  }
592
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ResizeConsumerService, decorators: [{
616
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ResizeConsumerService, decorators: [{
593
617
  type: Injectable,
594
618
  args: [{
595
619
  providedIn: 'root'
@@ -723,10 +747,10 @@ class ScalableDirective {
723
747
  this.renderer.setStyle(this.elem.nativeElement, 'min-height', `${height}px`);
724
748
  }
725
749
  }
726
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ScalableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
727
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.15", 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 }); }
750
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ScalableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
751
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.17", 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 }); }
728
752
  }
729
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ScalableDirective, decorators: [{
753
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ScalableDirective, decorators: [{
730
754
  type: Directive,
731
755
  args: [{
732
756
  selector: '[scalable]',
@@ -884,10 +908,10 @@ class ThemeProducerService {
884
908
  this.logger.error('Error in theme service message', message);
885
909
  this.revertToPreviousTheme();
886
910
  }
887
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeProducerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
888
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeProducerService, providedIn: 'root' }); }
911
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeProducerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
912
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeProducerService, providedIn: 'root' }); }
889
913
  }
890
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeProducerService, decorators: [{
914
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeProducerService, decorators: [{
891
915
  type: Injectable,
892
916
  args: [{
893
917
  providedIn: 'root'
@@ -920,10 +944,10 @@ class ApplyTheme {
920
944
  }
921
945
  return undefined;
922
946
  }
923
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ApplyTheme, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
924
- /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: ApplyTheme, isStandalone: true, name: "applyTheme" }); }
947
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ApplyTheme, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
948
+ /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: ApplyTheme, isStandalone: true, name: "applyTheme" }); }
925
949
  }
926
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ApplyTheme, decorators: [{
950
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ApplyTheme, decorators: [{
927
951
  type: Pipe,
928
952
  args: [{
929
953
  name: 'applyTheme'
@@ -952,10 +976,10 @@ class SandboxDirective {
952
976
  ngOnInit() {
953
977
  this.renderer.setAttribute(this.elementRef.nativeElement, 'sandbox', this.mfeSandbox());
954
978
  }
955
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SandboxDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
956
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.15", type: SandboxDirective, isStandalone: true, selector: "iframe[mfeSandbox]", inputs: { mfeSandbox: { classPropertyName: "mfeSandbox", publicName: "mfeSandbox", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
979
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SandboxDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
980
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.17", type: SandboxDirective, isStandalone: true, selector: "iframe[mfeSandbox]", inputs: { mfeSandbox: { classPropertyName: "mfeSandbox", publicName: "mfeSandbox", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
957
981
  }
958
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SandboxDirective, decorators: [{
982
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SandboxDirective, decorators: [{
959
983
  type: Directive,
960
984
  args: [{
961
985
  selector: 'iframe[mfeSandbox]'
@@ -988,10 +1012,10 @@ class IframeEmbedComponent {
988
1012
  */
989
1013
  this.sandbox = input('allow-scripts allow-same-origin', ...(ngDevMode ? [{ debugName: "sandbox" }] : /* istanbul ignore next */ []));
990
1014
  }
991
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IframeEmbedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
992
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.15", type: IframeEmbedComponent, isStandalone: true, selector: "mfe-iframe-embed", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: true, transformFunction: null }, moduleId: { classPropertyName: "moduleId", publicName: "moduleId", isSignal: true, isRequired: true, transformFunction: null }, hostApplicationId: { classPropertyName: "hostApplicationId", publicName: "hostApplicationId", isSignal: true, isRequired: true, transformFunction: null }, sandbox: { classPropertyName: "sandbox", publicName: "sandbox", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@let hostInfoOptions = {hostId: hostApplicationId(), moduleId: moduleId()};\n<iframe\n [connect]=\"hostInfoOptions.moduleId\"\n scalable\n [src]=\"safeSrc() | hostInfo: hostInfoOptions | applyTheme\"\n [mfeSandbox]=\"sandbox()\">\n</iframe>\n", styles: ["mfe-iframe-embed iframe{height:100%;width:100%;display:block}\n"], dependencies: [{ kind: "directive", type: ConnectDirective, selector: "iframe[connect]", inputs: ["connect", "src"] }, { kind: "directive", type: ScalableDirective, selector: "[scalable]", inputs: ["connect", "scalable"] }, { kind: "directive", type: SandboxDirective, selector: "iframe[mfeSandbox]", inputs: ["mfeSandbox"] }, { kind: "pipe", type: ApplyTheme, name: "applyTheme" }, { kind: "pipe", type: HostInfoPipe, name: "hostInfo" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1015
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: IframeEmbedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1016
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: IframeEmbedComponent, isStandalone: true, selector: "mfe-iframe-embed", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: true, transformFunction: null }, moduleId: { classPropertyName: "moduleId", publicName: "moduleId", isSignal: true, isRequired: true, transformFunction: null }, hostApplicationId: { classPropertyName: "hostApplicationId", publicName: "hostApplicationId", isSignal: true, isRequired: true, transformFunction: null }, sandbox: { classPropertyName: "sandbox", publicName: "sandbox", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@let hostInfoOptions = {hostId: hostApplicationId(), moduleId: moduleId()};\n<iframe\n [connect]=\"hostInfoOptions.moduleId\"\n scalable\n [src]=\"safeSrc() | hostInfo: hostInfoOptions | applyTheme\"\n [mfeSandbox]=\"sandbox()\">\n</iframe>\n", styles: ["mfe-iframe-embed iframe{height:100%;width:100%;display:block}\n"], dependencies: [{ kind: "directive", type: ConnectDirective, selector: "iframe[connect]", inputs: ["connect", "src"] }, { kind: "directive", type: ScalableDirective, selector: "[scalable]", inputs: ["connect", "scalable"] }, { kind: "directive", type: SandboxDirective, selector: "iframe[mfeSandbox]", inputs: ["mfeSandbox"] }, { kind: "pipe", type: ApplyTheme, name: "applyTheme" }, { kind: "pipe", type: HostInfoPipe, name: "hostInfo" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
993
1017
  }
994
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IframeEmbedComponent, decorators: [{
1018
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: IframeEmbedComponent, decorators: [{
995
1019
  type: Component,
996
1020
  args: [{ selector: 'mfe-iframe-embed', imports: [
997
1021
  ConnectDirective,
@@ -1007,8 +1031,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
1007
1031
  *
1008
1032
  * This service listens for navigation messages and updates the router state accordingly.
1009
1033
  */
1010
- class NavigationConsumerService {
1034
+ class NavigationConsumerService extends AbstractMessageConsumer {
1011
1035
  constructor() {
1036
+ super();
1012
1037
  this.router = inject(Router);
1013
1038
  this.activeRoute = inject(ActivatedRoute);
1014
1039
  this.requestedUrl = new Subject();
@@ -1046,9 +1071,11 @@ class NavigationConsumerService {
1046
1071
  this.navigate(message.payload.url, message.payload.extras);
1047
1072
  }
1048
1073
  };
1049
- this.consumerManagerService = inject(ConsumerManagerService);
1074
+ /**
1075
+ * Auto-starts the consumer on creation.
1076
+ * @deprecated The constructor auto-starts the consumer for backwards compatibility. It will be removed in v15;
1077
+ */
1050
1078
  this.start();
1051
- inject(DestroyRef).onDestroy(() => this.stop());
1052
1079
  }
1053
1080
  /**
1054
1081
  * Parses a URL and returns an object containing the paths and query parameters.
@@ -1076,22 +1103,10 @@ class NavigationConsumerService {
1076
1103
  replaceUrl: extras?.replaceUrl
1077
1104
  });
1078
1105
  }
1079
- /**
1080
- * @inheritdoc
1081
- */
1082
- start() {
1083
- this.consumerManagerService.register(this);
1084
- }
1085
- /**
1086
- * @inheritdoc
1087
- */
1088
- stop() {
1089
- this.consumerManagerService.unregister(this);
1090
- }
1091
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavigationConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1092
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavigationConsumerService, providedIn: 'root' }); }
1106
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1107
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationConsumerService, providedIn: 'root' }); }
1093
1108
  }
1094
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavigationConsumerService, decorators: [{
1109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationConsumerService, decorators: [{
1095
1110
  type: Injectable,
1096
1111
  args: [{
1097
1112
  providedIn: 'root'
@@ -1134,10 +1149,10 @@ class RouteMemorizeService {
1134
1149
  getRoute(channelId) {
1135
1150
  return this.routeStack[channelId];
1136
1151
  }
1137
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RouteMemorizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1138
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RouteMemorizeService, providedIn: 'root' }); }
1152
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RouteMemorizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1153
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RouteMemorizeService, providedIn: 'root' }); }
1139
1154
  }
1140
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RouteMemorizeService, decorators: [{
1155
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RouteMemorizeService, decorators: [{
1141
1156
  type: Injectable,
1142
1157
  args: [{
1143
1158
  providedIn: 'root'
@@ -1185,10 +1200,10 @@ class RestoreRoute {
1185
1200
  return typeof url === 'string' ? moduleUrlStringyfied : this.domSanitizer.bypassSecurityTrustResourceUrl(moduleUrlStringyfied);
1186
1201
  }
1187
1202
  }
1188
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RestoreRoute, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
1189
- /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: RestoreRoute, isStandalone: true, name: "restoreRoute" }); }
1203
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RestoreRoute, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
1204
+ /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: RestoreRoute, isStandalone: true, name: "restoreRoute" }); }
1190
1205
  }
1191
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RestoreRoute, decorators: [{
1206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RestoreRoute, decorators: [{
1192
1207
  type: Pipe,
1193
1208
  args: [{
1194
1209
  name: 'restoreRoute'
@@ -1242,10 +1257,10 @@ class RouteMemorizeDirective {
1242
1257
  }
1243
1258
  });
1244
1259
  }
1245
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RouteMemorizeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1246
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.15", 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 }); }
1260
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RouteMemorizeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1261
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.17", 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 }); }
1247
1262
  }
1248
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RouteMemorizeDirective, decorators: [{
1263
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RouteMemorizeDirective, decorators: [{
1249
1264
  type: Directive,
1250
1265
  args: [{
1251
1266
  selector: 'iframe[memorizeRoute]',
@@ -1359,16 +1374,574 @@ class RoutingService {
1359
1374
  }
1360
1375
  });
1361
1376
  }
1362
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RoutingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1363
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RoutingService, providedIn: 'root' }); }
1377
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RoutingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1378
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RoutingService, providedIn: 'root' }); }
1379
+ }
1380
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RoutingService, decorators: [{
1381
+ type: Injectable,
1382
+ args: [{
1383
+ providedIn: 'root'
1384
+ }]
1385
+ }], ctorParameters: () => [] });
1386
+
1387
+ /**
1388
+ * Module-side writable source of truth for the navigation block state.
1389
+ *
1390
+ * Feature code (forms, editors, etc.) calls {@link block} when unsaved changes appear and {@link unblock} once they are saved or discarded.
1391
+ * The {@link NavigationBlockStateProducerService} watches this signal and mirrors the state to the shell;
1392
+ * the {@link navigationBlockModuleGuard} reads it to decide whether to intercept in-module navigation.
1393
+ */
1394
+ class NavigationBlockService {
1395
+ constructor() {
1396
+ this.stateSignal = signal({ blocked: false }, ...(ngDevMode ? [{ debugName: "stateSignal" }] : /* istanbul ignore next */ []));
1397
+ /** Readonly view of the current navigation block state. */
1398
+ this.state = this.stateSignal.asReadonly();
1399
+ }
1400
+ /**
1401
+ * Mark the module as blocked (unsaved changes present).
1402
+ * @param reason Optional human-readable reason shown in the confirmation modal.
1403
+ */
1404
+ block(reason) {
1405
+ this.stateSignal.set({ blocked: true, reason });
1406
+ }
1407
+ /** Mark the module as unblocked (no unsaved changes). */
1408
+ unblock() {
1409
+ this.stateSignal.set({ blocked: false });
1410
+ }
1411
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1412
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockService, providedIn: 'root' }); }
1413
+ }
1414
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockService, decorators: [{
1415
+ type: Injectable,
1416
+ args: [{
1417
+ providedIn: 'root'
1418
+ }]
1419
+ }] });
1420
+
1421
+ /**
1422
+ * Module-side producer that mirrors {@link NavigationBlockService} to the shell via `navigation-block-state` messages.
1423
+ * Every state change triggers a broadcast so the shell guard can decide without a round-trip.
1424
+ *
1425
+ * Runs module-side only (it watches the module's writable state). The shell never instantiates it.
1426
+ */
1427
+ class NavigationBlockStateProducerService {
1428
+ constructor() {
1429
+ /**
1430
+ * @inheritdoc
1431
+ */
1432
+ this.types = NAVIGATION_BLOCK_STATE_MESSAGE_TYPE;
1433
+ this.connectionService = inject(MessagePeerService);
1434
+ this.producerManagerService = inject(ProducerManagerService);
1435
+ this.logger = inject(LoggerService);
1436
+ this.store = inject(NavigationBlockService);
1437
+ this.producerManagerService.register(this);
1438
+ inject(DestroyRef).onDestroy(() => this.producerManagerService.unregister(this));
1439
+ effect(() => {
1440
+ const state = this.store.state();
1441
+ const message = {
1442
+ type: NAVIGATION_BLOCK_STATE_MESSAGE_TYPE,
1443
+ version: '1.0',
1444
+ blocked: state.blocked,
1445
+ reason: state.reason
1446
+ };
1447
+ this.connectionService.send(message);
1448
+ });
1449
+ }
1450
+ /**
1451
+ * @inheritdoc
1452
+ */
1453
+ handleError(message) {
1454
+ this.logger.error('navigation-block state message could not be consumed by the shell', message);
1455
+ }
1456
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockStateProducerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1457
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockStateProducerService, providedIn: 'root' }); }
1458
+ }
1459
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockStateProducerService, decorators: [{
1460
+ type: Injectable,
1461
+ args: [{
1462
+ providedIn: 'root'
1463
+ }]
1464
+ }], ctorParameters: () => [] });
1465
+
1466
+ /**
1467
+ * Shell-side consumer for `navigation-block-state` messages sent by modules.
1468
+ *
1469
+ * Keeps the last received state in a signal that the shell guard reads to decide whether to intercept shell-initiated navigation.
1470
+ * The state stays `undefined` until any module reports a value (interpreted as "no block known" which means navigation is allowed).
1471
+ */
1472
+ class NavigationBlockStateConsumerService extends AbstractMessageConsumer {
1473
+ constructor() {
1474
+ super(...arguments);
1475
+ /**
1476
+ * @inheritdoc
1477
+ */
1478
+ this.type = NAVIGATION_BLOCK_STATE_MESSAGE_TYPE;
1479
+ /**
1480
+ * @inheritdoc
1481
+ */
1482
+ this.supportedVersions = {
1483
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- expected naming for versions
1484
+ '1.0': (message) => {
1485
+ this.blockStateSignal.set({
1486
+ blocked: message.payload.blocked,
1487
+ reason: message.payload.reason,
1488
+ channelId: message.from
1489
+ });
1490
+ }
1491
+ };
1492
+ this.blockStateSignal = signal(undefined, ...(ngDevMode ? [{ debugName: "blockStateSignal" }] : /* istanbul ignore next */ []));
1493
+ /** Last navigation block state reported by any module. */
1494
+ this.blockState = this.blockStateSignal.asReadonly();
1495
+ }
1496
+ /**
1497
+ * Mark the state as unblocked after the shell has resolved a confirmation (e.g. the user confirmed a sidebar-initiated navigation).
1498
+ */
1499
+ clear() {
1500
+ this.blockStateSignal.set({ blocked: false });
1501
+ }
1502
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockStateConsumerService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1503
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockStateConsumerService, providedIn: 'root' }); }
1504
+ }
1505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockStateConsumerService, decorators: [{
1506
+ type: Injectable,
1507
+ args: [{
1508
+ providedIn: 'root'
1509
+ }]
1510
+ }] });
1511
+
1512
+ /**
1513
+ * Manages navigation request/decision round-trip communication for **both** shell and module.
1514
+ * Sends `navigation-request` messages, tracks pending requests, and sends `navigation-decision` replies.
1515
+ * Correlates responses with their originating requests using correlation IDs.
1516
+ *
1517
+ * - Module-initiated navigation → guard calls `requestNavigation()` with no target, broadcasting to the shell;
1518
+ * the shell's handler opens the modal and replies.
1519
+ * - Shell-initiated navigation → guard calls `requestNavigation(channelId)` after the user already confirmed locally,
1520
+ * so the module can run its unblock / draft-persistence logic and reply.
1521
+ *
1522
+ * If the peer never replies the returned promise stays pending and the navigation is held — callers rely on Angular
1523
+ * tearing their context down (the producer's `ngOnDestroy` resolves pending promises to `false`).
1524
+ */
1525
+ class NavigationRequestManagerService {
1526
+ constructor() {
1527
+ /**
1528
+ * @inheritdoc
1529
+ */
1530
+ this.types = [NAVIGATION_REQUEST_MESSAGE_TYPE, NAVIGATION_DECISION_MESSAGE_TYPE];
1531
+ this.connectionService = inject(MessagePeerService);
1532
+ this.producerManagerService = inject(ProducerManagerService);
1533
+ this.logger = inject(LoggerService);
1534
+ this.producerManagerService.register(this);
1535
+ }
1536
+ /**
1537
+ * Ask the peer to handle the navigation. Resolves when the peer replies with a `navigation-decision`.
1538
+ * If the peer never replies the promise stays pending.
1539
+ *
1540
+ * Re-entrant calls while a request is pending (e.g. the same navigation firing both `canActivate` and `canActivateChild`)
1541
+ * return the same promise, so only one round-trip is sent.
1542
+ * @param target Optional target peer id. Omit to broadcast (module → shell).
1543
+ * @param reason Optional human-readable reason surfaced in the shell modal.
1544
+ */
1545
+ requestNavigation(target, reason) {
1546
+ if (this.pendingRequest) {
1547
+ return this.pendingRequest.promise;
1548
+ }
1549
+ const correlationId = generateCorrelationId('nav-req');
1550
+ let resolveFn;
1551
+ const promise = new Promise((resolve) => {
1552
+ resolveFn = resolve;
1553
+ });
1554
+ this.pendingRequest = { correlationId, promise, resolve: resolveFn };
1555
+ const message = {
1556
+ type: NAVIGATION_REQUEST_MESSAGE_TYPE,
1557
+ version: '1.0',
1558
+ correlationId,
1559
+ reason
1560
+ };
1561
+ this.connectionService.send(message, target ? { to: target } : undefined);
1562
+ return promise;
1563
+ }
1564
+ /**
1565
+ * Send a `navigation-decision` reply with the given `correlationId`.
1566
+ * Called by {@link NavigationNegotiationConsumerService} after the side-specific handler has finished.
1567
+ * @param correlationId id echoed from the request
1568
+ * @param target peer id of the original sender
1569
+ * @param proceed whether to allow navigation (default true)
1570
+ */
1571
+ sendDecision(correlationId, target, proceed = true) {
1572
+ const message = {
1573
+ type: NAVIGATION_DECISION_MESSAGE_TYPE,
1574
+ version: '1.0',
1575
+ correlationId,
1576
+ proceed
1577
+ };
1578
+ this.connectionService.send(message, { to: target });
1579
+ }
1580
+ /**
1581
+ * Called by {@link NavigationDecisionConsumerService} when a decision arrives.
1582
+ * Resolves the pending promise if the `correlationId` matches.
1583
+ * @param correlationId
1584
+ * @param proceed
1585
+ */
1586
+ resolvePendingRequest(correlationId, proceed) {
1587
+ const pending = this.pendingRequest;
1588
+ if (!pending || pending.correlationId !== correlationId) {
1589
+ return;
1590
+ }
1591
+ this.pendingRequest = undefined;
1592
+ pending.resolve(proceed);
1593
+ }
1594
+ /**
1595
+ * @inheritdoc
1596
+ */
1597
+ handleError(message) {
1598
+ this.logger.error('navigation negotiation message could not be consumed by a peer', message);
1599
+ }
1600
+ ngOnDestroy() {
1601
+ if (this.pendingRequest) {
1602
+ this.pendingRequest.resolve(false);
1603
+ this.pendingRequest = undefined;
1604
+ }
1605
+ this.producerManagerService.unregister(this);
1606
+ }
1607
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationRequestManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1608
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationRequestManagerService, providedIn: 'root' }); }
1364
1609
  }
1365
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RoutingService, decorators: [{
1610
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationRequestManagerService, decorators: [{
1366
1611
  type: Injectable,
1367
1612
  args: [{
1368
1613
  providedIn: 'root'
1369
1614
  }]
1370
1615
  }], ctorParameters: () => [] });
1371
1616
 
1617
+ /**
1618
+ * Default module-side `navigation-request` handler. Runs the module's local cleanup — at minimum clearing the block state — and resolves.
1619
+ * Modules cannot refuse a navigation (only the shell modal can), so this always resolves and a `navigation-decision` is always sent back.
1620
+ *
1621
+ * Used as the default factory of {@link NAVIGATION_REQUEST_HANDLER}, so a module gets this behavior without any explicit provider.
1622
+ * Apps that need to persist drafts before unblocking can override the token with their own handler.
1623
+ */
1624
+ const createNavigationRequestHandler = () => {
1625
+ const store = inject(NavigationBlockService);
1626
+ return {
1627
+ handle: () => {
1628
+ store.unblock();
1629
+ }
1630
+ };
1631
+ };
1632
+ /**
1633
+ * Injection token for the per-side request handler.
1634
+ *
1635
+ * **Default behavior (modules):** Clears the block state (unblock) — see {@link createNavigationRequestHandler}.
1636
+ * **Shell override:** Opens confirmation modal and awaits user decision.
1637
+ *
1638
+ * The module handler is provided by default at root level. Only the shell application needs to override it
1639
+ * with `provideNavigationRequestShellHandler()`.
1640
+ */
1641
+ const NAVIGATION_REQUEST_HANDLER = new InjectionToken('NAVIGATION_REQUEST_HANDLER', {
1642
+ providedIn: 'root',
1643
+ factory: createNavigationRequestHandler
1644
+ });
1645
+
1646
+ /**
1647
+ * Agnostic consumer for `navigation-request` messages.
1648
+ *
1649
+ * On each incoming request, invokes the side-specific handler registered under {@link NAVIGATION_REQUEST_HANDLER}:
1650
+ * - **Cockpit side** — handler opens the confirmation modal and awaits the user's answer. If the user cancels the handler
1651
+ * throws; this consumer catches it and replies with a decision carrying `proceed: false`, so the module's pending promise
1652
+ * resolves to `false` and the in-iframe navigation is held until a fresh request is made.
1653
+ * - **Module side** — handler runs the unblock / future draft-persistence logic and resolves. Modules cannot refuse;
1654
+ * a decision is always sent.
1655
+ */
1656
+ class NavigationRequestConsumerService extends AbstractMessageConsumer {
1657
+ constructor() {
1658
+ super(...arguments);
1659
+ /**
1660
+ * @inheritdoc
1661
+ */
1662
+ this.type = NAVIGATION_REQUEST_MESSAGE_TYPE;
1663
+ /**
1664
+ * @inheritdoc
1665
+ */
1666
+ this.supportedVersions = {
1667
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- expected naming for versions
1668
+ '1.0': (message) => this.handleRequest(message)
1669
+ };
1670
+ this.producerService = inject(NavigationRequestManagerService);
1671
+ this.handler = inject(NAVIGATION_REQUEST_HANDLER);
1672
+ }
1673
+ async handleRequest(message) {
1674
+ try {
1675
+ await this.handler.handle({ from: message.from, reason: message.payload.reason });
1676
+ }
1677
+ catch (error) {
1678
+ // Handler rejected — usually the user cancelled, but any unexpected
1679
+ // exception ends up here too. Log it so the failure is observable, then
1680
+ // send a decision with proceed=false so the requester's pending promise
1681
+ // resolves and subsequent navigation attempts can create a fresh request.
1682
+ this.logger.error('navigation-request handler rejected', error, message);
1683
+ this.producerService.sendDecision(message.payload.correlationId, message.from, false);
1684
+ return;
1685
+ }
1686
+ this.producerService.sendDecision(message.payload.correlationId, message.from);
1687
+ }
1688
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationRequestConsumerService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1689
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationRequestConsumerService, providedIn: 'root' }); }
1690
+ }
1691
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationRequestConsumerService, decorators: [{
1692
+ type: Injectable,
1693
+ args: [{
1694
+ providedIn: 'root'
1695
+ }]
1696
+ }] });
1697
+
1698
+ /**
1699
+ * Provider wiring {@link NAVIGATION_REQUEST_HANDLER} to the module handler.
1700
+ * Not normally needed — the token already defaults to this handler — but
1701
+ * available for apps that want to register it explicitly.
1702
+ */
1703
+ const provideNavigationRequestModuleHandler = () => makeEnvironmentProviders([
1704
+ {
1705
+ provide: NAVIGATION_REQUEST_HANDLER,
1706
+ useFactory: createNavigationRequestHandler
1707
+ }
1708
+ ]);
1709
+
1710
+ /**
1711
+ * Default confirmation strategy using browser's native `window.confirm()`.
1712
+ * Simple, no dependencies, works in any environment. Suitable for:
1713
+ * - Development/testing
1714
+ * - Apps without custom modal libraries
1715
+ * - `@ama-mfe` packages that need basic confirmation
1716
+ *
1717
+ * Production apps typically override this with a modal-based strategy.
1718
+ */
1719
+ class BrowserConfirmationStrategy {
1720
+ /**
1721
+ * Show native browser confirmation dialog.
1722
+ * @param reason Optional reason displayed in the message
1723
+ * @returns Promise<true> if user clicks OK, Promise<false> if user clicks Cancel
1724
+ */
1725
+ confirm(reason) {
1726
+ const message = `${reason ? reason + '\n' : ''}Do you want to leave this page?`;
1727
+ // eslint-disable-next-line no-alert -- intentional use of window.confirm for basic confirmation strategy
1728
+ return Promise.resolve(window.confirm(message));
1729
+ }
1730
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: BrowserConfirmationStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1731
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: BrowserConfirmationStrategy, providedIn: 'root' }); }
1732
+ }
1733
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: BrowserConfirmationStrategy, decorators: [{
1734
+ type: Injectable,
1735
+ args: [{
1736
+ providedIn: 'root'
1737
+ }]
1738
+ }] });
1739
+
1740
+ /**
1741
+ * Injection token for the navigation block confirmation strategy.
1742
+ * Defaults to {@link BrowserConfirmationStrategy} (uses `window.confirm()`).
1743
+ * Apps with a styled modal override the default by passing their own class via `provideNavigationConfig({ confirmationStrategy })`
1744
+ * or by binding this token directly.
1745
+ */
1746
+ const NAVIGATION_BLOCK_CONFIRMATION = new InjectionToken('NAVIGATION_BLOCK_CONFIRMATION', {
1747
+ providedIn: 'root',
1748
+ factory: () => inject(BrowserConfirmationStrategy)
1749
+ });
1750
+
1751
+ /**
1752
+ * Orchestrates navigation block confirmation by delegating to a pluggable strategy.
1753
+ * Handles concurrent call deduplication to prevent duplicate confirmations when guards run multiple times.
1754
+ *
1755
+ * The confirmation UI is read from the `NAVIGATION_BLOCK_CONFIRMATION` token, which defaults to {@link BrowserConfirmationStrategy}
1756
+ * (no setup required). Apps with a styled modal override the token via `provideNavigationConfig({ confirmationStrategy })`
1757
+ * or by binding the token directly.
1758
+ */
1759
+ class NavigationBlockConfirmationService {
1760
+ constructor() {
1761
+ this.strategy = inject(NAVIGATION_BLOCK_CONFIRMATION);
1762
+ }
1763
+ /**
1764
+ * Show confirmation and await user decision. Concurrent calls return the same promise to prevent duplicate confirmations.
1765
+ * @param reason Optional reason displayed in the confirmation UI
1766
+ * @returns `true` when the user confirms, `false` when they cancel
1767
+ */
1768
+ confirm(reason) {
1769
+ // Deduplication: if confirmation already in progress, return same promise
1770
+ if (this.pendingConfirmation) {
1771
+ return this.pendingConfirmation;
1772
+ }
1773
+ // Delegate to injected strategy. Clear the slot only once the promise
1774
+ // settles, so concurrent callers in the meantime get the same promise.
1775
+ const pending = this.strategy.confirm(reason).finally(() => {
1776
+ this.pendingConfirmation = undefined;
1777
+ });
1778
+ this.pendingConfirmation = pending;
1779
+ return pending;
1780
+ }
1781
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockConfirmationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1782
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockConfirmationService, providedIn: 'root' }); }
1783
+ }
1784
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationBlockConfirmationService, decorators: [{
1785
+ type: Injectable,
1786
+ args: [{
1787
+ providedIn: 'root'
1788
+ }]
1789
+ }] });
1790
+
1791
+ /**
1792
+ * Shell application `navigation-request` handler used when a module initiates the navigation (in-iframe link click).
1793
+ * Opens the shared confirmation modal, awaits the user's answer, and — on confirm — clears the shell's block mirror.
1794
+ * On cancel the handler throws; the consumer catches it and replies with a `navigation-decision` carrying `proceed: false`,
1795
+ * so the module's pending promise resolves to `false` and the iframe navigation is held until a fresh request is made.
1796
+ */
1797
+ const createNavigationRequestShellHandler = () => {
1798
+ const confirmation = inject(NavigationBlockConfirmationService);
1799
+ const blockConsumer = inject(NavigationBlockStateConsumerService);
1800
+ return {
1801
+ handle: async ({ reason }) => {
1802
+ const confirmed = await confirmation.confirm(reason);
1803
+ if (!confirmed) {
1804
+ throw new Error('navigation-request cancelled by user');
1805
+ }
1806
+ blockConsumer.clear();
1807
+ }
1808
+ };
1809
+ };
1810
+ /**
1811
+ * Provider wiring {@link NAVIGATION_REQUEST_HANDLER} to the shell application
1812
+ * handler. Register once in the shell app providers to override the default
1813
+ * module handler.
1814
+ */
1815
+ const provideNavigationRequestShellHandler = () => makeEnvironmentProviders([
1816
+ {
1817
+ provide: NAVIGATION_REQUEST_HANDLER,
1818
+ useFactory: createNavigationRequestShellHandler
1819
+ }
1820
+ ]);
1821
+
1822
+ /**
1823
+ * Agnostic consumer for `navigation-decision` messages — the reply to a
1824
+ * previously sent `navigation-request`. Forwards the decision to
1825
+ * {@link NavigationRequestManagerService.resolvePendingRequest} so
1826
+ * the awaiting caller's promise resolves.
1827
+ */
1828
+ class NavigationDecisionConsumerService extends AbstractMessageConsumer {
1829
+ constructor() {
1830
+ super(...arguments);
1831
+ /**
1832
+ * @inheritdoc
1833
+ */
1834
+ this.type = NAVIGATION_DECISION_MESSAGE_TYPE;
1835
+ /**
1836
+ * @inheritdoc
1837
+ */
1838
+ this.supportedVersions = {
1839
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- expected naming for versions
1840
+ '1.0': (message) => {
1841
+ this.producerService.resolvePendingRequest(message.payload.correlationId, message.payload.proceed);
1842
+ }
1843
+ };
1844
+ this.producerService = inject(NavigationRequestManagerService);
1845
+ }
1846
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationDecisionConsumerService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1847
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationDecisionConsumerService, providedIn: 'root' }); }
1848
+ }
1849
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationDecisionConsumerService, decorators: [{
1850
+ type: Injectable,
1851
+ args: [{
1852
+ providedIn: 'root'
1853
+ }]
1854
+ }] });
1855
+
1856
+ /**
1857
+ * Shell application guard intercepting shell-initiated navigation (sidebar clicks, URL bar, programmatic `router.navigate`)
1858
+ * when the last state received from a module is `blocked`.
1859
+ *
1860
+ * Can be used as both `canActivate` and `canActivateChild` to ensure the guard runs when entering a route directly
1861
+ * or navigating to its children.
1862
+ *
1863
+ * Flow:
1864
+ * - No state received, or `blocked === false` → navigation proceeds.
1865
+ * - `blocked === true` → open the confirmation modal.
1866
+ * - On cancel/dismiss → return `false`, state is untouched, no message sent to the module.
1867
+ * - On confirm → clear the shell mirror, send a `navigation-request` to the originating module (so it can run its unblock /
1868
+ * future draft-persistence logic), await its `navigation-decision`, then return `true`.
1869
+ */
1870
+ const navigationBlockShellGuard = async () => {
1871
+ const consumer = inject(NavigationBlockStateConsumerService);
1872
+ const confirmation = inject(NavigationBlockConfirmationService);
1873
+ const negotiation = inject(NavigationRequestManagerService);
1874
+ const state = consumer.blockState();
1875
+ if (!state?.blocked) {
1876
+ return true;
1877
+ }
1878
+ const confirmed = await confirmation.confirm(state.reason);
1879
+ if (!confirmed) {
1880
+ return false;
1881
+ }
1882
+ consumer.clear();
1883
+ if (!state.channelId) {
1884
+ return true;
1885
+ }
1886
+ return negotiation.requestNavigation(state.channelId, state.reason);
1887
+ };
1888
+
1889
+ /**
1890
+ * Module-side guard intercepting navigation away from a page that holds unsaved changes.
1891
+ *
1892
+ * - `blocked === false` → navigation proceeds.
1893
+ * - `blocked === true` → broadcast a `navigation-request` to the shell and await the reply. The shell opens the confirmation modal
1894
+ * and replies in both cases: `proceed === true` on confirm, `proceed === false` on cancel/dismiss. On proceed, clear the local
1895
+ * state and return `true`; on cancel, return `false` and leave the block state intact so the navigation is held and a later
1896
+ * attempt can negotiate again.
1897
+ *
1898
+ * Wire it as `canDeactivate` only on the routes that can actually hold unsaved work — modules opt in per page.
1899
+ */
1900
+ const navigationBlockModuleGuard = async () => {
1901
+ const store = inject(NavigationBlockService);
1902
+ const negotiation = inject(NavigationRequestManagerService);
1903
+ const { blocked, reason } = store.state();
1904
+ if (!blocked) {
1905
+ return true;
1906
+ }
1907
+ const proceed = await negotiation.requestNavigation(undefined, reason);
1908
+ if (proceed) {
1909
+ store.unblock();
1910
+ }
1911
+ return proceed;
1912
+ };
1913
+
1914
+ /**
1915
+ * Convenience helper that explicitly binds the {@link NAVIGATION_BLOCK_CONFIRMATION} token to {@link BrowserConfirmationStrategy}.
1916
+ *
1917
+ * **Usually unnecessary** — the token already defaults to `BrowserConfirmationStrategy` via its tree-shakable factory,
1918
+ * so the helper only re-binds the same value. Use it when you want the binding to be visible at the call site
1919
+ * (e.g. for documentation in `app.config.ts`) or when you've previously overridden the token and want to switch back
1920
+ * to the default in a child injector.
1921
+ *
1922
+ * Production apps with a styled modal pass their own strategy via `provideNavigationConfig({ confirmationStrategy })` instead.
1923
+ * @example
1924
+ * ```typescript
1925
+ * // app.config.ts
1926
+ * export const appConfig: ApplicationConfig = {
1927
+ * providers: [
1928
+ * provideDefaultNavigationBlockConfirmation(),
1929
+ * // ... other providers
1930
+ * ]
1931
+ * };
1932
+ * ```
1933
+ */
1934
+ function provideDefaultNavigationBlockConfirmation() {
1935
+ return makeEnvironmentProviders([
1936
+ {
1937
+ provide: NAVIGATION_BLOCK_CONFIRMATION,
1938
+ useClass: BrowserConfirmationStrategy
1939
+ }
1940
+ ]);
1941
+ }
1942
+
1943
+ // Block state (module state, its producer, and the shell-side mirror consumer)
1944
+
1372
1945
  /**
1373
1946
  * This service observe changes in the document's body height.
1374
1947
  * When the height changes, it sends a resize message with the new height, to the connected peers
@@ -1409,10 +1982,10 @@ class ResizeService {
1409
1982
  });
1410
1983
  afterNextRender(() => this.resizeObserver?.observe(document.body));
1411
1984
  }
1412
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ResizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1413
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ResizeService, providedIn: 'root' }); }
1985
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ResizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1986
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ResizeService, providedIn: 'root' }); }
1414
1987
  }
1415
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ResizeService, decorators: [{
1988
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ResizeService, decorators: [{
1416
1989
  type: Injectable,
1417
1990
  args: [{
1418
1991
  providedIn: 'root'
@@ -1422,11 +1995,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
1422
1995
  /**
1423
1996
  * A service that handles theme messages and applies the received theme.
1424
1997
  */
1425
- class ThemeConsumerService {
1998
+ class ThemeConsumerService extends AbstractMessageConsumer {
1426
1999
  constructor() {
2000
+ super();
1427
2001
  this.domSanitizer = inject(DomSanitizer);
1428
- this.consumerManagerService = inject(ConsumerManagerService);
1429
- this.logger = inject(LoggerService);
1430
2002
  /**
1431
2003
  * The type of messages this service handles ('theme').
1432
2004
  */
@@ -1453,25 +2025,16 @@ class ThemeConsumerService {
1453
2025
  }
1454
2026
  }
1455
2027
  };
2028
+ /**
2029
+ * Auto-starts the consumer on creation.
2030
+ * @deprecated The constructor auto-starts the consumer for backwards compatibility. It will be removed in v15;
2031
+ */
1456
2032
  this.start();
1457
- inject(DestroyRef).onDestroy(() => this.stop());
1458
- }
1459
- /**
1460
- * Starts the theme handler service by registering it into the consumer manager service.
1461
- */
1462
- start() {
1463
- this.consumerManagerService.register(this);
1464
- }
1465
- /**
1466
- * Stops the theme handler service by unregistering it from the consumer manager service.
1467
- */
1468
- stop() {
1469
- this.consumerManagerService.unregister(this);
1470
2033
  }
1471
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1472
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeConsumerService, providedIn: 'root' }); }
2034
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2035
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeConsumerService, providedIn: 'root' }); }
1473
2036
  }
1474
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeConsumerService, decorators: [{
2037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeConsumerService, decorators: [{
1475
2038
  type: Injectable,
1476
2039
  args: [{
1477
2040
  providedIn: 'root'
@@ -1644,10 +2207,10 @@ class IframeActivityTrackerService {
1644
2207
  this.stopActivityInterval();
1645
2208
  this.config = undefined;
1646
2209
  }
1647
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IframeActivityTrackerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1648
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IframeActivityTrackerService, providedIn: 'root' }); }
2210
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: IframeActivityTrackerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2211
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: IframeActivityTrackerService, providedIn: 'root' }); }
1649
2212
  }
1650
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IframeActivityTrackerService, decorators: [{
2213
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: IframeActivityTrackerService, decorators: [{
1651
2214
  type: Injectable,
1652
2215
  args: [{
1653
2216
  providedIn: 'root'
@@ -1824,10 +2387,10 @@ class ActivityProducerService {
1824
2387
  this.lastEmitTimestamps.clear();
1825
2388
  this.iframeActivityTracker.stop();
1826
2389
  }
1827
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActivityProducerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1828
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActivityProducerService, providedIn: 'root' }); }
2390
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActivityProducerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2391
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActivityProducerService, providedIn: 'root' }); }
1829
2392
  }
1830
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActivityProducerService, decorators: [{
2393
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActivityProducerService, decorators: [{
1831
2394
  type: Injectable,
1832
2395
  args: [{
1833
2396
  providedIn: 'root'
@@ -1880,10 +2443,10 @@ class ActivityConsumerService {
1880
2443
  stop() {
1881
2444
  this.consumerManagerService.unregister(this);
1882
2445
  }
1883
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActivityConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1884
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActivityConsumerService, providedIn: 'root' }); }
2446
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActivityConsumerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2447
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActivityConsumerService, providedIn: 'root' }); }
1885
2448
  }
1886
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActivityConsumerService, decorators: [{
2449
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActivityConsumerService, decorators: [{
1887
2450
  type: Injectable,
1888
2451
  args: [{
1889
2452
  providedIn: 'root'
@@ -1894,5 +2457,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
1894
2457
  * Generated bundle index. Do not edit.
1895
2458
  */
1896
2459
 
1897
- export { ACTIVITY_EVENTS, ActivityConsumerService, ActivityProducerService, ApplyTheme, ConnectDirective, ConsumerManagerService, DEFAULT_ACTIVITY_PRODUCER_CONFIG, ERROR_MESSAGE_TYPE, HIGH_FREQUENCY_EVENTS, HistoryConsumerService, HostInfoPipe, IFRAME_INTERACTION_EVENT, IframeActivityTrackerService, IframeEmbedComponent, 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, VISIBILITY_CHANGE_EVENT, applyInitialTheme, applyTheme, downloadApplicationThemeCss, getAvailableConsumers, getDefaultClientEndpointStartOptions, getHostInfo, getStyle, hostQueryParams, isEmbedded, isErrorMessage, isUserActivityMessage, persistHostInfo, provideConnection, provideHistoryOverrides, registerConsumer, registerProducer, sendError };
2460
+ export { ACTIVITY_EVENTS, AbstractMessageConsumer, ActivityConsumerService, ActivityProducerService, ApplyTheme, BrowserConfirmationStrategy, ConnectDirective, ConsumerManagerService, DEFAULT_ACTIVITY_PRODUCER_CONFIG, ERROR_MESSAGE_TYPE, HIGH_FREQUENCY_EVENTS, HistoryConsumerService, HostInfoPipe, IFRAME_INTERACTION_EVENT, IframeActivityTrackerService, IframeEmbedComponent, KNOWN_MESSAGES, MFE_HOST_APPLICATION_ID_PARAM, MFE_HOST_URL_PARAM, MFE_MODULE_APPLICATION_ID_PARAM, NAVIGATION_BLOCK_CONFIRMATION, NAVIGATION_REQUEST_HANDLER, NavigationBlockConfirmationService, NavigationBlockService, NavigationBlockStateConsumerService, NavigationBlockStateProducerService, NavigationConsumerService, NavigationDecisionConsumerService, NavigationRequestConsumerService, NavigationRequestManagerService, ProducerManagerService, ResizeConsumerService, ResizeService, RestoreRoute, RouteMemorizeDirective, RouteMemorizeService, RoutingService, ScalableDirective, THEME_QUERY_PARAM_NAME, THEME_URL_SUFFIX, ThemeConsumerService, ThemeProducerService, VISIBILITY_CHANGE_EVENT, applyInitialTheme, applyTheme, createNavigationRequestHandler, createNavigationRequestShellHandler, downloadApplicationThemeCss, generateCorrelationId, getAvailableConsumers, getDefaultClientEndpointStartOptions, getHostInfo, getStyle, hostQueryParams, isEmbedded, isErrorMessage, isUserActivityMessage, navigationBlockModuleGuard, navigationBlockShellGuard, persistHostInfo, provideConnection, provideDefaultNavigationBlockConfirmation, provideHistoryOverrides, provideNavigationRequestModuleHandler, provideNavigationRequestShellHandler, registerConsumer, registerProducer, sendError };
1898
2461
  //# sourceMappingURL=ama-mfe-ng-utils.mjs.map