teckos-client 0.2.5 → 0.3.2

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