@rws-framework/client 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bin/add-v.sh +10 -0
- package/.eslintrc.json +53 -0
- package/.setup/.eslintrc.json +11 -0
- package/.setup/tsconfig.json +29 -0
- package/README.md +691 -0
- package/_rws_externals.js +40 -0
- package/_tools.js +317 -0
- package/console.js +87 -0
- package/declarations.d.ts +9 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/26e93147f10415a0ed4a.svg +6 -0
- package/docs/assets/75c9471662e97ee24f29.svg +7 -0
- package/docs/assets/db90e4df2373980c497d.svg +9 -0
- package/docs/assets/hierarchy.css +1 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/assets/highlight.css +120 -0
- package/docs/assets/main.js +59 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1414 -0
- package/docs/classes/ApiServiceInstance.html +20 -0
- package/docs/classes/DOMServiceInstance.html +10 -0
- package/docs/classes/NotifyServiceInstance.html +12 -0
- package/docs/classes/RWSClient.html +11 -0
- package/docs/classes/RWSRouter.html +9 -0
- package/docs/classes/RWSService.html +7 -0
- package/docs/classes/RWSUploader.html +35 -0
- package/docs/classes/RWSViewComponent.html +24 -0
- package/docs/classes/RouterComponent.html +31 -0
- package/docs/classes/RoutingServiceInstance.html +13 -0
- package/docs/classes/UtilsServiceInstance.html +11 -0
- package/docs/classes/WSServiceInstance.html +32 -0
- package/docs/functions/RWSView.html +1 -0
- package/docs/functions/ngAttr.html +1 -0
- package/docs/functions/registerRWSComponents.html +1 -0
- package/docs/functions/renderRouteComponent.html +1 -0
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +53 -0
- package/docs/interfaces/IRWSAssetShowOptions.html +1 -0
- package/docs/interfaces/IRWSConfig.html +11 -0
- package/docs/interfaces/IRWSDecoratorOptions.html +4 -0
- package/docs/interfaces/IRWSHttpRoute.html +3 -0
- package/docs/interfaces/IRWSPrefixedHTTProutes.html +3 -0
- package/docs/interfaces/IRoutingEvent.html +3 -0
- package/docs/modules.html +39 -0
- package/docs/types/DOMOutputType.html +1 -0
- package/docs/types/IRWSBackendRoute.html +1 -0
- package/docs/types/IRWSFrontRoutes.html +1 -0
- package/docs/types/IRWSRouteResult.html +1 -0
- package/docs/types/IRWSWebsocketStatus.html +1 -0
- package/docs/types/NotifyLogType.html +1 -0
- package/docs/types/NotifyUiType.html +1 -0
- package/docs/types/RWSNotify.html +1 -0
- package/docs/types/RouteReturn.html +1 -0
- package/docs/variables/ApiService.html +1 -0
- package/docs/variables/DOMService.html +1 -0
- package/docs/variables/NotifyService.html +1 -0
- package/docs/variables/RoutingService.html +1 -0
- package/docs/variables/UtilsService.html +1 -0
- package/docs/variables/WSService.html +1 -0
- package/docs/variables/_ROUTING_EVENT_NAME.html +1 -0
- package/package.json +93 -0
- package/package.webpack.config.js +17 -0
- package/rws.webpack.config.js +260 -0
- package/src/client.ts +304 -0
- package/src/components/_attrs/angular-attr.ts +64 -0
- package/src/components/_attrs/sanitize-html.ts +81 -0
- package/src/components/_component.ts +290 -0
- package/src/components/_container.ts +16 -0
- package/src/components/_decorator.ts +112 -0
- package/src/components/_design_system.ts +6 -0
- package/src/components/index.ts +9 -0
- package/src/components/progress/component.ts +55 -0
- package/src/components/progress/styles/layout.scss +91 -0
- package/src/components/progress/template.html +25 -0
- package/src/components/router/component.ts +67 -0
- package/src/components/uploader/component.ts +75 -0
- package/src/components/uploader/styles/layout.scss +105 -0
- package/src/components/uploader/template.html +17 -0
- package/src/hmr.ts +19 -0
- package/src/index.ts +98 -0
- package/src/interfaces/IRWSConfig.ts +24 -0
- package/src/interfaces/IRWSUser.ts +7 -0
- package/src/interfaces/IRWSViewComponent.ts +37 -0
- package/src/interfaces/RWSWindow.ts +39 -0
- package/src/routing/_router.ts +59 -0
- package/src/routing/index.ts +7 -0
- package/src/run.ts +35 -0
- package/src/service_worker/src/_service_worker.ts +88 -0
- package/src/service_worker/tsconfig.json +21 -0
- package/src/service_worker/webpack.config.js +67 -0
- package/src/services/ApiService.ts +241 -0
- package/src/services/ConfigService.ts +107 -0
- package/src/services/DOMService.ts +91 -0
- package/src/services/NotifyService.ts +49 -0
- package/src/services/RoutingService.ts +46 -0
- package/src/services/ServiceWorkerService.ts +60 -0
- package/src/services/UtilsService.ts +103 -0
- package/src/services/WSService.ts +218 -0
- package/src/services/_service.ts +50 -0
- package/src/services/_ws_handlers/ConnectionHandler.ts +52 -0
- package/src/services/_ws_handlers/EventHandler.ts +28 -0
- package/src/services/_ws_handlers/MessageHandler.ts +49 -0
- package/src/styles/includes.scss +102 -0
- package/src/types/RWSNotify.ts +7 -0
- package/tsconfig.json +27 -0
- package/typedoc.json +13 -0
- package/webpack/after/copy.js +73 -0
- package/webpack/after/sw.js +14 -0
- package/webpack/index.js +11 -0
- package/webpack/rws_after_plugin.js +80 -0
- package/webpack/rws_fast_css_loader.js +16 -0
- package/webpack/rws_fast_html_loader.js +4 -0
- package/webpack/rws_fast_scss_loader.js +50 -0
- package/webpack/rws_fast_ts_loader.js +134 -0
- package/webpack/rws_plugin.js +337 -0
package/src/run.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ConfigServiceInstance } from './services/ConfigService';
|
|
2
|
+
import { NotifyServiceInstance } from './services/NotifyService';
|
|
3
|
+
import { WSServiceInstance} from './services/WSService';
|
|
4
|
+
|
|
5
|
+
import { RoutingServiceInstance} from './services/RoutingService';
|
|
6
|
+
import { RouterComponent } from './components/router/component';
|
|
7
|
+
import { RWSClientInstance } from './client';
|
|
8
|
+
|
|
9
|
+
const main = async (
|
|
10
|
+
config: ConfigServiceInstance,
|
|
11
|
+
WSService: WSServiceInstance,
|
|
12
|
+
NotifyService: NotifyServiceInstance,
|
|
13
|
+
RoutingService: RoutingServiceInstance
|
|
14
|
+
): Promise<boolean> => {
|
|
15
|
+
if(config.get('backendUrl')){
|
|
16
|
+
WSService.on('ws:disconnected', (instance, params) => {
|
|
17
|
+
NotifyService.notify(`Your websocket client disconnected from the server. Your ID was <strong>${params.socketId}</strong>`, 'error');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
WSService.on('ws:connected', (instance, params) => {
|
|
21
|
+
NotifyService.notify('You are connected to websocket. Your ID is: <strong>' + instance.socket().id + '</strong>', 'info');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
WSService.on('ws:reconnect', (instance, params) => {
|
|
25
|
+
console.info('WS RECONNECTION ' + (params.reconnects + 1));
|
|
26
|
+
NotifyService.notify('Your websocket client has tried to reconnect to server. Attempt #' + (params.reconnects+1), 'warning');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
WSService.init(config.get('wsUrl'), config.get('user'), config.get('transports'));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return true;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default main;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import IRWSUser from '../../interfaces/IRWSUser';
|
|
2
|
+
import RWSContainer from '../../components/_container';
|
|
3
|
+
|
|
4
|
+
//@4DI
|
|
5
|
+
import { WSServiceInstance } from '../../services/WSService'
|
|
6
|
+
import { DI, Container } from "@microsoft/fast-foundation";
|
|
7
|
+
|
|
8
|
+
type SWMsgType = {
|
|
9
|
+
command: string,
|
|
10
|
+
asset_type?: string,
|
|
11
|
+
params: any
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
abstract class RWSServiceWorker<UserType extends IRWSUser> {
|
|
15
|
+
protected DI: Container;
|
|
16
|
+
protected user: UserType = null;
|
|
17
|
+
protected ignoredUrls: RegExp[] = [];
|
|
18
|
+
protected wsService: WSServiceInstance
|
|
19
|
+
protected regExTypes: { [key: string]: RegExp }
|
|
20
|
+
|
|
21
|
+
public workerScope: ServiceWorkerGlobalScope;
|
|
22
|
+
|
|
23
|
+
protected static _instances: { [key: string]: RWSServiceWorker<IRWSUser> } | null = {};
|
|
24
|
+
|
|
25
|
+
onInit(): Promise<void> { return; }
|
|
26
|
+
|
|
27
|
+
onInstall(): Promise<void> { return; }
|
|
28
|
+
onActivate(): Promise<void> { return; }
|
|
29
|
+
|
|
30
|
+
constructor(workerScope: ServiceWorkerGlobalScope, DI: Container){
|
|
31
|
+
this.DI = DI;
|
|
32
|
+
this.wsService = DI.get<WSServiceInstance>(WSServiceInstance);
|
|
33
|
+
this.workerScope = workerScope;
|
|
34
|
+
|
|
35
|
+
this.onInit().then(() => {
|
|
36
|
+
this.workerScope.addEventListener('install', () => {
|
|
37
|
+
console.log('Service Worker: Installed');
|
|
38
|
+
|
|
39
|
+
this.onInstall();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
this.workerScope.addEventListener('activate', () => {
|
|
43
|
+
console.log('[SW] Service Worker: Activated');
|
|
44
|
+
|
|
45
|
+
this.onActivate();
|
|
46
|
+
|
|
47
|
+
return workerScope.clients.claim();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
sendMessageToClient = (clientId: string, payload: any) => {
|
|
53
|
+
return this.workerScope.clients.get(clientId)
|
|
54
|
+
.then((client: any) => {
|
|
55
|
+
if (client) {
|
|
56
|
+
client.postMessage(payload);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
getUser(): UserType
|
|
62
|
+
{
|
|
63
|
+
return this.user;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setUser(user: UserType): RWSServiceWorker<UserType>
|
|
67
|
+
{
|
|
68
|
+
this.user = user;
|
|
69
|
+
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static create<T extends new (...args: any[]) => RWSServiceWorker<IRWSUser>>(this: T, workerScope: ServiceWorkerGlobalScope): InstanceType<T>
|
|
74
|
+
{
|
|
75
|
+
const className = this.name;
|
|
76
|
+
|
|
77
|
+
if (!RWSServiceWorker._instances[className]) {
|
|
78
|
+
const WSService = RWSContainer().get<WSServiceInstance>(WSServiceInstance);
|
|
79
|
+
RWSServiceWorker._instances[className] = new this(workerScope, WSService);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return RWSServiceWorker._instances[className] as InstanceType<T>;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default RWSServiceWorker;
|
|
87
|
+
|
|
88
|
+
export { SWMsgType }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": "../",
|
|
4
|
+
"experimentalDecorators": true,
|
|
5
|
+
"emitDecoratorMetadata": true,
|
|
6
|
+
"target": "ES2018",
|
|
7
|
+
"module": "es2022",
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"sourceMap": true,
|
|
12
|
+
"outDir": "dist",
|
|
13
|
+
"strictNullChecks": false,
|
|
14
|
+
"allowSyntheticDefaultImports": true,
|
|
15
|
+
"lib": ["DOM", "ESNext", "WebWorker"],
|
|
16
|
+
"paths": {
|
|
17
|
+
// "rws-js-client/*": ["../*"],
|
|
18
|
+
// "rws-js-client": ["../index"],
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const webpack = require('webpack');
|
|
3
|
+
const tools = require('rws-js-client/_tools');
|
|
4
|
+
const gThis = require.resolve('globalthis')
|
|
5
|
+
const {rwsExternals} = require('rws-js-client/_rws_externals');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const executionDir = process.cwd();
|
|
9
|
+
const rootPackageNodeModules = path.resolve(tools.findRootWorkspacePath(process.cwd()), 'node_modules');
|
|
10
|
+
|
|
11
|
+
const mergeCodeBaseOptions = {
|
|
12
|
+
incl: ['rws-js-client/src/services'],
|
|
13
|
+
not_incl: ['./services/RoutingService'],
|
|
14
|
+
exceptions_context: ['socket.io-', '@socket.io'],
|
|
15
|
+
exceptions: ['rws-js-client/src/services', './service', './ws_handlers', 'socket.io-', '@socket.io','uuid',]
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
entry: process.env.SWPATH,
|
|
20
|
+
mode: 'development',
|
|
21
|
+
target: 'web',
|
|
22
|
+
devtool: 'source-map',
|
|
23
|
+
output: {
|
|
24
|
+
path: path.resolve(executionDir, 'public'),
|
|
25
|
+
filename: 'service_worker.js',
|
|
26
|
+
},
|
|
27
|
+
resolve: {
|
|
28
|
+
extensions: ['.ts', '.js'],
|
|
29
|
+
alias: {
|
|
30
|
+
document: false,
|
|
31
|
+
globalThis: gThis,
|
|
32
|
+
'@cwd' : process.cwd(),
|
|
33
|
+
// 'rws-js-client': path.resolve(__dirname, '..') + '/index.ts',
|
|
34
|
+
// 'rws-js-client/*': path.resolve(__dirname, '..', '..')
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
plugins: [
|
|
38
|
+
new webpack.ProvidePlugin({
|
|
39
|
+
global: 'globalThis' // Use 'globalThis' as a fallback for the global object
|
|
40
|
+
}),
|
|
41
|
+
new webpack.DefinePlugin({
|
|
42
|
+
'__SWPATH': "'" + process.env.SWPATH + "'",
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
|
+
module: {
|
|
46
|
+
rules: [
|
|
47
|
+
{
|
|
48
|
+
test: /\.(ts)$/,
|
|
49
|
+
use: [
|
|
50
|
+
{
|
|
51
|
+
loader: 'ts-loader',
|
|
52
|
+
options: {
|
|
53
|
+
allowTsInNodeModules: true,
|
|
54
|
+
configFile: path.resolve(__dirname, 'tsconfig.json')
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
loader: path.resolve(tools.findPackageDir(),'webpack','rws_fast_ts_loader.js'),
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
resolveLoader: {
|
|
65
|
+
modules: [rootPackageNodeModules],
|
|
66
|
+
}
|
|
67
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import TheService from './_service';
|
|
2
|
+
|
|
3
|
+
//@4DI
|
|
4
|
+
import ConfigService, { ConfigServiceInstance } from '../services/ConfigService';
|
|
5
|
+
|
|
6
|
+
import { upload, UploadResponse } from 'upload';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
interface RequestOptions {
|
|
10
|
+
method?: string;
|
|
11
|
+
headers: HeadersInit;
|
|
12
|
+
body?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface IAPIOptions {
|
|
16
|
+
headers?: Headers,
|
|
17
|
+
routeParams?: {
|
|
18
|
+
[key: string]: string
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface IHTTProute {
|
|
23
|
+
name: string;
|
|
24
|
+
path: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
interface IPrefixedHTTProutes {
|
|
29
|
+
prefix: string;
|
|
30
|
+
routes: IHTTProute[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type IBackendRoute = IHTTProute | IPrefixedHTTProutes;
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const _DEFAULT_CONTENT_TYPE = 'application/json';
|
|
37
|
+
|
|
38
|
+
class ApiServiceInstance extends TheService {
|
|
39
|
+
private token?: string;
|
|
40
|
+
|
|
41
|
+
constructor(@ConfigService private config: ConfigServiceInstance) {
|
|
42
|
+
super();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private addHeader(headers: Headers | [string, string][] | {[key: string]: string}, key: string, val: string)
|
|
46
|
+
{
|
|
47
|
+
if (headers instanceof Headers) {
|
|
48
|
+
headers.append(key, val);
|
|
49
|
+
} else if (Array.isArray(headers)) {
|
|
50
|
+
headers.push([key, val]);
|
|
51
|
+
} else {
|
|
52
|
+
headers[key] = val;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Function to get headers
|
|
57
|
+
private getHeaders(optHeaders: HeadersInit = {}): HeadersInit {
|
|
58
|
+
const headers: HeadersInit = { ...optHeaders };
|
|
59
|
+
|
|
60
|
+
if (!('Content-Type' in headers)) {
|
|
61
|
+
this.addHeader(headers, 'Content-Type', _DEFAULT_CONTENT_TYPE);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.token) {
|
|
65
|
+
this.addHeader(headers, 'Authorization', `Bearer ${this.token}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if(!!(headers as any)['Content-Type']){
|
|
69
|
+
this.addHeader(headers, 'Accept', '*/*');
|
|
70
|
+
}else{
|
|
71
|
+
this.addHeader(headers, 'Accept', (headers as any)['Content-Type']);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return headers;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public setToken(token: string)
|
|
78
|
+
{
|
|
79
|
+
this.token = token;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public async pureGet(url: string, options: IAPIOptions = {}): Promise<string> {
|
|
83
|
+
try {
|
|
84
|
+
const response = await fetch(url, {
|
|
85
|
+
headers: this.getHeaders(options.headers),
|
|
86
|
+
});
|
|
87
|
+
return await response.text();
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error('GET request failed:', error);
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public async isGetTargetReachable(url: string, options: IAPIOptions = {}): Promise<boolean> {
|
|
95
|
+
try {
|
|
96
|
+
return !!(await this.pureGet(url, options));
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public async get<T>(url: string, options: IAPIOptions = {}): Promise<T> {
|
|
103
|
+
try {
|
|
104
|
+
const response = await fetch(url, {
|
|
105
|
+
headers: this.getHeaders(options.headers),
|
|
106
|
+
});
|
|
107
|
+
return await response.json();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('GET request failed:', error);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public async post<T, P extends Object = {}>(url: string, payload?: P, options: IAPIOptions = {}): Promise<T> {
|
|
115
|
+
try {
|
|
116
|
+
const response = await fetch(url, {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: this.getHeaders(options.headers),
|
|
119
|
+
body: payload ? JSON.stringify(payload) : null,
|
|
120
|
+
});
|
|
121
|
+
return await response.json();
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error('POST request failed:', error);
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public async put<T, P extends Object = {}>(url: string, payload?: P, options: IAPIOptions = {}): Promise<T> {
|
|
129
|
+
try {
|
|
130
|
+
const response = await fetch(url, {
|
|
131
|
+
method: 'PUT',
|
|
132
|
+
headers: this.getHeaders(options.headers),
|
|
133
|
+
body: payload ? JSON.stringify(payload) : null,
|
|
134
|
+
});
|
|
135
|
+
return await response.json();
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('PUT request failed:', error);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public async delete<T>(url: string, options: IAPIOptions = {}): Promise<T> {
|
|
143
|
+
try {
|
|
144
|
+
const response = await fetch(url, {
|
|
145
|
+
method: 'DELETE',
|
|
146
|
+
headers: this.getHeaders(options.headers),
|
|
147
|
+
});
|
|
148
|
+
return await response.json();
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.error('DELETE request failed:', error);
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private getBackendUrl(routeName: string, params: {[key: string]: string} = {})
|
|
156
|
+
{
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
const routesPackage = this.config.get('backendRoutes');
|
|
160
|
+
|
|
161
|
+
let routes: IHTTProute[] = [];
|
|
162
|
+
|
|
163
|
+
routesPackage.forEach((item: IBackendRoute) => {
|
|
164
|
+
// Check if item is an instance of IPrefixedHTTProutes
|
|
165
|
+
if ('prefix' in item && 'routes' in item && Array.isArray(item.routes)) {
|
|
166
|
+
// Handle the case where item is of type IPrefixedHTTProutes
|
|
167
|
+
routes = [...routes, ...item.routes.map((subRouteItem: IHTTProute): IHTTProute => {
|
|
168
|
+
const subRoute: IHTTProute = {
|
|
169
|
+
path: item.prefix + subRouteItem.path,
|
|
170
|
+
name: subRouteItem.name
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
return subRoute;
|
|
174
|
+
})];
|
|
175
|
+
} else {
|
|
176
|
+
// Handle the case where item is of type IHTTProute
|
|
177
|
+
routes.push(item as IHTTProute);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const route = routes.find((item: IHTTProute) => item.name === routeName);
|
|
182
|
+
|
|
183
|
+
if(!route){
|
|
184
|
+
throw new Error(`Backend route '${routeName}' does not exist.`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
let apiPath = route.path;
|
|
188
|
+
|
|
189
|
+
Object.keys(params).forEach((paramKey: string) => {
|
|
190
|
+
const paramValue = params[paramKey];
|
|
191
|
+
|
|
192
|
+
apiPath = apiPath.replace(`:${paramKey}`, paramValue);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return `${this.config.get('backendUrl')}${this.config.get('apiPrefix') || ''}${apiPath}`;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async uploadFile(url: string, file: File, onProgress: (progress: number) => void, options: IAPIOptions = {}): Promise<UploadResponse>
|
|
199
|
+
{
|
|
200
|
+
return upload(
|
|
201
|
+
|
|
202
|
+
url,
|
|
203
|
+
{
|
|
204
|
+
file,
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
onProgress,
|
|
208
|
+
headers: this.token ? { Authorization: `Bearer ${this.token}` } : null,
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public back = {
|
|
214
|
+
get: <T>(routeName: string, options?: IAPIOptions): Promise<T> => this.get(this.getBackendUrl(routeName, options?.routeParams), options),
|
|
215
|
+
post: <T, P extends Object = {}>(routeName: string, payload?: P, options?: IAPIOptions): Promise<T> => this.post(this.getBackendUrl(routeName, options?.routeParams), payload, options),
|
|
216
|
+
put: <T, P extends Object = {}>(routeName: string, payload: P, options?: IAPIOptions): Promise<T> => this.put(this.getBackendUrl(routeName, options?.routeParams), payload, options),
|
|
217
|
+
delete: <T>(routeName: string, options?: IAPIOptions): Promise<T> => this.delete(this.getBackendUrl(routeName, options?.routeParams), options),
|
|
218
|
+
uploadFile: (routeName: string, file: File, onProgress: (progress: number) => void, options: IAPIOptions = {}): Promise<UploadResponse> => this.uploadFile(this.getBackendUrl(routeName, options?.routeParams), file, onProgress),
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
connectToAmplify()
|
|
222
|
+
{
|
|
223
|
+
// "use client"
|
|
224
|
+
// const client = generateClient<Schema>() // use this Data client for CRUDL requests
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
// /*== STEP 3 ===============================================================
|
|
228
|
+
// Fetch records from the database and use them in your frontend component.
|
|
229
|
+
// (THIS SNIPPET WILL ONLY WORK IN THE FRONTEND CODE FILE.)
|
|
230
|
+
// =========================================================================*/
|
|
231
|
+
|
|
232
|
+
// /* For example, in a React component, you can use this snippet in your
|
|
233
|
+
// function's RETURN statement */
|
|
234
|
+
// // const { data: todos } = client.models.Todo.list()
|
|
235
|
+
|
|
236
|
+
// // return <ul>{todos.map(todo => <li key={todo.id}>{todo.content}</li>)}</ul>
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export default ApiServiceInstance.getSingleton();
|
|
241
|
+
export { IBackendRoute, RequestOptions, ApiServiceInstance, IHTTProute, IPrefixedHTTProutes };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import TheService from './_service';
|
|
2
|
+
import IRWSConfig from '../interfaces/IRWSConfig';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const _DEFAULTS: {[property: string]: any} = {
|
|
6
|
+
'pubPrefix': '/',
|
|
7
|
+
'pubUrl' : window.origin,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const __SENT_TO_COMPONENTS: string[] = [];
|
|
11
|
+
|
|
12
|
+
class ConfigService extends TheService {
|
|
13
|
+
static isLoaded: boolean = false;
|
|
14
|
+
|
|
15
|
+
private data: IRWSConfig = {};
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public get(key: keyof IRWSConfig): any
|
|
22
|
+
{
|
|
23
|
+
|
|
24
|
+
const isInData: boolean = Object.keys(this.data).includes(key);
|
|
25
|
+
const isInDefaults: boolean = Object.keys(_DEFAULTS).includes(key);
|
|
26
|
+
|
|
27
|
+
if(!isInData && isInDefaults){
|
|
28
|
+
let defaultVal = _DEFAULTS[key];
|
|
29
|
+
|
|
30
|
+
if(defaultVal[0] === '@'){
|
|
31
|
+
defaultVal = this.data[((defaultVal as string).slice(1)) as keyof IRWSConfig];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return defaultVal;
|
|
35
|
+
} else if(!isInData && !isInDefaults) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
return this.data[key as keyof IRWSConfig];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public async reloadConfig(cfgString: string): Promise<ConfigService>
|
|
44
|
+
{
|
|
45
|
+
const module = await import(/* webpackIgnore: true */ cfgString);
|
|
46
|
+
const cfg: () => IRWSConfig = module.defaults;
|
|
47
|
+
this.data = cfg();
|
|
48
|
+
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async waitForConfig(tagName: string): Promise<boolean>
|
|
53
|
+
{
|
|
54
|
+
let t: NodeJS.Timeout | null = null;
|
|
55
|
+
|
|
56
|
+
if(!this.data._noLoad || __SENT_TO_COMPONENTS.includes(tagName)){
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
__SENT_TO_COMPONENTS.push(tagName);
|
|
61
|
+
|
|
62
|
+
document.dispatchEvent(new CustomEvent<{tagName: string}>('rws_cfg_call', {
|
|
63
|
+
detail: {tagName},
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
return new Promise((resolve) => {
|
|
67
|
+
const tick = () => {
|
|
68
|
+
if(ConfigService.isLoaded){
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// console.log('resolved', tagName);
|
|
72
|
+
clearTimeout(t);
|
|
73
|
+
resolve(true);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
t = setTimeout(tick, 200);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
t = setTimeout(tick, 200);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
isLoaded(): boolean
|
|
85
|
+
{
|
|
86
|
+
return ConfigService.isLoaded;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
mergeConfig(config: IRWSConfig) {
|
|
90
|
+
const unloaded = ConfigService.isLoaded;
|
|
91
|
+
|
|
92
|
+
this.data = Object.assign(this.data, config);
|
|
93
|
+
|
|
94
|
+
if(unloaded){
|
|
95
|
+
ConfigService.isLoaded = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
getData(): IRWSConfig
|
|
100
|
+
{
|
|
101
|
+
return this.data;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export default ConfigService.getSingleton();
|
|
106
|
+
|
|
107
|
+
export { ConfigService as ConfigServiceInstance };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import RWSService from './_service';
|
|
2
|
+
import { DOM } from '@microsoft/fast-element';
|
|
3
|
+
import htmlSanitizer, { Transformer, IOptions } from 'sanitize-html';
|
|
4
|
+
|
|
5
|
+
type TagsProcessorType = { [tagName: string]: string | Transformer };
|
|
6
|
+
type DOMOutputType<T extends Element> = NodeListOf<T> | T | null;
|
|
7
|
+
|
|
8
|
+
//@ts-expect-error tsconfig.json problem
|
|
9
|
+
declare var trustedTypes: TrustedTypePolicyFactory;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DOMServiceInstance extends RWSService {
|
|
13
|
+
parse$<T extends Element>(input: NodeListOf<T>, directReturn: boolean = false): DOMOutputType<T> {
|
|
14
|
+
if(input.length > 1 || directReturn) {
|
|
15
|
+
return input;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if(input.length === 1) {
|
|
19
|
+
return input[0];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
$<T extends Element>(shadowRoot: ShadowRoot, selectors: string, directReturn: boolean = false): DOMOutputType<T> {
|
|
26
|
+
const elements = shadowRoot.querySelectorAll<T>(selectors);
|
|
27
|
+
return elements ? this.parse$<T>(elements, directReturn) : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async scrollToBottom(scrollContainer: HTMLDivElement, contentSelector: string = '.scroll-content') {
|
|
31
|
+
if (scrollContainer) {
|
|
32
|
+
const scrollContent = scrollContainer.querySelector(contentSelector) as HTMLElement;
|
|
33
|
+
|
|
34
|
+
if (scrollContent) {
|
|
35
|
+
scrollContainer.scrollTop = (scrollContent.scrollHeight - scrollContainer.clientHeight) + 150;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setHTMLPolicy(policyName: string, policyImplementation: (html: string) => string): void
|
|
41
|
+
{
|
|
42
|
+
const myPolicy = trustedTypes.createPolicy(policyName, {
|
|
43
|
+
createHTML(html: string) {
|
|
44
|
+
return policyImplementation(html);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
DOM.setHTMLPolicy(myPolicy);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private enforceAllowedTags(htmlText: string, allowedHTMLTags: string[]): string
|
|
52
|
+
{
|
|
53
|
+
// Create a regular expression pattern to match HTML tags
|
|
54
|
+
const tagPattern = /<\s*\/?\s*([^\s>/]+)(\s+[^>]*)?>/g;
|
|
55
|
+
|
|
56
|
+
// Replace any tags in the htmlText that are not in allowedHTMLTags array
|
|
57
|
+
const sanitizedText = htmlText.replace(tagPattern, (match, tag, attributes) => {
|
|
58
|
+
const lowerCaseTag = tag.toLowerCase();
|
|
59
|
+
|
|
60
|
+
if (allowedHTMLTags.includes(lowerCaseTag)) {
|
|
61
|
+
return match; // Return the original tag if it's allowed
|
|
62
|
+
} else {
|
|
63
|
+
// Replace the disallowed tag with an empty string
|
|
64
|
+
return '';
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return sanitizedText;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
sanitizeHTML(
|
|
72
|
+
line: string,
|
|
73
|
+
allowedHTMLTags: string[] = null,
|
|
74
|
+
sanitizeOptions: IOptions = {})
|
|
75
|
+
{
|
|
76
|
+
let output: string = line.trim();
|
|
77
|
+
|
|
78
|
+
if(allowedHTMLTags){
|
|
79
|
+
sanitizeOptions.allowedTags = allowedHTMLTags;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const sanitized = htmlSanitizer(output, sanitizeOptions);
|
|
83
|
+
|
|
84
|
+
return sanitized;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const DOMService = DOMServiceInstance.getSingleton();
|
|
89
|
+
|
|
90
|
+
export default DOMService;
|
|
91
|
+
export { DOMOutputType, DOMServiceInstance, TagsProcessorType };
|