@schukai/monster 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schukai/monster",
3
- "version": "3.1.1",
3
+ "version": "3.2.0",
4
4
  "description": "Monster is a simple library for creating fast, robust and lightweight websites.",
5
5
  "keywords": [
6
6
  "framework",
@@ -24,7 +24,7 @@ const receiveQueueSymbol = Symbol("queue");
24
24
  /**
25
25
  * @private
26
26
  * @type {Symbol}
27
- *
27
+ *
28
28
  * hint: this name is used in the tests. if you want to change it, please change it in the tests as well.
29
29
  */
30
30
  const connectionSymbol = Symbol("connection");
@@ -55,6 +55,96 @@ const connectionStatusCode = {
55
55
  1015: "TLS handshake"
56
56
  };
57
57
 
58
+ /**
59
+ * @private
60
+ * @this {WebSocketDatasource}
61
+ * @throws {Error} No url defined for websocket datasource.
62
+ */
63
+ function connectServer(resolve, reject) {
64
+ const self = this;
65
+
66
+ let promiseAllredyResolved = false;
67
+ let connectionTimeout = self.getOption('connection.timeout');
68
+ if (!isInteger(connectionTimeout) || connectionTimeout < 100) {
69
+ connectionTimeout = 5000;
70
+ }
71
+
72
+ setTimeout(() => {
73
+ if (promiseAllredyResolved) {
74
+ return;
75
+ }
76
+ reject(new Error("Connection timeout"));
77
+ }, connectionTimeout);
78
+
79
+ let reconnectTimeout = self.getOption('connection.reconnect.timeout');
80
+ if (!isInteger(reconnectTimeout) || reconnectTimeout < 1000) reconnectTimeout = 1000;
81
+ let reconnectAttempts = self.getOption('connection.reconnect.attempts');
82
+ if (!isInteger(reconnectAttempts) || reconnectAttempts < 1) reconnectAttempts = 1;
83
+ let reconnectEnabled = self.getOption('connection.reconnect.enabled');
84
+ if (reconnectEnabled !== true) reconnectEnabled = false;
85
+
86
+ self[manualCloseSymbol] = false;
87
+ self[connectionSymbol].reconnectCounter++;
88
+
89
+ if (self[connectionSymbol].socket && self[connectionSymbol].socket.readyState < 2) {
90
+ self[connectionSymbol].socket.close();
91
+ }
92
+ self[connectionSymbol].socket = null;
93
+
94
+ const url = self.getOption('url');
95
+ if (!url) {
96
+ reject('No url defined for websocket datasource.');
97
+ return;
98
+ }
99
+
100
+ self[connectionSymbol].socket = new WebSocket(url);
101
+
102
+ self[connectionSymbol].socket.onmessage = function (event) {
103
+ self[receiveQueueSymbol].add(event);
104
+ setTimeout(function () {
105
+ self.read();
106
+ }, 1);
107
+ };
108
+
109
+ self[connectionSymbol].socket.onopen = function () {
110
+ self[connectionSymbol].reconnectCounter = 0;
111
+ if (typeof resolve === 'function' && !promiseAllredyResolved) {
112
+ promiseAllredyResolved = true;
113
+ resolve();
114
+ }
115
+ };
116
+
117
+ self[connectionSymbol].socket.close = function (event) {
118
+
119
+ if (self[manualCloseSymbol]) {
120
+ self[manualCloseSymbol] = false;
121
+ return;
122
+ }
123
+
124
+ if (reconnectEnabled && this[connectionSymbol].reconnectCounter < reconnectAttempts) {
125
+ setTimeout(() => {
126
+ self.connect();
127
+ }, reconnectTimeout * this[connectionSymbol].reconnectCounter);
128
+ }
129
+
130
+ };
131
+
132
+ self[connectionSymbol].socket.onerror = (error) => {
133
+
134
+ if (reconnectEnabled && self[connectionSymbol].reconnectCounter < reconnectAttempts) {
135
+ setTimeout(() => {
136
+ self.connect();
137
+ }, reconnectTimeout * this[connectionSymbol].reconnectCounter);
138
+ } else {
139
+ if (typeof reject === 'function' && !promiseAllredyResolved) {
140
+ promiseAllredyResolved = true;
141
+ reject(error);
142
+ }
143
+ }
144
+
145
+ };
146
+ }
147
+
58
148
  /**
59
149
  * The RestAPI is a class that enables a REST API server.
60
150
  *
@@ -85,78 +175,26 @@ class WebSocketDatasource extends Datasource {
85
175
  this[connectionSymbol] = {};
86
176
  this[connectionSymbol].socket = null;
87
177
  this[connectionSymbol].reconnectCounter = 0;
88
- this[manualCloseSymbol]=false;
178
+ this[manualCloseSymbol] = false;
89
179
  }
90
180
 
91
181
  /**
92
182
  *
93
- * @returns {Websocketdatasource}
94
- * @throws {Error} No url defined for websocket datasource.
183
+ * @returns {Promise}
95
184
  */
96
185
  connect() {
97
186
  const self = this;
98
187
 
99
- let connected = false;
100
- let reconnectTimeout = self.getOption('reconnect.timeout');
101
- if (!isInteger(reconnectTimeout) || reconnectTimeout < 1000) reconnectTimeout = 1000;
102
- let reconnectAttempts = self.getOption('reconnect.attempts');
103
- if (!isInteger(reconnectAttempts) || reconnectAttempts < 1) reconnectAttempts = 1;
104
- let reconnectEnabled = self.getOption('reconnect.enabled');
105
- if (reconnectEnabled !== true) reconnectEnabled = false;
106
-
107
- self[manualCloseSymbol] = false;
108
- self[connectionSymbol].reconnectCounter++;
109
-
110
- if (self[connectionSymbol].socket && self[connectionSymbol].socket.readyState < 2) {
111
- self[connectionSymbol].socket.close();
112
- }
113
- self[connectionSymbol].socket = null;
114
-
115
- const url = self.getOption('url');
116
- if (!url) throw new Error('No url defined for websocket datasource.');
117
-
118
- self[connectionSymbol].socket = new WebSocket(url);
119
-
120
- self[connectionSymbol].socket.onmessage = function (event) {
121
- self[receiveQueueSymbol].add(event);
122
- setTimeout(function () {
123
- self.read();
124
- }, 0);
125
- };
126
-
127
- self[connectionSymbol].socket.onopen = function () {
128
- connected = true;
129
- self[connectionSymbol].reconnectCounter = 0;
130
- };
131
-
132
- self[connectionSymbol].socket.close = function (event) {
133
-
134
- if (self[manualCloseSymbol]) {
135
- self[manualCloseSymbol] = false;
136
- return;
137
- }
138
-
139
- if (reconnectEnabled && this[connectionSymbol].reconnectCounter < reconnectAttempts) {
140
- setTimeout(() => {
141
- self.connect();
142
- }, reconnectTimeout * this[connectionSymbol].reconnectCounter);
143
- }
144
-
145
- };
146
-
147
- self[connectionSymbol].socket.onerror = (error) => {
148
-
149
- if (reconnectEnabled && self[connectionSymbol].reconnectCounter < reconnectAttempts) {
150
- setTimeout(() => {
151
- self.connect();
152
- }, reconnectTimeout * this[connectionSymbol].reconnectCounter);
153
- }
154
-
155
- };
188
+ return new Promise((resolve, reject) => {
189
+ connectServer.call(this, resolve, reject);
190
+ });
156
191
  }
157
192
 
193
+ /**
194
+ * @returns {boolean}
195
+ */
158
196
  isConnected() {
159
- return this[connectionSymbol].socket && this[connectionSymbol].socket.readyState === 1;
197
+ return this[connectionSymbol]?.socket?.readyState === 1;
160
198
  }
161
199
 
162
200
  /**
@@ -169,9 +207,11 @@ class WebSocketDatasource extends Datasource {
169
207
 
170
208
  /**
171
209
  * @property {string} url=undefined Defines the resource that you wish to fetch.
172
- * @property {Number} reconnect.timeout The timeout in milliseconds for the reconnect.
173
- * @property {Number} reconnect.attempts The maximum number of reconnects.
174
- * @property {Bool} reconnect.enabled If the reconnect is enabled.
210
+ * @property {Object} connection
211
+ * @property {Object} connection.timeout=5000 Defines the timeout for the connection.
212
+ * @property {Number} connection.reconnect.timeout The timeout in milliseconds for the reconnect.
213
+ * @property {Number} connection.reconnect.attempts The maximum number of reconnects.
214
+ * @property {Bool} connection.reconnect.enabled If the reconnect is enabled.
175
215
  * @property {Object} write={} Options
176
216
  * @property {Object} write.mapping the mapping is applied before writing.
177
217
  * @property {String} write.mapping.transformer Transformer to select the appropriate entries
@@ -208,21 +248,24 @@ class WebSocketDatasource extends Datasource {
208
248
  callbacks: []
209
249
  },
210
250
  },
211
- reconnect: {
212
- timeout: 1000,
213
- attempts: 10,
214
- enabled: true
251
+ connection: {
252
+ timeout: 5000,
253
+ reconnect: {
254
+ timeout: 1000,
255
+ attempts: 1,
256
+ enabled: false,
257
+ }
215
258
  }
216
259
  });
217
260
  }
218
261
 
219
262
  /**
220
263
  * This method closes the connection.
221
- *
264
+ *
222
265
  * @returns {Promise}
223
266
  */
224
267
  close() {
225
- this[manualCloseSymbol]=true;
268
+ this[manualCloseSymbol] = true;
226
269
  if (this[connectionSymbol].socket) {
227
270
  this[connectionSymbol].socket.close();
228
271
  }
@@ -231,21 +274,22 @@ class WebSocketDatasource extends Datasource {
231
274
 
232
275
  /**
233
276
  * @return {Promise}
234
- * @throws {Error} the options does not contain a valid json definition
235
- * @throws {Error} the data cannot be read
236
- * @throws {TypeError} value is not an object
237
277
  */
238
278
  read() {
239
279
  const self = this;
240
280
  let response;
241
281
 
282
+ if (self[connectionSymbol]?.socket?.readyState !== 1) {
283
+ return Promise.reject('The connection is not established.');
284
+ }
285
+
242
286
  return new Promise((resolve, reject) => {
243
287
  if (self[receiveQueueSymbol].isEmpty()) {
244
288
  resolve();
245
289
  }
246
290
 
247
291
  while (!self[receiveQueueSymbol].isEmpty()) {
248
-
292
+
249
293
  const event = self[receiveQueueSymbol].poll();
250
294
  const body = event?.data;
251
295
  if (!body) continue;
@@ -291,6 +335,10 @@ class WebSocketDatasource extends Datasource {
291
335
  write() {
292
336
  const self = this;
293
337
 
338
+ if (self[connectionSymbol]?.socket?.readyState !== 1) {
339
+ return Promise.reject('The connection is not established.');
340
+ }
341
+
294
342
  let obj = self.get();
295
343
  let transformation = self.getOption('write.mapping.transformer');
296
344
  if (transformation !== undefined) {
@@ -314,7 +362,7 @@ class WebSocketDatasource extends Datasource {
314
362
  }
315
363
 
316
364
  return new Promise((resolve, reject) => {
317
-
365
+
318
366
  if (self[connectionSymbol].socket.readyState !== 1) {
319
367
  reject('the socket is not ready');
320
368
  }
@@ -149,7 +149,7 @@ function getMonsterVersion() {
149
149
  }
150
150
 
151
151
  /** don't touch, replaced by make with package.json version */
152
- monsterVersion = new Version('3.1.1')
152
+ monsterVersion = new Version('3.2.0')
153
153
 
154
154
  return monsterVersion;
155
155
 
@@ -98,7 +98,8 @@ describe('Websocket', function () {
98
98
  }).catch((err) => {
99
99
  done(new Error(err));
100
100
  })
101
- }, 1000)
101
+ },
102
+ 500)
102
103
 
103
104
 
104
105
  }).timeout(10000);
@@ -7,7 +7,7 @@ describe('Monster', function () {
7
7
  let monsterVersion
8
8
 
9
9
  /** don´t touch, replaced by make with package.json version */
10
- monsterVersion = new Version('3.1.1')
10
+ monsterVersion = new Version('3.2.0')
11
11
 
12
12
  let m = getMonsterVersion();
13
13