@scion/microfrontend-platform
Version:
SCION Microfrontend Platform enables you to successfully implement a framework-agnostic microfrontend architecture using iframes. It provides you fundamental APIs for microfrontends to communicate with each other across origins and facilitates embedding m
1 lines • 617 kB
Source Map (JSON)
{"version":3,"file":"scion-microfrontend-platform.mjs","sources":["../../../../projects/scion/microfrontend-platform/src/lib/platform-state.ts","../../../../projects/scion/microfrontend-platform/src/lib/platform.model.ts","../../../../projects/scion/microfrontend-platform/src/lib/ɵplatform.model.ts","../../../../projects/scion/microfrontend-platform/src/lib/microfrontend-platform-stopper.ts","../../../../projects/scion/microfrontend-platform/src/lib/logger.ts","../../../../projects/scion/microfrontend-platform/src/lib/microfrontend-platform.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/microfrontend-platform-config.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/host-manifest-interceptor.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/client-registry/client.registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/message-client.ts","../../../../projects/scion/microfrontend-platform/src/lib/ɵmessaging.model.ts","../../../../projects/scion/microfrontend-platform/src/lib/messaging.model.ts","../../../../projects/scion/microfrontend-platform/src/lib/topics.util.ts","../../../../projects/scion/microfrontend-platform/src/lib/topic-matcher.util.ts","../../../../projects/scion/microfrontend-platform/src/lib/operators.ts","../../../../projects/scion/microfrontend-platform/src/lib/safe-runner.ts","../../../../projects/scion/microfrontend-platform/src/lib/error.util.ts","../../../../projects/scion/microfrontend-platform/src/lib/observable-decorator.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/message-selector.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/broker-gateway.ts","../../../../projects/scion/microfrontend-platform/src/lib/platform-property-service.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/http-client.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/manifest-registry/manifest-registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/url.util.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/application-registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/qualifier-matcher.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/manifest-registry/manifest-object-store.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/manifest-registry/capability-interceptors.ts","../../../../projects/scion/microfrontend-platform/src/lib/qualifiers.util.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/manifest-registry/ɵmanifest-registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/focus/focus-tracker.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/manifest-fetcher.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/message-subscription.registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/topic-subscription.registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/message-interception.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/semver.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/client-registry/client.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/client-registry/ɵclient.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/intent-subscription.registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/predicates.util.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/param-matcher.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/intent-params.util.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/message-broker.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/manifest-registry/manifest-service.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/context/context.model.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/context/router-outlet-context-provider.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/router-outlet/router-outlet-url-assigner.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/keyboard-event/keystroke.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/router-outlet/metadata.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/router-outlet/router-outlet.element.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/context/context-service.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/router-outlet/relative-path-resolver.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/intent-client.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/router-outlet/outlet-router.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/router/microfrontend-intent-navigator.interceptor.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/client-registry/ɵclient.registry.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/host-app-config-provider.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/progress-monitor/progress-monitor.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/progress-monitor/progress-monitors.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/app-installer.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/activator/activator-installer.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/focus/focus-monitor.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/focus/focus-in-event-dispatcher.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/mouse-event/mouse-move-event-dispatcher.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/mouse-event/mouse-up-event-dispatcher.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/preferred-size/preferred-size-service.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/keyboard-event/keyboard-event-dispatcher.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/message-handler.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/ɵmessage-client.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/ɵintent-client.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/microfrontend-platform-client.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/microfrontend-platform-host.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/host-config.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/application-config.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/manifest-registry/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/message-broker/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/liveness-config.ts","../../../../projects/scion/microfrontend-platform/src/lib/host/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/connect-options.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/router-outlet/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/context/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/focus/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/preferred-size/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/manifest-registry/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/messaging/public_api.ts","../../../../projects/scion/microfrontend-platform/src/lib/client/public_api.ts","../../../../projects/scion/microfrontend-platform/src/public-api.ts","../../../../projects/scion/microfrontend-platform/src/scion-microfrontend-platform.ts"],"sourcesContent":["/*\n * Copyright (c) 2018-2020 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\n/**\n * Lifecycle states of the microfrontend platform.\n *\n * @category Platform\n */\nexport enum PlatformState {\n /**\n * Indicates that the platform is about to start.\n */\n Starting = 1,\n /**\n * Indicates that the platform started.\n */\n Started = 2,\n /**\n * Indicates that the platform is about to stop.\n */\n Stopping = 3,\n /**\n * Indicates that the platform is not yet started.\n */\n Stopped = 4,\n}\n\n/**\n * Runlevels are used to control in which startup phase to execute initializers when starting the platform.\n *\n * The platform reports that it has started after all initializers have completed successfully.\n *\n * @internal\n */\nexport enum Runlevel {\n /**\n * In runlevel 0, the platform host fetches manifests of registered micro applications.\n */\n Zero = 0,\n /**\n * In runlevel 1, the platform constructs eager beans.\n */\n One = 1,\n /**\n * From runlevel 2 and above, messaging is enabled. This is the default runlevel at which initializers execute if not specifying any runlevel.\n */\n Two = 2,\n /**\n * In runlevel 3, the platform host installs activator microfrontends.\n */\n Three = 3,\n}\n","/*\n * Copyright (c) 2018-2020 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\n/**\n * Manifest of an application.\n *\n * The manifest is a special file that contains information about a micro application. A micro application declares\n * its intentions and capabilities in its manifest file. The manifest needs to be registered in the host application.\n *\n * @category Platform\n * @category Intention API\n */\nexport interface Manifest {\n /**\n * The name of the application, e.g. displayed in the DevTools.\n */\n name: string;\n /**\n * URL to the application root. The URL can be fully qualified, or a path relative to the origin under\n * which serving the manifest file. If not specified, the origin of the manifest file acts as the base\n * URL. The platform uses the base URL to resolve microfrontends such as activator endpoints.\n * For a Single Page Application that uses hash-based routing, you typically specify the hash symbol (`#`)\n * as the base URL.\n */\n baseUrl?: string;\n /**\n * Functionality which this application intends to use.\n */\n intentions?: Intention[];\n /**\n * Functionality which this application provides that qualified apps can call via intent.\n */\n capabilities?: Capability[];\n}\n\n/**\n * Represents a dictionary of key-value pairs to qualify an intention, intent or capability.\n *\n * See {@link Intention}, {@link Capability} or {@link Intent} for the usage of wildcards\n * in qualifier properties.\n *\n * @category Intention API\n */\nexport interface Qualifier {\n [key: string]: string | number | boolean;\n}\n\n/**\n * Represents an application registered in the platform.\n *\n * @category Platform\n */\nexport interface Application {\n /**\n * Unique symbolic name of the application.\n */\n symbolicName: string;\n /**\n * Name of the application as specified in the manifest.\n */\n name: string;\n /**\n * URL to the application root.\n */\n baseUrl: string;\n /**\n * URL to the manifest of this application.\n */\n manifestUrl: string;\n /**\n * Maximum time (in milliseconds) that the host waits until the manifest for this application is loaded.\n *\n * This is the effective timeout, i.e, either the application-specific timeout as defined in {@link ApplicationConfig.manifestLoadTimeout},\n * or the global timeout as defined in {@link MicrofrontendPlatformConfig.manifestLoadTimeout}, otherwise `undefined`.\n */\n manifestLoadTimeout?: number;\n /**\n * Maximum time (in milliseconds) that the host waits for this application to signal readiness.\n *\n * This is the effective timeout, i.e, either the application-specific timeout as defined in {@link ApplicationConfig.activatorLoadTimeout},\n * or the global timeout as defined in {@link MicrofrontendPlatformConfig.activatorLoadTimeout}, otherwise `undefined`.\n */\n activatorLoadTimeout?: number;\n /**\n * Indicates whether this application can interact with private capabilities of other applications.\n */\n scopeCheckDisabled: boolean;\n /**\n * Indicates whether this application can interact with capabilities of other applications without having to declare respective intentions.\n */\n intentionCheckDisabled: boolean;\n /**\n * Indicates whether this application can register and unregister intentions dynamically at runtime.\n */\n intentionRegisterApiDisabled: boolean;\n /**\n * Version of the SCION Microfrontend Platform used by this application.\n */\n platformVersion: Promise<string>;\n}\n\n/**\n * The term capability refers to the Intention API of the SCION Microfrontend Platform.\n *\n * A capability represents some functionality of a micro application that is available to qualified micro applications through the Intention API.\n * A micro application declares its capabilities in its manifest. Qualified micro applications can browse capabilities similar to a catalog, or\n * interact with capabilities via intent.\n *\n * A capability is formulated in an abstract way consisting of a type and optionally a qualifier. The type categorizes a capability in terms of its\n * functional semantics. A capability may also define a qualifier to differentiate different capabilities of the same type.\n *\n * A capability can have private or public visibility. If private, which is by default, the capability is not visible to other micro\n * applications; thus, it can only be invoked or browsed by the providing micro application itself.\n *\n * A capability can specify parameters which the intent issuer can/must pass along with the intent. Parameters are part of the contract between\n * the intent publisher and the capability provider. They do not affect the intent routing, unlike the qualifier.\n *\n * Metadata can be associated with a capability in its properties section. For example, if providing a microfrontend, the URL to the\n * microfrontend can be added as property, or if the capability contributes an item to a menu, its label to be displayed.\n *\n * @category Intention API\n */\nexport interface Capability {\n /**\n * Categorizes the capability in terms of its functional semantics (e.g., `microfrontend` if providing a microfrontend).\n * It can be an arbitrary `string` literal and has no meaning to the platform.\n */\n type: string;\n /**\n * The qualifier is a dictionary of arbitrary key-value pairs to differentiate capabilities of the same `type` and is like\n * an abstract description of the capability. It should include enough information to uniquely identify the capability.\n *\n * Intents must exactly match the qualifier of the capability, if any.\n */\n qualifier?: Qualifier;\n /**\n * Specifies parameters which the intent issuer can/must pass along with the intent.\n *\n * Parameters are part of the contract between the intent publisher and the capability provider.\n * They do not affect the intent routing, unlike the qualifier.\n */\n params?: ParamDefinition[];\n /**\n * Controls if this capability is visible to other micro applications. If private, which is by default, the capability is not visible\n * to other micro applications; thus, it can only be invoked or looked up by the providing micro application.\n */\n private?: boolean;\n /**\n * A short description to explain the capability.\n */\n description?: string;\n /**\n * Arbitrary metadata to be associated with the capability.\n */\n properties?: {\n [key: string]: any;\n };\n /**\n * Metadata about the capability (read-only, exclusively managed by the platform).\n * @ignore\n */\n metadata?: {\n /**\n * Unique identity of this capability.\n */\n id: string;\n /**\n * Symbolic name of the application which provides this capability.\n */\n appSymbolicName: string;\n };\n}\n\n/**\n * The term intention refers to the Intention API of the SCION Microfrontend Platform.\n *\n * An intention refers to one or more capabilities that a micro application wants to interact with.\n *\n * Intentions are declared in the application’s manifest and are formulated in an abstract way, consisting of a type\n * and optionally a qualifier. The qualifier is used to differentiate capabilities of the same type.\n *\n * @category Intention API\n */\nexport interface Intention {\n /**\n * The type of capability to interact with.\n */\n type: string;\n /**\n * Qualifies the capability which to interact with.\n *\n * The qualifier is a dictionary of arbitrary key-value pairs to differentiate capabilities of the same `type`.\n *\n * The intention must exactly match the qualifier of the capability, if any. The intention qualifier allows using\n * wildcards to match multiple capabilities simultaneously.\n *\n * In the intention, the following wildcards are supported:\n * - **Asterisk wildcard character (`*`):**\\\n * Matches capabilities with such a qualifier property no matter of its value (except `null` or `undefined`).\n * Use it like this: `{property: '*'}`.\n * - **Partial wildcard (`**`):**\n * Matches capabilities even if having additional properties. Use it like this: `{'*': '*'}`.\n */\n qualifier?: Qualifier;\n /**\n * Metadata about this intention (read-only, exclusively managed by the platform).\n * @ignore\n */\n metadata?: {\n /**\n * Unique identity of this intent declaration.\n */\n id: string;\n /**\n * Symbolic name of the application which declares this intention.\n */\n appSymbolicName: string;\n };\n}\n\n/**\n * Built in capability types.\n *\n * @category Intention API\n */\nexport enum PlatformCapabilityTypes {\n /**\n * Type for registering an activator capability.\n *\n * @see ActivatorCapability\n */\n Activator = 'activator',\n /**\n * Type for registering a microfrontend capability.\n *\n * @see MicrofrontendCapability\n */\n Microfrontend = 'microfrontend',\n}\n\n/**\n * An activator allows a micro application to initialize and connect to the platform upon host application's startup,\n * i.e., when the user loads the web application into the browser.\n *\n * In the broadest sense, an activator is a kind of microfrontend, i.e. an HTML page that runs in an iframe. In contrast\n * to regular microfrontends, however, at platform startup, the platform loads activator microfrontends into hidden iframes\n * for the entire platform lifecycle, thus, providing a stateful session to the micro application on the client-side.\n *\n * Some typical use cases for activators are receiving messages and intents, preloading data, or flexibly providing capabilities.\n *\n * A micro application registers an activator as public _activator_ capability in its manifest, as follows:\n *\n * ```json\n * \"capabilities\": [\n * {\n * \"type\": \"activator\",\n * \"private\": false,\n * \"properties\": {\n * \"path\": \"path/to/the/activator\"\n * }\n * }\n * ]\n * ```\n *\n * #### Activation Context\n * An activator's microfrontend runs inside an activation context. The context provides access\n * to the activator capability, allowing to read properties declared on the activator capability.\n *\n * You can obtain the activation context using the {@link ContextService} as following.\n *\n * ```ts\n * // Looks up the activation context.\n * const ctx: ActivationContext = await Beans.get(ContextService).lookup(ACTIVATION_CONTEXT);\n * ```\n *\n * #### Multiple Activators\n * A micro application can register multiple activators. Note, that each activator boots the micro\n * application on its own and runs in a separate browsing context. The platform nominates one activator\n * of each micro application as its primary activator. The nomination has no relevance to the platform but\n * can help code decide whether to install singleton functionality.\n *\n * You can test if running in the primary activation context as following.\n * ```ts\n * // Looks up the activation context.\n * const ctx = await Beans.get(ContextService).lookup<ActivationContext>(ACTIVATION_CONTEXT);\n * // Checks if running in the context of the primary activator.\n * const isPrimary: boolean = ctx.primary;\n * ```\n *\n * #### Sharing State\n * Since an activator runs in a separate browsing context, microfrontends cannot directly access its state.\n * Instead, an activator could put data, for example, into session storage, so that microfrontends of its micro\n * application can access it. Alternatively, an activator could install a message listener, allowing microfrontends\n * to request data via client-side messaging.\n *\n * @category Platform\n * @category Intention API\n */\nexport interface ActivatorCapability extends Capability {\n type: PlatformCapabilityTypes.Activator;\n private: false;\n properties: {\n /**\n * Path where the platform can load the activator microfrontend. The path is relative to the base URL\n * of the micro application, as specified in the application manifest.\n */\n path: string;\n /**\n * Starting an activator may take some time. In order not to miss any messages or intents, you can instruct the platform host to\n * wait to enter started state until you signal the activator to be ready. For this purpose, you can define a set of topics where\n * to publish a ready message to signal readiness. If you specify multiple topics, the activator enters ready state after you have\n * published a ready message to all these topics. A ready message is an event; thus, a message without payload.\n *\n * If not specifying a readiness topic, the platform host does not wait for this activator to become ready. However, if you specify a\n * readiness topic, make sure that your activator has a fast startup time and signals readiness as early as possible not to delay\n * the startup of the platform host.\n */\n readinessTopics?: string | string[];\n /**\n * Arbitrary metadata to be associated with the capability.\n */\n [key: string]: any;\n };\n}\n\n/**\n * Represents a microfrontend that can be loaded into a <sci-router-outlet> using the {@link OutletRouter}.\n *\n * @category Intention API\n */\nexport interface MicrofrontendCapability extends Capability {\n type: PlatformCapabilityTypes.Microfrontend;\n properties: {\n /**\n * Specifies the path of the microfrontend.\n *\n * The path is relative to the base URL, as specified in the application manifest. If the\n * application does not declare a base URL, it is relative to the origin of the manifest file.\n *\n * The path allows the use of navigational symbols and named parameters to reference qualifier and parameter values.\n * A named parameter begins with a colon (`:`) followed by the qualifier or parameter name, and is allowed in path segments,\n * query parameters, matrix parameters and the fragment part. Named query and matrix parameters without a replacement are removed,\n * e.g., if referencing an optional parameter.\n *\n * #### Usage of named parameters in the path:\n * ```json\n * {\n * \"type\": \"microfrontend\",\n * \"qualifier\": {\n * \"entity\": \"product\"\n * },\n * \"params\": [\n * {\"name\": \"id\", \"required\": true}\n * ]\n * \"properties\": {\n * \"path\": \"product/:id\",\n * }\n * }\n * ```\n *\n * #### Path parameter example:\n * segment/:param1/segment/:param2\n *\n * #### Matrix parameter example:\n * segment/segment;matrixParam1=:param1;matrixParam2=:param2\n *\n * #### Query parameter example:\n * segment/segment?queryParam1=:param1&queryParam2=:param2\n */\n path: string;\n /**\n * Specifies the preferred outlet to load this microfrontend into.\n * Note that this preference is only a hint that will be ignored if the navigator\n * specifies an outlet for navigation.\n *\n * The precedence is as follows:\n * - Outlet as specified by navigator via {@link NavigationOptions#outlet}.\n * - Preferred outlet as specified in the microfrontend capability.\n * - Current outlet if navigating in the context of an outlet.\n * - {@link PRIMARY_OUTLET primary} outlet.\n */\n outlet?: string;\n /**\n * Instructs the router outlet to show a splash, such as a skeleton or loading indicator, until the microfrontend signals readiness.\n * The splash is the markup between the opening and closing tags of the router outlet element.\n *\n * @see SciRouterOutletElement\n * @see MicrofrontendPlatformClient.signalReady\n */\n showSplash?: boolean;\n /**\n * Arbitrary metadata to be associated with the capability.\n */\n [key: string]: any;\n };\n}\n\n/**\n * Describes a parameter to be passed along with an intent.\n *\n * @category Intention API\n */\nexport interface ParamDefinition {\n /**\n * Specifies the name of the parameter.\n */\n name: string;\n /**\n * Describes the parameter and its usage in more detail.\n */\n description?: string;\n /**\n * Specifies whether the parameter must be passed along with the intent.\n */\n required: boolean;\n /**\n * Allows deprecating the parameter.\n *\n * It is good practice to explain the deprecation, provide the date of removal, and how to migrate.\n * If renaming the parameter, you can set the `useInstead` property to specify which parameter to use\n * instead. At runtime, this will map the parameter to the specified replacement, allowing for\n * straightforward migration on the provider side.\n */\n deprecated?: true | {message?: string; useInstead?: string};\n\n /**\n * Allows the declaration of additional metadata that can be interpreted in an interceptor, for example.\n */\n [property: string]: any;\n}\n\n/**\n * Symbol to determine if this app instance is running as the platform host.\n *\n * ```ts\n * const isPlatformHost: boolean = Beans.get(IS_PLATFORM_HOST);\n * ```\n *\n * @category Platform\n */\nexport const IS_PLATFORM_HOST = Symbol('IS_PLATFORM_HOST');\n\n/**\n * Symbol to get the application's symbolic name from the bean manager.\n *\n * @category Platform\n */\nexport const APP_IDENTITY = Symbol('APP_IDENTITY');\n\n/**\n * Key for obtaining the current activation context using {@link ContextService}.\n *\n * The activation context is only available to microfrontends loaded by an activator.\n *\n * @see {@link ActivationContext}\n * @see {@link ContextService}\n * @category Platform\n */\nexport const ACTIVATION_CONTEXT = 'ɵACTIVATION_CONTEXT';\n\n/**\n * Information about the activator that loaded a microfrontend.\n *\n * This context is available to a microfrontend if loaded by an application activator.\n * This object can be obtained from the {@link ContextService} using the name {@link ACTIVATION_CONTEXT}.\n *\n * ```ts\n * const ctx = await Beans.get(ContextService).lookup<ActivationContext>(ACTIVATION_CONTEXT);\n * ```\n *\n * @see {@link ACTIVATION_CONTEXT}\n * @see {@link ContextService}\n * @category Platform\n */\nexport interface ActivationContext {\n /**\n * Indicates whether running in the context of the primary activator.\n * The platform nominates one activator of each app as primary activator.\n */\n primary: boolean;\n /**\n * Metadata about the activator that activated the microfrontend.\n */\n activator: ActivatorCapability;\n}\n\n/**\n * Allows filtering manifest objects like capabilities or intentions.\n *\n * All specified filter criteria are \"AND\"ed together. Unspecified filter criteria are ignored.\n * If no filter criterion is specified, no filtering takes place, thus all available objects are returned.\n *\n * @category Intention API\n */\nexport interface ManifestObjectFilter {\n /**\n * Manifest objects of the given identity.\n */\n id?: string;\n /**\n * Manifest objects of the given function type.\n */\n type?: string;\n /**\n * Manifest objects matching the given qualifier.\n */\n qualifier?: Qualifier;\n /**\n * Manifest objects provided by the given app.\n */\n appSymbolicName?: string;\n}\n\n/**\n * Represents a request to determine if an application is qualified to interact with a given capability.\n */\nexport interface ApplicationQualifiedForCapabilityRequest {\n /**\n * Specifies the symbolic name of the application under test.\n */\n appSymbolicName: string;\n /**\n * Identifies the capability for which to request the application's qualification.\n */\n capabilityId: string;\n}\n","/*\n * Copyright (c) 2018-2022 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {Application} from './platform.model';\n\n/**\n * Represents an application registered in the platform.\n *\n * The version is omitted because not known at the time of registration, but only when first connecting to the host, e.g., in an activator.\n *\n * @internal\n */\nexport interface ɵApplication extends Omit<Application, 'platformVersion'> { // eslint-disable-line @typescript-eslint/no-empty-interface\n /**\n * Specifies the origin(s) where message from this application must originate from. Messages of a different origin will be rejected.\n */\n allowedMessageOrigins: Set<string>;\n}\n\n/**\n * Symbol to get the version of the SCION Microfrontend Platform.\n *\n * @internal\n */\nexport const ɵVERSION = Symbol('ɵVERSION');\n\n/**\n * Symbol to get the topmost window in the window hierarchy from the bean manager.\n *\n * Alias for `window.top` that can be overridden in tests, e.g., to simulate\n * the client to connect to a remote host.\n *\n * @internal\n */\nexport const ɵWINDOW_TOP = Symbol('ɵWINDOW_TOP');\n","/*\n * Copyright (c) 2018-2022 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\nimport {PreDestroy} from '@scion/toolkit/bean-manager';\nimport {MicrofrontendPlatform} from './microfrontend-platform';\nimport {fromEvent, race, Subject} from 'rxjs';\nimport {take, takeUntil} from 'rxjs/operators';\n\n/**\n * Stops the platform and disconnects this client from the host when the browser unloads the document.\n *\n * By default, the platform initiates shutdown when the browser unloads the document, i.e., when `beforeunload` is triggered.\n * The main reason for `beforeunload` instead of `unload` is to avoid posting messages to disposed windows.\n * However, if `beforeunload` is not triggered, e.g., when an iframe is removed, we fall back to `unload`.\n *\n * @category Platform\n */\nexport abstract class MicrofrontendPlatformStopper {\n}\n\n/**\n * @internal\n */\nexport class ɵMicrofrontendPlatformStopper implements MicrofrontendPlatformStopper, PreDestroy {\n\n private _destroy$ = new Subject<void>();\n\n constructor() {\n race(fromEvent(window, 'beforeunload'), fromEvent(window, 'unload'))\n .pipe(\n take(1),\n takeUntil(this._destroy$),\n )\n .subscribe(() => {\n MicrofrontendPlatform.destroy();\n });\n }\n\n public preDestroy(): void {\n this._destroy$.next();\n }\n}\n","/*\n * Copyright (c) 2018-2020 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {Beans} from '@scion/toolkit/bean-manager';\nimport {APP_IDENTITY} from './platform.model';\nimport {ɵVERSION} from './ɵplatform.model';\n\n/**\n * Logger used by the platform to log to the console.\n *\n * Replace this bean to capture the log output.\n *\n * @category Platform\n */\nexport abstract class Logger {\n\n /**\n * Logs with severity debug.\n */\n public abstract debug(message?: any, ...args: any[]): void;\n\n /**\n * Logs with severity info.\n */\n public abstract info(message?: any, ...args: any[]): void;\n\n /**\n * Logs with severity warn.\n */\n public abstract warn(message?: any, ...args: any[]): void;\n\n /**\n * Logs with severity error.\n */\n public abstract error(message?: any, ...args: any[]): void;\n}\n\n/**\n * Logger used by the platform to log to the console.\n *\n * Replace this bean to capture the log output.\n *\n * @internal\n */\nexport class ConsoleLogger implements Logger {\n\n public debug(message?: any, ...args: any[]): void {\n this.log('debug', message, args);\n }\n\n public info(message?: any, ...args: any[]): void {\n this.log('info', message, args);\n }\n\n public warn(message?: any, ...args: any[]): void {\n this.log('warn', message, args);\n }\n\n public error(message?: any, ...args: any[]): void {\n this.log('error', message, args);\n }\n\n private log(severity: 'debug' | 'info' | 'warn' | 'error', message: any, args: any[]): void {\n const loggingContext: LoggingContext = args[0] instanceof LoggingContext ? args.shift() : {appSymbolicName: Beans.get(APP_IDENTITY), version: Beans.get(ɵVERSION)};\n const prefix = new Array<string>()\n .concat(loggingContext.version ? `[@scion/microfrontend-platform@${loggingContext.version}]` : '[@scion/microfrontend-platform]')\n .concat(`[${loggingContext.appSymbolicName}]`)\n .join('');\n\n if (console && typeof console[severity] === 'function') {\n const consoleFn = console[severity];\n args?.length ? consoleFn(`${prefix} ${message}`, ...args) : consoleFn(`${prefix} ${message}`);\n }\n }\n}\n\n/**\n * Logger that does nothing.\n *\n * @internal\n */\nexport const NULL_LOGGER = new class extends Logger {\n\n public debug(message?: any, ...args: any[]): void {\n // NOOP\n }\n\n public info(message?: any, ...args: any[]): void {\n // NOOP\n }\n\n public warn(message?: any, ...args: any[]): void {\n // NOOP\n }\n\n public error(message?: any, ...args: any[]): void {\n // NOOP\n }\n};\n\n/**\n * Contextual information to add to the log message.\n *\n * Pass an instance of this class as the first argument to the logger when logging a message.\n *\n * @internal\n */\nexport class LoggingContext {\n\n constructor(public appSymbolicName: string, public version?: string) {\n }\n}\n","/*\n * Copyright (c) 2018-2022 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\nimport {BehaviorSubject, Observable} from 'rxjs';\nimport {first} from 'rxjs/operators';\nimport {PlatformState, Runlevel} from './platform-state';\nimport {Beans} from '@scion/toolkit/bean-manager';\nimport {APP_IDENTITY, IS_PLATFORM_HOST} from './platform.model';\nimport {ɵVERSION, ɵWINDOW_TOP} from './ɵplatform.model';\nimport {MicrofrontendPlatformStopper, ɵMicrofrontendPlatformStopper} from './microfrontend-platform-stopper';\nimport {ConsoleLogger, Logger} from './logger';\n\n/**\n * Current version of the SCION Microfrontend Platform.\n */\nconst version = '1.4.0';\n\n/**\n * The central class of the SCION Microfrontend Platform. This class cannot be instantiated. All functionality is provided by static methods.\n *\n * To enable tree-shaking of the SCION Microfrontend Platform, the platform provides three separate entry points:\n * - {@link MicrofrontendPlatformHost} to configure and start the platform in the host\n * - {@link MicrofrontendPlatformClient} to connect to the platform from a microfrontend\n * - {@link MicrofrontendPlatform} to react to platform lifecycle events and stop the platform\n *\n * ## SCION Microfrontend Platform\n *\n * SCION Microfrontend Platform is a TypeScript-based open source library that enables the implementation of a framework-agnostic\n * microfrontend architecture using iframes. It provides fundamental APIs for microfrontends to communicate with each other across origins\n * and facilitates embedding microfrontends using a web component and a router. SCION Microfrontend Platform is a lightweight, web stack\n * agnostic library that has no user-facing components and does not dictate any form of application structure.\n *\n * You can continue using the frameworks you love since the platform integrates microfrontends via iframes. Iframes by nature provide\n * maximum isolation and allow the integration of any web application without complex adaptation. The platform aims to shield developers\n * from iframe specifics and the low-level messaging mechanism to focus instead on integrating microfrontends.\n *\n * #### Cross-microfrontend communication\n * The platform adds a pub/sub layer on top of the native `postMessage` mechanism to enable microfrontends to communicate with each other\n * easily across origins. Communication comes in two flavors: topic-based and intent-based. Both models feature request-response message\n * exchange, support retained messages for late subscribers to receive the latest messages, and provide API to intercept messages to\n * implement cross-cutting messaging concerns.\n *\n * Topic-based messaging enables you to publish messages to multiple subscribers via a common topic. Intent-based communication focuses on\n * controlled collaboration between applications. To collaborate, an application must express an intention. Manifesting intentions enables\n * us to see dependencies between applications down to the functional level.\n *\n * #### Microfrontend Integration and Routing\n * The platform makes it easy to integrate microfrontends through its router-outlet. The router-outlet is a web component that wraps an iframe.\n * It solves many of the cumbersome quirks of iframes and helps to overcome iframe restrictions. For example, it can adapt its size to the\n * preferred size of embedded content, supports keyboard event propagation and lets you pass contextual data to embedded content.\n * Using the router, you control which web content to display in an outlet. Multiple outlets can display different content, determined by\n * different outlet names, all at the same time. Routing works across application boundaries and enables features such as persistent navigation.\n *\n * ***\n *\n * A microfrontend architecture can be achieved in many ways, each with its pros and cons. The SCION Microfrontend Platform uses\n * the iframe approach primarily since iframes by nature provide the highest possible level of isolation through a separate browsing context.\n * The microfrontend design approach is very tempting and has obvious advantages, especially for large-scale and long-lasting projects, most\n * notably because we are observing an enormous dynamic in web frameworks. The SCION Microfrontend Platform provides you with the necessary\n * tools to best support you in implementing such an architecture.\n *\n * @see {@link MicrofrontendPlatformHost}\n * @see {@link MicrofrontendPlatformClient}\n *\n * @see {@link MessageClient}\n * @see {@link IntentClient}\n * @see {@link SciRouterOutletElement}\n * @see {@link OutletRouter}\n * @see {@link ContextService}\n * @see {@link PreferredSizeService}\n * @see {@link ManifestService}\n * @see {@link FocusMonitor}\n * @see {@link ActivatorCapability}\n *\n * @category Platform\n * @category Lifecycle\n */\nexport class MicrofrontendPlatform {\n\n private static readonly _state$ = new BehaviorSubject<PlatformState>(PlatformState.Stopped);\n\n private constructor() {\n }\n\n /**\n * @internal\n */\n public static async startPlatform(startupFn?: () => void): Promise<void> {\n if (this.state === PlatformState.Started) {\n return Promise.reject(Error('[MicrofrontendPlatformStartupError] Platform already started'));\n }\n\n try {\n startupFn?.();\n await this.enterState(PlatformState.Starting);\n await Beans.start({eagerBeanConstructRunlevel: Runlevel.One, initializerDefaultRunlevel: Runlevel.Two});\n await this.enterState(PlatformState.Started);\n return Promise.resolve();\n }\n catch (error) {\n await this.destroy();\n return Promise.reject(Error(`[MicrofrontendPlatformStartupError] Microfrontend platform failed to start: ${error}`));\n }\n }\n\n /**\n * Destroys this platform and releases resources allocated.\n *\n * @return a Promise that resolves once the platformed stopped.\n */\n public static async destroy(): Promise<void> {\n await this.enterState(PlatformState.Stopping);\n Beans.destroy();\n await this.enterState(PlatformState.Stopped);\n }\n\n /**\n * @return the current platform state.\n */\n public static get state(): PlatformState {\n return this._state$.getValue();\n }\n\n /**\n * Observable that, when subscribed, emits the current platform lifecycle state.\n * It never completes and emits continuously when the platform enters\n * another state.\n */\n public static get state$(): Observable<PlatformState> {\n return this._state$;\n }\n\n /**\n * Waits for the platform to enter the specified {@link PlatformState}.\n * If already in that state, the Promise resolves instantly.\n *\n * @param state - the state to wait for.\n * @return A Promise that resolves when the platform enters the given state.\n * If already in that state, the Promise resolves instantly.\n */\n public static async whenState(state: PlatformState): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this._state$\n .pipe(first(it => it === state))\n .subscribe({\n error: reject,\n complete: resolve,\n });\n });\n }\n\n private static async enterState(newState: PlatformState): Promise<void> {\n const currentState = (this.state === PlatformState.Stopped) ? -1 : this.state;\n if (currentState >= newState) {\n throw Error(`[PlatformStateError] Failed to enter platform state [prevState=${PlatformState[this.state]}, newState=${PlatformState[newState]}].`);\n }\n\n this._state$.next(newState);\n\n // Let microtasks waiting for entering that state to resolve first.\n await this.whenState(newState);\n }\n}\n\n/**\n * @internal\n */\nexport function providePlatformEnvironment(config: {symbolicName: string; isPlatformHost: boolean}): void {\n Beans.register(IS_PLATFORM_HOST, {useValue: config.isPlatformHost});\n Beans.register(APP_IDENTITY, {useValue: config.symbolicName});\n Beans.registerIfAbsent(ɵWINDOW_TOP, {useValue: window.top});\n Beans.registerIfAbsent(ɵVERSION, {useValue: version, destroyOrder: BeanDestroyOrders.CORE});\n Beans.registerIfAbsent(MicrofrontendPlatformStopper, {useClass: ɵMicrofrontendPlatformStopper, eager: true});\n Beans.registerIfAbsent(Logger, {useClass: ConsoleLogger, destroyOrder: BeanDestroyOrders.CORE});\n}\n\n/**\n * Specifies destroy orders of platform-specific beans, enabling controlled termination of the platform.\n *\n * @internal\n */\nexport enum BeanDestroyOrders {\n /**\n * Use for core platform beans which should be destroyed as the very last beans.\n */\n CORE = Number.MAX_SAFE_INTEGER,\n /**\n * Use for the {@link MessageBroker}.\n */\n BROKER = CORE - 1,\n /**\n * Use for messaging-related beans.\n */\n MESSAGING = BROKER - 1\n}\n","/*\n * Copyright (c) 2018-2020 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {ApplicationConfig} from './application-config';\nimport {HostConfig} from './host-config';\nimport {LivenessConfig} from './liveness-config';\n\n/**\n * Configures the platform and defines the micro applications running in the platform.\n *\n * @category Platform\n */\nexport abstract class MicrofrontendPlatformConfig {\n /**\n * Lists the micro applications able to connect to the platform to interact with other micro applications.\n */\n public abstract readonly applications: ApplicationConfig[];\n /**\n * Configures the interaction of the host application with the platform.\n *\n * As with micro applications, you can provide a manifest for the host, allowing the host to contribute capabilities and declare intentions.\n */\n public abstract readonly host?: HostConfig;\n /**\n * Controls whether the Activator API is enabled.\n *\n * Activating the Activator API enables micro applications to contribute `activator` microfrontends. Activator microfrontends are loaded\n * at platform startup for the entire lifecycle of the platform. An activator is a startup hook for micro applications to initialize\n * or register message or intent handlers to provide functionality.\n *\n * By default, this API is enabled.\n *\n * @see {@link ActivatorCapability}\n */\n public abstract readonly activatorApiDisabled?: boolean;\n /**\n * Maximum time (in milliseconds) that the platform waits until the manifest of an application is loaded.\n * You can set a different timeout per application via {@link ApplicationConfig.manifestLoadTimeout}.\n * If not set, by default, the browser's HTTP fetch timeout applies.\n *\n * Consider setting this timeout if, for example, a web application firewall delays the responses of unavailable\n * applications.\n */\n public abstract readonly manifestLoadTimeout?: number;\n /**\n * Maximum time (in milliseconds) for each application to signal readiness.\n *\n * If specified and activating an application takes longer, the host logs an error and continues startup.\n * Has no effect for applications which provide no activator(s) or are not configured to signal readiness.\n * You can set a different timeout per application via {@link ApplicationConfig.activatorLoadTimeout}.\n *\n * By default, no timeout is set, meaning that if an app fails to signal readiness, e.g., due to an error,\n * that app would block the host startup process indefinitely. It is therefore recommended to specify a\n * timeout accordingly.\n */\n public abstract readonly activatorLoadTimeout?: number;\n /**\n * Configures the liveness probe performed at regular intervals between host and clients to detect and dispose stale clients.\n * Clients not replying to the probe are removed.\n */\n public abstract readonly liveness?: LivenessConfig;\n /**\n * Defines user-defined properties which can be read by micro applications via {@link PlatformPropertyService}.\n */\n public abstract readonly properties?: {\n [key: string]: any;\n };\n}\n","/*\n * Copyright (c) 2018-2020 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {Intention, Manifest, PlatformCapabilityTypes} from '../platform.model';\nimport {MicrofrontendPlatformConfig} from './microfrontend-platform-config';\nimport {Beans} from '@scion/toolkit/bean-manager';\n\n/**\n * Hook to intercept the host manifest before it is registered in the platform.\n *\n * If integrating the platform in a library, you may need to intercept the manifest of the host in order to introduce library-specific behavior.\n *\n * You can register the interceptor in the bean manager, as follows:\n *\n * ```ts\n * Beans.register(HostManifestInterceptor, {useClass: YourInterceptor, multi: true});\n * ```\n *\n * The interceptor may look as following:\n * ```ts\n * class YourInterceptor implements HostManifestInterceptor {\n *\n * public intercept(hostManifest: Manifest): void {\n * hostManifest.intentions = [\n * ...hostManifest.intentions || [],\n * provideMicrofrontendIntention(),\n * ];\n * hostManifest.capabilities = [\n * ...hostManifest.capabilities || [],\n * provideMessageBoxCapability(),\n * ];\n * }\n * }\n *\n * function provideMicrofrontendIntention(): Intention {\n * return {\n * type: 'microfrontend',\n * qualifier: {'*': '*'},\n * };\n * }\n *\n * function provideMessageBoxCapability(): Capability {\n * return {\n * type: 'messagebox',\n * qualifier: {},\n * private: false,\n * description: 'Allows displaying a simple message to the user.',\n * };\n * }\n *\n * ```\n *\n * @category Platform\n * @category Intention API\n */\nexport abstract class HostManifestInterceptor {\n\n /**\n * Allows modifying the host manifest before it i