@feature-hub/core
Version:
Create scalable web applications using micro frontends.
211 lines • 10 kB
TypeScript
import { AsyncValue } from './async-value';
import { ExternalsValidator } from './externals-validator';
import { FeatureServiceConsumerDefinition, FeatureServiceProviderDefinition, FeatureServiceRegistry, FeatureServices, SharedFeatureService } from './feature-service-registry';
import { Logger } from './logger';
export interface FeatureAppDescriptor {
/**
* The ID that the integrator (or parent Feature App) has assigned to the
* Feature App instance.
*/
readonly featureAppId: string;
/**
* The name that the integrator (or parent Feature App) might have assigned to
* the Feature App.
*/
readonly featureAppName?: string;
}
export interface FeatureAppEnvironment<TFeatureServices extends FeatureServices, TConfig> extends FeatureAppDescriptor {
/**
* An object of required Feature Services that are semver-compatible with the
* declared dependencies in the Feature App definition.
*/
readonly featureServices: TFeatureServices;
/**
* A config object that is provided by the integrator.
*/
readonly config: TConfig | undefined;
/**
* The absolute or relative base URL of the Feature App's assets and/or BFF.
*/
readonly baseUrl: string | undefined;
/**
* If this callback is defined, a short-lived Feature App can call this
* function when it has completed its task. The Integrator (or parent Feature
* App) can then decide to e.g. unmount the Feature App.
*
* Optionally, the Feature App can pass a result into the done callback. The
* type/structure of the result must be agreed between the Integrator (or
* parent Feature App) and the Feature App.
*/
readonly done?: (result?: unknown) => void;
}
export interface FeatureAppDefinition<TFeatureApp, TFeatureServices extends FeatureServices = FeatureServices, TConfig = unknown> extends FeatureServiceConsumerDefinition {
readonly ownFeatureServiceDefinitions?: FeatureServiceProviderDefinition<SharedFeatureService>[];
create(env: FeatureAppEnvironment<TFeatureServices, TConfig>): TFeatureApp;
}
/**
* @param url A URL pointing to a [[FeatureAppDefinition]] bundle in a module
* format compatible with the module loader.
*
* @param moduleType The module type of the [[FeatureAppDefinition]] bundle.
* This can be used to choose different loading strategies based on the module
* type of the Feature App.
*/
export type ModuleLoader = (url: string, moduleType?: string) => Promise<unknown>;
export interface FeatureAppScope<TFeatureApp> {
readonly featureApp: TFeatureApp;
/**
* When the `FeatureAppScope` is not needed anymore, e.g. the Feature App is
* unmounted, `release` must be called. When all scopes for a Feature App ID
* have been released, the Feature App instance is destroyed.
*/
release(): void;
}
export interface FeatureAppScopeOptions<TFeatureServices extends FeatureServices, TConfig> {
/**
* The Feature App's name. In contrast to the `featureAppId`, the name must
* not be unique. It can be used by required Feature Services for display
* purposes, logging, looking up Feature App configuration meta data, etc.
*/
readonly featureAppName?: string;
/**
* The absolute or relative base URL of the Feature App's assets and/or BFF.
*/
readonly baseUrl?: string;
/**
* A config object that is intended for a specific Feature App instance.
*/
readonly config?: TConfig;
/**
* A callback that is called before the Feature App is created.
*/
readonly beforeCreate?: (env: FeatureAppEnvironment<TFeatureServices, TConfig>) => void;
/**
* A callback that is passed to the Feature App's `create` method. A
* short-lived Feature App can call this function when it has completed its
* task. The Integrator (or parent Feature App) can then decide to e.g.
* unmount the Feature App.
*
* Optionally, the Feature App can pass a result into the done callback. The
* type/structure of the result must be agreed between the Integrator (or
* parent Feature App) and the Feature App.
*/
readonly done?: (result?: unknown) => void;
/**
* If the Feature App is created in the context of another Feature App, the
* `parentFeatureApp` property should be populated accordingly. This allows
* the integrator to collect information about "Feature App in Feature App"
* usage.
*/
readonly parentFeatureApp?: FeatureAppDescriptor;
}
export interface OnBindParams extends FeatureAppDescriptor {
readonly featureAppDefinition: FeatureServiceConsumerDefinition;
readonly parentFeatureApp?: FeatureAppDescriptor;
}
export interface FeatureAppManagerOptions {
/**
* For the `FeatureAppManager` to be able to load Feature Apps from a remote
* location, a module loader must be provided. This can either be one of the
* module loaders that are provided by @feature-hub, i.e.
* `@feature-hub/module-loader-amd`, `@feature-hub/module-loader-federation`,
* and `@feature-hub/module-loader-commonjs`, or a custom loader.
*/
readonly moduleLoader?: ModuleLoader;
/**
* When using a [[moduleLoader]], it might make sense to validate
* external dependencies that are required by Feature Apps against the
* shared dependencies that are provided by the integrator. This makes it
* possible that an error is already thrown when creating a Feature App with
* incompatible external dependencies, and thus enables early feedback as to
* whether a Feature App is compatible with the integration environment.
*/
readonly externalsValidator?: ExternalsValidator;
/**
* A custom logger that shall be used instead of `console`.
*/
readonly logger?: Logger;
/**
* A function that is called for every Feature App when its dependent Feature
* Services are bound. This allows the integrator to collect information about
* Feature Service and Feature App usage.
*/
readonly onBind?: (params: OnBindParams) => void;
}
/**
* The `FeatureAppManager` manages the lifecycle of Feature Apps.
*/
export declare class FeatureAppManager {
private readonly featureServiceRegistry;
private readonly options;
private readonly asyncFeatureAppDefinitions;
private readonly featureAppDefinitionsWithRegisteredOwnFeatureServices;
private readonly featureAppRetainers;
private readonly logger;
constructor(featureServiceRegistry: FeatureServiceRegistry, options?: FeatureAppManagerOptions);
/**
* Load a [[FeatureAppDefinition]] using the module loader the
* [[FeatureAppManager]] was initilized with.
*
* @throws Throws an error if no module loader was provided on initilization.
*
* @param url A URL pointing to a [[FeatureAppDefinition]] bundle in a module
* format compatible with the module loader.
*
* @param moduleType The module type of the [[FeatureAppDefinition]] bundle.
* This value can be used by the provided
* [[FeatureAppManagerOptions.moduleLoader]].
*
* @returns An [[AsyncValue]] containing a promise that resolves with the
* loaded [[FeatureAppDefinition]]. If called again with the same URL it
* returns the same [[AsyncValue]]. The promise rejects when loading fails, or
* when the loaded bundle doesn't export a [[FeatureAppDefinition]] as
* default.
*/
getAsyncFeatureAppDefinition(url: string, moduleType?: string): AsyncValue<FeatureAppDefinition<unknown>>;
/**
* Create a [[FeatureAppScope]] which includes validating externals, binding
* all available Feature Service dependencies, and calling the `create` method
* of the [[FeatureAppDefinition]].
*
* @throws Throws an error if Feature Services that the
* [[FeatureAppDefinition]] provides with its `ownFeatureServices` key fail to
* be registered.
* @throws Throws an error if the required externals can't be satisfied.
* @throws Throws an error if the required Feature Services can't be
* satisfied.
* @throws Throws an error the [[FeatureAppDefinition]]'s `create` method
* throws.
*
* @param featureAppID The ID of the Feature App to create a scope for.
* @param featureAppDefinition The definition of the Feature App to create a
* scope for.
*
* @returns A [[FeatureAppScope]] for the provided Feature App ID and
* [[FeatureAppDefinition]]. A new scope is created for every call of
* `createFeatureAppScope`, even with the same ID and definiton.
*/
createFeatureAppScope<TFeatureApp, TFeatureServices extends FeatureServices = FeatureServices, TConfig = unknown>(featureAppId: string, featureAppDefinition: FeatureAppDefinition<TFeatureApp, TFeatureServices, TConfig>, options?: FeatureAppScopeOptions<TFeatureServices, TConfig>): FeatureAppScope<TFeatureApp>;
/**
* Preload a [[FeatureAppDefinition]] using the module loader the
* [[FeatureAppManager]] was initilized with. Useful before hydration of a
* server rendered page to avoid render result mismatch between client and
* server due missing [[FeatureAppDefinition]]s.
*
* @throws Throws an error if no module loader was provided on initilization.
*
* @param url A URL pointing to a [[FeatureAppDefinition]] bundle in a module
* format compatible with the module loader.
*
* @param moduleType The module type of the [[FeatureAppDefinition]] bundle.
* This value can be used by the provided
* [[FeatureAppManagerOptions.moduleLoader]].
*/
preloadFeatureApp(url: string, moduleType?: string): Promise<void>;
private createAsyncFeatureAppDefinition;
private registerOwnFeatureServices;
private getFeatureAppRetainer;
private createFeatureAppRetainer;
private validateExternals;
}
//# sourceMappingURL=feature-app-manager.d.ts.map