teckos-client 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.js +456 -5
- package/dist/index.min.js +1 -0
- package/es/index.js +459 -0
- package/es/index.mjs +1 -0
- package/lib/index.js +484 -0
- package/package.json +61 -46
- package/src/ITeckosClient.js +2 -0
- package/src/ITeckosClient.js.map +1 -0
- package/src/ITeckosClient.ts +3 -3
- package/src/TeckosClient.js +235 -0
- package/src/TeckosClient.js.map +1 -0
- package/src/TeckosClient.ts +40 -32
- package/src/TeckosClientWithJWT.js +63 -0
- package/src/TeckosClientWithJWT.js.map +1 -0
- package/src/TeckosClientWithJWT.ts +8 -10
- package/src/index.js +8 -0
- package/src/index.js.map +1 -0
- package/src/index.ts +3 -3
- package/src/types/ConnectionState.js +9 -0
- package/src/types/ConnectionState.js.map +1 -0
- package/src/types/Options.js +2 -0
- package/src/types/Options.js.map +1 -0
- package/src/types/Packet.js +2 -0
- package/src/types/Packet.js.map +1 -0
- package/src/types/PacketType.js +7 -0
- package/src/types/PacketType.js.map +1 -0
- package/src/types/SocketEvent.js +2 -0
- package/src/types/SocketEvent.js.map +1 -0
- package/src/types/index.js +4 -0
- package/src/types/index.js.map +1 -0
- package/src/util/Converter.js +6 -0
- package/src/util/Converter.js.map +1 -0
- package/src/util/SocketEventEmitter.js +99 -0
- package/src/util/SocketEventEmitter.js.map +1 -0
- package/src/util/formatProdErrorMessage.ts +16 -0
- package/{dist → types}/ITeckosClient.d.ts +3 -3
- package/{dist → types}/TeckosClient.d.ts +6 -6
- package/{dist → types}/TeckosClientWithJWT.d.ts +0 -0
- package/types/index.d.ts +9 -0
- package/{dist → types}/types/ConnectionState.d.ts +0 -0
- package/{dist → types}/types/Options.d.ts +0 -0
- package/{dist → types}/types/Packet.d.ts +0 -0
- package/{dist → types}/types/PacketType.d.ts +0 -0
- package/{dist → types}/types/SocketEvent.d.ts +0 -0
- package/{dist → types}/types/index.d.ts +0 -0
- package/{dist → types}/util/Converter.d.ts +0 -0
- package/{dist → types}/util/SocketEventEmitter.d.ts +1 -1
- package/types/util/formatProdErrorMessage.d.ts +9 -0
- package/dist/index.d.ts +0 -9
- package/dist/teckos-client.cjs.development.js +0 -617
- package/dist/teckos-client.cjs.development.js.map +0 -1
- package/dist/teckos-client.cjs.production.min.js +0 -2
- package/dist/teckos-client.cjs.production.min.js.map +0 -1
- package/dist/teckos-client.esm.js +0 -614
- package/dist/teckos-client.esm.js.map +0 -1
package/dist/index.js
CHANGED
@@ -1,8 +1,459 @@
|
|
1
|
+
(function (global, factory) {
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["Teckos Client"] = {}));
|
5
|
+
})(this, (function (exports) { 'use strict';
|
1
6
|
|
2
|
-
|
7
|
+
module.exports = require('ws');
|
3
8
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
9
|
+
const enc = new TextEncoder();
|
10
|
+
const dec = new TextDecoder();
|
11
|
+
|
12
|
+
const encodePacket = packet => enc.encode(JSON.stringify(packet));
|
13
|
+
|
14
|
+
const decodePacket = buffer => JSON.parse(dec.decode(buffer).toString());
|
15
|
+
|
16
|
+
class SocketEventEmitter {
|
17
|
+
maxListeners = 50;
|
18
|
+
handlers = {};
|
19
|
+
addListener = (event, listener) => {
|
20
|
+
if (Object.keys(this.handlers).length === this.maxListeners) {
|
21
|
+
throw new Error('Max listeners reached');
|
22
|
+
}
|
23
|
+
|
24
|
+
if (typeof listener !== 'function') {
|
25
|
+
throw new Error('The given listener is not a function');
|
26
|
+
}
|
27
|
+
|
28
|
+
this.handlers[event] = this.handlers[event] || [];
|
29
|
+
this.handlers[event].push(listener);
|
30
|
+
return this;
|
31
|
+
};
|
32
|
+
once = (event, listener) => {
|
33
|
+
if (Object.keys(this.handlers).length === this.maxListeners) {
|
34
|
+
throw new Error('Max listeners reached');
|
35
|
+
}
|
36
|
+
|
37
|
+
if (typeof listener !== 'function') {
|
38
|
+
throw new Error('The given listener is not a function');
|
39
|
+
}
|
40
|
+
|
41
|
+
this.handlers[event] = this.handlers[event] || [];
|
42
|
+
|
43
|
+
const onceWrapper = () => {
|
44
|
+
listener();
|
45
|
+
this.off(event, onceWrapper);
|
46
|
+
};
|
47
|
+
|
48
|
+
this.handlers[event].push(onceWrapper);
|
49
|
+
return this;
|
50
|
+
};
|
51
|
+
removeListener = (event, listener) => {
|
52
|
+
if (this.handlers[event]) {
|
53
|
+
this.handlers[event] = this.handlers[event].filter(handler => handler !== listener);
|
54
|
+
}
|
55
|
+
|
56
|
+
return this;
|
57
|
+
};
|
58
|
+
off = (event, listener) => this.removeListener(event, listener);
|
59
|
+
removeAllListeners = event => {
|
60
|
+
if (event) {
|
61
|
+
delete this.handlers[event];
|
62
|
+
} else {
|
63
|
+
this.handlers = {};
|
64
|
+
}
|
65
|
+
|
66
|
+
return this;
|
67
|
+
};
|
68
|
+
setMaxListeners = n => {
|
69
|
+
this.maxListeners = n;
|
70
|
+
return this;
|
71
|
+
};
|
72
|
+
getMaxListeners = () => this.maxListeners;
|
73
|
+
listeners = event => {
|
74
|
+
if (this.handlers[event]) {
|
75
|
+
return [...this.handlers[event]];
|
76
|
+
}
|
77
|
+
|
78
|
+
return [];
|
79
|
+
};
|
80
|
+
rawListeners = event => [...this.handlers[event]];
|
81
|
+
listenerCount = event => {
|
82
|
+
if (this.handlers[event]) {
|
83
|
+
return Object.keys(this.handlers[event]).length;
|
84
|
+
}
|
85
|
+
|
86
|
+
return 0;
|
87
|
+
};
|
88
|
+
prependListener = (event, listener) => {
|
89
|
+
if (Object.keys(this.handlers).length === this.maxListeners) {
|
90
|
+
throw new Error('Max listeners reached');
|
91
|
+
}
|
92
|
+
|
93
|
+
this.handlers[event] = this.handlers[event] || [];
|
94
|
+
this.handlers[event].unshift(listener);
|
95
|
+
return this;
|
96
|
+
};
|
97
|
+
prependOnceListener = (event, listener) => {
|
98
|
+
if (Object.keys(this.handlers).length === this.maxListeners) {
|
99
|
+
throw new Error('Max listeners reached');
|
100
|
+
}
|
101
|
+
|
102
|
+
this.handlers[event] = this.handlers[event] || [];
|
103
|
+
|
104
|
+
const onceWrapper = () => {
|
105
|
+
listener();
|
106
|
+
this.off(event, onceWrapper);
|
107
|
+
};
|
108
|
+
|
109
|
+
this.handlers[event].unshift(onceWrapper);
|
110
|
+
return this;
|
111
|
+
};
|
112
|
+
eventNames = () => Object.keys(this.handlers);
|
113
|
+
on = (event, listener) => this.addListener(event, listener);
|
114
|
+
emit = (event, ...args) => {
|
115
|
+
const listeners = this.listeners(event);
|
116
|
+
|
117
|
+
if (listeners.length > 0) {
|
118
|
+
listeners.forEach(listener => {
|
119
|
+
if (listener) listener(args);
|
120
|
+
});
|
121
|
+
return true;
|
122
|
+
}
|
123
|
+
|
124
|
+
return false;
|
125
|
+
};
|
8
126
|
}
|
127
|
+
|
128
|
+
exports.PacketType = void 0;
|
129
|
+
|
130
|
+
(function (PacketType) {
|
131
|
+
PacketType[PacketType["EVENT"] = 0] = "EVENT";
|
132
|
+
PacketType[PacketType["ACK"] = 1] = "ACK";
|
133
|
+
})(exports.PacketType || (exports.PacketType = {}));
|
134
|
+
|
135
|
+
exports.ConnectionState = void 0;
|
136
|
+
|
137
|
+
(function (ConnectionState) {
|
138
|
+
ConnectionState["DISCONNECTED"] = "disconnected";
|
139
|
+
ConnectionState["CONNECTING"] = "connecting";
|
140
|
+
ConnectionState["CONNECTED"] = "connected";
|
141
|
+
ConnectionState["DISCONNECTING"] = "disconnecting";
|
142
|
+
})(exports.ConnectionState || (exports.ConnectionState = {}));
|
143
|
+
|
144
|
+
const DEFAULT_OPTIONS = {
|
145
|
+
reconnection: true,
|
146
|
+
reconnectionDelay: 1000,
|
147
|
+
reconnectionDelayMax: 5000,
|
148
|
+
reconnectionAttempts: Infinity,
|
149
|
+
randomizationFactor: 0.5,
|
150
|
+
timeout: 5000,
|
151
|
+
debug: false
|
152
|
+
};
|
153
|
+
|
154
|
+
class TeckosClient extends SocketEventEmitter {
|
155
|
+
url;
|
156
|
+
options;
|
157
|
+
ws;
|
158
|
+
currentReconnectDelay;
|
159
|
+
currentReconnectionAttempts = 0;
|
160
|
+
acks = new Map();
|
161
|
+
fnId = 0;
|
162
|
+
connectionTimeout;
|
163
|
+
reconnectionTimeout;
|
164
|
+
|
165
|
+
constructor(url, options) {
|
166
|
+
super();
|
167
|
+
this.options = { ...DEFAULT_OPTIONS,
|
168
|
+
...options
|
169
|
+
};
|
170
|
+
this.currentReconnectDelay = this.options.reconnectionDelay;
|
171
|
+
this.url = url;
|
172
|
+
}
|
173
|
+
|
174
|
+
attachHandler = () => {
|
175
|
+
if (this.ws) {
|
176
|
+
this.ws.onopen = this.handleOpen;
|
177
|
+
this.ws.onerror = this.handleError;
|
178
|
+
this.ws.onclose = this.handleClose;
|
179
|
+
this.ws.onmessage = this.handleMessage;
|
180
|
+
}
|
181
|
+
};
|
182
|
+
|
183
|
+
get webSocket() {
|
184
|
+
return this.ws;
|
185
|
+
}
|
186
|
+
|
187
|
+
connect = () => {
|
188
|
+
if (this.options.debug) console.log(`(teckos:client) Connecting to ${this.url}...`); // This will try to connect immediately
|
189
|
+
// eslint-disable-next-line new-cap
|
190
|
+
|
191
|
+
this.ws = new undefined(this.url); // Attach handlers
|
192
|
+
|
193
|
+
this.attachHandler(); // Handle timeout
|
194
|
+
|
195
|
+
this.connectionTimeout = setTimeout(() => {
|
196
|
+
if (this.ws && this.ws.readyState === 0
|
197
|
+
/* = CONNECTING */
|
198
|
+
) {
|
199
|
+
this.ws.close();
|
200
|
+
}
|
201
|
+
}, this.options.timeout);
|
202
|
+
};
|
203
|
+
reconnect = () => {
|
204
|
+
this.listeners('reconnect_attempt').forEach(listener => listener());
|
205
|
+
this.connect();
|
206
|
+
};
|
207
|
+
|
208
|
+
getConnectionState() {
|
209
|
+
if (this.ws) {
|
210
|
+
switch (this.ws.readyState) {
|
211
|
+
case 0
|
212
|
+
/* = CONNECTING */
|
213
|
+
:
|
214
|
+
return exports.ConnectionState.CONNECTING;
|
215
|
+
|
216
|
+
case 1
|
217
|
+
/* = OPEN */
|
218
|
+
:
|
219
|
+
return exports.ConnectionState.CONNECTED;
|
220
|
+
|
221
|
+
case 2
|
222
|
+
/* = CLOSING */
|
223
|
+
:
|
224
|
+
return exports.ConnectionState.DISCONNECTING;
|
225
|
+
|
226
|
+
default:
|
227
|
+
/* 3 = CLOSED */
|
228
|
+
return exports.ConnectionState.DISCONNECTED;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
return exports.ConnectionState.DISCONNECTED;
|
233
|
+
}
|
234
|
+
|
235
|
+
get state() {
|
236
|
+
return this.getConnectionState();
|
237
|
+
}
|
238
|
+
|
239
|
+
get connected() {
|
240
|
+
return this.getConnectionState() === exports.ConnectionState.CONNECTED;
|
241
|
+
}
|
242
|
+
|
243
|
+
get disconnected() {
|
244
|
+
return this.getConnectionState() === exports.ConnectionState.DISCONNECTED;
|
245
|
+
}
|
246
|
+
|
247
|
+
emit = (event, ...args) => {
|
248
|
+
args.unshift(event);
|
249
|
+
const packet = {
|
250
|
+
type: exports.PacketType.EVENT,
|
251
|
+
data: args
|
252
|
+
};
|
253
|
+
|
254
|
+
if (typeof args[args.length - 1] === 'function') {
|
255
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
256
|
+
this.acks.set(this.fnId, args.pop());
|
257
|
+
packet.id = this.fnId;
|
258
|
+
this.fnId += 1;
|
259
|
+
}
|
260
|
+
|
261
|
+
return this.sendPackage(packet);
|
262
|
+
};
|
263
|
+
send = (...args) => {
|
264
|
+
args.unshift('message');
|
265
|
+
return this.sendPackage({
|
266
|
+
type: exports.PacketType.EVENT,
|
267
|
+
data: args
|
268
|
+
});
|
269
|
+
};
|
270
|
+
sendPackage = packet => {
|
271
|
+
if (this.ws !== undefined && this.ws.readyState === 1
|
272
|
+
/* = OPEN */
|
273
|
+
) {
|
274
|
+
const buffer = encodePacket(packet);
|
275
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Send packet: ${JSON.stringify(packet)}`);
|
276
|
+
this.ws.send(buffer);
|
277
|
+
return true;
|
278
|
+
}
|
279
|
+
|
280
|
+
return false;
|
281
|
+
};
|
282
|
+
handleMessage = msg => {
|
283
|
+
const packet = typeof msg.data === 'string' ? JSON.parse(msg.data) : decodePacket(msg.data);
|
284
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Got packet: ${JSON.stringify(packet)}`);
|
285
|
+
|
286
|
+
if (packet.type === exports.PacketType.EVENT) {
|
287
|
+
const event = packet.data[0];
|
288
|
+
const args = packet.data.slice(1);
|
289
|
+
|
290
|
+
if (event) {
|
291
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
292
|
+
this.listeners(event).forEach(listener => listener(...args));
|
293
|
+
} else {
|
294
|
+
throw new Error(`(teckos-client) [${this.url}] Got invalid event message: ${JSON.stringify(msg.data)}`);
|
295
|
+
}
|
296
|
+
} else if (packet.type === exports.PacketType.ACK && packet.id !== undefined) {
|
297
|
+
// Call assigned function
|
298
|
+
const ack = this.acks.get(packet.id);
|
299
|
+
|
300
|
+
if (typeof ack === 'function') {
|
301
|
+
ack.apply(this, packet.data);
|
302
|
+
this.acks.delete(packet.id);
|
303
|
+
}
|
304
|
+
} else {
|
305
|
+
throw new Error(`(teckos-client) [${this.url}] Got invalid message type: ${packet.type}`);
|
306
|
+
}
|
307
|
+
};
|
308
|
+
handleOpen = () => {
|
309
|
+
if (this.currentReconnectionAttempts > 0) {
|
310
|
+
// Reset reconnection settings to default
|
311
|
+
this.currentReconnectDelay = this.options.reconnectionDelay;
|
312
|
+
this.currentReconnectionAttempts = 0; // Inform listeners
|
313
|
+
|
314
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Reconnected!`); // eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
315
|
+
|
316
|
+
this.listeners('reconnect').forEach(listener => listener());
|
317
|
+
} // Inform listeners
|
318
|
+
|
319
|
+
|
320
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Connected!`);
|
321
|
+
this.listeners('connect').forEach(listener => listener());
|
322
|
+
};
|
323
|
+
handleError = error => {
|
324
|
+
if (this.handlers && this.handlers.error) {
|
325
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Got error from server: ${JSON.stringify(error)}`);
|
326
|
+
this.handlers.error.forEach(listener => listener(error));
|
327
|
+
}
|
328
|
+
};
|
329
|
+
handleClose = () => {
|
330
|
+
// Stop connection timeout
|
331
|
+
if (this.connectionTimeout) {
|
332
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
333
|
+
clearTimeout(this.connectionTimeout);
|
334
|
+
} // Stop reconnection timeout
|
335
|
+
|
336
|
+
|
337
|
+
if (this.reconnectionTimeout) {
|
338
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
339
|
+
clearTimeout(this.reconnectionTimeout);
|
340
|
+
} // Inform listeners
|
341
|
+
|
342
|
+
|
343
|
+
if (this.currentReconnectionAttempts > 0) {
|
344
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Reconnect #${this.currentReconnectionAttempts} failed!`);
|
345
|
+
this.listeners('reconnect_error').forEach(listener => {
|
346
|
+
if (listener) listener();
|
347
|
+
});
|
348
|
+
} else {
|
349
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Disconnected!`);
|
350
|
+
this.listeners('disconnect').forEach(listener => {
|
351
|
+
if (listener) listener();
|
352
|
+
});
|
353
|
+
}
|
354
|
+
|
355
|
+
if (this.options.reconnection) {
|
356
|
+
// Apply reconnection logic
|
357
|
+
this.currentReconnectionAttempts += 1;
|
358
|
+
|
359
|
+
if (this.options.reconnectionAttempts === Infinity || this.currentReconnectionAttempts <= this.options.reconnectionAttempts) {
|
360
|
+
const timeout = Math.min(this.options.reconnectionDelayMax, this.currentReconnectDelay); // Increase reconnection delay
|
361
|
+
|
362
|
+
this.currentReconnectDelay = Math.round(this.currentReconnectDelay + this.currentReconnectDelay * this.options.randomizationFactor);
|
363
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Try reconnecting (${this.currentReconnectionAttempts}/${this.options.reconnectionAttempts}) in ${timeout}ms to ${this.url}...`);
|
364
|
+
this.reconnectionTimeout = setTimeout(() => {
|
365
|
+
this.reconnect();
|
366
|
+
}, timeout);
|
367
|
+
} else {
|
368
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Reconnection maximum of ${this.options.reconnectionAttempts} reached`);
|
369
|
+
this.listeners('reconnect_failed').forEach(listener => listener());
|
370
|
+
}
|
371
|
+
}
|
372
|
+
};
|
373
|
+
close = () => {
|
374
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Closing connection (client-side)`);
|
375
|
+
|
376
|
+
if (this.ws !== undefined) {
|
377
|
+
this.ws.onclose = () => {};
|
378
|
+
|
379
|
+
this.ws.close();
|
380
|
+
this.listeners('disconnect').forEach(listener => listener());
|
381
|
+
}
|
382
|
+
};
|
383
|
+
disconnect = () => {
|
384
|
+
this.close();
|
385
|
+
};
|
386
|
+
}
|
387
|
+
|
388
|
+
/* eslint-disable no-console */
|
389
|
+
|
390
|
+
class TeckosClientWithJWT extends TeckosClient {
|
391
|
+
token;
|
392
|
+
initialData;
|
393
|
+
receivedReady = false; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
394
|
+
|
395
|
+
constructor(url, options, token, initialData) {
|
396
|
+
super(url, options);
|
397
|
+
this.token = token; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
398
|
+
|
399
|
+
this.initialData = initialData;
|
400
|
+
this.on('disconnect', () => {
|
401
|
+
this.receivedReady = false;
|
402
|
+
});
|
403
|
+
}
|
404
|
+
|
405
|
+
getConnectionState() {
|
406
|
+
if (this.ws) {
|
407
|
+
switch (this.ws.readyState) {
|
408
|
+
case undefined:
|
409
|
+
if (this.receivedReady) {
|
410
|
+
return exports.ConnectionState.CONNECTED;
|
411
|
+
}
|
412
|
+
|
413
|
+
return exports.ConnectionState.CONNECTING;
|
414
|
+
|
415
|
+
case undefined:
|
416
|
+
return exports.ConnectionState.CONNECTING;
|
417
|
+
|
418
|
+
case undefined:
|
419
|
+
return exports.ConnectionState.DISCONNECTING;
|
420
|
+
|
421
|
+
default:
|
422
|
+
return exports.ConnectionState.DISCONNECTED;
|
423
|
+
}
|
424
|
+
}
|
425
|
+
|
426
|
+
return exports.ConnectionState.DISCONNECTED;
|
427
|
+
}
|
428
|
+
|
429
|
+
handleReadyEvent = () => {
|
430
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Connected!`);
|
431
|
+
this.receivedReady = true;
|
432
|
+
|
433
|
+
if (this.currentReconnectionAttempts > 0) {
|
434
|
+
if (this.options.debug) console.log(`(teckos:client) [${this.url}] Reconnected!`);
|
435
|
+
this.listeners('reconnect').forEach(listener => listener()); // Reset reconnection settings to default
|
436
|
+
|
437
|
+
this.currentReconnectDelay = this.options.reconnectionDelay;
|
438
|
+
this.currentReconnectionAttempts = 0;
|
439
|
+
}
|
440
|
+
|
441
|
+
this.listeners('connect').forEach(listener => listener());
|
442
|
+
};
|
443
|
+
handleOpen = () => {
|
444
|
+
this.receivedReady = false;
|
445
|
+
this.once('ready', this.handleReadyEvent);
|
446
|
+
if (this.options.debug) console.log(`(teckos:client) Connection opened, sending token now`);
|
447
|
+
this.emit('token', {
|
448
|
+
token: this.token,
|
449
|
+
...this.initialData
|
450
|
+
});
|
451
|
+
};
|
452
|
+
}
|
453
|
+
|
454
|
+
exports.TeckosClient = TeckosClient;
|
455
|
+
exports.TeckosClientWithJWT = TeckosClientWithJWT;
|
456
|
+
|
457
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
458
|
+
|
459
|
+
}));
|
@@ -0,0 +1 @@
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["Teckos Client"]={})}(this,(function(e){"use strict";function t(e){return`Minified Redux error #${e}; visit https://redux.js.org/Errors?code=${e} for the full message or use the non-minified dev environment for full errors. `}module.exports=require("ws");const n=new TextEncoder,s=new TextDecoder;var i,o;e.PacketType=void 0,(i=e.PacketType||(e.PacketType={}))[i.EVENT=0]="EVENT",i[i.ACK=1]="ACK",e.ConnectionState=void 0,(o=e.ConnectionState||(e.ConnectionState={})).DISCONNECTED="disconnected",o.CONNECTING="connecting",o.CONNECTED="connected",o.DISCONNECTING="disconnecting";const c={reconnection:!0,reconnectionDelay:1e3,reconnectionDelayMax:5e3,reconnectionAttempts:1/0,randomizationFactor:.5,timeout:5e3,debug:!1};class r extends class{maxListeners=50;handlers={};addListener=(e,n)=>{if(Object.keys(this.handlers).length===this.maxListeners)throw Error(t(2));if("function"!=typeof n)throw Error(t(3));return this.handlers[e]=this.handlers[e]||[],this.handlers[e].push(n),this};once=(e,n)=>{if(Object.keys(this.handlers).length===this.maxListeners)throw Error(t(2));if("function"!=typeof n)throw Error(t(3));this.handlers[e]=this.handlers[e]||[];const s=()=>{n(),this.off(e,s)};return this.handlers[e].push(s),this};removeListener=(e,t)=>(this.handlers[e]&&(this.handlers[e]=this.handlers[e].filter((e=>e!==t))),this);off=(e,t)=>this.removeListener(e,t);removeAllListeners=e=>(e?delete this.handlers[e]:this.handlers={},this);setMaxListeners=e=>(this.maxListeners=e,this);getMaxListeners=()=>this.maxListeners;listeners=e=>this.handlers[e]?[...this.handlers[e]]:[];rawListeners=e=>[...this.handlers[e]];listenerCount=e=>this.handlers[e]?Object.keys(this.handlers[e]).length:0;prependListener=(e,n)=>{if(Object.keys(this.handlers).length===this.maxListeners)throw Error(t(2));return this.handlers[e]=this.handlers[e]||[],this.handlers[e].unshift(n),this};prependOnceListener=(e,n)=>{if(Object.keys(this.handlers).length===this.maxListeners)throw Error(t(2));this.handlers[e]=this.handlers[e]||[];const s=()=>{n(),this.off(e,s)};return this.handlers[e].unshift(s),this};eventNames=()=>Object.keys(this.handlers);on=(e,t)=>this.addListener(e,t);emit=(e,...t)=>{const n=this.listeners(e);return n.length>0&&(n.forEach((e=>{e&&e(t)})),!0)}}{url;options;ws;currentReconnectDelay;currentReconnectionAttempts=0;acks=new Map;fnId=0;connectionTimeout;reconnectionTimeout;constructor(e,t){super(),this.options={...c,...t},this.currentReconnectDelay=this.options.reconnectionDelay,this.url=e}attachHandler=()=>{this.ws&&(this.ws.onopen=this.handleOpen,this.ws.onerror=this.handleError,this.ws.onclose=this.handleClose,this.ws.onmessage=this.handleMessage)};get webSocket(){return this.ws}connect=()=>{this.options.debug&&console.log(`(teckos:client) Connecting to ${this.url}...`),this.ws=new(void 0)(this.url),this.attachHandler(),this.connectionTimeout=setTimeout((()=>{this.ws&&0===this.ws.readyState&&this.ws.close()}),this.options.timeout)};reconnect=()=>{this.listeners("reconnect_attempt").forEach((e=>e())),this.connect()};getConnectionState(){if(this.ws)switch(this.ws.readyState){case 0:return e.ConnectionState.CONNECTING;case 1:return e.ConnectionState.CONNECTED;case 2:return e.ConnectionState.DISCONNECTING;default:return e.ConnectionState.DISCONNECTED}return e.ConnectionState.DISCONNECTED}get state(){return this.getConnectionState()}get connected(){return this.getConnectionState()===e.ConnectionState.CONNECTED}get disconnected(){return this.getConnectionState()===e.ConnectionState.DISCONNECTED}emit=(t,...n)=>{n.unshift(t);const s={type:e.PacketType.EVENT,data:n};return"function"==typeof n[n.length-1]&&(this.acks.set(this.fnId,n.pop()),s.id=this.fnId,this.fnId+=1),this.sendPackage(s)};send=(...t)=>(t.unshift("message"),this.sendPackage({type:e.PacketType.EVENT,data:t}));sendPackage=e=>{if(void 0!==this.ws&&1===this.ws.readyState){const t=(e=>n.encode(JSON.stringify(e)))(e);return this.options.debug&&console.log(`(teckos:client) [${this.url}] Send packet: ${JSON.stringify(e)}`),this.ws.send(t),!0}return!1};handleMessage=n=>{const i="string"==typeof n.data?JSON.parse(n.data):JSON.parse(""+s.decode(n.data));if(this.options.debug&&console.log(`(teckos:client) [${this.url}] Got packet: ${JSON.stringify(i)}`),i.type===e.PacketType.EVENT){const e=i.data[0],n=i.data.slice(1);if(!e)throw Error(t(0));this.listeners(e).forEach((e=>e(...n)))}else{if(i.type!==e.PacketType.ACK||void 0===i.id)throw Error(t(1));{const e=this.acks.get(i.id);"function"==typeof e&&(e.apply(this,i.data),this.acks.delete(i.id))}}};handleOpen=()=>{this.currentReconnectionAttempts>0&&(this.currentReconnectDelay=this.options.reconnectionDelay,this.currentReconnectionAttempts=0,this.options.debug&&console.log(`(teckos:client) [${this.url}] Reconnected!`),this.listeners("reconnect").forEach((e=>e()))),this.options.debug&&console.log(`(teckos:client) [${this.url}] Connected!`),this.listeners("connect").forEach((e=>e()))};handleError=e=>{this.handlers&&this.handlers.error&&(this.options.debug&&console.log(`(teckos:client) [${this.url}] Got error from server: ${JSON.stringify(e)}`),this.handlers.error.forEach((t=>t(e))))};handleClose=()=>{if(this.connectionTimeout&&clearTimeout(this.connectionTimeout),this.reconnectionTimeout&&clearTimeout(this.reconnectionTimeout),this.currentReconnectionAttempts>0?(this.options.debug&&console.log(`(teckos:client) [${this.url}] Reconnect #${this.currentReconnectionAttempts} failed!`),this.listeners("reconnect_error").forEach((e=>{e&&e()}))):(this.options.debug&&console.log(`(teckos:client) [${this.url}] Disconnected!`),this.listeners("disconnect").forEach((e=>{e&&e()}))),this.options.reconnection)if(this.currentReconnectionAttempts+=1,this.options.reconnectionAttempts!==1/0&&this.currentReconnectionAttempts>this.options.reconnectionAttempts)this.options.debug&&console.log(`(teckos:client) [${this.url}] Reconnection maximum of ${this.options.reconnectionAttempts} reached`),this.listeners("reconnect_failed").forEach((e=>e()));else{const e=Math.min(this.options.reconnectionDelayMax,this.currentReconnectDelay);this.currentReconnectDelay=Math.round(this.currentReconnectDelay+this.currentReconnectDelay*this.options.randomizationFactor),this.options.debug&&console.log(`(teckos:client) [${this.url}] Try reconnecting (${this.currentReconnectionAttempts}/${this.options.reconnectionAttempts}) in ${e}ms to ${this.url}...`),this.reconnectionTimeout=setTimeout((()=>{this.reconnect()}),e)}};close=()=>{this.options.debug&&console.log(`(teckos:client) [${this.url}] Closing connection (client-side)`),void 0!==this.ws&&(this.ws.onclose=()=>{},this.ws.close(),this.listeners("disconnect").forEach((e=>e())))};disconnect=()=>{this.close()}}e.TeckosClient=r,e.TeckosClientWithJWT=class extends r{token;initialData;receivedReady=!1;constructor(e,t,n,s){super(e,t),this.token=n,this.initialData=s,this.on("disconnect",(()=>{this.receivedReady=!1}))}getConnectionState(){if(this.ws)switch(this.ws.readyState){case void 0:return this.receivedReady?e.ConnectionState.CONNECTED:e.ConnectionState.CONNECTING;case void 0:return e.ConnectionState.CONNECTING;case void 0:return e.ConnectionState.DISCONNECTING;default:return e.ConnectionState.DISCONNECTED}return e.ConnectionState.DISCONNECTED}handleReadyEvent=()=>{this.options.debug&&console.log(`(teckos:client) [${this.url}] Connected!`),this.receivedReady=!0,this.currentReconnectionAttempts>0&&(this.options.debug&&console.log(`(teckos:client) [${this.url}] Reconnected!`),this.listeners("reconnect").forEach((e=>e())),this.currentReconnectDelay=this.options.reconnectionDelay,this.currentReconnectionAttempts=0),this.listeners("connect").forEach((e=>e()))};handleOpen=()=>{this.receivedReady=!1,this.once("ready",this.handleReadyEvent),this.options.debug&&console.log("(teckos:client) Connection opened, sending token now"),this.emit("token",{token:this.token,...this.initialData})}},Object.defineProperty(e,"__esModule",{value:!0})}));
|