grexxconnect-ess 1.1.1 → 1.2.1
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/client.js +4 -0
- package/index.js +106 -27
- package/package.json +3 -2
- package/schema/client.d.ts +26 -0
- package/schema/index.d.ts +21 -0
package/client.js
CHANGED
|
@@ -91,6 +91,10 @@ class WebSocketClient extends EventEmitter {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
disconnect(code, message) {
|
|
95
|
+
this.instance.close(code, message);
|
|
96
|
+
}
|
|
97
|
+
|
|
94
98
|
reconnect( code, msg ) {
|
|
95
99
|
this.log('connection failed'.red, `retry in ${this.autoReconnectInterval}ms`, code.toString().red, (msg || '').yellow);
|
|
96
100
|
this.instance.removeAllListeners();
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (C) 2014-
|
|
2
|
+
* Copyright (C) 2014-2022 Grexx - All Rights Reserved
|
|
3
3
|
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
4
4
|
* Proprietary and confidential
|
|
5
5
|
*/
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
const EventEmitter = require('events');
|
|
9
9
|
const WebSocket = require('./client');
|
|
10
10
|
|
|
11
|
+
const TIMEOUT_LONG = 30 * 1000; //== 30 seconds
|
|
12
|
+
|
|
11
13
|
class EssConnect extends EventEmitter {
|
|
12
|
-
constructor(
|
|
14
|
+
constructor(settings) {
|
|
13
15
|
super();
|
|
14
16
|
|
|
15
17
|
const thisVersion = require('./package.json').version;
|
|
@@ -21,51 +23,128 @@ class EssConnect extends EventEmitter {
|
|
|
21
23
|
debug: settings.debug
|
|
22
24
|
});
|
|
23
25
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
+
const _waitQueue = {},
|
|
27
|
+
_unfinishedResponses = {};
|
|
28
|
+
|
|
29
|
+
const send = (type, content, timeout = TIMEOUT_LONG) => {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const essCorrelationId = content?.['ess-correlation-id'];
|
|
32
|
+
|
|
33
|
+
if (!essCorrelationId || !this._ackFunctional) {
|
|
34
|
+
try {
|
|
35
|
+
ws.send(JSON.stringify({
|
|
36
|
+
type: type,
|
|
37
|
+
content: content,
|
|
38
|
+
timestamp: Date.now()
|
|
39
|
+
}));
|
|
40
|
+
return resolve();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return reject(error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const exceededTimeout = setTimeout(async () => {
|
|
47
|
+
ws.debug(`timeout of ${timeout}ms exceeded for ack response from server`);
|
|
48
|
+
return reject('Timeout exceeded');
|
|
49
|
+
}, timeout);
|
|
50
|
+
|
|
51
|
+
_waitQueue[essCorrelationId] = () => {
|
|
52
|
+
clearTimeout(exceededTimeout);
|
|
53
|
+
ws.debug(`ack response received from server`);
|
|
54
|
+
return resolve('Ack response received from server');
|
|
55
|
+
};
|
|
56
|
+
|
|
26
57
|
ws.send(JSON.stringify({
|
|
27
58
|
type: type,
|
|
28
59
|
content: content,
|
|
29
60
|
timestamp: Date.now()
|
|
30
|
-
}), error => {
|
|
31
|
-
if (
|
|
32
|
-
reject(error);
|
|
33
|
-
} else {
|
|
34
|
-
resolve();
|
|
61
|
+
}), (error) => {
|
|
62
|
+
if (error) {
|
|
63
|
+
return reject(error);
|
|
35
64
|
}
|
|
36
65
|
});
|
|
37
66
|
});
|
|
38
67
|
};
|
|
39
68
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
69
|
+
const sendAck = async (connectCorrelationId, message = '', type = 'ack') => {
|
|
70
|
+
this.ws.debug(`acknowledging message from server for message header ID: ${connectCorrelationId}`.gray);
|
|
71
|
+
await send(type, {'connect-correlation-id': connectCorrelationId, message});
|
|
72
|
+
this.emit(type);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const completeUnfinishedResponses = () => {
|
|
76
|
+
this.ws.debug(`checking for any incomplete message responses: ${Object.keys(_unfinishedResponses).length.toString().blue} unfinished responses`);
|
|
77
|
+
for (const key in _unfinishedResponses) {
|
|
78
|
+
const {type, content} = _unfinishedResponses[key];
|
|
79
|
+
send(type, content).then(() => {
|
|
80
|
+
delete _unfinishedResponses[key];
|
|
81
|
+
}).catch(() => handleTimeout(type, content));
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const handleTimeout = (type, content) => {
|
|
86
|
+
const id = content['ess-correlation-id'];
|
|
87
|
+
_unfinishedResponses[id] = {type, content};
|
|
88
|
+
ws.disconnect(1012, "Ack response from server timed out");
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
ws.on('close', (code, msg) => this.emit('disconnected', code, msg));
|
|
92
|
+
ws.on('message', async (_message) => {
|
|
93
|
+
const connectCorrelationId = _message['connect-correlation-id'],
|
|
94
|
+
essCorrelationId = _message['ess-correlation-id'];
|
|
95
|
+
|
|
96
|
+
switch (_message.type) {
|
|
43
97
|
case 'ping':
|
|
44
|
-
this.ws.debug('responding to connection-ping');
|
|
45
|
-
send('pong');
|
|
98
|
+
this.ws.debug('responding to connection-ping'.gray);
|
|
46
99
|
this.emit('ping');
|
|
100
|
+
await send('pong');
|
|
101
|
+
break;
|
|
102
|
+
case 'ackFunctional':
|
|
103
|
+
this.ws.debug('responding to functionality check'.green, 'acknowledgements'.blue);
|
|
104
|
+
this._ackFunctional = true;
|
|
105
|
+
await sendAck(connectCorrelationId, null, 'ackFunctional');
|
|
106
|
+
completeUnfinishedResponses();
|
|
107
|
+
break;
|
|
108
|
+
case 'ack':
|
|
109
|
+
this.ws.debug(`received ack from GrexxConnect for message with header ID: ${essCorrelationId}`);
|
|
110
|
+
if (typeof (essCorrelationId) != 'undefined' && typeof (_waitQueue[essCorrelationId]) == 'function') {
|
|
111
|
+
const execFunc = _waitQueue[essCorrelationId];
|
|
112
|
+
execFunc();
|
|
113
|
+
delete _waitQueue[essCorrelationId];
|
|
114
|
+
}
|
|
47
115
|
break;
|
|
48
116
|
case 'authorized':
|
|
49
117
|
this.log('connected and authorized for'.green, _message.namespace.blue);
|
|
50
118
|
this.emit('authorized', _message.namespace);
|
|
51
119
|
break;
|
|
120
|
+
case 'opened':
|
|
121
|
+
this.log('open'.green, 'ready to receive messages'.blue);
|
|
122
|
+
break;
|
|
52
123
|
case 'system':
|
|
53
124
|
this.handleSystemMessage(_message, send);
|
|
54
125
|
break;
|
|
55
126
|
case'message':
|
|
127
|
+
await sendAck(connectCorrelationId, "message received and being processed");
|
|
56
128
|
this.emit('message', {
|
|
57
129
|
content: _message.content,
|
|
58
130
|
parsed: this.parseMessage(_message.content.data),
|
|
59
131
|
resolve: outputData => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
132
|
+
const type = 'response',
|
|
133
|
+
content = {
|
|
134
|
+
'ess-correlation-id': connectCorrelationId,
|
|
135
|
+
toMessage: _message,
|
|
136
|
+
outputData: outputData
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return send(type, content).catch(() => {
|
|
140
|
+
handleTimeout(type, content);
|
|
63
141
|
});
|
|
64
142
|
},
|
|
65
|
-
reject: (
|
|
143
|
+
reject: (publicMessage, debugMessage, additionalContext) => {
|
|
66
144
|
return send('reject', {
|
|
67
|
-
|
|
68
|
-
|
|
145
|
+
'ess-correlation-id': connectCorrelationId,
|
|
146
|
+
toMessage: _message,
|
|
147
|
+
errorContext: Object.assign({
|
|
69
148
|
publicMessage,
|
|
70
149
|
debugMessage
|
|
71
150
|
}, additionalContext)
|
|
@@ -96,27 +175,27 @@ class EssConnect extends EventEmitter {
|
|
|
96
175
|
/**Set a monitoring function. Should return {status:'ok|warning|error', ...}
|
|
97
176
|
* @param {function} statusFunction
|
|
98
177
|
*/
|
|
99
|
-
setMonitoringResponse(
|
|
178
|
+
setMonitoringResponse(statusFunction) {
|
|
100
179
|
this._statusFunction = statusFunction;
|
|
101
180
|
}
|
|
102
181
|
|
|
103
|
-
log(
|
|
182
|
+
log(...args) {
|
|
104
183
|
console.info(' [ESS][MAIN] '.gray, ...args);
|
|
105
184
|
}
|
|
106
185
|
|
|
107
|
-
handleSystemMessage(
|
|
108
|
-
if (
|
|
109
|
-
this.ws.debug('responding to system-ping');
|
|
186
|
+
handleSystemMessage(message, send) {
|
|
187
|
+
if (message.content.action === 'ping') {
|
|
188
|
+
this.ws.debug('responding to system-ping'.gray);
|
|
110
189
|
send('system', {
|
|
111
190
|
action: 'pong',
|
|
112
191
|
client_data: typeof this._statusFunction === 'function' ?
|
|
113
|
-
this._statusFunction() : {
|
|
192
|
+
this._statusFunction() : {status: 'ok'},
|
|
114
193
|
server_data: message.content.id
|
|
115
194
|
});
|
|
116
195
|
}
|
|
117
196
|
}
|
|
118
197
|
|
|
119
|
-
parseMessage(
|
|
198
|
+
parseMessage(message = []) {
|
|
120
199
|
const result = {};
|
|
121
200
|
|
|
122
201
|
message.forEach(part => {
|
package/package.json
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"name" : "grexxconnect-ess",
|
|
3
3
|
"author" : "Grexx <info@grexxboxx.com>",
|
|
4
4
|
"description" : "Grexx Connect - External System Service Helper",
|
|
5
|
-
"version" : "1.
|
|
5
|
+
"version" : "1.2.1",
|
|
6
|
+
"types" : "./schema/index.d.ts",
|
|
6
7
|
"contributors" : [
|
|
7
8
|
{
|
|
8
9
|
"name" : "Jeffrey van Norden",
|
|
@@ -19,6 +20,6 @@
|
|
|
19
20
|
},
|
|
20
21
|
"license" : "MIT",
|
|
21
22
|
"engines" : {
|
|
22
|
-
"node": ">=
|
|
23
|
+
"node": ">=12"
|
|
23
24
|
}
|
|
24
25
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2014-2022 Grexx - All Rights Reserved
|
|
3
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
4
|
+
* Proprietary and confidential
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export = WebSocketClient;
|
|
8
|
+
declare class WebSocketClient extends EventEmitter {
|
|
9
|
+
constructor(url: any, options: any);
|
|
10
|
+
number: number;
|
|
11
|
+
autoReconnectInterval: number;
|
|
12
|
+
_debug: any;
|
|
13
|
+
log(...args: any[]): void;
|
|
14
|
+
debug(...args: any[]): void;
|
|
15
|
+
open(url: any, options: any): void;
|
|
16
|
+
url: any;
|
|
17
|
+
options: any;
|
|
18
|
+
instance: any;
|
|
19
|
+
send(data: any, option: any, cb: any): void;
|
|
20
|
+
reconnect(code: any, msg: any): void;
|
|
21
|
+
onOpen(...args: any[]): void;
|
|
22
|
+
onMessage(data: any, flags: any, number: any): void;
|
|
23
|
+
onError(error: any): void;
|
|
24
|
+
onClose(code: any, msg: any): void;
|
|
25
|
+
}
|
|
26
|
+
import EventEmitter = require("node/events");
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2014-2022 Grexx - All Rights Reserved
|
|
3
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
4
|
+
* Proprietary and confidential
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export = EssConnect;
|
|
8
|
+
declare class EssConnect extends EventEmitter {
|
|
9
|
+
constructor(settings: any);
|
|
10
|
+
ws: WebSocket;
|
|
11
|
+
/**Set a monitoring function. Should return {status:'ok|warning|error', ...}
|
|
12
|
+
* @param {function} statusFunction
|
|
13
|
+
*/
|
|
14
|
+
setMonitoringResponse(statusFunction: Function): void;
|
|
15
|
+
_statusFunction: Function | undefined;
|
|
16
|
+
log(...args: any[]): void;
|
|
17
|
+
handleSystemMessage(message: any, send: any): void;
|
|
18
|
+
parseMessage(message?: any[]): {};
|
|
19
|
+
}
|
|
20
|
+
import EventEmitter = require("node/events");
|
|
21
|
+
import WebSocket = require("./client");
|