@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,229 lines (1,219 loc) • 147 kB
TypeScript
import { Observable, MonoTypeOperatorFunction, OperatorFunction, Subscription } from 'rxjs';
import { Dictionary } from '@scion/toolkit/util';
import { PreDestroy, Initializer } from '@scion/toolkit/bean-manager';
/**
* Lifecycle states of the microfrontend platform.
*
* @category Platform
*/
declare enum PlatformState {
/**
* Indicates that the platform is about to start.
*/
Starting = 1,
/**
* Indicates that the platform started.
*/
Started = 2,
/**
* Indicates that the platform is about to stop.
*/
Stopping = 3,
/**
* Indicates that the platform is not yet started.
*/
Stopped = 4
}
/**
* The central class of the SCION Microfrontend Platform. This class cannot be instantiated. All functionality is provided by static methods.
*
* To enable tree-shaking of the SCION Microfrontend Platform, the platform provides three separate entry points:
* - {@link MicrofrontendPlatformHost} to configure and start the platform in the host
* - {@link MicrofrontendPlatformClient} to connect to the platform from a microfrontend
* - {@link MicrofrontendPlatform} to react to platform lifecycle events and stop the platform
*
* ## SCION Microfrontend Platform
*
* SCION Microfrontend Platform is a TypeScript-based open source library that enables the implementation of a framework-agnostic
* microfrontend architecture using iframes. It provides fundamental APIs for microfrontends to communicate with each other across origins
* and facilitates embedding microfrontends using a web component and a router. SCION Microfrontend Platform is a lightweight, web stack
* agnostic library that has no user-facing components and does not dictate any form of application structure.
*
* You can continue using the frameworks you love since the platform integrates microfrontends via iframes. Iframes by nature provide
* maximum isolation and allow the integration of any web application without complex adaptation. The platform aims to shield developers
* from iframe specifics and the low-level messaging mechanism to focus instead on integrating microfrontends.
*
* #### Cross-microfrontend communication
* The platform adds a pub/sub layer on top of the native `postMessage` mechanism to enable microfrontends to communicate with each other
* easily across origins. Communication comes in two flavors: topic-based and intent-based. Both models feature request-response message
* exchange, support retained messages for late subscribers to receive the latest messages, and provide API to intercept messages to
* implement cross-cutting messaging concerns.
*
* Topic-based messaging enables you to publish messages to multiple subscribers via a common topic. Intent-based communication focuses on
* controlled collaboration between applications. To collaborate, an application must express an intention. Manifesting intentions enables
* us to see dependencies between applications down to the functional level.
*
* #### Microfrontend Integration and Routing
* The platform makes it easy to integrate microfrontends through its router-outlet. The router-outlet is a web component that wraps an iframe.
* It solves many of the cumbersome quirks of iframes and helps to overcome iframe restrictions. For example, it can adapt its size to the
* preferred size of embedded content, supports keyboard event propagation and lets you pass contextual data to embedded content.
* Using the router, you control which web content to display in an outlet. Multiple outlets can display different content, determined by
* different outlet names, all at the same time. Routing works across application boundaries and enables features such as persistent navigation.
*
* ***
*
* A microfrontend architecture can be achieved in many ways, each with its pros and cons. The SCION Microfrontend Platform uses
* the iframe approach primarily since iframes by nature provide the highest possible level of isolation through a separate browsing context.
* The microfrontend design approach is very tempting and has obvious advantages, especially for large-scale and long-lasting projects, most
* notably because we are observing an enormous dynamic in web frameworks. The SCION Microfrontend Platform provides you with the necessary
* tools to best support you in implementing such an architecture.
*
* @see {@link MicrofrontendPlatformHost}
* @see {@link MicrofrontendPlatformClient}
*
* @see {@link MessageClient}
* @see {@link IntentClient}
* @see {@link SciRouterOutletElement}
* @see {@link OutletRouter}
* @see {@link ContextService}
* @see {@link PreferredSizeService}
* @see {@link ManifestService}
* @see {@link FocusMonitor}
* @see {@link ActivatorCapability}
*
* @category Platform
* @category Lifecycle
*/
declare class MicrofrontendPlatform {
private static readonly _state$;
private constructor();
/**
* Destroys this platform and releases resources allocated.
*
* @return a Promise that resolves once the platformed stopped.
*/
static destroy(): Promise<void>;
/**
* @return the current platform state.
*/
static get state(): PlatformState;
/**
* Observable that, when subscribed, emits the current platform lifecycle state.
* It never completes and emits continuously when the platform enters
* another state.
*/
static get state$(): Observable<PlatformState>;
/**
* Waits for the platform to enter the specified {@link PlatformState}.
* If already in that state, the Promise resolves instantly.
*
* @param state - the state to wait for.
* @return A Promise that resolves when the platform enters the given state.
* If already in that state, the Promise resolves instantly.
*/
static whenState(state: PlatformState): Promise<void>;
private static enterState;
}
/**
* Describes how to register an application in the platform.
*
* @category Platform
*/
interface ApplicationConfig {
/**
* Unique symbolic name of this micro application.
*
* The symbolic name must be unique and contain only lowercase alphanumeric characters and hyphens.
*/
symbolicName: string;
/**
* URL to the application manifest.
*/
manifestUrl: string;
/**
* Specifies an additional origin (in addition to the origin of the application) from which the application is allowed
* to connect to the platform.
*
* By default, if not set, the application is allowed to connect from the origin of the manifest URL or the base URL as
* specified in the manifest file. Setting an additional origin may be necessary if, for example, integrating microfrontends
* into a rich client, enabling an integrator to bridge messages between clients and host across browser boundaries.
*/
secondaryOrigin?: string;
/**
* Maximum time (in milliseconds) that the host waits until the manifest for this application is loaded.
*
* If set, overrides the global timeout as configured in {@link MicrofrontendPlatformConfig.manifestLoadTimeout}.
*/
manifestLoadTimeout?: number;
/**
* Maximum time (in milliseconds) for this application to signal readiness.
*
* If activating this application takes longer, the host logs an error and continues startup.
* If set, overrides the global timeout as configured in {@link MicrofrontendPlatformConfig.activatorLoadTimeout}.
*/
activatorLoadTimeout?: number;
/**
* Excludes this micro application from registration, e.g. to not register it in a specific environment.
*/
exclude?: boolean;
/**
* Allows this application to access private capabilities of other applications.
*
* Disabling this check is discouraged. Enabled by default.
*/
scopeCheckDisabled?: boolean;
/**
* Allows this application to access public capabilities of other applications without declaring an intention.
*
* Disabling this check is discouraged. Enabled by default.
*/
intentionCheckDisabled?: boolean;
/**
* Allows this application to access inactive capabilities.
*
* Disabling this check is discouraged. Enabled by default.
*/
capabilityActiveCheckDisabled?: boolean;
/**
* Allows this application to register and unregister intentions at runtime.
*
* Enabling this API is discouraged. Disabled by default.
*/
intentionRegisterApiDisabled?: boolean;
}
/**
* Manifest of an application.
*
* The manifest is a special file that contains information about a micro application. A micro application declares
* its intentions and capabilities in its manifest file. The manifest needs to be registered in the host application.
*
* @category Platform
* @category Intention API
*/
interface Manifest {
/**
* The name of the application, e.g. displayed in the DevTools.
*/
name: string;
/**
* URL to the application root. The URL can be fully qualified, or a path relative to the origin under
* which serving the manifest file. If not specified, the origin of the manifest file acts as the base
* URL. The platform uses the base URL to resolve microfrontends such as activator endpoints.
* For a Single Page Application that uses hash-based routing, you typically specify the hash symbol (`#`)
* as the base URL.
*/
baseUrl?: string;
/**
* Functionality which this application intends to use.
*/
intentions?: Intention[];
/**
* Functionality which this application provides that qualified apps can call via intent.
*/
capabilities?: Capability[];
}
/**
* Represents a dictionary of key-value pairs to qualify an intention, intent or capability.
*
* See {@link Intention}, {@link Capability} or {@link Intent} for the usage of wildcards
* in qualifier properties.
*
* @category Intention API
*/
interface Qualifier {
[key: string]: string | number | boolean;
}
/**
* Represents an application registered in the platform.
*
* @category Platform
*/
interface Application {
/**
* Unique symbolic name of the application.
*/
symbolicName: string;
/**
* Name of the application as specified in the manifest.
*/
name: string;
/**
* URL to the application root.
*/
baseUrl: string;
/**
* URL to the manifest of this application.
*/
manifestUrl: string;
/**
* Maximum time (in milliseconds) that the host waits until the manifest for this application is loaded.
*
* This is the effective timeout, i.e, either the application-specific timeout as defined in {@link ApplicationConfig.manifestLoadTimeout},
* or the global timeout as defined in {@link MicrofrontendPlatformConfig.manifestLoadTimeout}, otherwise `undefined`.
*/
manifestLoadTimeout?: number;
/**
* Maximum time (in milliseconds) that the host waits for this application to signal readiness.
*
* This is the effective timeout, i.e, either the application-specific timeout as defined in {@link ApplicationConfig.activatorLoadTimeout},
* or the global timeout as defined in {@link MicrofrontendPlatformConfig.activatorLoadTimeout}, otherwise `undefined`.
*/
activatorLoadTimeout?: number;
/**
* Indicates whether this application is allowed to access private capabilities of other applications.
*/
scopeCheckDisabled: boolean;
/**
* Indicates whether this application is allowed to access public capabilities of other applications without declaring an intention.
*/
intentionCheckDisabled: boolean;
/**
* Indicates whether this application is allowed to access inactive capabilities.
*/
capabilityActiveCheckDisabled: boolean;
/**
* Indicates whether this application is allowed to register and unregister intentions at runtime.
*/
intentionRegisterApiDisabled: boolean;
/**
* Version of the SCION Microfrontend Platform used by this application.
*/
platformVersion: Promise<string>;
}
/**
* The term capability refers to the Intention API of the SCION Microfrontend Platform.
*
* A capability represents some functionality of a micro application that is available to qualified micro applications through the Intention API.
* A micro application declares its capabilities in its manifest. Qualified micro applications can browse capabilities similar to a catalog, or
* interact with capabilities via intent.
*
* 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
* functional semantics. A capability may also define a qualifier to differentiate different capabilities of the same type.
*
* A capability can have private or public visibility. If private, which is by default, the capability is not visible to other micro
* applications; thus, it can only be invoked or browsed by the providing micro application itself.
*
* A capability can specify parameters which the intent issuer can/must pass along with the intent. Parameters are part of the contract between
* the intent publisher and the capability provider. They do not affect the intent routing, unlike the qualifier.
*
* Metadata can be associated with a capability in its properties section. For example, if providing a microfrontend, the URL to the
* microfrontend can be added as property, or if the capability contributes an item to a menu, its label to be displayed.
*
* @category Intention API
*/
interface Capability {
/**
* Categorizes the capability in terms of its functional semantics (e.g., `microfrontend` if providing a microfrontend).
* It can be an arbitrary `string` literal and has no meaning to the platform.
*/
type: string;
/**
* The qualifier is a dictionary of arbitrary key-value pairs to differentiate capabilities of the same `type` and is like
* an abstract description of the capability. It should include enough information to uniquely identify the capability.
*
* Intents must exactly match the qualifier of the capability, if any.
*/
qualifier?: Qualifier;
/**
* Specifies parameters which the intent issuer can/must pass along with the intent.
*
* Parameters are part of the contract between the intent publisher and the capability provider.
* They do not affect the intent routing, unlike the qualifier.
*/
params?: ParamDefinition[];
/**
* Controls whether this capability is private. Defaults to `true`.
*
* If private, the capability is not visible to other applications and can only be accessed by the providing application.
*
* Note: Applications configured with `scopeCheckDisabled` can still access private capabilities (discouraged).
*/
private?: boolean;
/**
* Controls whether this capability is inactive. Defaults to `false`.
*
* Capabilities can be marked as inactive in a capability interceptor, for example, based on user permissions.
* Inactive capabilities are unavailable to applications but still visible in the SCION DevTools for discovery.
*
* Note: Applications configured with `capabilityActiveCheckDisabled` can still access inactive capabilities (discouraged).
*/
inactive?: boolean;
/**
* A short description to explain the capability.
*/
description?: string;
/**
* Arbitrary metadata to be associated with the capability.
*/
properties?: {
[key: string]: unknown;
};
/**
* Metadata about the capability (read-only, exclusively managed by the platform).
* @ignore
*/
metadata?: {
/**
* Unique identity of this capability.
*/
id: string;
/**
* Symbolic name of the application which provides this capability.
*/
appSymbolicName: string;
};
}
/**
* The term intention refers to the Intention API of the SCION Microfrontend Platform.
*
* An intention refers to one or more capabilities that a micro application wants to interact with.
*
* Intentions are declared in the application’s manifest and are formulated in an abstract way, consisting of a type
* and optionally a qualifier. The qualifier is used to differentiate capabilities of the same type.
*
* @category Intention API
*/
interface Intention {
/**
* The type of capability to interact with.
*/
type: string;
/**
* Qualifies the capability which to interact with.
*
* The qualifier is a dictionary of arbitrary key-value pairs to differentiate capabilities of the same `type`.
*
* The intention must exactly match the qualifier of the capability, if any. The intention qualifier allows using
* wildcards to match multiple capabilities simultaneously.
*
* In the intention, the following wildcards are supported:
* - **Asterisk wildcard character (`*`):**\
* Matches capabilities with such a qualifier property no matter of its value (except `null` or `undefined`).
* Use it like this: `{property: '*'}`.
* - **Partial wildcard (`**`):**
* Matches capabilities even if having additional properties. Use it like this: `{'*': '*'}`.
*/
qualifier?: Qualifier;
/**
* Metadata about this intention (read-only, exclusively managed by the platform).
* @ignore
*/
metadata?: {
/**
* Unique identity of this intent declaration.
*/
id: string;
/**
* Symbolic name of the application which declares this intention.
*/
appSymbolicName: string;
};
}
/**
* Built in capability types.
*
* @category Intention API
*/
declare enum PlatformCapabilityTypes {
/**
* Type for registering an activator capability.
*
* @see ActivatorCapability
*/
Activator = "activator",
/**
* Type for registering a microfrontend capability.
*
* @see MicrofrontendCapability
*/
Microfrontend = "microfrontend"
}
/**
* An activator allows a micro application to initialize and connect to the platform upon host application's startup,
* i.e., when the user loads the web application into the browser.
*
* In the broadest sense, an activator is a kind of microfrontend, i.e. an HTML page that runs in an iframe. In contrast
* to regular microfrontends, however, at platform startup, the platform loads activator microfrontends into hidden iframes
* for the entire platform lifecycle, thus, providing a stateful session to the micro application on the client-side.
*
* Some typical use cases for activators are receiving messages and intents, preloading data, or flexibly providing capabilities.
*
* A micro application registers an activator as public _activator_ capability in its manifest, as follows:
*
* ```json
* "capabilities": [
* {
* "type": "activator",
* "private": false,
* "properties": {
* "path": "path/to/the/activator"
* }
* }
* ]
* ```
*
* #### Activation Context
* An activator's microfrontend runs inside an activation context. The context provides access
* to the activator capability, allowing to read properties declared on the activator capability.
*
* You can obtain the activation context using the {@link ContextService} as following.
*
* ```ts
* // Looks up the activation context.
* const ctx: ActivationContext = await Beans.get(ContextService).lookup(ACTIVATION_CONTEXT);
* ```
*
* #### Multiple Activators
* A micro application can register multiple activators. Note, that each activator boots the micro
* application on its own and runs in a separate browsing context. The platform nominates one activator
* of each micro application as its primary activator. The nomination has no relevance to the platform but
* can help code decide whether to install singleton functionality.
*
* You can test if running in the primary activation context as following.
* ```ts
* // Looks up the activation context.
* const ctx = await Beans.get(ContextService).lookup<ActivationContext>(ACTIVATION_CONTEXT);
* // Checks if running in the context of the primary activator.
* const isPrimary: boolean = ctx.primary;
* ```
*
* #### Sharing State
* Since an activator runs in a separate browsing context, microfrontends cannot directly access its state.
* Instead, an activator could put data, for example, into session storage, so that microfrontends of its micro
* application can access it. Alternatively, an activator could install a message listener, allowing microfrontends
* to request data via client-side messaging.
*
* @category Platform
* @category Intention API
*/
interface ActivatorCapability extends Capability {
type: PlatformCapabilityTypes.Activator;
private: false;
properties: {
/**
* Path where the platform can load the activator microfrontend. The path is relative to the base URL
* of the micro application, as specified in the application manifest.
*/
path: string;
/**
* Starting an activator may take some time. In order not to miss any messages or intents, you can instruct the platform host to
* wait to enter started state until you signal the activator to be ready. For this purpose, you can define a set of topics where
* to publish a ready message to signal readiness. If you specify multiple topics, the activator enters ready state after you have
* published a ready message to all these topics. A ready message is an event; thus, a message without payload.
*
* If not specifying a readiness topic, the platform host does not wait for this activator to become ready. However, if you specify a
* readiness topic, make sure that your activator has a fast startup time and signals readiness as early as possible not to delay
* the startup of the platform host.
*/
readinessTopics?: string | string[];
/**
* Arbitrary metadata to be associated with the capability.
*/
[key: string]: unknown;
};
}
/**
* Represents a microfrontend that can be loaded into a <sci-router-outlet> using the {@link OutletRouter}.
*
* @category Intention API
*/
interface MicrofrontendCapability extends Capability {
type: PlatformCapabilityTypes.Microfrontend;
properties: {
/**
* Specifies the path of the microfrontend.
*
* The path is relative to the base URL, as specified in the application manifest. If the
* application does not declare a base URL, it is relative to the origin of the manifest file.
*
* The path allows the use of navigational symbols and named parameters to reference qualifier and parameter values.
* A named parameter begins with a colon (`:`) followed by the qualifier or parameter name, and is allowed in path segments,
* query parameters, matrix parameters and the fragment part. Named query and matrix parameters without a replacement are removed,
* e.g., if referencing an optional parameter.
*
* #### Usage of named parameters in the path:
* ```json
* {
* "type": "microfrontend",
* "qualifier": {
* "entity": "product"
* },
* "params": [
* {"name": "id", "required": true}
* ]
* "properties": {
* "path": "product/:id",
* }
* }
* ```
*
* #### Path parameter example:
* segment/:param1/segment/:param2
*
* #### Matrix parameter example:
* segment/segment;matrixParam1=:param1;matrixParam2=:param2
*
* #### Query parameter example:
* segment/segment?queryParam1=:param1&queryParam2=:param2
*/
path: string;
/**
* Specifies the preferred outlet to load this microfrontend into.
* Note that this preference is only a hint that will be ignored if the navigator
* specifies an outlet for navigation.
*
* The precedence is as follows:
* - Outlet as specified by navigator via {@link NavigationOptions#outlet}.
* - Preferred outlet as specified in the microfrontend capability.
* - Current outlet if navigating in the context of an outlet.
* - {@link PRIMARY_OUTLET primary} outlet.
*/
outlet?: string;
/**
* Instructs the router outlet to show a splash, such as a skeleton or loading indicator, until the microfrontend signals readiness.
* The splash is the markup between the opening and closing tags of the router outlet element.
*
* @see SciRouterOutletElement
* @see MicrofrontendPlatformClient.signalReady
*/
showSplash?: boolean;
/**
* Arbitrary metadata to be associated with the capability.
*/
[key: string]: unknown;
};
}
/**
* Describes a parameter to be passed along with an intent.
*
* @category Intention API
*/
interface ParamDefinition {
/**
* Specifies the name of the parameter.
*/
name: string;
/**
* Describes the parameter and its usage in more detail.
*/
description?: string;
/**
* Specifies whether the parameter must be passed along with the intent.
*/
required: boolean;
/**
* Defines a default value. Only applies to optional parameters.
*
* The default value is used when the parameter is not provided.
*/
default?: unknown;
/**
* Allows deprecating the parameter.
*
* It is good practice to explain the deprecation, provide the date of removal, and how to migrate.
* If renaming the parameter, you can set the `useInstead` property to specify which parameter to use
* instead. At runtime, this will map the parameter to the specified replacement, allowing for
* straightforward migration on the provider side.
*/
deprecated?: true | {
message?: string;
useInstead?: string;
};
/**
* Allows the declaration of additional metadata that can be interpreted in an interceptor, for example.
*/
[property: string]: unknown;
}
/**
* Symbol to determine if this app instance is running as the platform host.
*
* ```ts
* const isPlatformHost: boolean = Beans.get(IS_PLATFORM_HOST);
* ```
*
* @category Platform
*/
declare const IS_PLATFORM_HOST: unique symbol;
/**
* Symbol to get the application's symbolic name from the bean manager.
*
* @category Platform
*/
declare const APP_IDENTITY: unique symbol;
/**
* Key for obtaining the current activation context using {@link ContextService}.
*
* The activation context is only available to microfrontends loaded by an activator.
*
* @see {@link ActivationContext}
* @see {@link ContextService}
* @category Platform
*/
declare const ACTIVATION_CONTEXT = "\u0275ACTIVATION_CONTEXT";
/**
* Information about the activator that loaded a microfrontend.
*
* This context is available to a microfrontend if loaded by an application activator.
* This object can be obtained from the {@link ContextService} using the name {@link ACTIVATION_CONTEXT}.
*
* ```ts
* const ctx = await Beans.get(ContextService).lookup<ActivationContext>(ACTIVATION_CONTEXT);
* ```
*
* @see {@link ACTIVATION_CONTEXT}
* @see {@link ContextService}
* @category Platform
*/
interface ActivationContext {
/**
* Indicates whether running in the context of the primary activator.
* The platform nominates one activator of each app as primary activator.
*/
primary: boolean;
/**
* Metadata about the activator that activated the microfrontend.
*/
activator: ActivatorCapability;
}
/**
* Allows filtering manifest objects like capabilities or intentions.
*
* All specified filter criteria are "AND"ed together. Unspecified filter criteria are ignored.
* If no filter criterion is specified, no filtering takes place, thus all available objects are returned.
*
* @category Intention API
*/
interface ManifestObjectFilter {
/**
* Manifest objects of the given identity.
*/
id?: string;
/**
* Manifest objects of the given function type.
*/
type?: string;
/**
* Manifest objects matching the given qualifier.
*/
qualifier?: Qualifier;
/**
* Manifest objects provided by the given app.
*/
appSymbolicName?: string;
}
/**
* Represents a request to determine if an application is qualified to interact with a given capability.
*/
interface ApplicationQualifiedForCapabilityRequest {
/**
* Specifies the symbolic name of the application under test.
*/
appSymbolicName: string;
/**
* Identifies the capability for which to request the application's qualification.
*/
capabilityId: string;
}
/**
* Configures the interaction of the host application with the platform.
*
* As with micro applications, you can provide a manifest for the host, allowing the host to contribute capabilities and declare intentions.
*
* @category Platform
*/
interface HostConfig {
/**
* Symbolic name of the host. If not set, 'host' is used as the symbolic name of the host.
*
* The symbolic name must be unique and contain only lowercase alphanumeric characters and hyphens.
*/
symbolicName?: string;
/**
* The manifest of the host.
*
* The manifest can be passed either as an {@link Manifest object literal} or specified as a URL to be loaded over the network.
* Providing a manifest lets the host contribute capabilities or declare intentions.
*/
readonly manifest?: Manifest | string;
/**
* Allows the host to access private capabilities of other applications.
*
* Disabling this check is discouraged. Enabled by default.
*/
readonly scopeCheckDisabled?: boolean;
/**
* Allows the host to access public capabilities of other applications without declaring an intention.
*
* Disabling this check is discouraged. Enabled by default.
*/
readonly intentionCheckDisabled?: boolean;
/**
* Allows the host to access inactive capabilities.
*
* Disabling this check is discouraged. Enabled by default.
*/
readonly capabilityActiveCheckDisabled?: boolean;
/**
* Allows the host to register and unregister intentions at runtime.
*
* Enabling this API is discouraged. Disabled by default.
*/
readonly intentionRegisterApiDisabled?: boolean;
/**
* Maximum time (in milliseconds) that the platform waits to receive dispatch confirmation for messages sent by the host until rejecting the publishing Promise.
* By default, a timeout of 10s is used.
*/
readonly messageDeliveryTimeout?: number;
}
/**
* Configures the liveness probe performed between host and clients to detect and dispose stale clients.
* Clients not replying to the probe are removed.
*
* @category Platform
*/
interface LivenessConfig {
/**
* Interval (in seconds) at which liveness probes are performed between host and connected clients.
* Note that the interval must not be 0 and be greater than twice the timeout period to give a probe enough time to complete before performing a new probe.
*
* By default, if not set, an interval of 60s is used.
*/
interval: number;
/**
* Timeout (in seconds) after which a client is unregistered if not replying to the probe.
* Note that timeout must not be 0 and be less than half the interval period to give a probe enough time to complete before performing a new probe.
*
* By default, if not set, a timeout of 10s is used.
*/
timeout: number;
}
/**
* Configures the platform and defines the micro applications running in the platform.
*
* @category Platform
*/
declare abstract class MicrofrontendPlatformConfig {
/**
* Lists the micro applications able to connect to the platform to interact with other micro applications.
*/
abstract readonly applications: ApplicationConfig[];
/**
* Configures the interaction of the host application with the platform.
*
* As with micro applications, you can provide a manifest for the host, allowing the host to contribute capabilities and declare intentions.
*/
abstract readonly host?: HostConfig;
/**
* Controls whether the Activator API is enabled.
*
* Activating the Activator API enables micro applications to contribute `activator` microfrontends. Activator microfrontends are loaded
* at platform startup for the entire lifecycle of the platform. An activator is a startup hook for micro applications to initialize
* or register message or intent handlers to provide functionality.
*
* By default, this API is enabled.
*
* @see {@link ActivatorCapability}
*/
abstract readonly activatorApiDisabled?: boolean;
/**
* Maximum time (in milliseconds) that the platform waits until the manifest of an application is loaded.
* You can set a different timeout per application via {@link ApplicationConfig.manifestLoadTimeout}.
* If not set, by default, the browser's HTTP fetch timeout applies.
*
* Consider setting this timeout if, for example, a web application firewall delays the responses of unavailable
* applications.
*/
abstract readonly manifestLoadTimeout?: number;
/**
* Maximum time (in milliseconds) for each application to signal readiness.
*
* If specified and activating an application takes longer, the host logs an error and continues startup.
* Has no effect for applications which provide no activator(s) or are not configured to signal readiness.
* You can set a different timeout per application via {@link ApplicationConfig.activatorLoadTimeout}.
*
* By default, no timeout is set, meaning that if an app fails to signal readiness, e.g., due to an error,
* that app would block the host startup process indefinitely. It is therefore recommended to specify a
* timeout accordingly.
*/
abstract readonly activatorLoadTimeout?: number;
/**
* Configures the liveness probe performed at regular intervals between host and clients to detect and dispose stale clients.
* Clients not replying to the probe are removed.
*/
abstract readonly liveness?: LivenessConfig;
/**
* Defines user-defined properties which can be read by micro applications via {@link PlatformPropertyService}.
*/
abstract readonly properties?: {
[key: string]: unknown;
};
}
/**
* Main entry point for configuring and starting the platform in the host application. This class cannot be instantiated. All functionality is provided by static methods.
*
* The host application, sometimes also called the container application, provides the top-level integration container for microfrontends. Typically, it is the web
* application which the user loads into the browser that provides the main application shell, defining areas to embed microfrontends.
*
* In the host application the SCION Microfrontend Platform is configured and web applications that want to interact with the platform are registered.
* The host application can provide a manifest to contribute behavior to integrated applications. For more information, see {@link HostConfig.manifest}
* in {@link MicrofrontendPlatformConfig.host}.
*
* If integrating the SCION Microfrontend Platform in a library, the manifest of the host can be augmented by registering a {@link HostManifestInterceptor}.
*
* @see MicrofrontendPlatform
* @see MicrofrontendPlatformHost
* @see MicrofrontendPlatformClient
*
* @category Platform
* @category Lifecycle
*/
declare class MicrofrontendPlatformHost {
private static _startupProgress$;
private constructor();
/**
* Starts the platform host.
*
* In the host application the SCION Microfrontend Platform is configured and web applications that want to interact with the platform are registered.
*
* The host application can provide a manifest to declare intentions and contribute behavior to integrated applications via {@link HostConfig.manifest} in
* {@link MicrofrontendPlatformConfig.host}. The manifest can be specified either as an object literal or as a URL to load it over the network.
*
* The platform should be started during the bootstrapping of the host application. In Angular, for example, the platform is typically
* started in an app initializer. Since starting the platform host may take some time, you should wait for the startup Promise to resolve
* before interacting with the platform.
*
* @param config - Configures the platform and lists applications allowed to interact with the platform.
* @return A Promise that resolves when started the platform host.
*/
static start(config: MicrofrontendPlatformConfig): Promise<void>;
/**
* Monitors the startup progress of the platform host.
*
* Starting the platform host may take some time. During startup, the manifests of the registered applications are fetched,
* activator microfrontends are installed, and the platform waits until all applications have signaled readiness.
*
* Subscribe to this Observable to monitor the startup progress and provide feedback to the user like displaying a
* progress bar or a spinner. The Observable reports the progress as a percentage number. The Observable completes
* after the platform has been started.
*/
static get startupProgress$(): Observable<number>;
}
/**
* Enables modification of capabilities before they are registered.
*
* Interceptors can intercept capabilities before they are registered, for example,
* to perform validation checks, add metadata, change properties, or prevent registration
* based on user permissions.
*
* The following interceptor assigns a stable identifier to each microfrontend capability.
*
* ```ts
* class MicrofrontendCapabilityInterceptor implements CapabilityInterceptor {
*
* public async intercept(capability: Capability): Promise<Capability> {
* if (capability.type === 'microfrontend') {
* return {
* ...capability,
* // `hash()` is illustrative and not part of the Microfrontend Platform API.
* metadata: {...capability.metadata, id: hash(capability)},
* };
* }
* return capability;
* }
* }
* ```
*
* The following interceptor marks capabilities as inactive based on user permissions.
*
* ```ts
* class UserAuthorizedCapabilityInterceptor implements CapabilityInterceptor {
*
* public async intercept(capability: Capability): Promise<Capability> {
* // Read required role from capability properties.
* const requiredRole = capability.properties?.['role'];
*
* // Mark capability as inactive if the user has no permission.
* // `hasRole()` is illustrative and not part of the Microfrontend Platform API.
* capability.inactive = requiredRole && !hasRole(requiredRole);
*
* return capability;
* }
* }
* ```
* Alternatively, the capability can be rejected. Unlike inactive capabilities, rejected capabilities are not listed in the SCION DevTools.
*
* ```ts
* class UserAuthorizedCapabilityInterceptor implements CapabilityInterceptor {
*
* public async intercept(capability: Capability): Promise<Capability | null> {
* // Read required role from capability properties.
* const requiredRole = capability.properties?.['role'];
*
* // `hasRole()` is illustrative and not part of the Microfrontend Platform API.
* return !requiredRole || hasRole(requiredRole) ? capability : null;
* }
* }
* ```
*
* The following interceptor extracts user information to a new capability.
*
* ```ts
* class UserCapabilityMigrator implements CapabilityInterceptor {
*
* public async intercept(capability: Capability, manifest: CapabilityInterceptor.Manifest): Promise<Capability> {
* if (capability.type === 'user' && capability.properties['info']) {
* // Move user info to new capability.
* await manifest.addCapability({
* type: 'user-info',
* properties: {
* ...capability.properties['info'],
* },
* });
* // Remove info on intercepted capability.
* delete capability.properties['info'];
* }
* return capability;
* }
* }
* ```
*
* #### Registering Interceptors
* Interceptors are registered in the bean manager of the host application under the symbol `CapabilityInterceptor` as multi bean.
* Multiple interceptors can be registered, forming a chain in which each interceptor is called one by one in registration order.
*
* ```ts
* Beans.register(CapabilityInterceptor, {useClass: MicrofrontendCapabilityInterceptor, multi: true});
* Beans.register(CapabilityInterceptor, {useClass: UserAuthorizedCapabilityInterceptor, multi: true});
* Beans.register(CapabilityInterceptor, {useClass: UserCapabilityMigrator, multi: true});
* ```
*
* @category Intention API
*/
declare abstract class CapabilityInterceptor {
/**
* Intercepts a capability before being registered.
*
* An interceptor can add extra capabilities and intentions to the manifest of the intercepted capability. This may be necessary to migrate capabilities.
*
* @param capability - Capability to be intercepted.
* @param manifest - Manifest of the application that provides the intercepted capability, allowing for the registration of extra capabilities and intentions.
* @return Promise that resolves to the intercepted capability, or `null` to prevent registration.
*/
abstract intercept(capability: Capability, manifest: CapabilityInterceptor.Manifest): Promise<Capability | null>;
}
/**
* Declares objects local to CapabilityInterceptor.
*/
declare namespace CapabilityInterceptor {
/**
* Manifest of the application that provides the intercepted capability.
*/
interface Manifest {
/**
* Adds specified capability to the application of the intercepted capability.
*/
addCapability<T extends Capability>(capability: T): Promise<string | null>;
/**
* Adds specified intention to the application of the intercepted capability.
*/
addIntention(intention: Intention): Promise<string>;
}
}
/**
* Represents a message with headers to transport additional information with a message.
*
* @category Messaging
*/
interface Message {
/**
* Additional information attached to this message.
*
* Header values must be JSON serializable. If no headers are set, the `Map` is empty.
*/
headers: Map<string, unknown>;
/**
* Indicates whether this message is retained on the broker for late subscribers.
*/
retain?: boolean;
}
/**
* Represents an intent sent by an application.
*
* The intent is transported to applications that provide a fulfilling capability visible to the sending application.
*
* @category Messaging
* @category Intention API
*/
interface IntentMessage<BODY = unknown> extends Message {
/**
* Intent that represents this message.
*/
intent: Intent;
/**
* Optional data passed along with the intent.
*/
body?: BODY;
/**
* Capability that fulfills the intent.
*/
capability: Capability;
}
/**
* The term intention refers to the Intention API of the SCION Microfrontend Platform.
*
* The intent is the message that a micro application sends to interact with functionality that is available in the form of a capability.
*
* The platform transports the intent to the micro applications that provide the requested capability. A micro application can issue an
* intent only if having declared an intention in its manifest. Otherwise, the platform rejects the intent.
*
* An intent is formulated in an abstract way, having assigned a type, and optionally a qualifier. This information is used for resolving
* the capability; thus, it can be thought of as a form of capability addressing. See the definition of a capability for more information.
*
* @category Messaging
* @category Intention API
*/
interface Intent {
/**
* Type of functionality to intend.
*/
type: string;
/**
* The qualifier is an abstract description of the intent and is expressed in the form of a dictionary.
*
* When issuing an intent, the qualifier must be exact, i.e. not contain wildcards.
*/
qualifier?: Qualifier;
/**
* Parameters allow additional data to be passed along with the intent.
*
* They are part of the contract between the intent publisher and the capability provider. The capability provider
* can declare mandatory and optional parameters. No additional parameters may be included.
*
* Parameters have no effect on the intent routing, unlike the qualifier. If mandatory parameters
* are missing or non-specified parameters are included, the intent is rejected.
*/
params?: Map<string, unknown>;
}
/**
* Represents a message published to a topic.
*
* The message is transported to all consumers subscribed to the topic.
*
* @category Messaging
*/
interface TopicMessage<BODY = unknown> extends Message {
/**
* The topic where to publish this message to.
*/
topic: string;
/**
* Optional message.
*/
body?: BODY;
/**
* Contains the resolved values of the wildcard segments as specified in the topic.
* For example: If subscribed to the topic `person/:id` and a message is published to the topic `person/5`,
* the resolved id with the value `5` is contained in the params map.
*/
params?: Map<string, string>;
}
/**
* Declares headers set by the platform when sending a message.
*
* Clients are allowed to read platform-defined headers from a message.
*
* @category Messaging
*/
declare enum MessageHeaders {
/**
* Identifies the sending client instance of a message.
* This header is set by the platform when publishing a message or intent.
*/
ClientId = "\u0275CLIENT_ID",
/**
* Identifies the sending application of a message.
* This header is set by the platform when publishing a message or intent.
*/
AppSymbolicName = "\u0275APP_SYMBOLIC_NAME",
/**
* Unique identity of the message.
* This header is set by the platform when publishing a message or intent.
*/
MessageId = "\u0275MESSAGE_ID",
/**
* Destination to which to send a response to this message.
* This header is set by the platform when sending a request.
*/
ReplyTo = "\u0275REPLY_TO",
/**
* The time the message was sent.
* This header is set by the platform when publishing a message or intent.
*/
Timestamp = "\u0275TIMESTAMP",
/**
* The version of the client.
*/
Version = "\u0275VERSION",
/**
* Use this header to set the request method to indicate the desired action to be performed for a given resource.
* @see RequestMethods
*/
Method = "\u0275METHOD",
/**
* Use this header to set the response status code to indicate whether a request has been successfully completed.
* See {@link ResponseStatusCodes} for available status codes. Other codes are also allowed.
*
* Status codes are primarily used in request-reply communication. In request-response communication, by default,
* the requestor’s Observable never completes. However, the replier can include the response status code in the reply’s
* headers, allowing to control the lifecycle of the requestor’s Observable.
*
* For example, the status code {@link ResponseStatusCodes.TERMINAL 250} allows completing the requestor’s Observable
* after emitted the reply, or the status code {@link ResponseStatusCodes.ERROR 500} to error the Observable.
*
* Note that the platform evaluates status codes only in request-response communication. They are ignored when observing
* topics or intents in pub/sub communication but can still be used; however, they must be handled by the application,
* e.g., by using the {@link throwOnErrorStatus} SCION RxJS operator.
*
* @see ResponseStatusCodes
*/
Status = "\u0275STATUS"
}
/**
* Defines a set of request methods to indicate the desired action to be performed for a given resource.
*
* @category Messaging
*/
declare enum RequestMethods {
/**
* The GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
*/
GET = "GET",
/**
* The DELETE method deletes the specified resource.
*/
DELETE = "DELETE",
/**
* The PUT method replaces all current representations of the target resource with the request payload.
*/
PUT = "PUT",
/**
* The POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server.
*/
POST = "POST",
/**
* The OBSERVE method is used to observe the specified resource.
*/
OBSERVE = "OBSERVE"
}
/**
* Defines a set of response status codes to indicate whether a request has been successfully completed.
*
* @see throwOnErrorStatus
* @see MessageClient.request$
* @see IntentClient.request$
*
* @category Messaging
*/
declare enum ResponseStatusCodes {
/**
* The request