@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
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import RWSNotify, { NotifyLogType } from '../types/RWSNotify';
|
|
2
|
+
import TheService from './_service';
|
|
3
|
+
/**
|
|
4
|
+
* @class
|
|
5
|
+
* @extends TheService
|
|
6
|
+
*/
|
|
7
|
+
class NotifyServiceInstance extends TheService {
|
|
8
|
+
private notifier: RWSNotify;
|
|
9
|
+
|
|
10
|
+
public setNotifier(notifier: RWSNotify)
|
|
11
|
+
{
|
|
12
|
+
this.notifier = notifier;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public alert(message: string, logType: NotifyLogType = 'info', onConfirm?: (params: any) => void): void
|
|
16
|
+
{
|
|
17
|
+
if(!this.notifier){
|
|
18
|
+
console.warn('No notifier added to RWS Client');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.notifier(message, logType, 'alert', onConfirm);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public notify(message: string, logType: NotifyLogType = 'info', onConfirm?: (params: any) => void): void
|
|
26
|
+
{
|
|
27
|
+
if(!this.notifier){
|
|
28
|
+
console.warn('No notifier added to RWS Client');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.notifier(message, logType, 'notification', onConfirm);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public silent(message: string, logType: NotifyLogType = 'info'): void
|
|
36
|
+
{
|
|
37
|
+
if(!this.notifier){
|
|
38
|
+
console.warn('No notifier added to RWS Client');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.notifier(message, logType, 'silent');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const NotifyService = NotifyServiceInstance.getSingleton();
|
|
47
|
+
|
|
48
|
+
export default NotifyService;
|
|
49
|
+
export { NotifyServiceInstance };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
import TheService from './_service';
|
|
3
|
+
import Router from 'url-router';
|
|
4
|
+
import { RWSRouter, IRWSRouteResult, RouteReturn } from '../routing/_router';
|
|
5
|
+
import UtilsService, {UtilsServiceInstance} from './UtilsService';
|
|
6
|
+
import { IRWSViewComponent } from '../interfaces/IRWSViewComponent';
|
|
7
|
+
import ConfigService, { ConfigServiceInstance } from './ConfigService';
|
|
8
|
+
|
|
9
|
+
type IFrontRoutes = Record<string, unknown>;
|
|
10
|
+
|
|
11
|
+
class RoutingService extends TheService {
|
|
12
|
+
private router: Router<any>;
|
|
13
|
+
private routes: IFrontRoutes;
|
|
14
|
+
|
|
15
|
+
constructor(@UtilsService private utilsService: UtilsServiceInstance, @ConfigService private config: ConfigServiceInstance){
|
|
16
|
+
super();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public apply(comp: IRWSViewComponent): RWSRouter
|
|
20
|
+
{
|
|
21
|
+
this.routes = this.config.get('routes');
|
|
22
|
+
this.router = new Router(this.routes);
|
|
23
|
+
|
|
24
|
+
return new RWSRouter(comp, this.router, this.utilsService);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public routeHandler = <T>(comp: T) => () => {
|
|
28
|
+
return comp;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
public getRoutes(): IFrontRoutes
|
|
32
|
+
{
|
|
33
|
+
return this.routes;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const renderRouteComponent = <T>(routeName: string, cmp: T, defaultRouteParams: any = {}) => (): [string, T, any] => [routeName, cmp, defaultRouteParams];
|
|
38
|
+
|
|
39
|
+
const _ROUTING_EVENT_NAME = 'routing.route.change';
|
|
40
|
+
interface IRoutingEvent {
|
|
41
|
+
routeName: string,
|
|
42
|
+
component: IRWSViewComponent
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default RoutingService.getSingleton();
|
|
46
|
+
export { RoutingService as RoutingServiceInstance, IFrontRoutes, RWSRouter, IRWSRouteResult, renderRouteComponent, RouteReturn, _ROUTING_EVENT_NAME, IRoutingEvent};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import RWSService from 'rws-js-client/src/services/_service';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ServiceWorkerService extends RWSService {
|
|
5
|
+
async registerServiceWorker(): Promise<void>
|
|
6
|
+
{
|
|
7
|
+
await ServiceWorkerService.registerServiceWorker();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static registerServiceWorker(): Promise<void>
|
|
11
|
+
{
|
|
12
|
+
if ('serviceWorker' in navigator)
|
|
13
|
+
{
|
|
14
|
+
navigator.serviceWorker.getRegistrations().then(registrations => {
|
|
15
|
+
if (registrations.length) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
return (navigator.serviceWorker.register(
|
|
21
|
+
'/service_worker.js',
|
|
22
|
+
{
|
|
23
|
+
scope: '/'
|
|
24
|
+
}
|
|
25
|
+
).then((registration) => {
|
|
26
|
+
if (registration.installing) {
|
|
27
|
+
console.log('Service worker installing');
|
|
28
|
+
} else if (registration.waiting) {
|
|
29
|
+
console.log('Service worker installed');
|
|
30
|
+
} else if (registration.active) {
|
|
31
|
+
console.log('Service worker active');
|
|
32
|
+
}
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error(`Registration failed with ${error}`);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
sendDataToServiceWorker(type: string, data: any, asset_type: string = 'data_push')
|
|
45
|
+
{
|
|
46
|
+
if (navigator.serviceWorker.controller) {
|
|
47
|
+
navigator.serviceWorker.controller.postMessage({
|
|
48
|
+
command: type,
|
|
49
|
+
asset_type,
|
|
50
|
+
params: data
|
|
51
|
+
});
|
|
52
|
+
} else {
|
|
53
|
+
throw new Error('Service worker is not available');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export default ServiceWorkerService.getSingleton();
|
|
60
|
+
export { ServiceWorkerService as ServiceWorkerServiceInstance };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import TheService from './_service';
|
|
2
|
+
import ApiService, {ApiServiceInstance} from './ApiService';
|
|
3
|
+
|
|
4
|
+
import { RawSourceMap } from 'source-map';
|
|
5
|
+
|
|
6
|
+
let sourceMap: RawSourceMap = null;
|
|
7
|
+
|
|
8
|
+
class UtilsService extends TheService {
|
|
9
|
+
private apiService: ApiServiceInstance;
|
|
10
|
+
|
|
11
|
+
constructor(@ApiService apiService: ApiServiceInstance){
|
|
12
|
+
super();
|
|
13
|
+
this.apiService = apiService;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async getFileContents(filePath: string): Promise<string>
|
|
17
|
+
{
|
|
18
|
+
return this.apiService.pureGet(filePath);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
mergeDeep<T>(target: T | any, source: T | any): T
|
|
22
|
+
{
|
|
23
|
+
const isObject = (obj: any) => obj && typeof obj === 'object';
|
|
24
|
+
|
|
25
|
+
if (!isObject(target) || !isObject(source)) {
|
|
26
|
+
return source;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Object.keys(source).forEach(key => {
|
|
30
|
+
const targetValue = target[key];
|
|
31
|
+
const sourceValue = source[key];
|
|
32
|
+
|
|
33
|
+
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
|
|
34
|
+
target[key] = targetValue.concat(sourceValue);
|
|
35
|
+
} else if (isObject(targetValue) && isObject(sourceValue)) {
|
|
36
|
+
target[key] = this.mergeDeep(Object.assign({}, targetValue), sourceValue);
|
|
37
|
+
} else {
|
|
38
|
+
target[key] = sourceValue;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return target;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async fetchSourceMap(jsFilePath: string): Promise<RawSourceMap>
|
|
46
|
+
{
|
|
47
|
+
// Assuming the source map URL is the JS file URL with a '.map' extension
|
|
48
|
+
const sourceMapUrl = jsFilePath;
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetch(sourceMapUrl);
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
54
|
+
}
|
|
55
|
+
return await response.json();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Failed to fetch source map:', error);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async getCurrentLineNumber(error: Error = null): Promise<number> {
|
|
63
|
+
if(!error){
|
|
64
|
+
error = new Error();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return 0;
|
|
68
|
+
|
|
69
|
+
// const stack = error.stack || '';
|
|
70
|
+
// const stackLines = stack.split('\n');
|
|
71
|
+
// const relevantLine = stackLines[1];
|
|
72
|
+
|
|
73
|
+
// // Extract file path from the stack line
|
|
74
|
+
// const match = relevantLine.match(/\((.*?):\d+:\d+\)/);
|
|
75
|
+
// if (!match) return -1;
|
|
76
|
+
// const filePath = match[1];
|
|
77
|
+
|
|
78
|
+
// // Assuming the source map is in the same directory with '.map' extension
|
|
79
|
+
// const sourceMapPath = `${filePath}.map`;
|
|
80
|
+
|
|
81
|
+
// if(sourceMap === null){
|
|
82
|
+
// sourceMap = await this.fetchSourceMap(sourceMapPath);
|
|
83
|
+
// }
|
|
84
|
+
|
|
85
|
+
// let originalPosition: any = null;
|
|
86
|
+
|
|
87
|
+
// await SourceMapConsumer.with(sourceMap, null, consumer => {
|
|
88
|
+
// const lineMatch = relevantLine.match(/:(\d+):(\d+)/);
|
|
89
|
+
// if (!lineMatch) return -1;
|
|
90
|
+
|
|
91
|
+
// originalPosition = consumer.originalPositionFor({
|
|
92
|
+
// line: parseInt(lineMatch[1]), // Example line and column
|
|
93
|
+
// column: parseInt(lineMatch[2])
|
|
94
|
+
// });
|
|
95
|
+
// });
|
|
96
|
+
|
|
97
|
+
// return originalPosition.line;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export default UtilsService.getSingleton();
|
|
102
|
+
|
|
103
|
+
export { UtilsService as UtilsServiceInstance }
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import TheService from './_service';
|
|
2
|
+
import { io, Socket } from 'socket.io-client';
|
|
3
|
+
import ITheUser from '../interfaces/IRWSUser';
|
|
4
|
+
import { v4 as uuid } from 'uuid';
|
|
5
|
+
import { ping, disconnect as disconnectWs, reconnect as reconnectWs } from './_ws_handlers/ConnectionHandler';
|
|
6
|
+
import WSEventHandler from './_ws_handlers/EventHandler';
|
|
7
|
+
import WSMessageHandler from './_ws_handlers/MessageHandler';
|
|
8
|
+
|
|
9
|
+
type WSEvent = string;
|
|
10
|
+
type WSStatus = 'WS_OPEN' | 'WS_CLOSED' | 'WS_CONNECTING';
|
|
11
|
+
|
|
12
|
+
// function logClickableLink(text: string, url: string) {
|
|
13
|
+
// console.log('[', url, ']:', text);
|
|
14
|
+
// }
|
|
15
|
+
|
|
16
|
+
// const getCurrentLineNumber = UtilsService.getCurrentLineNumber;
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const wsLog = async (fakeError: Error, text: any, socketId: string = null, isError: boolean = false): Promise<void> => {
|
|
20
|
+
const logit = isError ? console.error : console.log;
|
|
21
|
+
logit(`[webpack://junction_ai_trainer_ui/${module.id.replace('./', '')}:`, `<WS-CLIENT>${socketId ? `(${socketId})` : ''}`, text);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
class WSService extends TheService {
|
|
25
|
+
static websocket_instance: Socket;
|
|
26
|
+
private _ws: Socket | null = null;
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
private user: ITheUser | null = null;
|
|
30
|
+
private url: string | null = null;
|
|
31
|
+
|
|
32
|
+
private _status_string: WSStatus = 'WS_CLOSED';
|
|
33
|
+
|
|
34
|
+
public _wsId: string | null = null;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
public _interval: any = null;
|
|
38
|
+
public _connecting: boolean = false;
|
|
39
|
+
public _shut_down: boolean = false;
|
|
40
|
+
public reconnects: number = 0;
|
|
41
|
+
|
|
42
|
+
public eventListeners: Map<string, Array<(instance: WSService, params: any) => any>> = new Map();
|
|
43
|
+
|
|
44
|
+
public async init(url: string, user?: ITheUser, transports: string[] = null): Promise<WSService> {
|
|
45
|
+
this._connecting = true;
|
|
46
|
+
wsLog(new Error(), 'Connecting to: ' + url);
|
|
47
|
+
this.url = url;
|
|
48
|
+
this.user = user;
|
|
49
|
+
|
|
50
|
+
const headers = this.user?.jwt_token ? {
|
|
51
|
+
Authorization: 'Bearer ' + this.user?.jwt_token,
|
|
52
|
+
} : {};
|
|
53
|
+
|
|
54
|
+
if(!WSService.websocket_instance){
|
|
55
|
+
console.log('WSSERVICE', headers);
|
|
56
|
+
const tokenString = headers.Authorization ? `?token=${this.user.jwt_token}` : '' ;
|
|
57
|
+
WSService.websocket_instance = io(this.url + tokenString, {
|
|
58
|
+
auth: user?.jwt_token ? { token: user.jwt_token} : {},
|
|
59
|
+
transports: transports || null
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//, transports: ['websocket']
|
|
63
|
+
this._ws = WSService.websocket_instance;
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if (this.user?.mongoId) {
|
|
68
|
+
this._wsId = this.user.mongoId;
|
|
69
|
+
}else{
|
|
70
|
+
this._wsId = uuid();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let socketId: string = null;
|
|
74
|
+
|
|
75
|
+
this._ws.on('connect', () => {
|
|
76
|
+
socketId = this.socket().id;
|
|
77
|
+
|
|
78
|
+
wsLog(new Error(), 'Socket connected with ID: ' + socketId, socketId);
|
|
79
|
+
|
|
80
|
+
this._connecting = false;
|
|
81
|
+
this._ws.connected = true;
|
|
82
|
+
|
|
83
|
+
this.executeEventListener('ws:connected');
|
|
84
|
+
|
|
85
|
+
wsLog(new Error(), 'Emitting ping to server', socketId);
|
|
86
|
+
ping(this);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
this._ws.on('__PONG__', async (data: any) => {
|
|
90
|
+
if (data === '__PONG__') {
|
|
91
|
+
wsLog(new Error(), 'Recieving valid ping callback from server', socketId);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
this._ws.on('disconnect', async (e) => {
|
|
97
|
+
wsLog(new Error(), 'Disconnected from the server', socketId);
|
|
98
|
+
this.executeEventListener('ws:disconnected', { socketId: socketId, error: e });
|
|
99
|
+
socketId = null;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
this._ws.on('error', async (error: Error) => {
|
|
103
|
+
wsLog(error, 'Socket error:', socketId, true);
|
|
104
|
+
console.error(error);
|
|
105
|
+
this.executeEventListener('ws:error', { socketId: socketId, error: error });
|
|
106
|
+
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
// this._interval = setInterval(() => {
|
|
111
|
+
// ping(_self);
|
|
112
|
+
// }, 3000);
|
|
113
|
+
|
|
114
|
+
this.reconnects = 0;
|
|
115
|
+
|
|
116
|
+
if (this._ws?.connected) {
|
|
117
|
+
this._connecting = false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.statusChange();
|
|
121
|
+
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public getStatus(): WSStatus {
|
|
126
|
+
return this._status_string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public isActive(): boolean {
|
|
130
|
+
return !this._connecting && this._ws?.connected;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
setUser(user: ITheUser): void
|
|
134
|
+
{
|
|
135
|
+
this.user = user;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public listenForMessage(callback: (data: any, isJson?: boolean) => void, method?: string): () => void
|
|
139
|
+
{
|
|
140
|
+
const disableHandler = () => {
|
|
141
|
+
this.socket().off(method, callback);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
WSMessageHandler.listenForMessage(this, callback, method);
|
|
145
|
+
|
|
146
|
+
return disableHandler.bind(this);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async waitForStatus(): Promise<void>
|
|
150
|
+
{
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
let iteration = 0;
|
|
153
|
+
const t = setInterval(() => {
|
|
154
|
+
if(iteration > 4){
|
|
155
|
+
clearInterval(t);
|
|
156
|
+
reject('Websocket did not connect!');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if(this.isActive()){
|
|
160
|
+
clearInterval(t);
|
|
161
|
+
resolve();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
iteration++;
|
|
165
|
+
}, 1000);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public sendMessage<T>(method: string, msg: T): void {
|
|
170
|
+
WSMessageHandler.sendMessage<T>(this, method, msg);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public statusChange(): void {
|
|
174
|
+
let status: WSStatus = 'WS_CLOSED';
|
|
175
|
+
if (this._connecting) {
|
|
176
|
+
status = 'WS_CONNECTING';
|
|
177
|
+
} else if (this.isActive()) {
|
|
178
|
+
status = 'WS_OPEN';
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this.executeEventListener('ws:status_change', { status });
|
|
182
|
+
this._status_string = status;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
public on(event: WSEvent, callback: (wsInstance: WSService, params: any) => any): void {
|
|
186
|
+
WSEventHandler.on(this, event, callback);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
public executeEventListener(event: WSEvent, params: any = {}): void {
|
|
190
|
+
WSEventHandler.executeEventListener(this, event, params);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public socket(): Socket
|
|
194
|
+
{
|
|
195
|
+
return this._ws;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public disconnect()
|
|
199
|
+
{
|
|
200
|
+
disconnectWs(this);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
public reconnect()
|
|
204
|
+
{
|
|
205
|
+
reconnectWs(this);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
getUser(): ITheUser {
|
|
209
|
+
return this.user;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
getUrl(): string {
|
|
213
|
+
return this.url;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export default WSService.getSingleton();
|
|
218
|
+
export { WSService as WSServiceInstance, WSEvent, WSService as WSInstance, WSStatus };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DI, InterfaceSymbol, Key, Registration, FoundationElementDefinition } from "@microsoft/fast-foundation";
|
|
2
|
+
import RWSContainer from "../components/_container";
|
|
3
|
+
import RWSWindow, { loadRWSRichWindow, RWSWindowComponentInterface } from "../interfaces/RWSWindow";
|
|
4
|
+
|
|
5
|
+
export interface IWithDI<T> {
|
|
6
|
+
new (...args: any[]): T;
|
|
7
|
+
getSingleton: <T extends Key>(this: IWithDI<T>) => InterfaceSymbol<T>;
|
|
8
|
+
register: <T extends Key>(this: IWithDI<T>) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default abstract class TheRWSService {
|
|
12
|
+
_RELOADABLE: boolean = false;
|
|
13
|
+
|
|
14
|
+
constructor() {
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
register<T extends Key>(this: IWithDI<T>): void
|
|
18
|
+
{
|
|
19
|
+
this.getSingleton();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getSingleton<T extends Key>(this: IWithDI<T>): InterfaceSymbol<T>
|
|
23
|
+
{
|
|
24
|
+
return this.getSingleton();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public static register<T extends Key>(this: IWithDI<T>): void
|
|
28
|
+
{
|
|
29
|
+
this.getSingleton();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public static getSingleton<T extends Key>(this: IWithDI<T>): InterfaceSymbol<T>
|
|
33
|
+
{
|
|
34
|
+
const richWindow = loadRWSRichWindow();
|
|
35
|
+
|
|
36
|
+
if(Object.keys(richWindow.RWS._registered).includes(this.name)){
|
|
37
|
+
return richWindow.RWS._registered[this.name];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const interf = DI.createInterface<T>(this.name);
|
|
41
|
+
|
|
42
|
+
RWSContainer().register(
|
|
43
|
+
Registration.singleton(interf, this)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
richWindow.RWS._registered[this.name] = interf;
|
|
47
|
+
|
|
48
|
+
return interf;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { WSInstance } from '../WSService';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function ping(instance: WSInstance): void {
|
|
5
|
+
instance.socket().emit('__PING__');
|
|
6
|
+
// instance._timeout = setTimeout(() => {
|
|
7
|
+
// reconnect(instance);
|
|
8
|
+
// }, 3000);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
function reconnect(instance: WSInstance): void {
|
|
13
|
+
disconnect(instance, true);
|
|
14
|
+
const rc = instance.reconnects;
|
|
15
|
+
if (rc < 2) {
|
|
16
|
+
instance.executeEventListener('ws:reconnect', { reconnects: rc + 1 });
|
|
17
|
+
instance._connecting = true;
|
|
18
|
+
instance.reconnects++;
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
instance.init(instance.getUrl()!, instance.getUser());
|
|
21
|
+
instance.reconnects = rc + 1;
|
|
22
|
+
}, 1500);
|
|
23
|
+
|
|
24
|
+
instance.statusChange();
|
|
25
|
+
} else {
|
|
26
|
+
disconnect(instance);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function disconnect(instance: WSInstance, noEvent = false): void {
|
|
30
|
+
|
|
31
|
+
if(instance.socket()){
|
|
32
|
+
instance.socket().disconnect();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if(!noEvent){
|
|
36
|
+
console.log(`{WS}${instance.socket() ? `(${instance.socket().id}):` : ''} Disconnected from WS`);
|
|
37
|
+
instance.executeEventListener('ws:disconnected');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
clearInterval(instance._interval);
|
|
41
|
+
|
|
42
|
+
instance._connecting = false;
|
|
43
|
+
instance._shut_down = true;
|
|
44
|
+
|
|
45
|
+
instance.statusChange();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
ping,
|
|
50
|
+
reconnect,
|
|
51
|
+
disconnect
|
|
52
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { WSInstance, WSEvent } from '../WSService';
|
|
2
|
+
|
|
3
|
+
function on(instance: WSInstance, event: WSEvent, callback: (wsInstance: WSInstance, params: any) => any): void {
|
|
4
|
+
let listeners = instance.eventListeners.get(event);
|
|
5
|
+
if (!listeners) {
|
|
6
|
+
listeners = [];
|
|
7
|
+
instance.eventListeners.set(event, listeners);
|
|
8
|
+
}
|
|
9
|
+
listeners.push(callback);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function executeEventListener(instance: WSInstance, event: WSEvent, params: any = {}): void {
|
|
13
|
+
const listeners = instance.eventListeners.get(event);
|
|
14
|
+
if (listeners) {
|
|
15
|
+
listeners.forEach(callback => {
|
|
16
|
+
try {
|
|
17
|
+
callback(instance, params);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
console.error(`Error executing callback for event '${event}':`, e);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
on,
|
|
27
|
+
executeEventListener
|
|
28
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { WSInstance } from '../WSService';
|
|
2
|
+
|
|
3
|
+
function listenForMessage(instance: WSInstance, callback: (data: any, isJson?: boolean) => void, method?: string): WSInstance {
|
|
4
|
+
if (!instance.socket()) {
|
|
5
|
+
throw new Error('socket is not active');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
instance.socket().on(method || 'message', (data: any) => {
|
|
9
|
+
try {
|
|
10
|
+
const parsedData = JSON.parse(data);
|
|
11
|
+
if (!!method && parsedData.method === method) {
|
|
12
|
+
callback(parsedData, true);
|
|
13
|
+
instance.executeEventListener('ws:message_received', { message: parsedData });
|
|
14
|
+
|
|
15
|
+
} else if (!method) {
|
|
16
|
+
callback(parsedData, true);
|
|
17
|
+
}
|
|
18
|
+
} catch (e) {
|
|
19
|
+
console.error(e);
|
|
20
|
+
|
|
21
|
+
if (!method) {
|
|
22
|
+
callback(data);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return instance;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function sendMessage<T>(instance: WSInstance, method: string, msg: T): void {
|
|
31
|
+
if (!instance.socket()) {
|
|
32
|
+
throw new Error('socket is not active');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const the_message = {
|
|
36
|
+
user_id: instance.socket().id,
|
|
37
|
+
method: method,
|
|
38
|
+
msg: msg
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
instance.socket().emit(method, JSON.stringify(the_message));
|
|
43
|
+
instance.executeEventListener('ws:message_sent', { message: the_message });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default{
|
|
47
|
+
listenForMessage,
|
|
48
|
+
sendMessage
|
|
49
|
+
};
|