///
///
import * as Redux from 'redux';
import { ThrottledStore } from './throttledStore';
import { INTERNAL_DONT_USE_SHELL_GET_APP_HOST } from './__internal';
import { CustomCreateExtensionSlot } from './extensionSlot';
export interface AnySlotKey {
readonly name: string;
readonly public?: boolean;
}
/**
* A key that represents an {ExtensionSlot} of shape T that's held in the {AppHost}
* Created be calling {Shell.declareSlot}
* Retrieved by calling {Shell.getSlot} (scoped to specific {Shell})
*
* @export
* @interface SlotKey
* @extends {AnySlotKey}
* @template T
*/
export interface SlotKey extends AnySlotKey {
/**
* Holds no value, only triggers type-checking of T
*/
readonly empty?: T;
/**
* Application layer/layers that will restrict usage of APIs contributed by this entry point.
* Layers hierarchy is defined in the host options
* @See {AppHostOptions.layers}
*/
readonly layer?: string | string[];
/**
* Version of the API that will be part of the API key unique identification
*/
readonly version?: number;
}
export { AppHostAPI } from './appHostServices';
export type ScopedStore = Pick, 'dispatch' | 'getState' | 'subscribe' | 'flush' | 'hasPendingSubscribers' | 'deferSubscriberNotifications'>;
export type ReactComponentContributor = (props?: TProps) => React.ReactNode;
export type ReducersMapObjectContributor = () => Redux.ReducersMapObject;
export type ContributionPredicate = () => boolean;
export interface EntryPointTags {
[name: string]: string;
}
export type ShellsChangedCallback = (shellNames: string[]) => void;
export type DeclarationsChangedCallback = () => void;
export type UnsubscribeFromDeclarationsChanged = () => void;
export type ShellBoundaryAspect = React.FunctionComponent>;
/**
* Application part that will receive a {Shell} when loaded into the {AppHost}
* @export
* @interface EntryPoint
*/
export interface EntryPoint {
/**
* Unique name that will represent this entry point in the host
*/
readonly name: string;
readonly tags?: EntryPointTags;
/**
* Application layer / layers that will restrict usage of APIs contributed by this entry point.
* Layers hierarchy is defined in the host options
* See {AppHostOptions.layers}
*/
readonly layer?: string | string[];
/**
* Define which API keys (a.k.a. contracts) are mandatory for this entry point to be executed
* @return {SlotKey[]} API keys to wait for implementation
*/
getDependencyAPIs?(): SlotKey[];
/**
* Define which API keys (a.k.a. contracts) this entry point is going to implement and contribute
* @return {SlotKey[]} API keys that will be contributed
*/
declareAPIs?(): SlotKey[];
/**
* Execute logic that is independent from other entry points
* Most commonly - contribute APIs and state
* @param {Shell} shell
*/
attach?(shell: Shell): void;
/**
* Execute logic that is dependent on other entry points
* @param {Shell} shell
*/
extend?(shell: Shell): void;
/**
* Clean side effects
* @param {Shell} shell
*/
detach?(shell: Shell): void;
}
export type AnyEntryPoint = EntryPoint;
export type EntryPointOrPackage = AnyEntryPoint | AnyEntryPoint[];
export interface EntryPointOrPackagesMap {
[name: string]: EntryPointOrPackage;
}
export type ExtensionItemFilter = (extensionItem: ExtensionItem) => boolean;
/**
* A slot/container for holding any contribution of shape T
* Access to the slot is scoped to the {Shell}
*
* @export
* @interface ExtensionSlot
* @template T
*/
export interface ExtensionSlot {
/**
* a unique identifier for the slot
*/
readonly name: string;
readonly host: AppHost;
/**
* Which {Shell} owns this slot
*/
readonly declaringShell?: Shell;
/**
* Add an item to the slot
*
* @param {Shell} shell Who owns the contributed item
* @param {T} item Extension item to be added to the slot
* @param {ContributionPredicate} [condition] A predicate to condition the retrieval of the item when slot items are requested with {ExtensionSlot.getItems}
*/
contribute(shell: Shell, item: T, condition?: ContributionPredicate): void;
/**
* Get all items contributed to the slot
*
* @param {boolean} [forceAll] Ignore items' contribution predicates and get all anyway
* @return {ExtensionItem[]} All items contributed to the slot
*/
getItems(forceAll?: boolean): ExtensionItem[];
/**
* Get the first item in the slot
*
* @return {ExtensionItem} The first item in the slot
*/
getSingleItem(): ExtensionItem | undefined;
/**
* Get a specific item in the slot
*
* @param {string} name Extension item name
* @return {ExtensionItem | undefined} Extension item
*/
getItemByName(name: string): ExtensionItem | undefined;
/**
* Remove items from the slot by predicate
*
* @param {ExtensionItemFilter | undefined} predicate Remove all items matching this predicate
*/
discardBy(predicate: ExtensionItemFilter): void;
}
export interface PrivateExtensionSlot extends ExtensionSlot {
subscribe(callback: () => void): () => void;
}
export interface CustomExtensionSlotHandler {
contribute(fromShell: Shell, item: T, condition?: ContributionPredicate): void;
discardBy(predicate: ExtensionItemFilter): void;
}
export interface CustomExtensionSlot extends CustomExtensionSlotHandler {
readonly name: string;
readonly host: AppHost;
readonly declaringShell?: Shell;
}
/**
* Item of shape T that is contributed to a slot of shape T
*
* @export
* @interface ExtensionItem
* @template T
*/
export interface ExtensionItem {
readonly name?: string;
/**
* Which {Shell} owns this item
*/
readonly shell: Shell;
/**
* Contribution content
*/
readonly contribution: T;
/**
* Condition for the retrieval of this item by {ExtensionSlot.getItems}
*/
readonly condition: ContributionPredicate;
readonly uniqueId: string;
}
/**
* An application content container that will accept {EntryPoint} and provide registry for contracts
*
* @export
* @interface AppHost
*/
export interface AppHost {
/**
* Get the root store of the application
*
* @return {ThrottledStore}
*/
getStore(): ThrottledStore;
/**
* Get an implementation of API previously contributed to the {AppHost}
*
* @template TAPI
* @param {SlotKey} key API Key
* @return {*} {TAPI}
*/
getAPI(key: SlotKey): TAPI;
/**
* Check if an API implementation has been contributed to the {AppHost}
*
* @template TAPI
* @param {SlotKey} key API Key
* @return {*} {boolean}
*/
hasAPI(key: SlotKey): boolean;
/**
* Get an extension slot defined on the host
*
* @template TItem
* @param {SlotKey} key
* @return {ExtensionSlot}
*/
getSlot(key: SlotKey): ExtensionSlot;
/**
* Check if an extension slot has been contributed to the {AppHost}
*
* @template TItem
* @param {SlotKey} key
* @return {boolean}
*/
hasSlot(key: SlotKey): boolean;
/**
* Get all the extension slots defined on the host
*
* @return {*} {AnySlotKey[]}
*/
getAllSlotKeys(): AnySlotKey[];
/**
* Get all {EntryPoint}s addded to the {AppHost}
*
* @return {EntryPointsInfo[]}
*/
getAllEntryPoints(): EntryPointsInfo[];
/**
* Does the {AppHost} contain a specific {Shell}
*
* @param {string} name
* @return {boolean}
*/
hasShell(name: string): boolean;
/**
* Dynamically add {Shell}s after the host is created
*
* @param {EntryPointOrPackage[]} entryPointsOrPackages New packages or entry points to be added to the {AppHost}
* @return {Promise}
*/
addShells(entryPointsOrPackages: EntryPointOrPackage[]): Promise;
/**
* Dynamically remove {Shell}s after the host is created
*
* @param {string[]} names {Shell} names to be removed
* @return {Promise}
*/
removeShells(names: string[]): Promise;
/**
* Subscribe to changes in host declarations. This includes:
* - API additions and removals
* - Extension slot additions and removals
*
* @param {DeclarationsChangedCallback} callback Function to be called when host declarations change
* @return {UnsubscribeFromDeclarationsChanged} Function to unsubscribe from host declarations changes
*/
onDeclarationsChanged(callback: DeclarationsChangedCallback): UnsubscribeFromDeclarationsChanged;
onShellsChanged(callback: ShellsChangedCallback): string;
removeShellsChangedCallback(callbackId: string): void;
/**
* Verify if there are pending entry points waiting for APIs that will never be available.
* This usually happens when trying to consume a private API as a public API.
*
* @throws {Error} If there are pending entry points with API mismatches
*/
verifyPendingEntryPointsAPIsMismatch(): void;
readonly log: HostLogger;
readonly options: AppHostOptions;
}
export interface PrivateAppHost extends AppHost {
executeWhenFree(identifier: string, callback: () => void): void;
}
export interface MonitoringOptions {
enablePerformance?: boolean;
readonly disableMonitoring?: boolean;
readonly disableMemoization?: boolean;
readonly debugMemoization?: boolean;
}
export interface Trace {
name: string;
duration: number;
startTime: number;
res: any;
args: any[];
}
export interface APILayer {
level: number;
name: string;
}
interface AppHostPlugins {
extensionSlot?: {
customCreateExtensionSlot: CustomCreateExtensionSlot;
};
}
export type { CustomCreateExtensionSlot };
export interface AppHostOptions {
readonly logger?: HostLogger;
readonly monitoring: MonitoringOptions;
readonly layers?: APILayer[] | APILayer[][];
readonly disableLayersValidation?: boolean;
readonly disableCheckCircularDependencies?: boolean;
readonly enableStickyErrorBoundaries?: boolean;
readonly enableReduxDevtoolsExtension?: boolean;
readonly experimentalCyclicMode?: boolean;
readonly shouldScopeReducers?: boolean;
readonly plugins?: AppHostPlugins;
}
export interface MemoizeMissHit {
miss: number;
calls: number;
hit: number;
printHitMiss(): void;
}
export type enrichedMemoizationFunction = MemoizeMissHit & AnyFunction & _.MemoizedFunction;
export interface StatisticsMemoization {
func: enrichedMemoizationFunction;
name: string;
}
export interface ContributeAPIOptions {
includesNamespaces?: boolean;
disableMonitoring?: boolean | (keyof TAPI)[];
}
export type StateObserverUnsubscribe = () => void;
export type StateObserver = (next: TSelectorAPI) => void;
export interface ObservableState {
subscribe(fromShell: Shell, callback: StateObserver): StateObserverUnsubscribe;
current(allowUnsafeReading?: boolean): TSelectorAPI;
}
export type AnyFunction = (...args: any[]) => any;
export type FunctionWithSameArgs = (...args: Parameters) => any;
export interface Lazy {
get(): T;
}
/**
* An scoped communication terminal provided for an {EntryPoint}
* in order to contribute its application content to the {AppHost}
*
* @export
* @interface Shell
* @extends {(Pick>)}
*/
export interface Shell extends Pick> {
/**
* Unique name of the matching {EntryPoint}
*/
readonly name: string;
readonly log: ShellLogger;
/**
* Get store that is scoped for this {Shell}
*
* @template TState
* @return {ScopedStore} Scoped store for this {Shell}
*/
getStore(): ScopedStore;
/**
* Are APIs ready to be requested
*
* @return {*} {boolean}
*/
canUseAPIs(): boolean;
/**
* Is store ready to be requested
*
* @return {*} {boolean}
*/
canUseStore(): boolean;
/**
* Did the execution of {EntryPoint}s' lifecycle phases (attach, detach) are done
*
* @return {*} {boolean}
*/
wasInitializationCompleted(): boolean;
runLateInitializer(initializer: () => T): T;
/**
* Create an {ExtensionSlot}
*
* @template TItem
* @param {SlotKey} key Key that will represent the slot (an will be used for retrieval)
* @return {ExtensionSlot} Actual slot
*/
declareSlot(key: SlotKey): ExtensionSlot;
declareCustomSlot(key: SlotKey, handler: CustomExtensionSlotHandler): CustomExtensionSlot;
/**
* Contribute an implementation of an API (a.k.a contract)
*
* @template TAPI
* @param {SlotKey} key API Key that represents an interface TAPI
* @param {() => TAPI} factory Create an implementation of TAPI
* @param {ContributeAPIOptions} [options] Contribution options {ContributeAPIOptions}
* @return {TAPI} Result of the factory execution
*/
contributeAPI(key: SlotKey, factory: () => TAPI, options?: ContributeAPIOptions): TAPI;
/**
* Contribute a Redux reducer that will be added to the host store.
* Use it for slowly changing state (e.g. not changing because of mouse movement)
*
* @template TState
* @param {ReducersMapObjectContributor} contributor
*/
contributeState(contributor: ReducersMapObjectContributor): void;
/**
* Contribute a Redux reducer that will be added to the host store
* Use it for rapidly changing state (e.g. changing on every mouse movement event)
* Changes to this state won't trigger the usual subscribers.
* In order to subscribe to changes in this state, use the observer object returned by this function.
*
* @template TState
* @param {ReducersMapObjectContributor} contributor
* @return {TAPI} Observer object for subscribing to state changes. The observer can also be passed to {connectWithShell}.
*/
contributeObservableState(contributor: ReducersMapObjectContributor, selectorFactory: (state: TState) => TSelector): ObservableState;
/**
* Contribute the main view (root) of the application
* Intended to be used by a single {Shell} in an application
*
* @param {Shell} fromShell Who owns the main view
* @param {ReactComponentContributor} contributor Create the main view component
*/
contributeMainView(fromShell: Shell, contributor: ReactComponentContributor): void;
contributeBoundaryAspect(component: ShellBoundaryAspect): void;
/**
* Create a function with internal cache until any state change in the {AppHost} store
*
* @template T
* @param {T} func Function to build cache for
* @param {FunctionWithSameArgs} resolver Key creator to index results by
* @param {() => boolean} [shouldClear] Custom clear condition (if not provided, behaves like () => true)
* @return {*} {(((...args: Parameters) => ReturnType) & Partial<_.MemoizedFunction> & Partial)}
*/
memoizeForState(func: T, resolver: FunctionWithSameArgs, shouldClear?: () => boolean): ((...args: Parameters) => ReturnType) & Partial<_.MemoizedFunction> & Partial;
/**
* Manually trigger clear condition for function memoized with {Shell.memoizeForState}
*/
flushMemoizedForState(): void;
/**
* Create a function with internal cache
*
* @template T
* @param {T} func Function to build cache for
* @param {FunctionWithSameArgs} resolver Key creator to index results by
* @return {*} {(((...args: Parameters) => ReturnType) & Partial<_.MemoizedFunction> & Partial)}
*/
memoize(func: T, resolver: FunctionWithSameArgs): ((...args: Parameters) => ReturnType) & Partial<_.MemoizedFunction> & Partial;
/**
* Clear cache of a memoized function
*
* @param {(Partial<_.MemoizedFunction> & Partial)} memoizedFunction
*/
clearCache(memoizedFunction: Partial<_.MemoizedFunction> & Partial): void;
/**
* Creates a lazy-evaluated value. The function `func` is only executed once when `get` is called for the first time,
* and the result is cached for subsequent calls.
*
* @template T
* @param {F} func - The function that will be lazily evaluated. It should not take any arguments.
* @returns {Lazy} An object with a `get` method that returns the lazily evaluated value of type `T`.
*/
lazyEvaluator>(func: F): Lazy;
}
export interface PrivateShell extends Shell {
readonly entryPoint: EntryPoint;
setDependencyAPIs(APIs: AnySlotKey[]): void;
setLifecycleState(enableStore: boolean, enableAPIs: boolean, initCompleted: boolean): void;
getBoundaryAspects(): ShellBoundaryAspect[];
getHostOptions(): AppHostOptions;
[INTERNAL_DONT_USE_SHELL_GET_APP_HOST](): AppHost;
}
export interface EntryPointsInfo {
readonly name: string;
readonly lazy: boolean;
readonly attached: boolean;
}
export interface EntryPointInterceptor {
interceptName?(innerName: string): string;
interceptTags?(innerTags?: EntryPointTags): EntryPointTags;
interceptGetDependencyAPIs?(innerGetDependencyAPIs?: EntryPoint['getDependencyAPIs']): EntryPoint['getDependencyAPIs'];
interceptDeclareAPIs?(innerDeclareAPIs?: EntryPoint['declareAPIs']): EntryPoint['declareAPIs'];
interceptAttach?(innerAttach?: EntryPoint['attach']): EntryPoint['attach'];
interceptDetach?(innerDetach?: EntryPoint['detach']): EntryPoint['detach'];
interceptExtend?(innerExtend?: EntryPoint['extend']): EntryPoint['extend'];
}
export type LogSeverity = 'verbose' | 'debug' | 'info' | 'event' | 'warning' | 'error' | 'critical';
export type LogSpanFlag = 'begin' | 'end';
export interface HostLogger {
log(severity: LogSeverity, id: string, error?: Error, keyValuePairs?: Object): void;
spanChild(messageId: string, keyValuePairs?: Object): ShellLoggerSpan;
spanRoot(messageId: string, keyValuePairs?: Object): ShellLoggerSpan;
}
export interface ShellLogger extends HostLogger {
verbose(messageId: string, keyValuePairs?: Object): void;
debug(messageId: string, keyValuePairs?: Object): void;
info(messageId: string, keyValuePairs?: Object): void;
warning(messageId: string, keyValuePairs?: Object): void;
error(messageId: string, error?: Error, keyValuePairs?: Object): void;
critical(messageId: string, error?: Error, keyValuePairs?: Object): void;
spanChild(messageId: string, keyValuePairs?: Object): ShellLoggerSpan;
spanRoot(messageId: string, keyValuePairs?: Object): ShellLoggerSpan;
monitor(messageId: string, keyValuePairs: Object, monitoredCode: () => T): T;
}
export interface ShellLoggerSpan {
end(success: boolean, error?: Error, keyValuePairs?: Object): void;
}
//# sourceMappingURL=API.d.ts.map