@libreforge/libreforge-framework
v1.0.112
Published
``` npm login npm whoami
Downloads
12
Readme
LibreForge Framework
LibreForge Platform
LibreForge platform is WIX for enterprise - no code integrated development environment to let enterprises and agencies build user facing portals.
One of the main pillar of platform is open source LibreForge Framework.
The open source nature of framework empowers organizations to avoid vendor lock by providing freedom of choice,
enabling customization and control over the source code, ensuring long-term viability independent of vendor roadmaps,
promoting interoperability, and enhancing security through community-driven transparency and vigilance.
State Management
There are two types of state in LibreForge - Shared & Page states. Shared state is not cleared on page switch, Page state - is cleared.
Shared State
An example of Shared state usage is to keep the state of Loader, or keep the session information (like access token) and be sure that such information doesn't disappear, when user decides to move to another page. In other words, if we need the state to survive the page change, such state needs to be kept as shared.
E.g. if you inspect the default RouteToPageAction action, you will notice, that such action clears the page state, i.e.
dispatch.app.cleanCurrentPageState({})
Page State
Page state instead is used to keep the currently visible components values, metadata, etc - everything, which is needed to render the page, submit the data to backend, etc. On page change such data needs to be removed, as it isn't relevant for another page components.
Developer can assign DebugStateAction as the 'on click action' to the Button component
to be able to debug state at a runtime (for dev testing purposes only). Such action requires the State Type
parameter to be provided, which is either shared
or page
.
Framework Abstractions
This section delineates the framework's provided abstractions, essential for implementing a standardized collection of components, actions, etc. Furthermore, it defines the guiding principles of design that developers are expected to adhere to when crafting custom implementations.
AbstractAction
The framework furnishes a set of preconfigured UI actions, ready to be attached to UI components and triggered by the end-users, such as those triggered by button clicks. E.g. the actions triggered by the button click. For instance, the FormSubmitAction is usually attached to the FormSubmitButton component. Each action possesses unique characteristics, delineating specific conventions that developers must acknowledge and adhere to.
The framework offers flexibility beyond predefined actions, empowering developers to introduce custom actions seamlessly, thereby extending functionality accessible to both Designer and End Users Portal.
A prime illustration of this flexibility is evident in librepackage-security-oauth2-google
,
which provides Google based login capabilities, one of the enablement is OAuth2GoogleRedirectAction.
This action initiates the OAuth 2.0 Authorization Code flow and is Google specific.
By inspecting the AbstractAction
class, developers can understand, what is being available to the action at a time of execution.
@injectable()
export abstract class AbstractAction {
abstract execute(context: ActionExecutionContext): Promise<{ next: boolean, result: any }>;
The ActionExecutionContext
defines the next objects available during the action execution:
componentId
- id of a component, the action is attached to and which has triggered itcollectionRefIdx
- if UI component is rendered by iterating the collection (e.g. as it is done byforEach
component), then index of collection item is propagated to an action executionargs
- and object that keeps the value for action arguments, as it was defined during design time. E.g. if that's theFetchAction
, then that one requireurl
argument to be defined during the design timepageComponents
- page definition, i.e. all the components on a page, which is rendered. So that developer can get the component object by thecomponentId
currentPageState
- object, which represents the temporary state (it's cleaned during the page switch) the current active page works with. All the components write to / read from this statesharedState
- object representing the state, which is capable to survive the page change. Such state is used to store thesecurity token
orloader state
dispatch
- Redux dispatcher to let developer call reducers and change thecurrentPageState
orsharedState
during action executionsnackbar
- to let developer show temporary end user notificationrouter
- react router to let the end user be routed to another pagecontainer
-IoC/DI
container to let reach any of the discoverable components / services / etcprevExecutionState
- currently the object, which contains the result of previous action execution. I.e. there may be multiple actions attached to theButton
and these actions are executed one by one. It is possible to have a scenario, when 2nd action needs to work with result of 1st action execution (e.g. response from server)pagination
- pagination details (page, size), in case the action is executed in pagination context
As we can see the plenty of capabilities are made available to the action
- it can interact with user, read / change the state, redirect and literally access any service through the IoC/DI
context.
ComponentProvider
A "component provider" serves as an abstract interface enabling developers to seamlessly integrate new UI components. It acts as a conduit for the LibreForge framework to detect and incorporate these components, subsequently making them accessible to both Designer and the Portal.
To better understand the implementation, check
The Designer or Portal discovers about the component through the IoC/DI context, we make the component available by binding it to the context (see the binding details above). Then that's not the component itself, but the component provider the Designer & Portal deal with.
The ButtonProvider
abstract class looks like
@injectable()
export abstract class ComponentProvider {
abstract getCategory(): ComponentCategory;
abstract getIcon(): ReactElement;
abstract getName(): string;
abstract getComponent(...): ReactNode;
abstract getInspectorControls(): {
control: InspectorControlEnum;
props: any;
}[];
abstract getDefaultProps(): any;
abstract isContainer(): boolean;
}
where
getCategory
- defines the category under which the component is rendered in Designer. The next categories are available right nowlayout
,basic
,fields
,forms
,wizard
,tools
,blocks
getIcon
- icon rendered in DesignergetName
- rendered in Designer, needs to be unique, as later it is stored in application configuration and is used to render the component on UIgetPreview
- component itselfgetInspectorControls
- component specific controls enabled in Designer, e.g.FormSubmitButton
needs url,Button
doesn't need itgetDefaultProps
- default values for components propertiesisContainer
- tells to Designer, that other components are droppable to the current one or not
For more information about the collection of components provided by the framework see the list of docs and read about each component separately in https://github.com/getlibreforge/libreforge-framework/tree/main/docs
AbstractValidationRule
This abstraction defines the validation rules for UI input components, which are executed upon form submission. I.e. during FormSubmitAction execution.
Inspect LengthBetweenValidationRule to understand the implementation by an example.
AbstractCallbackHandler
The callback handler enables developers to expose additional URLs, facilitating actions such as handling user clicks within an email or accepting redirects from third-party services along with associated data for processing.
The perfect example is the implementation of OAuth 2.0 Authorization Code protocol,
when Service Provider needs to accept the redirect from Identity Provider with authorization code issued.
This exact example is implemented in librepackage-security-oauth2-google
, see OAuth2GoogleCallbackHandler
Security
LibreForge Framework provides the security abstractions to let developers implement end user authentication / authorization.
AuthorizationManager is an internal implementation, which drives the decision-making and undertakes the security related actions.
AbstractAuthorizationConfigProvider tells to AuthorizationManager
, which of urls are considered public and which are private. Developers shall override default implementation in projects in order to define project specific configuration.
E.g. inspect libreforge-general-dashboard-demo / DefaultAuthorizationConfigProvider. This is an example of end user portal with security configuration defined.
Additionally, AbstractSessionRefreshStrategy
defines the mechanism to refresh the user session, e.g. OAuth2SessionRefreshStrategy defines the Google OAuth 2.0 specific implementation.