@rws-framework/client
Version:
This package provides the core client-side framework for Realtime Web Suit (RWS), enabling modular, asynchronous web components, state management, and integration with backend services. It is located in `.dev/client`.
312 lines (227 loc) • 10.2 kB
Markdown
# @rws-framework/client
This package provides the core client-side framework for Realtime Web Suit (RWS), enabling modular, asynchronous web components, state management, and integration with backend services. It is located in `.dev/client`.
## Table of Contents
1. [Overview](#overview)
2. [Getting Started](#getting-started)
3. [Key Concepts](#key-concepts)
4. [Component Initialization](#component-initialization)
5. [Dependency Injection](#dependency-injection)
6. [Frontend Routes](#frontend-routes)
7. [Backend Imports](#backend-imports)
8. [Utilizing APIService](#utilizing-apiservice)
9. [Notifier](#notifier)
10. [Service Worker](#service-worker)
11. [Example: WebChat Component](#example-webchat-component)
12. [Other configs](#other-configs)
13. [Plugin System](#plugin-system)
14. [Nest Interconnectors](#nest-interconnectors)
15. [Styles Injection](#styles-injection)
16. [Links](#links)
## Overview
`@rws-framework/client` is the heart of the RWS frontend framework. It manages configuration, plugin management, service registration, application lifecycle, and provides the base for all RWSView components. It is designed for modular, fullstack-oriented web applications using the RWS/FAST paradigm.
### Main Features
- **RWSClient**: Main entry point for the frontend application. Handles configuration, plugin management, service registration, and application lifecycle.
- **Dependency Injection**: Uses a DI container for services and components.
- **Component Registration**: Supports modular component definition and registration.
- **Plugin System**: Add plugins for routing, websockets, and more.
- **Notifier**: Customizable notification system for UI messages.
- **Service Worker Integration**: Pushes config and user data to service workers.
- **User and Config Management**: Handles user state and application configuration.
- **API Service**: Integrates with backend API routes and authentication.
## Getting Started
Install dependencies and initialize the project:
```bash
yarn
rws-client init
yarn build # or yarn watch for dev
yarn server # to just start server
```
Start the engine in your site JavaScript:
```javascript
window.RWS.client.start(CFG); // async function
```
Or for initial setup on an event:
```javascript
window.RWS.client.setup(CFG).then(() => {
$.on('loaded', function(data){
const optionalNewCfg = { backendRoutes: data.backendRoutes };
window.RWSClient.start(optionalNewCfg).then();
})
});
```
### Default config for RWS
```javascript
const _DEFAULT_CONFIG_VARS = {
dev: false,
hot: false,
report: false,
publicDir: './public',
publicIndex: 'index.html',
outputFileName: 'client.rws.js',
outputDir: process.cwd() + '/build',
backendUrl: null,
wsUrl: null,
partedDirUrlPrefix: '/lib/rws',
partedPrefix: 'rws',
pubUrlFilePrefix: '/',
parted: false,
}
```
*See the table in the original README for all config options.*
## Key Concepts
### RWSClient
`RWSClient` is the main class, instantiated and managed via DI. It manages configuration, plugins, services, and the application lifecycle.
#### Example Usage
```typescript
import RWSClient, { RWSClientInstance } from '@rws-framework/client';
const theClient: RWSClientInstance = RWSContainer().get(RWSClient);
theClient.addPlugin(RWSBrowserRouter);
theClient.addPlugin(RWSWebsocketsPlugin, { enabled: true });
theClient.assignClientToBrowser();
theClient.onInit(async () => {
// Register components, routes, etc.
});
theClient.setNotifier((message, logType) => {
// Custom notification logic
});
theClient.start({
backendRoutes,
backendUrl: process.env.BACKEND_URL,
wsUrl: process.env.WS_URL,
hot: true,
parted: false
});
```
### Component Registration
- Components must extend `RWSViewComponent` and use the `@RWSView` decorator.
- Structure: `component-dir/component.ts`, `template.html`, `styles/layout.scss`
- See RWSDocs for more details.
### Plugin System
- Add plugins via `addPlugin` (e.g., routing, websockets).
- Plugins are initialized on client startup.
### Notifier
Set a custom notification handler with `setNotifier`:
```typescript
theClient.setNotifier((message: string, logType: NotifyLogType, uiType: NotifyUiType = 'notification', onConfirm: (params: any) => void) => {
// Implementation based on uiType
});
```
### Service Worker
If you pass `{serviceWorker: 'service_worker_class_path.ts'}` to the RWS Webpack wrapper, the code will build a ServiceWorker to pubDir.
## Dependency Injection
All services and components are registered and resolved via a DI container. Default and custom services can be injected and used throughout your app.
## Frontend Routes
Define frontend routes using `renderRouteComponent` and pass them to the router plugin. Example route definitions for use with the router component (see `.dev/router`):
```typescript
import { renderRouteComponent } from '@rws-framework/browser-router';
import { HomePage } from './pages/home/component';
import { CompanyList } from './pages/company/list/component';
import { GeneralSettings } from './pages/settings/general/component';
export const frontRoutes = [
{
path: '/',
name: 'Home',
component: HomePage,
icon: 'home',
inMenu: true
},
{
path: '/company/list',
name: 'Companies',
component: CompanyList,
icon: 'company',
inMenu: true
},
{
path: '/settings/general',
name: 'Settings',
component: GeneralSettings,
icon: 'settings',
inMenu: true
}
];
// Convert to route map for the router
const routeMap = {};
for (const route of frontRoutes) {
routeMap[route.path] = renderRouteComponent(route.name, route.component);
}
export default routeMap;
```
- Each route object can include `path`, `name`, `component`, `icon`, and `inMenu` fields.
- Use `renderRouteComponent` to wrap the component for the router.
- Pass the resulting `routeMap` to the router plugin or RWS client configuration.
## Backend Imports
`backendImport.ts` consolidates backend interfaces, routes, and models for synchronized frontend/backend development.
### HTTPRoutes Interface
The RWS client uses a typed interface for backend HTTP routes, typically called `IBackendRoute` or `HTTPRoutes`. This interface defines the structure for backend API endpoints, allowing for type-safe integration between frontend and backend. You can import and use these routes as follows:
```typescript
import { backendRoutes } from './backendImport';
theClient.setBackendRoutes(backendRoutes);
```
- Each route entry in `backendRoutes` should conform to the `IBackendRoute` (or `HTTPRoutes`) interface, describing the HTTP method, path, and any metadata required for API calls.
- This enables strong typing and autocompletion for API requests throughout your frontend codebase.
## Utilizing APIService
`APIService` is used for making HTTP requests to the backend. It supports dynamic types for response and payload, and can be accessed via DI or through the RWS client instance.
### Basic Usage
```typescript
// Injected in a component or service
@RWSInject(ApiService, true) protected apiService: ApiServiceInstance;
// Or via the client
const apiService = window.RWS.client.get('ApiService');
```
### Making Requests
You can use RESTful methods directly:
```typescript
// GET request
apiService.get('/api/some-endpoint');
// POST request with payload
type MyResponse = { ... };
type MyPayload = { ... };
const result = await apiService.post<MyResponse, MyPayload>('/api/some-endpoint', { foo: 'bar' });
```
### Using Named Backend Routes
If you use named backend routes (from `backendRoutes`):
```typescript
// By route name (controller:action)
const data = await apiService.back.get<MyResponse>('user:getProfile', { routeParams: { id: '123' } });
// POST with payload
type Payload = { name: string };
const result = await apiService.back.post<MyResponse, Payload>('user:updateProfile', { name: 'John' });
```
### File Upload Example
```typescript
await apiService.uploadFile('/api/upload', file, progress => {
console.log('Progress:', progress);
});
```
### Route Type Safety
If you use `IBackendRoute`/`HTTPRoutes` for your backend route definitions, you get type safety and autocompletion for all API calls.
## Example: WebChat Component
See the WebChat component for a practical example of APIService and RWSView usage.
## Other configs
See the original README for example `tsconfig.json` and webpack config.
## Plugin System
The plugin system allows you to extend the client with additional features. For example, you can add routing with `@rws-framework/browser-router` or websockets with `@rws-framework/nest-interconnectors`.
## Nest Interconnectors
The `@rws-framework/nest-interconnectors` package provides seamless integration with NestJS-based backend websockets and real-time features. You can add the plugin as follows:
```typescript
import { RWSWebsocketsPlugin, WSOptions } from '@rws-framework/nest-interconnectors';
theClient.addPlugin<WSOptions>(RWSWebsocketsPlugin, {
enabled: true,
auto_notify: true
});
```
This enables real-time communication and event-driven features between your RWS frontend and a NestJS backend.
## Styles Injection
RWS supports advanced styles injection for components. You can inject global or component-specific stylesheets using the static method:
```typescript
RWSViewComponent.injectStyles(["/css/global.css", "/css/theme.css"]);
```
- Styles can be injected in `adopted`, `legacy`, or `both` modes (default is `adopted`).
- Styles are cached in IndexedDB for performance and can be hot-reloaded.
- Each component can also inject its own styles via the `injectStyles` method or by specifying styles in the component definition.
This allows for efficient, encapsulated, and dynamic styling of your RWS components, supporting both modern and legacy browsers.
## Links
- [RWSDocs instructions](../../.github/instructions/RWSDocs.instructions.md)
- [FAST documentation](https://www.fast.design/docs/fast-element/getting-started)
- [WebComponents.org](https://www.webcomponents.org)