piral-core
Version:
The core library for creating a Piral instance.
347 lines (346 loc) • 11.5 kB
TypeScript
import type { ComponentType, ReactPortal, PropsWithChildren } from 'react';
import type { RouteComponentProps } from 'react-router';
import type { LoadPiletsOptions } from 'piral-base';
import type { UseBoundStore } from 'zustand';
import type { Dict, Without } from './common';
import type { NavigationApi } from './navigation';
import type { SharedDataItem, DataStoreTarget } from './data';
import type { PiralCustomActions, PiralCustomState, PiralCustomRegistryState, PiralCustomComponentsState } from './custom';
import type { EventEmitter, Pilet, BaseComponentProps, PageComponentProps, ExtensionComponentProps, PiletsBag, PiletEntry } from './api';
import type { PiralPageMeta, ComponentConverters, LoadingIndicatorProps, ErrorInfoProps, RouterProps, LayoutProps, Errors, RouteSwitchProps } from './components';
export interface StateDispatcher<TState> {
(state: TState): Partial<TState>;
}
export type WrappedComponent<TProps> = ComponentType<PropsWithChildren<Without<TProps, keyof BaseComponentProps>>>;
/**
* The base type for pilet component registration in the global state context.
*/
export interface BaseRegistration {
/**
* The pilet registering the component.
*/
pilet: string;
}
/**
* The interface modeling the registration of a pilet page component.
*/
export interface PageRegistration extends BaseRegistration {
/**
* The registered page component.
*/
component: WrappedComponent<PageComponentProps>;
/**
* The page's associated metadata.
*/
meta: PiralPageMeta;
}
/**
* The interface modeling the registration of a pilet extension component.
*/
export interface ExtensionRegistration extends BaseRegistration {
/**
* The wrapped registered extension component.
*/
component: WrappedComponent<ExtensionComponentProps<string>>;
/**
* The original extension component that has been registered.
*/
reference: any;
/**
* The default params (i.e., meta) of the extension.
*/
defaults: any;
}
/**
* The Piral global app sub-state container for shared components.
*/
export interface ComponentsState extends PiralCustomComponentsState {
/**
* The loading indicator renderer.
*/
LoadingIndicator: ComponentType<LoadingIndicatorProps>;
/**
* The error renderer.
*/
ErrorInfo: ComponentType<ErrorInfoProps>;
/**
* The router context.
*/
Router: ComponentType<RouterProps>;
/**
* The layout used for pages.
*/
Layout: ComponentType<LayoutProps>;
/**
* The route switch used for determining the route registration.
*/
RouteSwitch: ComponentType<RouteSwitchProps>;
/**
* A component that can be used for debugging purposes.
*/
Debug?: ComponentType;
}
/**
* The Piral global app sub-state container for app information.
*/
export interface AppState {
/**
* Gets if the application is currently performing a background loading
* activity, e.g., for loading modules asynchronously or fetching
* translations.
*/
loading: boolean;
/**
* Gets an unrecoverable application error, if any.
*/
error: Error | undefined;
/**
* Gets if the components from the micro frontends should be wrapped
* in a piral-component element.
*/
wrap: boolean;
}
/**
* The Piral global app sub-state container for component registrations.
*/
export interface RegistryState extends PiralCustomRegistryState {
/**
* The registered page components for the router.
*/
pages: Dict<PageRegistration>;
/**
* The registered extension components for extension slots.
*/
extensions: Dict<Array<ExtensionRegistration>>;
/**
* The registered wrappers for any component.
*/
wrappers: Dict<ComponentType<any>>;
}
export type ErrorComponentsState = {
[P in keyof Errors]?: ComponentType<Errors[P]>;
};
/**
* The Piral global app state container.
*/
export interface GlobalState extends PiralCustomState {
/**
* The relevant state for the app itself.
*/
app: AppState;
/**
* The relevant state for rendering errors of the app.
*/
errorComponents: ErrorComponentsState;
/**
* The relevant state for rendering parts of the app.
*/
components: ComponentsState;
/**
* The relevant state for the registered components.
*/
registry: RegistryState;
/**
* Gets the loaded modules.
*/
modules: Array<Pilet>;
/**
* The foreign component portals to render.
*/
portals: Record<string, Array<ReactPortal>>;
/**
* The application's shared data.
*/
data: Dict<SharedDataItem>;
/**
* The used (exact) application routes.
*/
routes: Dict<ComponentType<RouteComponentProps<any>> & {
/**
* The optional meta data registered with the page.
*/
meta?: PiralPageMeta;
}>;
/**
* The current provider.
*/
provider?: ComponentType;
}
/**
* The shape of an app action in Piral.
*/
export interface PiralAction<T extends (...args: any) => any> {
(ctx: GlobalStateContext, ...args: Parameters<T>): ReturnType<T>;
}
/**
* A subset of the available app actions in Piral.
*/
export type PiralDefineActions = Partial<{
[P in keyof PiralActions]: PiralAction<PiralActions[P]>;
}>;
/**
* The globally defined actions.
*/
export interface PiralActions extends PiralCustomActions {
/**
* Initializes the application shell.
* @param loading The current loading state.
* @param error The application error, if any.
* @param modules The loaded pilets.
*/
initialize(loading: boolean, error: Error | undefined, modules: Array<Pilet>): void;
/**
* Injects an evaluated pilet at runtime - removes the pilet from registry first if available.
* @param pilet The pilet to be injected.
* @returns The injected pilet.
*/
injectPilet(pilet: Pilet): Pilet;
/**
* Adds a pilet at runtime by loading it, evaluating it, and then injecting it.
* @param pilet The pilet to be added.
* @returns The promise indicating when the pilet was fully added.
*/
addPilet(pilet: PiletEntry): Promise<void>;
/**
* Removes a pilet by unloading it and deleting all component registrations.
* @param name The name of the pilet to remove.
*/
removePilet(name: string): Promise<void>;
/**
* Defines a single action for Piral.
* @param actionName The name of the action to define.
* @param action The action to include.
*/
defineAction<T extends keyof PiralActions>(actionName: T, action: PiralAction<PiralActions[T]>): void;
/**
* Defines a set of actions for Piral.
* @param actions The actions to define.
*/
defineActions(actions: PiralDefineActions): void;
/**
* Reads the value of a shared data item.
* @param name The name of the shared item.
*/
readDataValue(name: string): any;
/**
* Tries to write a shared data item. The write access is only
* possible if the name belongs to the provided owner or has not
* been taken yet.
* Setting the value to null will release it.
* @param name The name of the shared data item.
* @param value The value of the shared data item.
* @param owner The owner of the shared data item.
* @param target The target storage locatation.
* @param expiration The time for when to dispose the shared item.
*/
tryWriteDataItem(name: string, value: any, owner: string, target: DataStoreTarget, expiration: number): boolean;
/**
* Registers a new route to be resolved.
* @param route The route to register.
* @param value The page to be rendered on the route.
*/
registerPage(route: string, value: PageRegistration): void;
/**
* Unregisters an existing route.
* @param route The route to be removed.
*/
unregisterPage(route: string): void;
/**
* Registers a new extension.
* @param name The name of the extension category.
* @param value The extension registration.
*/
registerExtension(name: string, value: ExtensionRegistration): void;
/**
* Unregisters an existing extension.
* @param name The name of the extension category.
* @param value The extension that will be removed.
*/
unregisterExtension(name: string, reference: any): void;
/**
* Sets the common component to render.
* @param name The name of the component.
* @param component The component to use for rendering.
*/
setComponent<TKey extends keyof ComponentsState>(name: TKey, component: ComponentsState[TKey]): void;
/**
* Sets the error component to render.
* @param type The type of the error.
* @param component The component to use for rendering.
*/
setErrorComponent<TKey extends keyof ErrorComponentsState>(type: TKey, component: ErrorComponentsState[TKey]): void;
/**
* Sets the common routes to render.
* @param path The name of the component.
* @param component The component to use for rendering.
*/
setRoute<T extends {
[K in keyof T]?: string;
} = {}>(path: string, component: ComponentType<RouteComponentProps<T>>): void;
/**
* Includes a new provider as a sub-provider to the current provider.
* @param provider The provider to include.
*/
includeProvider(provider: JSX.Element): void;
/**
* Destroys (i.e., resets) the given portal instance.
* @param id The id of the portal to destroy.
*/
destroyPortal(id: string): void;
/**
* Includes the provided portal in the rendering pipeline.
* @param id The id of the portal to use.
* @param entry The child to render.
*/
showPortal(id: string, entry: ReactPortal): void;
/**
* Hides the provided portal in the rendering pipeline.
* @param id The id of the portal to use.
* @param entry The child to remove.
*/
hidePortal(id: string, entry: ReactPortal): void;
/**
* Updates the provided portal in the rendering pipeline.
* @param id The id of the portal to use.
* @param current The currently displayed child.
* @param next The updated child that should be displayed.
*/
updatePortal(id: string, current: ReactPortal, next: ReactPortal): void;
/**
* Dispatches a state change.
* @param update The update function creating a new state.
*/
dispatch(update: (state: GlobalState) => GlobalState): void;
/**
* Reads the selected part of the global state.
* @param select The selector for getting the desired part.
* @returns The desired part.
*/
readState<S>(select: (state: GlobalState) => S): S;
}
/**
* The Piral app instance context.
*/
export interface GlobalStateContext extends PiralActions, EventEmitter {
/**
* The global state context atom.
* Changes to the state should always be dispatched via the `dispatch` action.
*/
state: UseBoundStore<GlobalState>;
/**
* The API objects created for the loaded pilets.
*/
apis: PiletsBag;
/**
* The available component converters.
*/
converters: ComponentConverters<any>;
/**
* The navigation manager for the whole instance.
*/
navigation: NavigationApi;
/**
* The initial options.
*/
options: LoadPiletsOptions;
}