@everymatrix/nuts-inbox-widget 0.0.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.
Files changed (59) hide show
  1. package/dist/cjs/index-305bcf58.js +1349 -0
  2. package/dist/cjs/index.cjs.js +2 -0
  3. package/dist/cjs/loader.cjs.js +21 -0
  4. package/dist/cjs/nuts-inbox-widget.cjs.js +19 -0
  5. package/dist/cjs/nuts-inbox-widget_3.cjs.entry.js +39985 -0
  6. package/dist/collection/collection-manifest.json +14 -0
  7. package/dist/collection/components/nuts-inbox-widget/nuts-inbox-widget.css +15 -0
  8. package/dist/collection/components/nuts-inbox-widget/nuts-inbox-widget.js +450 -0
  9. package/dist/collection/components/nuts-notification/nuts-notification.css +147 -0
  10. package/dist/collection/components/nuts-notification/nuts-notification.js +426 -0
  11. package/dist/collection/components/nuts-popover/nuts-popover.css +75 -0
  12. package/dist/collection/components/nuts-popover/nuts-popover.js +265 -0
  13. package/dist/collection/index.js +1 -0
  14. package/dist/collection/types/nuts-inbox-widget.types.js +47 -0
  15. package/dist/collection/utils/utils.js +0 -0
  16. package/dist/components/index.d.ts +26 -0
  17. package/dist/components/index.js +1 -0
  18. package/dist/components/nuts-inbox-widget.d.ts +11 -0
  19. package/dist/components/nuts-inbox-widget.js +4216 -0
  20. package/dist/components/nuts-notification.d.ts +11 -0
  21. package/dist/components/nuts-notification.js +6 -0
  22. package/dist/components/nuts-notification2.js +35762 -0
  23. package/dist/components/nuts-popover.d.ts +11 -0
  24. package/dist/components/nuts-popover.js +6 -0
  25. package/dist/components/nuts-popover2.js +119 -0
  26. package/dist/esm/index-4e49d940.js +1322 -0
  27. package/dist/esm/index.js +1 -0
  28. package/dist/esm/loader.js +17 -0
  29. package/dist/esm/nuts-inbox-widget.js +17 -0
  30. package/dist/esm/nuts-inbox-widget_3.entry.js +39979 -0
  31. package/dist/esm/polyfills/core-js.js +11 -0
  32. package/dist/esm/polyfills/css-shim.js +1 -0
  33. package/dist/esm/polyfills/dom.js +79 -0
  34. package/dist/esm/polyfills/es5-html-element.js +1 -0
  35. package/dist/esm/polyfills/index.js +34 -0
  36. package/dist/esm/polyfills/system.js +6 -0
  37. package/dist/index.cjs.js +1 -0
  38. package/dist/index.js +1 -0
  39. package/dist/nuts-inbox-widget/index.esm.js +0 -0
  40. package/dist/nuts-inbox-widget/nuts-inbox-widget.esm.js +1 -0
  41. package/dist/nuts-inbox-widget/p-2f19681b.entry.js +1 -0
  42. package/dist/nuts-inbox-widget/p-d5a07a94.js +1 -0
  43. package/dist/stencil.config.js +22 -0
  44. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-stencil/packages/nuts-inbox-widget/.stencil/packages/nuts-inbox-widget/stencil.config.d.ts +2 -0
  45. package/dist/types/components/nuts-inbox-widget/nuts-inbox-widget.d.ts +70 -0
  46. package/dist/types/components/nuts-notification/nuts-notification.d.ts +38 -0
  47. package/dist/types/components/nuts-popover/nuts-popover.d.ts +29 -0
  48. package/dist/types/components.d.ts +225 -0
  49. package/dist/types/index.d.ts +1 -0
  50. package/dist/types/stencil-public-runtime.d.ts +1565 -0
  51. package/dist/types/types/nuts-inbox-widget.types.d.ts +98 -0
  52. package/dist/types/utils/utils.d.ts +0 -0
  53. package/loader/cdn.js +3 -0
  54. package/loader/index.cjs.js +3 -0
  55. package/loader/index.d.ts +12 -0
  56. package/loader/index.es2017.js +3 -0
  57. package/loader/index.js +4 -0
  58. package/loader/package.json +10 -0
  59. package/package.json +19 -0
@@ -0,0 +1,4216 @@
1
+ import { Build, getElement, proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
2
+ import { d as defineCustomElement$3 } from './nuts-notification2.js';
3
+ import { d as defineCustomElement$2 } from './nuts-popover2.js';
4
+
5
+ /******************************************************************************
6
+ Copyright (c) Microsoft Corporation.
7
+
8
+ Permission to use, copy, modify, and/or distribute this software for any
9
+ purpose with or without fee is hereby granted.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ ***************************************************************************** */
19
+
20
+ function __decorate(decorators, target, key, desc) {
21
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
22
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
23
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
24
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
25
+ }
26
+
27
+ function __metadata(metadataKey, metadataValue) {
28
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
29
+ }
30
+
31
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
32
+ var e = new Error(message);
33
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
34
+ };
35
+
36
+ const PACKET_TYPES = Object.create(null); // no Map = no polyfill
37
+ PACKET_TYPES["open"] = "0";
38
+ PACKET_TYPES["close"] = "1";
39
+ PACKET_TYPES["ping"] = "2";
40
+ PACKET_TYPES["pong"] = "3";
41
+ PACKET_TYPES["message"] = "4";
42
+ PACKET_TYPES["upgrade"] = "5";
43
+ PACKET_TYPES["noop"] = "6";
44
+ const PACKET_TYPES_REVERSE = Object.create(null);
45
+ Object.keys(PACKET_TYPES).forEach(key => {
46
+ PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
47
+ });
48
+ const ERROR_PACKET = { type: "error", data: "parser error" };
49
+
50
+ const withNativeBlob$1 = typeof Blob === "function" ||
51
+ (typeof Blob !== "undefined" &&
52
+ Object.prototype.toString.call(Blob) === "[object BlobConstructor]");
53
+ const withNativeArrayBuffer$2 = typeof ArrayBuffer === "function";
54
+ // ArrayBuffer.isView method is not defined in IE10
55
+ const isView$1 = obj => {
56
+ return typeof ArrayBuffer.isView === "function"
57
+ ? ArrayBuffer.isView(obj)
58
+ : obj && obj.buffer instanceof ArrayBuffer;
59
+ };
60
+ const encodePacket = ({ type, data }, supportsBinary, callback) => {
61
+ if (withNativeBlob$1 && data instanceof Blob) {
62
+ if (supportsBinary) {
63
+ return callback(data);
64
+ }
65
+ else {
66
+ return encodeBlobAsBase64(data, callback);
67
+ }
68
+ }
69
+ else if (withNativeArrayBuffer$2 &&
70
+ (data instanceof ArrayBuffer || isView$1(data))) {
71
+ if (supportsBinary) {
72
+ return callback(data);
73
+ }
74
+ else {
75
+ return encodeBlobAsBase64(new Blob([data]), callback);
76
+ }
77
+ }
78
+ // plain string
79
+ return callback(PACKET_TYPES[type] + (data || ""));
80
+ };
81
+ const encodeBlobAsBase64 = (data, callback) => {
82
+ const fileReader = new FileReader();
83
+ fileReader.onload = function () {
84
+ const content = fileReader.result.split(",")[1];
85
+ callback("b" + (content || ""));
86
+ };
87
+ return fileReader.readAsDataURL(data);
88
+ };
89
+ function toArray(data) {
90
+ if (data instanceof Uint8Array) {
91
+ return data;
92
+ }
93
+ else if (data instanceof ArrayBuffer) {
94
+ return new Uint8Array(data);
95
+ }
96
+ else {
97
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
98
+ }
99
+ }
100
+ let TEXT_ENCODER;
101
+ function encodePacketToBinary(packet, callback) {
102
+ if (withNativeBlob$1 && packet.data instanceof Blob) {
103
+ return packet.data
104
+ .arrayBuffer()
105
+ .then(toArray)
106
+ .then(callback);
107
+ }
108
+ else if (withNativeArrayBuffer$2 &&
109
+ (packet.data instanceof ArrayBuffer || isView$1(packet.data))) {
110
+ return callback(toArray(packet.data));
111
+ }
112
+ encodePacket(packet, false, encoded => {
113
+ if (!TEXT_ENCODER) {
114
+ TEXT_ENCODER = new TextEncoder();
115
+ }
116
+ callback(TEXT_ENCODER.encode(encoded));
117
+ });
118
+ }
119
+
120
+ // imported from https://github.com/socketio/base64-arraybuffer
121
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
122
+ // Use a lookup table to find the index.
123
+ const lookup$1 = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
124
+ for (let i = 0; i < chars.length; i++) {
125
+ lookup$1[chars.charCodeAt(i)] = i;
126
+ }
127
+ const decode$1 = (base64) => {
128
+ let bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4;
129
+ if (base64[base64.length - 1] === '=') {
130
+ bufferLength--;
131
+ if (base64[base64.length - 2] === '=') {
132
+ bufferLength--;
133
+ }
134
+ }
135
+ const arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer);
136
+ for (i = 0; i < len; i += 4) {
137
+ encoded1 = lookup$1[base64.charCodeAt(i)];
138
+ encoded2 = lookup$1[base64.charCodeAt(i + 1)];
139
+ encoded3 = lookup$1[base64.charCodeAt(i + 2)];
140
+ encoded4 = lookup$1[base64.charCodeAt(i + 3)];
141
+ bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
142
+ bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
143
+ bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
144
+ }
145
+ return arraybuffer;
146
+ };
147
+
148
+ const withNativeArrayBuffer$1 = typeof ArrayBuffer === "function";
149
+ const decodePacket = (encodedPacket, binaryType) => {
150
+ if (typeof encodedPacket !== "string") {
151
+ return {
152
+ type: "message",
153
+ data: mapBinary(encodedPacket, binaryType)
154
+ };
155
+ }
156
+ const type = encodedPacket.charAt(0);
157
+ if (type === "b") {
158
+ return {
159
+ type: "message",
160
+ data: decodeBase64Packet(encodedPacket.substring(1), binaryType)
161
+ };
162
+ }
163
+ const packetType = PACKET_TYPES_REVERSE[type];
164
+ if (!packetType) {
165
+ return ERROR_PACKET;
166
+ }
167
+ return encodedPacket.length > 1
168
+ ? {
169
+ type: PACKET_TYPES_REVERSE[type],
170
+ data: encodedPacket.substring(1)
171
+ }
172
+ : {
173
+ type: PACKET_TYPES_REVERSE[type]
174
+ };
175
+ };
176
+ const decodeBase64Packet = (data, binaryType) => {
177
+ if (withNativeArrayBuffer$1) {
178
+ const decoded = decode$1(data);
179
+ return mapBinary(decoded, binaryType);
180
+ }
181
+ else {
182
+ return { base64: true, data }; // fallback for old browsers
183
+ }
184
+ };
185
+ const mapBinary = (data, binaryType) => {
186
+ switch (binaryType) {
187
+ case "blob":
188
+ if (data instanceof Blob) {
189
+ // from WebSocket + binaryType "blob"
190
+ return data;
191
+ }
192
+ else {
193
+ // from HTTP long-polling or WebTransport
194
+ return new Blob([data]);
195
+ }
196
+ case "arraybuffer":
197
+ default:
198
+ if (data instanceof ArrayBuffer) {
199
+ // from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
200
+ return data;
201
+ }
202
+ else {
203
+ // from WebTransport (Uint8Array)
204
+ return data.buffer;
205
+ }
206
+ }
207
+ };
208
+
209
+ const SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
210
+ const encodePayload = (packets, callback) => {
211
+ // some packets may be added to the array while encoding, so the initial length must be saved
212
+ const length = packets.length;
213
+ const encodedPackets = new Array(length);
214
+ let count = 0;
215
+ packets.forEach((packet, i) => {
216
+ // force base64 encoding for binary packets
217
+ encodePacket(packet, false, encodedPacket => {
218
+ encodedPackets[i] = encodedPacket;
219
+ if (++count === length) {
220
+ callback(encodedPackets.join(SEPARATOR));
221
+ }
222
+ });
223
+ });
224
+ };
225
+ const decodePayload = (encodedPayload, binaryType) => {
226
+ const encodedPackets = encodedPayload.split(SEPARATOR);
227
+ const packets = [];
228
+ for (let i = 0; i < encodedPackets.length; i++) {
229
+ const decodedPacket = decodePacket(encodedPackets[i], binaryType);
230
+ packets.push(decodedPacket);
231
+ if (decodedPacket.type === "error") {
232
+ break;
233
+ }
234
+ }
235
+ return packets;
236
+ };
237
+ function createPacketEncoderStream() {
238
+ return new TransformStream({
239
+ transform(packet, controller) {
240
+ encodePacketToBinary(packet, encodedPacket => {
241
+ const payloadLength = encodedPacket.length;
242
+ let header;
243
+ // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
244
+ if (payloadLength < 126) {
245
+ header = new Uint8Array(1);
246
+ new DataView(header.buffer).setUint8(0, payloadLength);
247
+ }
248
+ else if (payloadLength < 65536) {
249
+ header = new Uint8Array(3);
250
+ const view = new DataView(header.buffer);
251
+ view.setUint8(0, 126);
252
+ view.setUint16(1, payloadLength);
253
+ }
254
+ else {
255
+ header = new Uint8Array(9);
256
+ const view = new DataView(header.buffer);
257
+ view.setUint8(0, 127);
258
+ view.setBigUint64(1, BigInt(payloadLength));
259
+ }
260
+ // first bit indicates whether the payload is plain text (0) or binary (1)
261
+ if (packet.data && typeof packet.data !== "string") {
262
+ header[0] |= 0x80;
263
+ }
264
+ controller.enqueue(header);
265
+ controller.enqueue(encodedPacket);
266
+ });
267
+ }
268
+ });
269
+ }
270
+ let TEXT_DECODER;
271
+ function totalLength(chunks) {
272
+ return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
273
+ }
274
+ function concatChunks(chunks, size) {
275
+ if (chunks[0].length === size) {
276
+ return chunks.shift();
277
+ }
278
+ const buffer = new Uint8Array(size);
279
+ let j = 0;
280
+ for (let i = 0; i < size; i++) {
281
+ buffer[i] = chunks[0][j++];
282
+ if (j === chunks[0].length) {
283
+ chunks.shift();
284
+ j = 0;
285
+ }
286
+ }
287
+ if (chunks.length && j < chunks[0].length) {
288
+ chunks[0] = chunks[0].slice(j);
289
+ }
290
+ return buffer;
291
+ }
292
+ function createPacketDecoderStream(maxPayload, binaryType) {
293
+ if (!TEXT_DECODER) {
294
+ TEXT_DECODER = new TextDecoder();
295
+ }
296
+ const chunks = [];
297
+ let state = 0 /* READ_HEADER */;
298
+ let expectedLength = -1;
299
+ let isBinary = false;
300
+ return new TransformStream({
301
+ transform(chunk, controller) {
302
+ chunks.push(chunk);
303
+ while (true) {
304
+ if (state === 0 /* READ_HEADER */) {
305
+ if (totalLength(chunks) < 1) {
306
+ break;
307
+ }
308
+ const header = concatChunks(chunks, 1);
309
+ isBinary = (header[0] & 0x80) === 0x80;
310
+ expectedLength = header[0] & 0x7f;
311
+ if (expectedLength < 126) {
312
+ state = 3 /* READ_PAYLOAD */;
313
+ }
314
+ else if (expectedLength === 126) {
315
+ state = 1 /* READ_EXTENDED_LENGTH_16 */;
316
+ }
317
+ else {
318
+ state = 2 /* READ_EXTENDED_LENGTH_64 */;
319
+ }
320
+ }
321
+ else if (state === 1 /* READ_EXTENDED_LENGTH_16 */) {
322
+ if (totalLength(chunks) < 2) {
323
+ break;
324
+ }
325
+ const headerArray = concatChunks(chunks, 2);
326
+ expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
327
+ state = 3 /* READ_PAYLOAD */;
328
+ }
329
+ else if (state === 2 /* READ_EXTENDED_LENGTH_64 */) {
330
+ if (totalLength(chunks) < 8) {
331
+ break;
332
+ }
333
+ const headerArray = concatChunks(chunks, 8);
334
+ const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
335
+ const n = view.getUint32(0);
336
+ if (n > Math.pow(2, 53 - 32) - 1) {
337
+ // the maximum safe integer in JavaScript is 2^53 - 1
338
+ controller.enqueue(ERROR_PACKET);
339
+ break;
340
+ }
341
+ expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
342
+ state = 3 /* READ_PAYLOAD */;
343
+ }
344
+ else {
345
+ if (totalLength(chunks) < expectedLength) {
346
+ break;
347
+ }
348
+ const data = concatChunks(chunks, expectedLength);
349
+ controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
350
+ state = 0 /* READ_HEADER */;
351
+ }
352
+ if (expectedLength === 0 || expectedLength > maxPayload) {
353
+ controller.enqueue(ERROR_PACKET);
354
+ break;
355
+ }
356
+ }
357
+ }
358
+ });
359
+ }
360
+ const protocol$1 = 4;
361
+
362
+ /**
363
+ * Initialize a new `Emitter`.
364
+ *
365
+ * @api public
366
+ */
367
+
368
+ function Emitter(obj) {
369
+ if (obj) return mixin(obj);
370
+ }
371
+
372
+ /**
373
+ * Mixin the emitter properties.
374
+ *
375
+ * @param {Object} obj
376
+ * @return {Object}
377
+ * @api private
378
+ */
379
+
380
+ function mixin(obj) {
381
+ for (var key in Emitter.prototype) {
382
+ obj[key] = Emitter.prototype[key];
383
+ }
384
+ return obj;
385
+ }
386
+
387
+ /**
388
+ * Listen on the given `event` with `fn`.
389
+ *
390
+ * @param {String} event
391
+ * @param {Function} fn
392
+ * @return {Emitter}
393
+ * @api public
394
+ */
395
+
396
+ Emitter.prototype.on =
397
+ Emitter.prototype.addEventListener = function(event, fn){
398
+ this._callbacks = this._callbacks || {};
399
+ (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
400
+ .push(fn);
401
+ return this;
402
+ };
403
+
404
+ /**
405
+ * Adds an `event` listener that will be invoked a single
406
+ * time then automatically removed.
407
+ *
408
+ * @param {String} event
409
+ * @param {Function} fn
410
+ * @return {Emitter}
411
+ * @api public
412
+ */
413
+
414
+ Emitter.prototype.once = function(event, fn){
415
+ function on() {
416
+ this.off(event, on);
417
+ fn.apply(this, arguments);
418
+ }
419
+
420
+ on.fn = fn;
421
+ this.on(event, on);
422
+ return this;
423
+ };
424
+
425
+ /**
426
+ * Remove the given callback for `event` or all
427
+ * registered callbacks.
428
+ *
429
+ * @param {String} event
430
+ * @param {Function} fn
431
+ * @return {Emitter}
432
+ * @api public
433
+ */
434
+
435
+ Emitter.prototype.off =
436
+ Emitter.prototype.removeListener =
437
+ Emitter.prototype.removeAllListeners =
438
+ Emitter.prototype.removeEventListener = function(event, fn){
439
+ this._callbacks = this._callbacks || {};
440
+
441
+ // all
442
+ if (0 == arguments.length) {
443
+ this._callbacks = {};
444
+ return this;
445
+ }
446
+
447
+ // specific event
448
+ var callbacks = this._callbacks['$' + event];
449
+ if (!callbacks) return this;
450
+
451
+ // remove all handlers
452
+ if (1 == arguments.length) {
453
+ delete this._callbacks['$' + event];
454
+ return this;
455
+ }
456
+
457
+ // remove specific handler
458
+ var cb;
459
+ for (var i = 0; i < callbacks.length; i++) {
460
+ cb = callbacks[i];
461
+ if (cb === fn || cb.fn === fn) {
462
+ callbacks.splice(i, 1);
463
+ break;
464
+ }
465
+ }
466
+
467
+ // Remove event specific arrays for event types that no
468
+ // one is subscribed for to avoid memory leak.
469
+ if (callbacks.length === 0) {
470
+ delete this._callbacks['$' + event];
471
+ }
472
+
473
+ return this;
474
+ };
475
+
476
+ /**
477
+ * Emit `event` with the given args.
478
+ *
479
+ * @param {String} event
480
+ * @param {Mixed} ...
481
+ * @return {Emitter}
482
+ */
483
+
484
+ Emitter.prototype.emit = function(event){
485
+ this._callbacks = this._callbacks || {};
486
+
487
+ var args = new Array(arguments.length - 1)
488
+ , callbacks = this._callbacks['$' + event];
489
+
490
+ for (var i = 1; i < arguments.length; i++) {
491
+ args[i - 1] = arguments[i];
492
+ }
493
+
494
+ if (callbacks) {
495
+ callbacks = callbacks.slice(0);
496
+ for (var i = 0, len = callbacks.length; i < len; ++i) {
497
+ callbacks[i].apply(this, args);
498
+ }
499
+ }
500
+
501
+ return this;
502
+ };
503
+
504
+ // alias used for reserved events (protected method)
505
+ Emitter.prototype.emitReserved = Emitter.prototype.emit;
506
+
507
+ /**
508
+ * Return array of callbacks for `event`.
509
+ *
510
+ * @param {String} event
511
+ * @return {Array}
512
+ * @api public
513
+ */
514
+
515
+ Emitter.prototype.listeners = function(event){
516
+ this._callbacks = this._callbacks || {};
517
+ return this._callbacks['$' + event] || [];
518
+ };
519
+
520
+ /**
521
+ * Check if this emitter has `event` handlers.
522
+ *
523
+ * @param {String} event
524
+ * @return {Boolean}
525
+ * @api public
526
+ */
527
+
528
+ Emitter.prototype.hasListeners = function(event){
529
+ return !! this.listeners(event).length;
530
+ };
531
+
532
+ const globalThisShim = (() => {
533
+ if (typeof self !== "undefined") {
534
+ return self;
535
+ }
536
+ else if (typeof window !== "undefined") {
537
+ return window;
538
+ }
539
+ else {
540
+ return Function("return this")();
541
+ }
542
+ })();
543
+
544
+ function pick(obj, ...attr) {
545
+ return attr.reduce((acc, k) => {
546
+ if (obj.hasOwnProperty(k)) {
547
+ acc[k] = obj[k];
548
+ }
549
+ return acc;
550
+ }, {});
551
+ }
552
+ // Keep a reference to the real timeout functions so they can be used when overridden
553
+ const NATIVE_SET_TIMEOUT = globalThisShim.setTimeout;
554
+ const NATIVE_CLEAR_TIMEOUT = globalThisShim.clearTimeout;
555
+ function installTimerFunctions(obj, opts) {
556
+ if (opts.useNativeTimers) {
557
+ obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThisShim);
558
+ obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThisShim);
559
+ }
560
+ else {
561
+ obj.setTimeoutFn = globalThisShim.setTimeout.bind(globalThisShim);
562
+ obj.clearTimeoutFn = globalThisShim.clearTimeout.bind(globalThisShim);
563
+ }
564
+ }
565
+ // base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
566
+ const BASE64_OVERHEAD = 1.33;
567
+ // we could also have used `new Blob([obj]).size`, but it isn't supported in IE9
568
+ function byteLength(obj) {
569
+ if (typeof obj === "string") {
570
+ return utf8Length(obj);
571
+ }
572
+ // arraybuffer or blob
573
+ return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD);
574
+ }
575
+ function utf8Length(str) {
576
+ let c = 0, length = 0;
577
+ for (let i = 0, l = str.length; i < l; i++) {
578
+ c = str.charCodeAt(i);
579
+ if (c < 0x80) {
580
+ length += 1;
581
+ }
582
+ else if (c < 0x800) {
583
+ length += 2;
584
+ }
585
+ else if (c < 0xd800 || c >= 0xe000) {
586
+ length += 3;
587
+ }
588
+ else {
589
+ i++;
590
+ length += 4;
591
+ }
592
+ }
593
+ return length;
594
+ }
595
+
596
+ // imported from https://github.com/galkn/querystring
597
+ /**
598
+ * Compiles a querystring
599
+ * Returns string representation of the object
600
+ *
601
+ * @param {Object}
602
+ * @api private
603
+ */
604
+ function encode$1(obj) {
605
+ let str = '';
606
+ for (let i in obj) {
607
+ if (obj.hasOwnProperty(i)) {
608
+ if (str.length)
609
+ str += '&';
610
+ str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
611
+ }
612
+ }
613
+ return str;
614
+ }
615
+ /**
616
+ * Parses a simple querystring into an object
617
+ *
618
+ * @param {String} qs
619
+ * @api private
620
+ */
621
+ function decode(qs) {
622
+ let qry = {};
623
+ let pairs = qs.split('&');
624
+ for (let i = 0, l = pairs.length; i < l; i++) {
625
+ let pair = pairs[i].split('=');
626
+ qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
627
+ }
628
+ return qry;
629
+ }
630
+
631
+ class TransportError extends Error {
632
+ constructor(reason, description, context) {
633
+ super(reason);
634
+ this.description = description;
635
+ this.context = context;
636
+ this.type = "TransportError";
637
+ }
638
+ }
639
+ class Transport extends Emitter {
640
+ /**
641
+ * Transport abstract constructor.
642
+ *
643
+ * @param {Object} opts - options
644
+ * @protected
645
+ */
646
+ constructor(opts) {
647
+ super();
648
+ this.writable = false;
649
+ installTimerFunctions(this, opts);
650
+ this.opts = opts;
651
+ this.query = opts.query;
652
+ this.socket = opts.socket;
653
+ }
654
+ /**
655
+ * Emits an error.
656
+ *
657
+ * @param {String} reason
658
+ * @param description
659
+ * @param context - the error context
660
+ * @return {Transport} for chaining
661
+ * @protected
662
+ */
663
+ onError(reason, description, context) {
664
+ super.emitReserved("error", new TransportError(reason, description, context));
665
+ return this;
666
+ }
667
+ /**
668
+ * Opens the transport.
669
+ */
670
+ open() {
671
+ this.readyState = "opening";
672
+ this.doOpen();
673
+ return this;
674
+ }
675
+ /**
676
+ * Closes the transport.
677
+ */
678
+ close() {
679
+ if (this.readyState === "opening" || this.readyState === "open") {
680
+ this.doClose();
681
+ this.onClose();
682
+ }
683
+ return this;
684
+ }
685
+ /**
686
+ * Sends multiple packets.
687
+ *
688
+ * @param {Array} packets
689
+ */
690
+ send(packets) {
691
+ if (this.readyState === "open") {
692
+ this.write(packets);
693
+ }
694
+ }
695
+ /**
696
+ * Called upon open
697
+ *
698
+ * @protected
699
+ */
700
+ onOpen() {
701
+ this.readyState = "open";
702
+ this.writable = true;
703
+ super.emitReserved("open");
704
+ }
705
+ /**
706
+ * Called with data.
707
+ *
708
+ * @param {String} data
709
+ * @protected
710
+ */
711
+ onData(data) {
712
+ const packet = decodePacket(data, this.socket.binaryType);
713
+ this.onPacket(packet);
714
+ }
715
+ /**
716
+ * Called with a decoded packet.
717
+ *
718
+ * @protected
719
+ */
720
+ onPacket(packet) {
721
+ super.emitReserved("packet", packet);
722
+ }
723
+ /**
724
+ * Called upon close.
725
+ *
726
+ * @protected
727
+ */
728
+ onClose(details) {
729
+ this.readyState = "closed";
730
+ super.emitReserved("close", details);
731
+ }
732
+ /**
733
+ * Pauses the transport, in order not to lose packets during an upgrade.
734
+ *
735
+ * @param onPause
736
+ */
737
+ pause(onPause) { }
738
+ createUri(schema, query = {}) {
739
+ return (schema +
740
+ "://" +
741
+ this._hostname() +
742
+ this._port() +
743
+ this.opts.path +
744
+ this._query(query));
745
+ }
746
+ _hostname() {
747
+ const hostname = this.opts.hostname;
748
+ return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
749
+ }
750
+ _port() {
751
+ if (this.opts.port &&
752
+ ((this.opts.secure && Number(this.opts.port !== 443)) ||
753
+ (!this.opts.secure && Number(this.opts.port) !== 80))) {
754
+ return ":" + this.opts.port;
755
+ }
756
+ else {
757
+ return "";
758
+ }
759
+ }
760
+ _query(query) {
761
+ const encodedQuery = encode$1(query);
762
+ return encodedQuery.length ? "?" + encodedQuery : "";
763
+ }
764
+ }
765
+
766
+ // imported from https://github.com/unshiftio/yeast
767
+ const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''), length = 64;
768
+ let seed = 0, prev;
769
+ /**
770
+ * Return a string representing the specified number.
771
+ *
772
+ * @param {Number} num The number to convert.
773
+ * @returns {String} The string representation of the number.
774
+ * @api public
775
+ */
776
+ function encode(num) {
777
+ let encoded = '';
778
+ do {
779
+ encoded = alphabet[num % length] + encoded;
780
+ num = Math.floor(num / length);
781
+ } while (num > 0);
782
+ return encoded;
783
+ }
784
+ /**
785
+ * Yeast: A tiny growing id generator.
786
+ *
787
+ * @returns {String} A unique id.
788
+ * @api public
789
+ */
790
+ function yeast() {
791
+ const now = encode(+new Date());
792
+ if (now !== prev)
793
+ return seed = 0, prev = now;
794
+ return now + '.' + encode(seed++);
795
+ }
796
+
797
+ // imported from https://github.com/component/has-cors
798
+ let value = false;
799
+ try {
800
+ value = typeof XMLHttpRequest !== 'undefined' &&
801
+ 'withCredentials' in new XMLHttpRequest();
802
+ }
803
+ catch (err) {
804
+ // if XMLHttp support is disabled in IE then it will throw
805
+ // when trying to create
806
+ }
807
+ const hasCORS = value;
808
+
809
+ // browser shim for xmlhttprequest module
810
+ function XHR(opts) {
811
+ const xdomain = opts.xdomain;
812
+ // XMLHttpRequest can be disabled on IE
813
+ try {
814
+ if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
815
+ return new XMLHttpRequest();
816
+ }
817
+ }
818
+ catch (e) { }
819
+ if (!xdomain) {
820
+ try {
821
+ return new globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
822
+ }
823
+ catch (e) { }
824
+ }
825
+ }
826
+ function createCookieJar() { }
827
+
828
+ function empty() { }
829
+ const hasXHR2 = (function () {
830
+ const xhr = new XHR({
831
+ xdomain: false,
832
+ });
833
+ return null != xhr.responseType;
834
+ })();
835
+ class Polling extends Transport {
836
+ /**
837
+ * XHR Polling constructor.
838
+ *
839
+ * @param {Object} opts
840
+ * @package
841
+ */
842
+ constructor(opts) {
843
+ super(opts);
844
+ this.polling = false;
845
+ if (typeof location !== "undefined") {
846
+ const isSSL = "https:" === location.protocol;
847
+ let port = location.port;
848
+ // some user agents have empty `location.port`
849
+ if (!port) {
850
+ port = isSSL ? "443" : "80";
851
+ }
852
+ this.xd =
853
+ (typeof location !== "undefined" &&
854
+ opts.hostname !== location.hostname) ||
855
+ port !== opts.port;
856
+ }
857
+ /**
858
+ * XHR supports binary
859
+ */
860
+ const forceBase64 = opts && opts.forceBase64;
861
+ this.supportsBinary = hasXHR2 && !forceBase64;
862
+ if (this.opts.withCredentials) {
863
+ this.cookieJar = createCookieJar();
864
+ }
865
+ }
866
+ get name() {
867
+ return "polling";
868
+ }
869
+ /**
870
+ * Opens the socket (triggers polling). We write a PING message to determine
871
+ * when the transport is open.
872
+ *
873
+ * @protected
874
+ */
875
+ doOpen() {
876
+ this.poll();
877
+ }
878
+ /**
879
+ * Pauses polling.
880
+ *
881
+ * @param {Function} onPause - callback upon buffers are flushed and transport is paused
882
+ * @package
883
+ */
884
+ pause(onPause) {
885
+ this.readyState = "pausing";
886
+ const pause = () => {
887
+ this.readyState = "paused";
888
+ onPause();
889
+ };
890
+ if (this.polling || !this.writable) {
891
+ let total = 0;
892
+ if (this.polling) {
893
+ total++;
894
+ this.once("pollComplete", function () {
895
+ --total || pause();
896
+ });
897
+ }
898
+ if (!this.writable) {
899
+ total++;
900
+ this.once("drain", function () {
901
+ --total || pause();
902
+ });
903
+ }
904
+ }
905
+ else {
906
+ pause();
907
+ }
908
+ }
909
+ /**
910
+ * Starts polling cycle.
911
+ *
912
+ * @private
913
+ */
914
+ poll() {
915
+ this.polling = true;
916
+ this.doPoll();
917
+ this.emitReserved("poll");
918
+ }
919
+ /**
920
+ * Overloads onData to detect payloads.
921
+ *
922
+ * @protected
923
+ */
924
+ onData(data) {
925
+ const callback = (packet) => {
926
+ // if its the first message we consider the transport open
927
+ if ("opening" === this.readyState && packet.type === "open") {
928
+ this.onOpen();
929
+ }
930
+ // if its a close packet, we close the ongoing requests
931
+ if ("close" === packet.type) {
932
+ this.onClose({ description: "transport closed by the server" });
933
+ return false;
934
+ }
935
+ // otherwise bypass onData and handle the message
936
+ this.onPacket(packet);
937
+ };
938
+ // decode payload
939
+ decodePayload(data, this.socket.binaryType).forEach(callback);
940
+ // if an event did not trigger closing
941
+ if ("closed" !== this.readyState) {
942
+ // if we got data we're not polling
943
+ this.polling = false;
944
+ this.emitReserved("pollComplete");
945
+ if ("open" === this.readyState) {
946
+ this.poll();
947
+ }
948
+ }
949
+ }
950
+ /**
951
+ * For polling, send a close packet.
952
+ *
953
+ * @protected
954
+ */
955
+ doClose() {
956
+ const close = () => {
957
+ this.write([{ type: "close" }]);
958
+ };
959
+ if ("open" === this.readyState) {
960
+ close();
961
+ }
962
+ else {
963
+ // in case we're trying to close while
964
+ // handshaking is in progress (GH-164)
965
+ this.once("open", close);
966
+ }
967
+ }
968
+ /**
969
+ * Writes a packets payload.
970
+ *
971
+ * @param {Array} packets - data packets
972
+ * @protected
973
+ */
974
+ write(packets) {
975
+ this.writable = false;
976
+ encodePayload(packets, (data) => {
977
+ this.doWrite(data, () => {
978
+ this.writable = true;
979
+ this.emitReserved("drain");
980
+ });
981
+ });
982
+ }
983
+ /**
984
+ * Generates uri for connection.
985
+ *
986
+ * @private
987
+ */
988
+ uri() {
989
+ const schema = this.opts.secure ? "https" : "http";
990
+ const query = this.query || {};
991
+ // cache busting is forced
992
+ if (false !== this.opts.timestampRequests) {
993
+ query[this.opts.timestampParam] = yeast();
994
+ }
995
+ if (!this.supportsBinary && !query.sid) {
996
+ query.b64 = 1;
997
+ }
998
+ return this.createUri(schema, query);
999
+ }
1000
+ /**
1001
+ * Creates a request.
1002
+ *
1003
+ * @param {String} method
1004
+ * @private
1005
+ */
1006
+ request(opts = {}) {
1007
+ Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
1008
+ return new Request(this.uri(), opts);
1009
+ }
1010
+ /**
1011
+ * Sends data.
1012
+ *
1013
+ * @param {String} data to send.
1014
+ * @param {Function} called upon flush.
1015
+ * @private
1016
+ */
1017
+ doWrite(data, fn) {
1018
+ const req = this.request({
1019
+ method: "POST",
1020
+ data: data,
1021
+ });
1022
+ req.on("success", fn);
1023
+ req.on("error", (xhrStatus, context) => {
1024
+ this.onError("xhr post error", xhrStatus, context);
1025
+ });
1026
+ }
1027
+ /**
1028
+ * Starts a poll cycle.
1029
+ *
1030
+ * @private
1031
+ */
1032
+ doPoll() {
1033
+ const req = this.request();
1034
+ req.on("data", this.onData.bind(this));
1035
+ req.on("error", (xhrStatus, context) => {
1036
+ this.onError("xhr poll error", xhrStatus, context);
1037
+ });
1038
+ this.pollXhr = req;
1039
+ }
1040
+ }
1041
+ class Request extends Emitter {
1042
+ /**
1043
+ * Request constructor
1044
+ *
1045
+ * @param {Object} options
1046
+ * @package
1047
+ */
1048
+ constructor(uri, opts) {
1049
+ super();
1050
+ installTimerFunctions(this, opts);
1051
+ this.opts = opts;
1052
+ this.method = opts.method || "GET";
1053
+ this.uri = uri;
1054
+ this.data = undefined !== opts.data ? opts.data : null;
1055
+ this.create();
1056
+ }
1057
+ /**
1058
+ * Creates the XHR object and sends the request.
1059
+ *
1060
+ * @private
1061
+ */
1062
+ create() {
1063
+ var _a;
1064
+ const opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
1065
+ opts.xdomain = !!this.opts.xd;
1066
+ const xhr = (this.xhr = new XHR(opts));
1067
+ try {
1068
+ xhr.open(this.method, this.uri, true);
1069
+ try {
1070
+ if (this.opts.extraHeaders) {
1071
+ xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
1072
+ for (let i in this.opts.extraHeaders) {
1073
+ if (this.opts.extraHeaders.hasOwnProperty(i)) {
1074
+ xhr.setRequestHeader(i, this.opts.extraHeaders[i]);
1075
+ }
1076
+ }
1077
+ }
1078
+ }
1079
+ catch (e) { }
1080
+ if ("POST" === this.method) {
1081
+ try {
1082
+ xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
1083
+ }
1084
+ catch (e) { }
1085
+ }
1086
+ try {
1087
+ xhr.setRequestHeader("Accept", "*/*");
1088
+ }
1089
+ catch (e) { }
1090
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
1091
+ // ie6 check
1092
+ if ("withCredentials" in xhr) {
1093
+ xhr.withCredentials = this.opts.withCredentials;
1094
+ }
1095
+ if (this.opts.requestTimeout) {
1096
+ xhr.timeout = this.opts.requestTimeout;
1097
+ }
1098
+ xhr.onreadystatechange = () => {
1099
+ var _a;
1100
+ if (xhr.readyState === 3) {
1101
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
1102
+ }
1103
+ if (4 !== xhr.readyState)
1104
+ return;
1105
+ if (200 === xhr.status || 1223 === xhr.status) {
1106
+ this.onLoad();
1107
+ }
1108
+ else {
1109
+ // make sure the `error` event handler that's user-set
1110
+ // does not throw in the same tick and gets caught here
1111
+ this.setTimeoutFn(() => {
1112
+ this.onError(typeof xhr.status === "number" ? xhr.status : 0);
1113
+ }, 0);
1114
+ }
1115
+ };
1116
+ xhr.send(this.data);
1117
+ }
1118
+ catch (e) {
1119
+ // Need to defer since .create() is called directly from the constructor
1120
+ // and thus the 'error' event can only be only bound *after* this exception
1121
+ // occurs. Therefore, also, we cannot throw here at all.
1122
+ this.setTimeoutFn(() => {
1123
+ this.onError(e);
1124
+ }, 0);
1125
+ return;
1126
+ }
1127
+ if (typeof document !== "undefined") {
1128
+ this.index = Request.requestsCount++;
1129
+ Request.requests[this.index] = this;
1130
+ }
1131
+ }
1132
+ /**
1133
+ * Called upon error.
1134
+ *
1135
+ * @private
1136
+ */
1137
+ onError(err) {
1138
+ this.emitReserved("error", err, this.xhr);
1139
+ this.cleanup(true);
1140
+ }
1141
+ /**
1142
+ * Cleans up house.
1143
+ *
1144
+ * @private
1145
+ */
1146
+ cleanup(fromError) {
1147
+ if ("undefined" === typeof this.xhr || null === this.xhr) {
1148
+ return;
1149
+ }
1150
+ this.xhr.onreadystatechange = empty;
1151
+ if (fromError) {
1152
+ try {
1153
+ this.xhr.abort();
1154
+ }
1155
+ catch (e) { }
1156
+ }
1157
+ if (typeof document !== "undefined") {
1158
+ delete Request.requests[this.index];
1159
+ }
1160
+ this.xhr = null;
1161
+ }
1162
+ /**
1163
+ * Called upon load.
1164
+ *
1165
+ * @private
1166
+ */
1167
+ onLoad() {
1168
+ const data = this.xhr.responseText;
1169
+ if (data !== null) {
1170
+ this.emitReserved("data", data);
1171
+ this.emitReserved("success");
1172
+ this.cleanup();
1173
+ }
1174
+ }
1175
+ /**
1176
+ * Aborts the request.
1177
+ *
1178
+ * @package
1179
+ */
1180
+ abort() {
1181
+ this.cleanup();
1182
+ }
1183
+ }
1184
+ Request.requestsCount = 0;
1185
+ Request.requests = {};
1186
+ /**
1187
+ * Aborts pending requests when unloading the window. This is needed to prevent
1188
+ * memory leaks (e.g. when using IE) and to ensure that no spurious error is
1189
+ * emitted.
1190
+ */
1191
+ if (typeof document !== "undefined") {
1192
+ // @ts-ignore
1193
+ if (typeof attachEvent === "function") {
1194
+ // @ts-ignore
1195
+ attachEvent("onunload", unloadHandler);
1196
+ }
1197
+ else if (typeof addEventListener === "function") {
1198
+ const terminationEvent = "onpagehide" in globalThisShim ? "pagehide" : "unload";
1199
+ addEventListener(terminationEvent, unloadHandler, false);
1200
+ }
1201
+ }
1202
+ function unloadHandler() {
1203
+ for (let i in Request.requests) {
1204
+ if (Request.requests.hasOwnProperty(i)) {
1205
+ Request.requests[i].abort();
1206
+ }
1207
+ }
1208
+ }
1209
+
1210
+ const nextTick = (() => {
1211
+ const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
1212
+ if (isPromiseAvailable) {
1213
+ return (cb) => Promise.resolve().then(cb);
1214
+ }
1215
+ else {
1216
+ return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
1217
+ }
1218
+ })();
1219
+ const WebSocket = globalThisShim.WebSocket || globalThisShim.MozWebSocket;
1220
+ const defaultBinaryType = "arraybuffer";
1221
+
1222
+ // detect ReactNative environment
1223
+ const isReactNative = typeof navigator !== "undefined" &&
1224
+ typeof navigator.product === "string" &&
1225
+ navigator.product.toLowerCase() === "reactnative";
1226
+ class WS extends Transport {
1227
+ /**
1228
+ * WebSocket transport constructor.
1229
+ *
1230
+ * @param {Object} opts - connection options
1231
+ * @protected
1232
+ */
1233
+ constructor(opts) {
1234
+ super(opts);
1235
+ this.supportsBinary = !opts.forceBase64;
1236
+ }
1237
+ get name() {
1238
+ return "websocket";
1239
+ }
1240
+ doOpen() {
1241
+ if (!this.check()) {
1242
+ // let probe timeout
1243
+ return;
1244
+ }
1245
+ const uri = this.uri();
1246
+ const protocols = this.opts.protocols;
1247
+ // React Native only supports the 'headers' option, and will print a warning if anything else is passed
1248
+ const opts = isReactNative
1249
+ ? {}
1250
+ : pick(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity");
1251
+ if (this.opts.extraHeaders) {
1252
+ opts.headers = this.opts.extraHeaders;
1253
+ }
1254
+ try {
1255
+ this.ws =
1256
+ !isReactNative
1257
+ ? protocols
1258
+ ? new WebSocket(uri, protocols)
1259
+ : new WebSocket(uri)
1260
+ : new WebSocket(uri, protocols, opts);
1261
+ }
1262
+ catch (err) {
1263
+ return this.emitReserved("error", err);
1264
+ }
1265
+ this.ws.binaryType = this.socket.binaryType;
1266
+ this.addEventListeners();
1267
+ }
1268
+ /**
1269
+ * Adds event listeners to the socket
1270
+ *
1271
+ * @private
1272
+ */
1273
+ addEventListeners() {
1274
+ this.ws.onopen = () => {
1275
+ if (this.opts.autoUnref) {
1276
+ this.ws._socket.unref();
1277
+ }
1278
+ this.onOpen();
1279
+ };
1280
+ this.ws.onclose = (closeEvent) => this.onClose({
1281
+ description: "websocket connection closed",
1282
+ context: closeEvent,
1283
+ });
1284
+ this.ws.onmessage = (ev) => this.onData(ev.data);
1285
+ this.ws.onerror = (e) => this.onError("websocket error", e);
1286
+ }
1287
+ write(packets) {
1288
+ this.writable = false;
1289
+ // encodePacket efficient as it uses WS framing
1290
+ // no need for encodePayload
1291
+ for (let i = 0; i < packets.length; i++) {
1292
+ const packet = packets[i];
1293
+ const lastPacket = i === packets.length - 1;
1294
+ encodePacket(packet, this.supportsBinary, (data) => {
1295
+ // Sometimes the websocket has already been closed but the browser didn't
1296
+ // have a chance of informing us about it yet, in that case send will
1297
+ // throw an error
1298
+ try {
1299
+ {
1300
+ // TypeError is thrown when passing the second argument on Safari
1301
+ this.ws.send(data);
1302
+ }
1303
+ }
1304
+ catch (e) {
1305
+ }
1306
+ if (lastPacket) {
1307
+ // fake drain
1308
+ // defer to next tick to allow Socket to clear writeBuffer
1309
+ nextTick(() => {
1310
+ this.writable = true;
1311
+ this.emitReserved("drain");
1312
+ }, this.setTimeoutFn);
1313
+ }
1314
+ });
1315
+ }
1316
+ }
1317
+ doClose() {
1318
+ if (typeof this.ws !== "undefined") {
1319
+ this.ws.close();
1320
+ this.ws = null;
1321
+ }
1322
+ }
1323
+ /**
1324
+ * Generates uri for connection.
1325
+ *
1326
+ * @private
1327
+ */
1328
+ uri() {
1329
+ const schema = this.opts.secure ? "wss" : "ws";
1330
+ const query = this.query || {};
1331
+ // append timestamp to URI
1332
+ if (this.opts.timestampRequests) {
1333
+ query[this.opts.timestampParam] = yeast();
1334
+ }
1335
+ // communicate binary support capabilities
1336
+ if (!this.supportsBinary) {
1337
+ query.b64 = 1;
1338
+ }
1339
+ return this.createUri(schema, query);
1340
+ }
1341
+ /**
1342
+ * Feature detection for WebSocket.
1343
+ *
1344
+ * @return {Boolean} whether this transport is available.
1345
+ * @private
1346
+ */
1347
+ check() {
1348
+ return !!WebSocket;
1349
+ }
1350
+ }
1351
+
1352
+ class WT extends Transport {
1353
+ get name() {
1354
+ return "webtransport";
1355
+ }
1356
+ doOpen() {
1357
+ // @ts-ignore
1358
+ if (typeof WebTransport !== "function") {
1359
+ return;
1360
+ }
1361
+ // @ts-ignore
1362
+ this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
1363
+ this.transport.closed
1364
+ .then(() => {
1365
+ this.onClose();
1366
+ })
1367
+ .catch((err) => {
1368
+ this.onError("webtransport error", err);
1369
+ });
1370
+ // note: we could have used async/await, but that would require some additional polyfills
1371
+ this.transport.ready.then(() => {
1372
+ this.transport.createBidirectionalStream().then((stream) => {
1373
+ const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
1374
+ const reader = stream.readable.pipeThrough(decoderStream).getReader();
1375
+ const encoderStream = createPacketEncoderStream();
1376
+ encoderStream.readable.pipeTo(stream.writable);
1377
+ this.writer = encoderStream.writable.getWriter();
1378
+ const read = () => {
1379
+ reader
1380
+ .read()
1381
+ .then(({ done, value }) => {
1382
+ if (done) {
1383
+ return;
1384
+ }
1385
+ this.onPacket(value);
1386
+ read();
1387
+ })
1388
+ .catch((err) => {
1389
+ });
1390
+ };
1391
+ read();
1392
+ const packet = { type: "open" };
1393
+ if (this.query.sid) {
1394
+ packet.data = `{"sid":"${this.query.sid}"}`;
1395
+ }
1396
+ this.writer.write(packet).then(() => this.onOpen());
1397
+ });
1398
+ });
1399
+ }
1400
+ write(packets) {
1401
+ this.writable = false;
1402
+ for (let i = 0; i < packets.length; i++) {
1403
+ const packet = packets[i];
1404
+ const lastPacket = i === packets.length - 1;
1405
+ this.writer.write(packet).then(() => {
1406
+ if (lastPacket) {
1407
+ nextTick(() => {
1408
+ this.writable = true;
1409
+ this.emitReserved("drain");
1410
+ }, this.setTimeoutFn);
1411
+ }
1412
+ });
1413
+ }
1414
+ }
1415
+ doClose() {
1416
+ var _a;
1417
+ (_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
1418
+ }
1419
+ }
1420
+
1421
+ const transports = {
1422
+ websocket: WS,
1423
+ webtransport: WT,
1424
+ polling: Polling,
1425
+ };
1426
+
1427
+ // imported from https://github.com/galkn/parseuri
1428
+ /**
1429
+ * Parses a URI
1430
+ *
1431
+ * Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
1432
+ *
1433
+ * See:
1434
+ * - https://developer.mozilla.org/en-US/docs/Web/API/URL
1435
+ * - https://caniuse.com/url
1436
+ * - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
1437
+ *
1438
+ * History of the parse() method:
1439
+ * - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
1440
+ * - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
1441
+ * - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
1442
+ *
1443
+ * @author Steven Levithan <stevenlevithan.com> (MIT license)
1444
+ * @api private
1445
+ */
1446
+ const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
1447
+ const parts = [
1448
+ 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
1449
+ ];
1450
+ function parse(str) {
1451
+ if (str.length > 2000) {
1452
+ throw "URI too long";
1453
+ }
1454
+ const src = str, b = str.indexOf('['), e = str.indexOf(']');
1455
+ if (b != -1 && e != -1) {
1456
+ str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
1457
+ }
1458
+ let m = re.exec(str || ''), uri = {}, i = 14;
1459
+ while (i--) {
1460
+ uri[parts[i]] = m[i] || '';
1461
+ }
1462
+ if (b != -1 && e != -1) {
1463
+ uri.source = src;
1464
+ uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
1465
+ uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
1466
+ uri.ipv6uri = true;
1467
+ }
1468
+ uri.pathNames = pathNames(uri, uri['path']);
1469
+ uri.queryKey = queryKey(uri, uri['query']);
1470
+ return uri;
1471
+ }
1472
+ function pathNames(obj, path) {
1473
+ const regx = /\/{2,9}/g, names = path.replace(regx, "/").split("/");
1474
+ if (path.slice(0, 1) == '/' || path.length === 0) {
1475
+ names.splice(0, 1);
1476
+ }
1477
+ if (path.slice(-1) == '/') {
1478
+ names.splice(names.length - 1, 1);
1479
+ }
1480
+ return names;
1481
+ }
1482
+ function queryKey(uri, query) {
1483
+ const data = {};
1484
+ query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
1485
+ if ($1) {
1486
+ data[$1] = $2;
1487
+ }
1488
+ });
1489
+ return data;
1490
+ }
1491
+
1492
+ class Socket$1 extends Emitter {
1493
+ /**
1494
+ * Socket constructor.
1495
+ *
1496
+ * @param {String|Object} uri - uri or options
1497
+ * @param {Object} opts - options
1498
+ */
1499
+ constructor(uri, opts = {}) {
1500
+ super();
1501
+ this.binaryType = defaultBinaryType;
1502
+ this.writeBuffer = [];
1503
+ if (uri && "object" === typeof uri) {
1504
+ opts = uri;
1505
+ uri = null;
1506
+ }
1507
+ if (uri) {
1508
+ uri = parse(uri);
1509
+ opts.hostname = uri.host;
1510
+ opts.secure = uri.protocol === "https" || uri.protocol === "wss";
1511
+ opts.port = uri.port;
1512
+ if (uri.query)
1513
+ opts.query = uri.query;
1514
+ }
1515
+ else if (opts.host) {
1516
+ opts.hostname = parse(opts.host).host;
1517
+ }
1518
+ installTimerFunctions(this, opts);
1519
+ this.secure =
1520
+ null != opts.secure
1521
+ ? opts.secure
1522
+ : typeof location !== "undefined" && "https:" === location.protocol;
1523
+ if (opts.hostname && !opts.port) {
1524
+ // if no port is specified manually, use the protocol default
1525
+ opts.port = this.secure ? "443" : "80";
1526
+ }
1527
+ this.hostname =
1528
+ opts.hostname ||
1529
+ (typeof location !== "undefined" ? location.hostname : "localhost");
1530
+ this.port =
1531
+ opts.port ||
1532
+ (typeof location !== "undefined" && location.port
1533
+ ? location.port
1534
+ : this.secure
1535
+ ? "443"
1536
+ : "80");
1537
+ this.transports = opts.transports || [
1538
+ "polling",
1539
+ "websocket",
1540
+ "webtransport",
1541
+ ];
1542
+ this.writeBuffer = [];
1543
+ this.prevBufferLen = 0;
1544
+ this.opts = Object.assign({
1545
+ path: "/engine.io",
1546
+ agent: false,
1547
+ withCredentials: false,
1548
+ upgrade: true,
1549
+ timestampParam: "t",
1550
+ rememberUpgrade: false,
1551
+ addTrailingSlash: true,
1552
+ rejectUnauthorized: true,
1553
+ perMessageDeflate: {
1554
+ threshold: 1024,
1555
+ },
1556
+ transportOptions: {},
1557
+ closeOnBeforeunload: false,
1558
+ }, opts);
1559
+ this.opts.path =
1560
+ this.opts.path.replace(/\/$/, "") +
1561
+ (this.opts.addTrailingSlash ? "/" : "");
1562
+ if (typeof this.opts.query === "string") {
1563
+ this.opts.query = decode(this.opts.query);
1564
+ }
1565
+ // set on handshake
1566
+ this.id = null;
1567
+ this.upgrades = null;
1568
+ this.pingInterval = null;
1569
+ this.pingTimeout = null;
1570
+ // set on heartbeat
1571
+ this.pingTimeoutTimer = null;
1572
+ if (typeof addEventListener === "function") {
1573
+ if (this.opts.closeOnBeforeunload) {
1574
+ // Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
1575
+ // ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
1576
+ // closed/reloaded)
1577
+ this.beforeunloadEventListener = () => {
1578
+ if (this.transport) {
1579
+ // silently close the transport
1580
+ this.transport.removeAllListeners();
1581
+ this.transport.close();
1582
+ }
1583
+ };
1584
+ addEventListener("beforeunload", this.beforeunloadEventListener, false);
1585
+ }
1586
+ if (this.hostname !== "localhost") {
1587
+ this.offlineEventListener = () => {
1588
+ this.onClose("transport close", {
1589
+ description: "network connection lost",
1590
+ });
1591
+ };
1592
+ addEventListener("offline", this.offlineEventListener, false);
1593
+ }
1594
+ }
1595
+ this.open();
1596
+ }
1597
+ /**
1598
+ * Creates transport of the given type.
1599
+ *
1600
+ * @param {String} name - transport name
1601
+ * @return {Transport}
1602
+ * @private
1603
+ */
1604
+ createTransport(name) {
1605
+ const query = Object.assign({}, this.opts.query);
1606
+ // append engine.io protocol identifier
1607
+ query.EIO = protocol$1;
1608
+ // transport name
1609
+ query.transport = name;
1610
+ // session id if we already have one
1611
+ if (this.id)
1612
+ query.sid = this.id;
1613
+ const opts = Object.assign({}, this.opts, {
1614
+ query,
1615
+ socket: this,
1616
+ hostname: this.hostname,
1617
+ secure: this.secure,
1618
+ port: this.port,
1619
+ }, this.opts.transportOptions[name]);
1620
+ return new transports[name](opts);
1621
+ }
1622
+ /**
1623
+ * Initializes transport to use and starts probe.
1624
+ *
1625
+ * @private
1626
+ */
1627
+ open() {
1628
+ let transport;
1629
+ if (this.opts.rememberUpgrade &&
1630
+ Socket$1.priorWebsocketSuccess &&
1631
+ this.transports.indexOf("websocket") !== -1) {
1632
+ transport = "websocket";
1633
+ }
1634
+ else if (0 === this.transports.length) {
1635
+ // Emit error on next tick so it can be listened to
1636
+ this.setTimeoutFn(() => {
1637
+ this.emitReserved("error", "No transports available");
1638
+ }, 0);
1639
+ return;
1640
+ }
1641
+ else {
1642
+ transport = this.transports[0];
1643
+ }
1644
+ this.readyState = "opening";
1645
+ // Retry with the next transport if the transport is disabled (jsonp: false)
1646
+ try {
1647
+ transport = this.createTransport(transport);
1648
+ }
1649
+ catch (e) {
1650
+ this.transports.shift();
1651
+ this.open();
1652
+ return;
1653
+ }
1654
+ transport.open();
1655
+ this.setTransport(transport);
1656
+ }
1657
+ /**
1658
+ * Sets the current transport. Disables the existing one (if any).
1659
+ *
1660
+ * @private
1661
+ */
1662
+ setTransport(transport) {
1663
+ if (this.transport) {
1664
+ this.transport.removeAllListeners();
1665
+ }
1666
+ // set up transport
1667
+ this.transport = transport;
1668
+ // set up transport listeners
1669
+ transport
1670
+ .on("drain", this.onDrain.bind(this))
1671
+ .on("packet", this.onPacket.bind(this))
1672
+ .on("error", this.onError.bind(this))
1673
+ .on("close", (reason) => this.onClose("transport close", reason));
1674
+ }
1675
+ /**
1676
+ * Probes a transport.
1677
+ *
1678
+ * @param {String} name - transport name
1679
+ * @private
1680
+ */
1681
+ probe(name) {
1682
+ let transport = this.createTransport(name);
1683
+ let failed = false;
1684
+ Socket$1.priorWebsocketSuccess = false;
1685
+ const onTransportOpen = () => {
1686
+ if (failed)
1687
+ return;
1688
+ transport.send([{ type: "ping", data: "probe" }]);
1689
+ transport.once("packet", (msg) => {
1690
+ if (failed)
1691
+ return;
1692
+ if ("pong" === msg.type && "probe" === msg.data) {
1693
+ this.upgrading = true;
1694
+ this.emitReserved("upgrading", transport);
1695
+ if (!transport)
1696
+ return;
1697
+ Socket$1.priorWebsocketSuccess = "websocket" === transport.name;
1698
+ this.transport.pause(() => {
1699
+ if (failed)
1700
+ return;
1701
+ if ("closed" === this.readyState)
1702
+ return;
1703
+ cleanup();
1704
+ this.setTransport(transport);
1705
+ transport.send([{ type: "upgrade" }]);
1706
+ this.emitReserved("upgrade", transport);
1707
+ transport = null;
1708
+ this.upgrading = false;
1709
+ this.flush();
1710
+ });
1711
+ }
1712
+ else {
1713
+ const err = new Error("probe error");
1714
+ // @ts-ignore
1715
+ err.transport = transport.name;
1716
+ this.emitReserved("upgradeError", err);
1717
+ }
1718
+ });
1719
+ };
1720
+ function freezeTransport() {
1721
+ if (failed)
1722
+ return;
1723
+ // Any callback called by transport should be ignored since now
1724
+ failed = true;
1725
+ cleanup();
1726
+ transport.close();
1727
+ transport = null;
1728
+ }
1729
+ // Handle any error that happens while probing
1730
+ const onerror = (err) => {
1731
+ const error = new Error("probe error: " + err);
1732
+ // @ts-ignore
1733
+ error.transport = transport.name;
1734
+ freezeTransport();
1735
+ this.emitReserved("upgradeError", error);
1736
+ };
1737
+ function onTransportClose() {
1738
+ onerror("transport closed");
1739
+ }
1740
+ // When the socket is closed while we're probing
1741
+ function onclose() {
1742
+ onerror("socket closed");
1743
+ }
1744
+ // When the socket is upgraded while we're probing
1745
+ function onupgrade(to) {
1746
+ if (transport && to.name !== transport.name) {
1747
+ freezeTransport();
1748
+ }
1749
+ }
1750
+ // Remove all listeners on the transport and on self
1751
+ const cleanup = () => {
1752
+ transport.removeListener("open", onTransportOpen);
1753
+ transport.removeListener("error", onerror);
1754
+ transport.removeListener("close", onTransportClose);
1755
+ this.off("close", onclose);
1756
+ this.off("upgrading", onupgrade);
1757
+ };
1758
+ transport.once("open", onTransportOpen);
1759
+ transport.once("error", onerror);
1760
+ transport.once("close", onTransportClose);
1761
+ this.once("close", onclose);
1762
+ this.once("upgrading", onupgrade);
1763
+ if (this.upgrades.indexOf("webtransport") !== -1 &&
1764
+ name !== "webtransport") {
1765
+ // favor WebTransport
1766
+ this.setTimeoutFn(() => {
1767
+ if (!failed) {
1768
+ transport.open();
1769
+ }
1770
+ }, 200);
1771
+ }
1772
+ else {
1773
+ transport.open();
1774
+ }
1775
+ }
1776
+ /**
1777
+ * Called when connection is deemed open.
1778
+ *
1779
+ * @private
1780
+ */
1781
+ onOpen() {
1782
+ this.readyState = "open";
1783
+ Socket$1.priorWebsocketSuccess = "websocket" === this.transport.name;
1784
+ this.emitReserved("open");
1785
+ this.flush();
1786
+ // we check for `readyState` in case an `open`
1787
+ // listener already closed the socket
1788
+ if ("open" === this.readyState && this.opts.upgrade) {
1789
+ let i = 0;
1790
+ const l = this.upgrades.length;
1791
+ for (; i < l; i++) {
1792
+ this.probe(this.upgrades[i]);
1793
+ }
1794
+ }
1795
+ }
1796
+ /**
1797
+ * Handles a packet.
1798
+ *
1799
+ * @private
1800
+ */
1801
+ onPacket(packet) {
1802
+ if ("opening" === this.readyState ||
1803
+ "open" === this.readyState ||
1804
+ "closing" === this.readyState) {
1805
+ this.emitReserved("packet", packet);
1806
+ // Socket is live - any packet counts
1807
+ this.emitReserved("heartbeat");
1808
+ this.resetPingTimeout();
1809
+ switch (packet.type) {
1810
+ case "open":
1811
+ this.onHandshake(JSON.parse(packet.data));
1812
+ break;
1813
+ case "ping":
1814
+ this.sendPacket("pong");
1815
+ this.emitReserved("ping");
1816
+ this.emitReserved("pong");
1817
+ break;
1818
+ case "error":
1819
+ const err = new Error("server error");
1820
+ // @ts-ignore
1821
+ err.code = packet.data;
1822
+ this.onError(err);
1823
+ break;
1824
+ case "message":
1825
+ this.emitReserved("data", packet.data);
1826
+ this.emitReserved("message", packet.data);
1827
+ break;
1828
+ }
1829
+ }
1830
+ }
1831
+ /**
1832
+ * Called upon handshake completion.
1833
+ *
1834
+ * @param {Object} data - handshake obj
1835
+ * @private
1836
+ */
1837
+ onHandshake(data) {
1838
+ this.emitReserved("handshake", data);
1839
+ this.id = data.sid;
1840
+ this.transport.query.sid = data.sid;
1841
+ this.upgrades = this.filterUpgrades(data.upgrades);
1842
+ this.pingInterval = data.pingInterval;
1843
+ this.pingTimeout = data.pingTimeout;
1844
+ this.maxPayload = data.maxPayload;
1845
+ this.onOpen();
1846
+ // In case open handler closes socket
1847
+ if ("closed" === this.readyState)
1848
+ return;
1849
+ this.resetPingTimeout();
1850
+ }
1851
+ /**
1852
+ * Sets and resets ping timeout timer based on server pings.
1853
+ *
1854
+ * @private
1855
+ */
1856
+ resetPingTimeout() {
1857
+ this.clearTimeoutFn(this.pingTimeoutTimer);
1858
+ this.pingTimeoutTimer = this.setTimeoutFn(() => {
1859
+ this.onClose("ping timeout");
1860
+ }, this.pingInterval + this.pingTimeout);
1861
+ if (this.opts.autoUnref) {
1862
+ this.pingTimeoutTimer.unref();
1863
+ }
1864
+ }
1865
+ /**
1866
+ * Called on `drain` event
1867
+ *
1868
+ * @private
1869
+ */
1870
+ onDrain() {
1871
+ this.writeBuffer.splice(0, this.prevBufferLen);
1872
+ // setting prevBufferLen = 0 is very important
1873
+ // for example, when upgrading, upgrade packet is sent over,
1874
+ // and a nonzero prevBufferLen could cause problems on `drain`
1875
+ this.prevBufferLen = 0;
1876
+ if (0 === this.writeBuffer.length) {
1877
+ this.emitReserved("drain");
1878
+ }
1879
+ else {
1880
+ this.flush();
1881
+ }
1882
+ }
1883
+ /**
1884
+ * Flush write buffers.
1885
+ *
1886
+ * @private
1887
+ */
1888
+ flush() {
1889
+ if ("closed" !== this.readyState &&
1890
+ this.transport.writable &&
1891
+ !this.upgrading &&
1892
+ this.writeBuffer.length) {
1893
+ const packets = this.getWritablePackets();
1894
+ this.transport.send(packets);
1895
+ // keep track of current length of writeBuffer
1896
+ // splice writeBuffer and callbackBuffer on `drain`
1897
+ this.prevBufferLen = packets.length;
1898
+ this.emitReserved("flush");
1899
+ }
1900
+ }
1901
+ /**
1902
+ * Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
1903
+ * long-polling)
1904
+ *
1905
+ * @private
1906
+ */
1907
+ getWritablePackets() {
1908
+ const shouldCheckPayloadSize = this.maxPayload &&
1909
+ this.transport.name === "polling" &&
1910
+ this.writeBuffer.length > 1;
1911
+ if (!shouldCheckPayloadSize) {
1912
+ return this.writeBuffer;
1913
+ }
1914
+ let payloadSize = 1; // first packet type
1915
+ for (let i = 0; i < this.writeBuffer.length; i++) {
1916
+ const data = this.writeBuffer[i].data;
1917
+ if (data) {
1918
+ payloadSize += byteLength(data);
1919
+ }
1920
+ if (i > 0 && payloadSize > this.maxPayload) {
1921
+ return this.writeBuffer.slice(0, i);
1922
+ }
1923
+ payloadSize += 2; // separator + packet type
1924
+ }
1925
+ return this.writeBuffer;
1926
+ }
1927
+ /**
1928
+ * Sends a message.
1929
+ *
1930
+ * @param {String} msg - message.
1931
+ * @param {Object} options.
1932
+ * @param {Function} callback function.
1933
+ * @return {Socket} for chaining.
1934
+ */
1935
+ write(msg, options, fn) {
1936
+ this.sendPacket("message", msg, options, fn);
1937
+ return this;
1938
+ }
1939
+ send(msg, options, fn) {
1940
+ this.sendPacket("message", msg, options, fn);
1941
+ return this;
1942
+ }
1943
+ /**
1944
+ * Sends a packet.
1945
+ *
1946
+ * @param {String} type: packet type.
1947
+ * @param {String} data.
1948
+ * @param {Object} options.
1949
+ * @param {Function} fn - callback function.
1950
+ * @private
1951
+ */
1952
+ sendPacket(type, data, options, fn) {
1953
+ if ("function" === typeof data) {
1954
+ fn = data;
1955
+ data = undefined;
1956
+ }
1957
+ if ("function" === typeof options) {
1958
+ fn = options;
1959
+ options = null;
1960
+ }
1961
+ if ("closing" === this.readyState || "closed" === this.readyState) {
1962
+ return;
1963
+ }
1964
+ options = options || {};
1965
+ options.compress = false !== options.compress;
1966
+ const packet = {
1967
+ type: type,
1968
+ data: data,
1969
+ options: options,
1970
+ };
1971
+ this.emitReserved("packetCreate", packet);
1972
+ this.writeBuffer.push(packet);
1973
+ if (fn)
1974
+ this.once("flush", fn);
1975
+ this.flush();
1976
+ }
1977
+ /**
1978
+ * Closes the connection.
1979
+ */
1980
+ close() {
1981
+ const close = () => {
1982
+ this.onClose("forced close");
1983
+ this.transport.close();
1984
+ };
1985
+ const cleanupAndClose = () => {
1986
+ this.off("upgrade", cleanupAndClose);
1987
+ this.off("upgradeError", cleanupAndClose);
1988
+ close();
1989
+ };
1990
+ const waitForUpgrade = () => {
1991
+ // wait for upgrade to finish since we can't send packets while pausing a transport
1992
+ this.once("upgrade", cleanupAndClose);
1993
+ this.once("upgradeError", cleanupAndClose);
1994
+ };
1995
+ if ("opening" === this.readyState || "open" === this.readyState) {
1996
+ this.readyState = "closing";
1997
+ if (this.writeBuffer.length) {
1998
+ this.once("drain", () => {
1999
+ if (this.upgrading) {
2000
+ waitForUpgrade();
2001
+ }
2002
+ else {
2003
+ close();
2004
+ }
2005
+ });
2006
+ }
2007
+ else if (this.upgrading) {
2008
+ waitForUpgrade();
2009
+ }
2010
+ else {
2011
+ close();
2012
+ }
2013
+ }
2014
+ return this;
2015
+ }
2016
+ /**
2017
+ * Called upon transport error
2018
+ *
2019
+ * @private
2020
+ */
2021
+ onError(err) {
2022
+ Socket$1.priorWebsocketSuccess = false;
2023
+ this.emitReserved("error", err);
2024
+ this.onClose("transport error", err);
2025
+ }
2026
+ /**
2027
+ * Called upon transport close.
2028
+ *
2029
+ * @private
2030
+ */
2031
+ onClose(reason, description) {
2032
+ if ("opening" === this.readyState ||
2033
+ "open" === this.readyState ||
2034
+ "closing" === this.readyState) {
2035
+ // clear timers
2036
+ this.clearTimeoutFn(this.pingTimeoutTimer);
2037
+ // stop event from firing again for transport
2038
+ this.transport.removeAllListeners("close");
2039
+ // ensure transport won't stay open
2040
+ this.transport.close();
2041
+ // ignore further transport communication
2042
+ this.transport.removeAllListeners();
2043
+ if (typeof removeEventListener === "function") {
2044
+ removeEventListener("beforeunload", this.beforeunloadEventListener, false);
2045
+ removeEventListener("offline", this.offlineEventListener, false);
2046
+ }
2047
+ // set ready state
2048
+ this.readyState = "closed";
2049
+ // clear session id
2050
+ this.id = null;
2051
+ // emit close event
2052
+ this.emitReserved("close", reason, description);
2053
+ // clean buffers after, so users can still
2054
+ // grab the buffers on `close` event
2055
+ this.writeBuffer = [];
2056
+ this.prevBufferLen = 0;
2057
+ }
2058
+ }
2059
+ /**
2060
+ * Filters upgrades, returning only those matching client transports.
2061
+ *
2062
+ * @param {Array} upgrades - server upgrades
2063
+ * @private
2064
+ */
2065
+ filterUpgrades(upgrades) {
2066
+ const filteredUpgrades = [];
2067
+ let i = 0;
2068
+ const j = upgrades.length;
2069
+ for (; i < j; i++) {
2070
+ if (~this.transports.indexOf(upgrades[i]))
2071
+ filteredUpgrades.push(upgrades[i]);
2072
+ }
2073
+ return filteredUpgrades;
2074
+ }
2075
+ }
2076
+ Socket$1.protocol = protocol$1;
2077
+
2078
+ /**
2079
+ * URL parser.
2080
+ *
2081
+ * @param uri - url
2082
+ * @param path - the request path of the connection
2083
+ * @param loc - An object meant to mimic window.location.
2084
+ * Defaults to window.location.
2085
+ * @public
2086
+ */
2087
+ function url(uri, path = "", loc) {
2088
+ let obj = uri;
2089
+ // default to window.location
2090
+ loc = loc || (typeof location !== "undefined" && location);
2091
+ if (null == uri)
2092
+ uri = loc.protocol + "//" + loc.host;
2093
+ // relative path support
2094
+ if (typeof uri === "string") {
2095
+ if ("/" === uri.charAt(0)) {
2096
+ if ("/" === uri.charAt(1)) {
2097
+ uri = loc.protocol + uri;
2098
+ }
2099
+ else {
2100
+ uri = loc.host + uri;
2101
+ }
2102
+ }
2103
+ if (!/^(https?|wss?):\/\//.test(uri)) {
2104
+ if ("undefined" !== typeof loc) {
2105
+ uri = loc.protocol + "//" + uri;
2106
+ }
2107
+ else {
2108
+ uri = "https://" + uri;
2109
+ }
2110
+ }
2111
+ // parse
2112
+ obj = parse(uri);
2113
+ }
2114
+ // make sure we treat `localhost:80` and `localhost` equally
2115
+ if (!obj.port) {
2116
+ if (/^(http|ws)$/.test(obj.protocol)) {
2117
+ obj.port = "80";
2118
+ }
2119
+ else if (/^(http|ws)s$/.test(obj.protocol)) {
2120
+ obj.port = "443";
2121
+ }
2122
+ }
2123
+ obj.path = obj.path || "/";
2124
+ const ipv6 = obj.host.indexOf(":") !== -1;
2125
+ const host = ipv6 ? "[" + obj.host + "]" : obj.host;
2126
+ // define unique id
2127
+ obj.id = obj.protocol + "://" + host + ":" + obj.port + path;
2128
+ // define href
2129
+ obj.href =
2130
+ obj.protocol +
2131
+ "://" +
2132
+ host +
2133
+ (loc && loc.port === obj.port ? "" : ":" + obj.port);
2134
+ return obj;
2135
+ }
2136
+
2137
+ const withNativeArrayBuffer = typeof ArrayBuffer === "function";
2138
+ const isView = (obj) => {
2139
+ return typeof ArrayBuffer.isView === "function"
2140
+ ? ArrayBuffer.isView(obj)
2141
+ : obj.buffer instanceof ArrayBuffer;
2142
+ };
2143
+ const toString = Object.prototype.toString;
2144
+ const withNativeBlob = typeof Blob === "function" ||
2145
+ (typeof Blob !== "undefined" &&
2146
+ toString.call(Blob) === "[object BlobConstructor]");
2147
+ const withNativeFile = typeof File === "function" ||
2148
+ (typeof File !== "undefined" &&
2149
+ toString.call(File) === "[object FileConstructor]");
2150
+ /**
2151
+ * Returns true if obj is a Buffer, an ArrayBuffer, a Blob or a File.
2152
+ *
2153
+ * @private
2154
+ */
2155
+ function isBinary(obj) {
2156
+ return ((withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj))) ||
2157
+ (withNativeBlob && obj instanceof Blob) ||
2158
+ (withNativeFile && obj instanceof File));
2159
+ }
2160
+ function hasBinary(obj, toJSON) {
2161
+ if (!obj || typeof obj !== "object") {
2162
+ return false;
2163
+ }
2164
+ if (Array.isArray(obj)) {
2165
+ for (let i = 0, l = obj.length; i < l; i++) {
2166
+ if (hasBinary(obj[i])) {
2167
+ return true;
2168
+ }
2169
+ }
2170
+ return false;
2171
+ }
2172
+ if (isBinary(obj)) {
2173
+ return true;
2174
+ }
2175
+ if (obj.toJSON &&
2176
+ typeof obj.toJSON === "function" &&
2177
+ arguments.length === 1) {
2178
+ return hasBinary(obj.toJSON(), true);
2179
+ }
2180
+ for (const key in obj) {
2181
+ if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
2182
+ return true;
2183
+ }
2184
+ }
2185
+ return false;
2186
+ }
2187
+
2188
+ /**
2189
+ * Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.
2190
+ *
2191
+ * @param {Object} packet - socket.io event packet
2192
+ * @return {Object} with deconstructed packet and list of buffers
2193
+ * @public
2194
+ */
2195
+ function deconstructPacket(packet) {
2196
+ const buffers = [];
2197
+ const packetData = packet.data;
2198
+ const pack = packet;
2199
+ pack.data = _deconstructPacket(packetData, buffers);
2200
+ pack.attachments = buffers.length; // number of binary 'attachments'
2201
+ return { packet: pack, buffers: buffers };
2202
+ }
2203
+ function _deconstructPacket(data, buffers) {
2204
+ if (!data)
2205
+ return data;
2206
+ if (isBinary(data)) {
2207
+ const placeholder = { _placeholder: true, num: buffers.length };
2208
+ buffers.push(data);
2209
+ return placeholder;
2210
+ }
2211
+ else if (Array.isArray(data)) {
2212
+ const newData = new Array(data.length);
2213
+ for (let i = 0; i < data.length; i++) {
2214
+ newData[i] = _deconstructPacket(data[i], buffers);
2215
+ }
2216
+ return newData;
2217
+ }
2218
+ else if (typeof data === "object" && !(data instanceof Date)) {
2219
+ const newData = {};
2220
+ for (const key in data) {
2221
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
2222
+ newData[key] = _deconstructPacket(data[key], buffers);
2223
+ }
2224
+ }
2225
+ return newData;
2226
+ }
2227
+ return data;
2228
+ }
2229
+ /**
2230
+ * Reconstructs a binary packet from its placeholder packet and buffers
2231
+ *
2232
+ * @param {Object} packet - event packet with placeholders
2233
+ * @param {Array} buffers - binary buffers to put in placeholder positions
2234
+ * @return {Object} reconstructed packet
2235
+ * @public
2236
+ */
2237
+ function reconstructPacket(packet, buffers) {
2238
+ packet.data = _reconstructPacket(packet.data, buffers);
2239
+ delete packet.attachments; // no longer useful
2240
+ return packet;
2241
+ }
2242
+ function _reconstructPacket(data, buffers) {
2243
+ if (!data)
2244
+ return data;
2245
+ if (data && data._placeholder === true) {
2246
+ const isIndexValid = typeof data.num === "number" &&
2247
+ data.num >= 0 &&
2248
+ data.num < buffers.length;
2249
+ if (isIndexValid) {
2250
+ return buffers[data.num]; // appropriate buffer (should be natural order anyway)
2251
+ }
2252
+ else {
2253
+ throw new Error("illegal attachments");
2254
+ }
2255
+ }
2256
+ else if (Array.isArray(data)) {
2257
+ for (let i = 0; i < data.length; i++) {
2258
+ data[i] = _reconstructPacket(data[i], buffers);
2259
+ }
2260
+ }
2261
+ else if (typeof data === "object") {
2262
+ for (const key in data) {
2263
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
2264
+ data[key] = _reconstructPacket(data[key], buffers);
2265
+ }
2266
+ }
2267
+ }
2268
+ return data;
2269
+ }
2270
+
2271
+ /**
2272
+ * These strings must not be used as event names, as they have a special meaning.
2273
+ */
2274
+ const RESERVED_EVENTS$1 = [
2275
+ "connect",
2276
+ "connect_error",
2277
+ "disconnect",
2278
+ "disconnecting",
2279
+ "newListener",
2280
+ "removeListener", // used by the Node.js EventEmitter
2281
+ ];
2282
+ /**
2283
+ * Protocol version.
2284
+ *
2285
+ * @public
2286
+ */
2287
+ const protocol = 5;
2288
+ var PacketType;
2289
+ (function (PacketType) {
2290
+ PacketType[PacketType["CONNECT"] = 0] = "CONNECT";
2291
+ PacketType[PacketType["DISCONNECT"] = 1] = "DISCONNECT";
2292
+ PacketType[PacketType["EVENT"] = 2] = "EVENT";
2293
+ PacketType[PacketType["ACK"] = 3] = "ACK";
2294
+ PacketType[PacketType["CONNECT_ERROR"] = 4] = "CONNECT_ERROR";
2295
+ PacketType[PacketType["BINARY_EVENT"] = 5] = "BINARY_EVENT";
2296
+ PacketType[PacketType["BINARY_ACK"] = 6] = "BINARY_ACK";
2297
+ })(PacketType || (PacketType = {}));
2298
+ /**
2299
+ * A socket.io Encoder instance
2300
+ */
2301
+ class Encoder {
2302
+ /**
2303
+ * Encoder constructor
2304
+ *
2305
+ * @param {function} replacer - custom replacer to pass down to JSON.parse
2306
+ */
2307
+ constructor(replacer) {
2308
+ this.replacer = replacer;
2309
+ }
2310
+ /**
2311
+ * Encode a packet as a single string if non-binary, or as a
2312
+ * buffer sequence, depending on packet type.
2313
+ *
2314
+ * @param {Object} obj - packet object
2315
+ */
2316
+ encode(obj) {
2317
+ if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) {
2318
+ if (hasBinary(obj)) {
2319
+ return this.encodeAsBinary({
2320
+ type: obj.type === PacketType.EVENT
2321
+ ? PacketType.BINARY_EVENT
2322
+ : PacketType.BINARY_ACK,
2323
+ nsp: obj.nsp,
2324
+ data: obj.data,
2325
+ id: obj.id,
2326
+ });
2327
+ }
2328
+ }
2329
+ return [this.encodeAsString(obj)];
2330
+ }
2331
+ /**
2332
+ * Encode packet as string.
2333
+ */
2334
+ encodeAsString(obj) {
2335
+ // first is type
2336
+ let str = "" + obj.type;
2337
+ // attachments if we have them
2338
+ if (obj.type === PacketType.BINARY_EVENT ||
2339
+ obj.type === PacketType.BINARY_ACK) {
2340
+ str += obj.attachments + "-";
2341
+ }
2342
+ // if we have a namespace other than `/`
2343
+ // we append it followed by a comma `,`
2344
+ if (obj.nsp && "/" !== obj.nsp) {
2345
+ str += obj.nsp + ",";
2346
+ }
2347
+ // immediately followed by the id
2348
+ if (null != obj.id) {
2349
+ str += obj.id;
2350
+ }
2351
+ // json data
2352
+ if (null != obj.data) {
2353
+ str += JSON.stringify(obj.data, this.replacer);
2354
+ }
2355
+ return str;
2356
+ }
2357
+ /**
2358
+ * Encode packet as 'buffer sequence' by removing blobs, and
2359
+ * deconstructing packet into object with placeholders and
2360
+ * a list of buffers.
2361
+ */
2362
+ encodeAsBinary(obj) {
2363
+ const deconstruction = deconstructPacket(obj);
2364
+ const pack = this.encodeAsString(deconstruction.packet);
2365
+ const buffers = deconstruction.buffers;
2366
+ buffers.unshift(pack); // add packet info to beginning of data list
2367
+ return buffers; // write all the buffers
2368
+ }
2369
+ }
2370
+ // see https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
2371
+ function isObject(value) {
2372
+ return Object.prototype.toString.call(value) === "[object Object]";
2373
+ }
2374
+ /**
2375
+ * A socket.io Decoder instance
2376
+ *
2377
+ * @return {Object} decoder
2378
+ */
2379
+ class Decoder extends Emitter {
2380
+ /**
2381
+ * Decoder constructor
2382
+ *
2383
+ * @param {function} reviver - custom reviver to pass down to JSON.stringify
2384
+ */
2385
+ constructor(reviver) {
2386
+ super();
2387
+ this.reviver = reviver;
2388
+ }
2389
+ /**
2390
+ * Decodes an encoded packet string into packet JSON.
2391
+ *
2392
+ * @param {String} obj - encoded packet
2393
+ */
2394
+ add(obj) {
2395
+ let packet;
2396
+ if (typeof obj === "string") {
2397
+ if (this.reconstructor) {
2398
+ throw new Error("got plaintext data when reconstructing a packet");
2399
+ }
2400
+ packet = this.decodeString(obj);
2401
+ const isBinaryEvent = packet.type === PacketType.BINARY_EVENT;
2402
+ if (isBinaryEvent || packet.type === PacketType.BINARY_ACK) {
2403
+ packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK;
2404
+ // binary packet's json
2405
+ this.reconstructor = new BinaryReconstructor(packet);
2406
+ // no attachments, labeled binary but no binary data to follow
2407
+ if (packet.attachments === 0) {
2408
+ super.emitReserved("decoded", packet);
2409
+ }
2410
+ }
2411
+ else {
2412
+ // non-binary full packet
2413
+ super.emitReserved("decoded", packet);
2414
+ }
2415
+ }
2416
+ else if (isBinary(obj) || obj.base64) {
2417
+ // raw binary data
2418
+ if (!this.reconstructor) {
2419
+ throw new Error("got binary data when not reconstructing a packet");
2420
+ }
2421
+ else {
2422
+ packet = this.reconstructor.takeBinaryData(obj);
2423
+ if (packet) {
2424
+ // received final buffer
2425
+ this.reconstructor = null;
2426
+ super.emitReserved("decoded", packet);
2427
+ }
2428
+ }
2429
+ }
2430
+ else {
2431
+ throw new Error("Unknown type: " + obj);
2432
+ }
2433
+ }
2434
+ /**
2435
+ * Decode a packet String (JSON data)
2436
+ *
2437
+ * @param {String} str
2438
+ * @return {Object} packet
2439
+ */
2440
+ decodeString(str) {
2441
+ let i = 0;
2442
+ // look up type
2443
+ const p = {
2444
+ type: Number(str.charAt(0)),
2445
+ };
2446
+ if (PacketType[p.type] === undefined) {
2447
+ throw new Error("unknown packet type " + p.type);
2448
+ }
2449
+ // look up attachments if type binary
2450
+ if (p.type === PacketType.BINARY_EVENT ||
2451
+ p.type === PacketType.BINARY_ACK) {
2452
+ const start = i + 1;
2453
+ while (str.charAt(++i) !== "-" && i != str.length) { }
2454
+ const buf = str.substring(start, i);
2455
+ if (buf != Number(buf) || str.charAt(i) !== "-") {
2456
+ throw new Error("Illegal attachments");
2457
+ }
2458
+ p.attachments = Number(buf);
2459
+ }
2460
+ // look up namespace (if any)
2461
+ if ("/" === str.charAt(i + 1)) {
2462
+ const start = i + 1;
2463
+ while (++i) {
2464
+ const c = str.charAt(i);
2465
+ if ("," === c)
2466
+ break;
2467
+ if (i === str.length)
2468
+ break;
2469
+ }
2470
+ p.nsp = str.substring(start, i);
2471
+ }
2472
+ else {
2473
+ p.nsp = "/";
2474
+ }
2475
+ // look up id
2476
+ const next = str.charAt(i + 1);
2477
+ if ("" !== next && Number(next) == next) {
2478
+ const start = i + 1;
2479
+ while (++i) {
2480
+ const c = str.charAt(i);
2481
+ if (null == c || Number(c) != c) {
2482
+ --i;
2483
+ break;
2484
+ }
2485
+ if (i === str.length)
2486
+ break;
2487
+ }
2488
+ p.id = Number(str.substring(start, i + 1));
2489
+ }
2490
+ // look up json data
2491
+ if (str.charAt(++i)) {
2492
+ const payload = this.tryParse(str.substr(i));
2493
+ if (Decoder.isPayloadValid(p.type, payload)) {
2494
+ p.data = payload;
2495
+ }
2496
+ else {
2497
+ throw new Error("invalid payload");
2498
+ }
2499
+ }
2500
+ return p;
2501
+ }
2502
+ tryParse(str) {
2503
+ try {
2504
+ return JSON.parse(str, this.reviver);
2505
+ }
2506
+ catch (e) {
2507
+ return false;
2508
+ }
2509
+ }
2510
+ static isPayloadValid(type, payload) {
2511
+ switch (type) {
2512
+ case PacketType.CONNECT:
2513
+ return isObject(payload);
2514
+ case PacketType.DISCONNECT:
2515
+ return payload === undefined;
2516
+ case PacketType.CONNECT_ERROR:
2517
+ return typeof payload === "string" || isObject(payload);
2518
+ case PacketType.EVENT:
2519
+ case PacketType.BINARY_EVENT:
2520
+ return (Array.isArray(payload) &&
2521
+ (typeof payload[0] === "number" ||
2522
+ (typeof payload[0] === "string" &&
2523
+ RESERVED_EVENTS$1.indexOf(payload[0]) === -1)));
2524
+ case PacketType.ACK:
2525
+ case PacketType.BINARY_ACK:
2526
+ return Array.isArray(payload);
2527
+ }
2528
+ }
2529
+ /**
2530
+ * Deallocates a parser's resources
2531
+ */
2532
+ destroy() {
2533
+ if (this.reconstructor) {
2534
+ this.reconstructor.finishedReconstruction();
2535
+ this.reconstructor = null;
2536
+ }
2537
+ }
2538
+ }
2539
+ /**
2540
+ * A manager of a binary event's 'buffer sequence'. Should
2541
+ * be constructed whenever a packet of type BINARY_EVENT is
2542
+ * decoded.
2543
+ *
2544
+ * @param {Object} packet
2545
+ * @return {BinaryReconstructor} initialized reconstructor
2546
+ */
2547
+ class BinaryReconstructor {
2548
+ constructor(packet) {
2549
+ this.packet = packet;
2550
+ this.buffers = [];
2551
+ this.reconPack = packet;
2552
+ }
2553
+ /**
2554
+ * Method to be called when binary data received from connection
2555
+ * after a BINARY_EVENT packet.
2556
+ *
2557
+ * @param {Buffer | ArrayBuffer} binData - the raw binary data received
2558
+ * @return {null | Object} returns null if more binary data is expected or
2559
+ * a reconstructed packet object if all buffers have been received.
2560
+ */
2561
+ takeBinaryData(binData) {
2562
+ this.buffers.push(binData);
2563
+ if (this.buffers.length === this.reconPack.attachments) {
2564
+ // done with buffer list
2565
+ const packet = reconstructPacket(this.reconPack, this.buffers);
2566
+ this.finishedReconstruction();
2567
+ return packet;
2568
+ }
2569
+ return null;
2570
+ }
2571
+ /**
2572
+ * Cleans up binary packet reconstruction variables.
2573
+ */
2574
+ finishedReconstruction() {
2575
+ this.reconPack = null;
2576
+ this.buffers = [];
2577
+ }
2578
+ }
2579
+
2580
+ const parser = /*#__PURE__*/Object.freeze({
2581
+ __proto__: null,
2582
+ protocol: protocol,
2583
+ get PacketType () { return PacketType; },
2584
+ Encoder: Encoder,
2585
+ Decoder: Decoder
2586
+ });
2587
+
2588
+ function on(obj, ev, fn) {
2589
+ obj.on(ev, fn);
2590
+ return function subDestroy() {
2591
+ obj.off(ev, fn);
2592
+ };
2593
+ }
2594
+
2595
+ /**
2596
+ * Internal events.
2597
+ * These events can't be emitted by the user.
2598
+ */
2599
+ const RESERVED_EVENTS = Object.freeze({
2600
+ connect: 1,
2601
+ connect_error: 1,
2602
+ disconnect: 1,
2603
+ disconnecting: 1,
2604
+ // EventEmitter reserved events: https://nodejs.org/api/events.html#events_event_newlistener
2605
+ newListener: 1,
2606
+ removeListener: 1,
2607
+ });
2608
+ /**
2609
+ * A Socket is the fundamental class for interacting with the server.
2610
+ *
2611
+ * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.
2612
+ *
2613
+ * @example
2614
+ * const socket = io();
2615
+ *
2616
+ * socket.on("connect", () => {
2617
+ * console.log("connected");
2618
+ * });
2619
+ *
2620
+ * // send an event to the server
2621
+ * socket.emit("foo", "bar");
2622
+ *
2623
+ * socket.on("foobar", () => {
2624
+ * // an event was received from the server
2625
+ * });
2626
+ *
2627
+ * // upon disconnection
2628
+ * socket.on("disconnect", (reason) => {
2629
+ * console.log(`disconnected due to ${reason}`);
2630
+ * });
2631
+ */
2632
+ class Socket extends Emitter {
2633
+ /**
2634
+ * `Socket` constructor.
2635
+ */
2636
+ constructor(io, nsp, opts) {
2637
+ super();
2638
+ /**
2639
+ * Whether the socket is currently connected to the server.
2640
+ *
2641
+ * @example
2642
+ * const socket = io();
2643
+ *
2644
+ * socket.on("connect", () => {
2645
+ * console.log(socket.connected); // true
2646
+ * });
2647
+ *
2648
+ * socket.on("disconnect", () => {
2649
+ * console.log(socket.connected); // false
2650
+ * });
2651
+ */
2652
+ this.connected = false;
2653
+ /**
2654
+ * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
2655
+ * be transmitted by the server.
2656
+ */
2657
+ this.recovered = false;
2658
+ /**
2659
+ * Buffer for packets received before the CONNECT packet
2660
+ */
2661
+ this.receiveBuffer = [];
2662
+ /**
2663
+ * Buffer for packets that will be sent once the socket is connected
2664
+ */
2665
+ this.sendBuffer = [];
2666
+ /**
2667
+ * The queue of packets to be sent with retry in case of failure.
2668
+ *
2669
+ * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.
2670
+ * @private
2671
+ */
2672
+ this._queue = [];
2673
+ /**
2674
+ * A sequence to generate the ID of the {@link QueuedPacket}.
2675
+ * @private
2676
+ */
2677
+ this._queueSeq = 0;
2678
+ this.ids = 0;
2679
+ this.acks = {};
2680
+ this.flags = {};
2681
+ this.io = io;
2682
+ this.nsp = nsp;
2683
+ if (opts && opts.auth) {
2684
+ this.auth = opts.auth;
2685
+ }
2686
+ this._opts = Object.assign({}, opts);
2687
+ if (this.io._autoConnect)
2688
+ this.open();
2689
+ }
2690
+ /**
2691
+ * Whether the socket is currently disconnected
2692
+ *
2693
+ * @example
2694
+ * const socket = io();
2695
+ *
2696
+ * socket.on("connect", () => {
2697
+ * console.log(socket.disconnected); // false
2698
+ * });
2699
+ *
2700
+ * socket.on("disconnect", () => {
2701
+ * console.log(socket.disconnected); // true
2702
+ * });
2703
+ */
2704
+ get disconnected() {
2705
+ return !this.connected;
2706
+ }
2707
+ /**
2708
+ * Subscribe to open, close and packet events
2709
+ *
2710
+ * @private
2711
+ */
2712
+ subEvents() {
2713
+ if (this.subs)
2714
+ return;
2715
+ const io = this.io;
2716
+ this.subs = [
2717
+ on(io, "open", this.onopen.bind(this)),
2718
+ on(io, "packet", this.onpacket.bind(this)),
2719
+ on(io, "error", this.onerror.bind(this)),
2720
+ on(io, "close", this.onclose.bind(this)),
2721
+ ];
2722
+ }
2723
+ /**
2724
+ * Whether the Socket will try to reconnect when its Manager connects or reconnects.
2725
+ *
2726
+ * @example
2727
+ * const socket = io();
2728
+ *
2729
+ * console.log(socket.active); // true
2730
+ *
2731
+ * socket.on("disconnect", (reason) => {
2732
+ * if (reason === "io server disconnect") {
2733
+ * // the disconnection was initiated by the server, you need to manually reconnect
2734
+ * console.log(socket.active); // false
2735
+ * }
2736
+ * // else the socket will automatically try to reconnect
2737
+ * console.log(socket.active); // true
2738
+ * });
2739
+ */
2740
+ get active() {
2741
+ return !!this.subs;
2742
+ }
2743
+ /**
2744
+ * "Opens" the socket.
2745
+ *
2746
+ * @example
2747
+ * const socket = io({
2748
+ * autoConnect: false
2749
+ * });
2750
+ *
2751
+ * socket.connect();
2752
+ */
2753
+ connect() {
2754
+ if (this.connected)
2755
+ return this;
2756
+ this.subEvents();
2757
+ if (!this.io["_reconnecting"])
2758
+ this.io.open(); // ensure open
2759
+ if ("open" === this.io._readyState)
2760
+ this.onopen();
2761
+ return this;
2762
+ }
2763
+ /**
2764
+ * Alias for {@link connect()}.
2765
+ */
2766
+ open() {
2767
+ return this.connect();
2768
+ }
2769
+ /**
2770
+ * Sends a `message` event.
2771
+ *
2772
+ * This method mimics the WebSocket.send() method.
2773
+ *
2774
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
2775
+ *
2776
+ * @example
2777
+ * socket.send("hello");
2778
+ *
2779
+ * // this is equivalent to
2780
+ * socket.emit("message", "hello");
2781
+ *
2782
+ * @return self
2783
+ */
2784
+ send(...args) {
2785
+ args.unshift("message");
2786
+ this.emit.apply(this, args);
2787
+ return this;
2788
+ }
2789
+ /**
2790
+ * Override `emit`.
2791
+ * If the event is in `events`, it's emitted normally.
2792
+ *
2793
+ * @example
2794
+ * socket.emit("hello", "world");
2795
+ *
2796
+ * // all serializable datastructures are supported (no need to call JSON.stringify)
2797
+ * socket.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
2798
+ *
2799
+ * // with an acknowledgement from the server
2800
+ * socket.emit("hello", "world", (val) => {
2801
+ * // ...
2802
+ * });
2803
+ *
2804
+ * @return self
2805
+ */
2806
+ emit(ev, ...args) {
2807
+ if (RESERVED_EVENTS.hasOwnProperty(ev)) {
2808
+ throw new Error('"' + ev.toString() + '" is a reserved event name');
2809
+ }
2810
+ args.unshift(ev);
2811
+ if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {
2812
+ this._addToQueue(args);
2813
+ return this;
2814
+ }
2815
+ const packet = {
2816
+ type: PacketType.EVENT,
2817
+ data: args,
2818
+ };
2819
+ packet.options = {};
2820
+ packet.options.compress = this.flags.compress !== false;
2821
+ // event ack callback
2822
+ if ("function" === typeof args[args.length - 1]) {
2823
+ const id = this.ids++;
2824
+ const ack = args.pop();
2825
+ this._registerAckCallback(id, ack);
2826
+ packet.id = id;
2827
+ }
2828
+ const isTransportWritable = this.io.engine &&
2829
+ this.io.engine.transport &&
2830
+ this.io.engine.transport.writable;
2831
+ const discardPacket = this.flags.volatile && (!isTransportWritable || !this.connected);
2832
+ if (discardPacket) ;
2833
+ else if (this.connected) {
2834
+ this.notifyOutgoingListeners(packet);
2835
+ this.packet(packet);
2836
+ }
2837
+ else {
2838
+ this.sendBuffer.push(packet);
2839
+ }
2840
+ this.flags = {};
2841
+ return this;
2842
+ }
2843
+ /**
2844
+ * @private
2845
+ */
2846
+ _registerAckCallback(id, ack) {
2847
+ var _a;
2848
+ const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;
2849
+ if (timeout === undefined) {
2850
+ this.acks[id] = ack;
2851
+ return;
2852
+ }
2853
+ // @ts-ignore
2854
+ const timer = this.io.setTimeoutFn(() => {
2855
+ delete this.acks[id];
2856
+ for (let i = 0; i < this.sendBuffer.length; i++) {
2857
+ if (this.sendBuffer[i].id === id) {
2858
+ this.sendBuffer.splice(i, 1);
2859
+ }
2860
+ }
2861
+ ack.call(this, new Error("operation has timed out"));
2862
+ }, timeout);
2863
+ this.acks[id] = (...args) => {
2864
+ // @ts-ignore
2865
+ this.io.clearTimeoutFn(timer);
2866
+ ack.apply(this, [null, ...args]);
2867
+ };
2868
+ }
2869
+ /**
2870
+ * Emits an event and waits for an acknowledgement
2871
+ *
2872
+ * @example
2873
+ * // without timeout
2874
+ * const response = await socket.emitWithAck("hello", "world");
2875
+ *
2876
+ * // with a specific timeout
2877
+ * try {
2878
+ * const response = await socket.timeout(1000).emitWithAck("hello", "world");
2879
+ * } catch (err) {
2880
+ * // the server did not acknowledge the event in the given delay
2881
+ * }
2882
+ *
2883
+ * @return a Promise that will be fulfilled when the server acknowledges the event
2884
+ */
2885
+ emitWithAck(ev, ...args) {
2886
+ // the timeout flag is optional
2887
+ const withErr = this.flags.timeout !== undefined || this._opts.ackTimeout !== undefined;
2888
+ return new Promise((resolve, reject) => {
2889
+ args.push((arg1, arg2) => {
2890
+ if (withErr) {
2891
+ return arg1 ? reject(arg1) : resolve(arg2);
2892
+ }
2893
+ else {
2894
+ return resolve(arg1);
2895
+ }
2896
+ });
2897
+ this.emit(ev, ...args);
2898
+ });
2899
+ }
2900
+ /**
2901
+ * Add the packet to the queue.
2902
+ * @param args
2903
+ * @private
2904
+ */
2905
+ _addToQueue(args) {
2906
+ let ack;
2907
+ if (typeof args[args.length - 1] === "function") {
2908
+ ack = args.pop();
2909
+ }
2910
+ const packet = {
2911
+ id: this._queueSeq++,
2912
+ tryCount: 0,
2913
+ pending: false,
2914
+ args,
2915
+ flags: Object.assign({ fromQueue: true }, this.flags),
2916
+ };
2917
+ args.push((err, ...responseArgs) => {
2918
+ if (packet !== this._queue[0]) {
2919
+ // the packet has already been acknowledged
2920
+ return;
2921
+ }
2922
+ const hasError = err !== null;
2923
+ if (hasError) {
2924
+ if (packet.tryCount > this._opts.retries) {
2925
+ this._queue.shift();
2926
+ if (ack) {
2927
+ ack(err);
2928
+ }
2929
+ }
2930
+ }
2931
+ else {
2932
+ this._queue.shift();
2933
+ if (ack) {
2934
+ ack(null, ...responseArgs);
2935
+ }
2936
+ }
2937
+ packet.pending = false;
2938
+ return this._drainQueue();
2939
+ });
2940
+ this._queue.push(packet);
2941
+ this._drainQueue();
2942
+ }
2943
+ /**
2944
+ * Send the first packet of the queue, and wait for an acknowledgement from the server.
2945
+ * @param force - whether to resend a packet that has not been acknowledged yet
2946
+ *
2947
+ * @private
2948
+ */
2949
+ _drainQueue(force = false) {
2950
+ if (!this.connected || this._queue.length === 0) {
2951
+ return;
2952
+ }
2953
+ const packet = this._queue[0];
2954
+ if (packet.pending && !force) {
2955
+ return;
2956
+ }
2957
+ packet.pending = true;
2958
+ packet.tryCount++;
2959
+ this.flags = packet.flags;
2960
+ this.emit.apply(this, packet.args);
2961
+ }
2962
+ /**
2963
+ * Sends a packet.
2964
+ *
2965
+ * @param packet
2966
+ * @private
2967
+ */
2968
+ packet(packet) {
2969
+ packet.nsp = this.nsp;
2970
+ this.io._packet(packet);
2971
+ }
2972
+ /**
2973
+ * Called upon engine `open`.
2974
+ *
2975
+ * @private
2976
+ */
2977
+ onopen() {
2978
+ if (typeof this.auth == "function") {
2979
+ this.auth((data) => {
2980
+ this._sendConnectPacket(data);
2981
+ });
2982
+ }
2983
+ else {
2984
+ this._sendConnectPacket(this.auth);
2985
+ }
2986
+ }
2987
+ /**
2988
+ * Sends a CONNECT packet to initiate the Socket.IO session.
2989
+ *
2990
+ * @param data
2991
+ * @private
2992
+ */
2993
+ _sendConnectPacket(data) {
2994
+ this.packet({
2995
+ type: PacketType.CONNECT,
2996
+ data: this._pid
2997
+ ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)
2998
+ : data,
2999
+ });
3000
+ }
3001
+ /**
3002
+ * Called upon engine or manager `error`.
3003
+ *
3004
+ * @param err
3005
+ * @private
3006
+ */
3007
+ onerror(err) {
3008
+ if (!this.connected) {
3009
+ this.emitReserved("connect_error", err);
3010
+ }
3011
+ }
3012
+ /**
3013
+ * Called upon engine `close`.
3014
+ *
3015
+ * @param reason
3016
+ * @param description
3017
+ * @private
3018
+ */
3019
+ onclose(reason, description) {
3020
+ this.connected = false;
3021
+ delete this.id;
3022
+ this.emitReserved("disconnect", reason, description);
3023
+ }
3024
+ /**
3025
+ * Called with socket packet.
3026
+ *
3027
+ * @param packet
3028
+ * @private
3029
+ */
3030
+ onpacket(packet) {
3031
+ const sameNamespace = packet.nsp === this.nsp;
3032
+ if (!sameNamespace)
3033
+ return;
3034
+ switch (packet.type) {
3035
+ case PacketType.CONNECT:
3036
+ if (packet.data && packet.data.sid) {
3037
+ this.onconnect(packet.data.sid, packet.data.pid);
3038
+ }
3039
+ else {
3040
+ this.emitReserved("connect_error", new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));
3041
+ }
3042
+ break;
3043
+ case PacketType.EVENT:
3044
+ case PacketType.BINARY_EVENT:
3045
+ this.onevent(packet);
3046
+ break;
3047
+ case PacketType.ACK:
3048
+ case PacketType.BINARY_ACK:
3049
+ this.onack(packet);
3050
+ break;
3051
+ case PacketType.DISCONNECT:
3052
+ this.ondisconnect();
3053
+ break;
3054
+ case PacketType.CONNECT_ERROR:
3055
+ this.destroy();
3056
+ const err = new Error(packet.data.message);
3057
+ // @ts-ignore
3058
+ err.data = packet.data.data;
3059
+ this.emitReserved("connect_error", err);
3060
+ break;
3061
+ }
3062
+ }
3063
+ /**
3064
+ * Called upon a server event.
3065
+ *
3066
+ * @param packet
3067
+ * @private
3068
+ */
3069
+ onevent(packet) {
3070
+ const args = packet.data || [];
3071
+ if (null != packet.id) {
3072
+ args.push(this.ack(packet.id));
3073
+ }
3074
+ if (this.connected) {
3075
+ this.emitEvent(args);
3076
+ }
3077
+ else {
3078
+ this.receiveBuffer.push(Object.freeze(args));
3079
+ }
3080
+ }
3081
+ emitEvent(args) {
3082
+ if (this._anyListeners && this._anyListeners.length) {
3083
+ const listeners = this._anyListeners.slice();
3084
+ for (const listener of listeners) {
3085
+ listener.apply(this, args);
3086
+ }
3087
+ }
3088
+ super.emit.apply(this, args);
3089
+ if (this._pid && args.length && typeof args[args.length - 1] === "string") {
3090
+ this._lastOffset = args[args.length - 1];
3091
+ }
3092
+ }
3093
+ /**
3094
+ * Produces an ack callback to emit with an event.
3095
+ *
3096
+ * @private
3097
+ */
3098
+ ack(id) {
3099
+ const self = this;
3100
+ let sent = false;
3101
+ return function (...args) {
3102
+ // prevent double callbacks
3103
+ if (sent)
3104
+ return;
3105
+ sent = true;
3106
+ self.packet({
3107
+ type: PacketType.ACK,
3108
+ id: id,
3109
+ data: args,
3110
+ });
3111
+ };
3112
+ }
3113
+ /**
3114
+ * Called upon a server acknowlegement.
3115
+ *
3116
+ * @param packet
3117
+ * @private
3118
+ */
3119
+ onack(packet) {
3120
+ const ack = this.acks[packet.id];
3121
+ if ("function" === typeof ack) {
3122
+ ack.apply(this, packet.data);
3123
+ delete this.acks[packet.id];
3124
+ }
3125
+ }
3126
+ /**
3127
+ * Called upon server connect.
3128
+ *
3129
+ * @private
3130
+ */
3131
+ onconnect(id, pid) {
3132
+ this.id = id;
3133
+ this.recovered = pid && this._pid === pid;
3134
+ this._pid = pid; // defined only if connection state recovery is enabled
3135
+ this.connected = true;
3136
+ this.emitBuffered();
3137
+ this.emitReserved("connect");
3138
+ this._drainQueue(true);
3139
+ }
3140
+ /**
3141
+ * Emit buffered events (received and emitted).
3142
+ *
3143
+ * @private
3144
+ */
3145
+ emitBuffered() {
3146
+ this.receiveBuffer.forEach((args) => this.emitEvent(args));
3147
+ this.receiveBuffer = [];
3148
+ this.sendBuffer.forEach((packet) => {
3149
+ this.notifyOutgoingListeners(packet);
3150
+ this.packet(packet);
3151
+ });
3152
+ this.sendBuffer = [];
3153
+ }
3154
+ /**
3155
+ * Called upon server disconnect.
3156
+ *
3157
+ * @private
3158
+ */
3159
+ ondisconnect() {
3160
+ this.destroy();
3161
+ this.onclose("io server disconnect");
3162
+ }
3163
+ /**
3164
+ * Called upon forced client/server side disconnections,
3165
+ * this method ensures the manager stops tracking us and
3166
+ * that reconnections don't get triggered for this.
3167
+ *
3168
+ * @private
3169
+ */
3170
+ destroy() {
3171
+ if (this.subs) {
3172
+ // clean subscriptions to avoid reconnections
3173
+ this.subs.forEach((subDestroy) => subDestroy());
3174
+ this.subs = undefined;
3175
+ }
3176
+ this.io["_destroy"](this);
3177
+ }
3178
+ /**
3179
+ * Disconnects the socket manually. In that case, the socket will not try to reconnect.
3180
+ *
3181
+ * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.
3182
+ *
3183
+ * @example
3184
+ * const socket = io();
3185
+ *
3186
+ * socket.on("disconnect", (reason) => {
3187
+ * // console.log(reason); prints "io client disconnect"
3188
+ * });
3189
+ *
3190
+ * socket.disconnect();
3191
+ *
3192
+ * @return self
3193
+ */
3194
+ disconnect() {
3195
+ if (this.connected) {
3196
+ this.packet({ type: PacketType.DISCONNECT });
3197
+ }
3198
+ // remove socket from pool
3199
+ this.destroy();
3200
+ if (this.connected) {
3201
+ // fire events
3202
+ this.onclose("io client disconnect");
3203
+ }
3204
+ return this;
3205
+ }
3206
+ /**
3207
+ * Alias for {@link disconnect()}.
3208
+ *
3209
+ * @return self
3210
+ */
3211
+ close() {
3212
+ return this.disconnect();
3213
+ }
3214
+ /**
3215
+ * Sets the compress flag.
3216
+ *
3217
+ * @example
3218
+ * socket.compress(false).emit("hello");
3219
+ *
3220
+ * @param compress - if `true`, compresses the sending data
3221
+ * @return self
3222
+ */
3223
+ compress(compress) {
3224
+ this.flags.compress = compress;
3225
+ return this;
3226
+ }
3227
+ /**
3228
+ * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
3229
+ * ready to send messages.
3230
+ *
3231
+ * @example
3232
+ * socket.volatile.emit("hello"); // the server may or may not receive it
3233
+ *
3234
+ * @returns self
3235
+ */
3236
+ get volatile() {
3237
+ this.flags.volatile = true;
3238
+ return this;
3239
+ }
3240
+ /**
3241
+ * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
3242
+ * given number of milliseconds have elapsed without an acknowledgement from the server:
3243
+ *
3244
+ * @example
3245
+ * socket.timeout(5000).emit("my-event", (err) => {
3246
+ * if (err) {
3247
+ * // the server did not acknowledge the event in the given delay
3248
+ * }
3249
+ * });
3250
+ *
3251
+ * @returns self
3252
+ */
3253
+ timeout(timeout) {
3254
+ this.flags.timeout = timeout;
3255
+ return this;
3256
+ }
3257
+ /**
3258
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
3259
+ * callback.
3260
+ *
3261
+ * @example
3262
+ * socket.onAny((event, ...args) => {
3263
+ * console.log(`got ${event}`);
3264
+ * });
3265
+ *
3266
+ * @param listener
3267
+ */
3268
+ onAny(listener) {
3269
+ this._anyListeners = this._anyListeners || [];
3270
+ this._anyListeners.push(listener);
3271
+ return this;
3272
+ }
3273
+ /**
3274
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
3275
+ * callback. The listener is added to the beginning of the listeners array.
3276
+ *
3277
+ * @example
3278
+ * socket.prependAny((event, ...args) => {
3279
+ * console.log(`got event ${event}`);
3280
+ * });
3281
+ *
3282
+ * @param listener
3283
+ */
3284
+ prependAny(listener) {
3285
+ this._anyListeners = this._anyListeners || [];
3286
+ this._anyListeners.unshift(listener);
3287
+ return this;
3288
+ }
3289
+ /**
3290
+ * Removes the listener that will be fired when any event is emitted.
3291
+ *
3292
+ * @example
3293
+ * const catchAllListener = (event, ...args) => {
3294
+ * console.log(`got event ${event}`);
3295
+ * }
3296
+ *
3297
+ * socket.onAny(catchAllListener);
3298
+ *
3299
+ * // remove a specific listener
3300
+ * socket.offAny(catchAllListener);
3301
+ *
3302
+ * // or remove all listeners
3303
+ * socket.offAny();
3304
+ *
3305
+ * @param listener
3306
+ */
3307
+ offAny(listener) {
3308
+ if (!this._anyListeners) {
3309
+ return this;
3310
+ }
3311
+ if (listener) {
3312
+ const listeners = this._anyListeners;
3313
+ for (let i = 0; i < listeners.length; i++) {
3314
+ if (listener === listeners[i]) {
3315
+ listeners.splice(i, 1);
3316
+ return this;
3317
+ }
3318
+ }
3319
+ }
3320
+ else {
3321
+ this._anyListeners = [];
3322
+ }
3323
+ return this;
3324
+ }
3325
+ /**
3326
+ * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
3327
+ * e.g. to remove listeners.
3328
+ */
3329
+ listenersAny() {
3330
+ return this._anyListeners || [];
3331
+ }
3332
+ /**
3333
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
3334
+ * callback.
3335
+ *
3336
+ * Note: acknowledgements sent to the server are not included.
3337
+ *
3338
+ * @example
3339
+ * socket.onAnyOutgoing((event, ...args) => {
3340
+ * console.log(`sent event ${event}`);
3341
+ * });
3342
+ *
3343
+ * @param listener
3344
+ */
3345
+ onAnyOutgoing(listener) {
3346
+ this._anyOutgoingListeners = this._anyOutgoingListeners || [];
3347
+ this._anyOutgoingListeners.push(listener);
3348
+ return this;
3349
+ }
3350
+ /**
3351
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
3352
+ * callback. The listener is added to the beginning of the listeners array.
3353
+ *
3354
+ * Note: acknowledgements sent to the server are not included.
3355
+ *
3356
+ * @example
3357
+ * socket.prependAnyOutgoing((event, ...args) => {
3358
+ * console.log(`sent event ${event}`);
3359
+ * });
3360
+ *
3361
+ * @param listener
3362
+ */
3363
+ prependAnyOutgoing(listener) {
3364
+ this._anyOutgoingListeners = this._anyOutgoingListeners || [];
3365
+ this._anyOutgoingListeners.unshift(listener);
3366
+ return this;
3367
+ }
3368
+ /**
3369
+ * Removes the listener that will be fired when any event is emitted.
3370
+ *
3371
+ * @example
3372
+ * const catchAllListener = (event, ...args) => {
3373
+ * console.log(`sent event ${event}`);
3374
+ * }
3375
+ *
3376
+ * socket.onAnyOutgoing(catchAllListener);
3377
+ *
3378
+ * // remove a specific listener
3379
+ * socket.offAnyOutgoing(catchAllListener);
3380
+ *
3381
+ * // or remove all listeners
3382
+ * socket.offAnyOutgoing();
3383
+ *
3384
+ * @param [listener] - the catch-all listener (optional)
3385
+ */
3386
+ offAnyOutgoing(listener) {
3387
+ if (!this._anyOutgoingListeners) {
3388
+ return this;
3389
+ }
3390
+ if (listener) {
3391
+ const listeners = this._anyOutgoingListeners;
3392
+ for (let i = 0; i < listeners.length; i++) {
3393
+ if (listener === listeners[i]) {
3394
+ listeners.splice(i, 1);
3395
+ return this;
3396
+ }
3397
+ }
3398
+ }
3399
+ else {
3400
+ this._anyOutgoingListeners = [];
3401
+ }
3402
+ return this;
3403
+ }
3404
+ /**
3405
+ * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
3406
+ * e.g. to remove listeners.
3407
+ */
3408
+ listenersAnyOutgoing() {
3409
+ return this._anyOutgoingListeners || [];
3410
+ }
3411
+ /**
3412
+ * Notify the listeners for each packet sent
3413
+ *
3414
+ * @param packet
3415
+ *
3416
+ * @private
3417
+ */
3418
+ notifyOutgoingListeners(packet) {
3419
+ if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) {
3420
+ const listeners = this._anyOutgoingListeners.slice();
3421
+ for (const listener of listeners) {
3422
+ listener.apply(this, packet.data);
3423
+ }
3424
+ }
3425
+ }
3426
+ }
3427
+
3428
+ /**
3429
+ * Initialize backoff timer with `opts`.
3430
+ *
3431
+ * - `min` initial timeout in milliseconds [100]
3432
+ * - `max` max timeout [10000]
3433
+ * - `jitter` [0]
3434
+ * - `factor` [2]
3435
+ *
3436
+ * @param {Object} opts
3437
+ * @api public
3438
+ */
3439
+ function Backoff(opts) {
3440
+ opts = opts || {};
3441
+ this.ms = opts.min || 100;
3442
+ this.max = opts.max || 10000;
3443
+ this.factor = opts.factor || 2;
3444
+ this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
3445
+ this.attempts = 0;
3446
+ }
3447
+ /**
3448
+ * Return the backoff duration.
3449
+ *
3450
+ * @return {Number}
3451
+ * @api public
3452
+ */
3453
+ Backoff.prototype.duration = function () {
3454
+ var ms = this.ms * Math.pow(this.factor, this.attempts++);
3455
+ if (this.jitter) {
3456
+ var rand = Math.random();
3457
+ var deviation = Math.floor(rand * this.jitter * ms);
3458
+ ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;
3459
+ }
3460
+ return Math.min(ms, this.max) | 0;
3461
+ };
3462
+ /**
3463
+ * Reset the number of attempts.
3464
+ *
3465
+ * @api public
3466
+ */
3467
+ Backoff.prototype.reset = function () {
3468
+ this.attempts = 0;
3469
+ };
3470
+ /**
3471
+ * Set the minimum duration
3472
+ *
3473
+ * @api public
3474
+ */
3475
+ Backoff.prototype.setMin = function (min) {
3476
+ this.ms = min;
3477
+ };
3478
+ /**
3479
+ * Set the maximum duration
3480
+ *
3481
+ * @api public
3482
+ */
3483
+ Backoff.prototype.setMax = function (max) {
3484
+ this.max = max;
3485
+ };
3486
+ /**
3487
+ * Set the jitter
3488
+ *
3489
+ * @api public
3490
+ */
3491
+ Backoff.prototype.setJitter = function (jitter) {
3492
+ this.jitter = jitter;
3493
+ };
3494
+
3495
+ class Manager extends Emitter {
3496
+ constructor(uri, opts) {
3497
+ var _a;
3498
+ super();
3499
+ this.nsps = {};
3500
+ this.subs = [];
3501
+ if (uri && "object" === typeof uri) {
3502
+ opts = uri;
3503
+ uri = undefined;
3504
+ }
3505
+ opts = opts || {};
3506
+ opts.path = opts.path || "/socket.io";
3507
+ this.opts = opts;
3508
+ installTimerFunctions(this, opts);
3509
+ this.reconnection(opts.reconnection !== false);
3510
+ this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
3511
+ this.reconnectionDelay(opts.reconnectionDelay || 1000);
3512
+ this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
3513
+ this.randomizationFactor((_a = opts.randomizationFactor) !== null && _a !== void 0 ? _a : 0.5);
3514
+ this.backoff = new Backoff({
3515
+ min: this.reconnectionDelay(),
3516
+ max: this.reconnectionDelayMax(),
3517
+ jitter: this.randomizationFactor(),
3518
+ });
3519
+ this.timeout(null == opts.timeout ? 20000 : opts.timeout);
3520
+ this._readyState = "closed";
3521
+ this.uri = uri;
3522
+ const _parser = opts.parser || parser;
3523
+ this.encoder = new _parser.Encoder();
3524
+ this.decoder = new _parser.Decoder();
3525
+ this._autoConnect = opts.autoConnect !== false;
3526
+ if (this._autoConnect)
3527
+ this.open();
3528
+ }
3529
+ reconnection(v) {
3530
+ if (!arguments.length)
3531
+ return this._reconnection;
3532
+ this._reconnection = !!v;
3533
+ return this;
3534
+ }
3535
+ reconnectionAttempts(v) {
3536
+ if (v === undefined)
3537
+ return this._reconnectionAttempts;
3538
+ this._reconnectionAttempts = v;
3539
+ return this;
3540
+ }
3541
+ reconnectionDelay(v) {
3542
+ var _a;
3543
+ if (v === undefined)
3544
+ return this._reconnectionDelay;
3545
+ this._reconnectionDelay = v;
3546
+ (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMin(v);
3547
+ return this;
3548
+ }
3549
+ randomizationFactor(v) {
3550
+ var _a;
3551
+ if (v === undefined)
3552
+ return this._randomizationFactor;
3553
+ this._randomizationFactor = v;
3554
+ (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setJitter(v);
3555
+ return this;
3556
+ }
3557
+ reconnectionDelayMax(v) {
3558
+ var _a;
3559
+ if (v === undefined)
3560
+ return this._reconnectionDelayMax;
3561
+ this._reconnectionDelayMax = v;
3562
+ (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMax(v);
3563
+ return this;
3564
+ }
3565
+ timeout(v) {
3566
+ if (!arguments.length)
3567
+ return this._timeout;
3568
+ this._timeout = v;
3569
+ return this;
3570
+ }
3571
+ /**
3572
+ * Starts trying to reconnect if reconnection is enabled and we have not
3573
+ * started reconnecting yet
3574
+ *
3575
+ * @private
3576
+ */
3577
+ maybeReconnectOnOpen() {
3578
+ // Only try to reconnect if it's the first time we're connecting
3579
+ if (!this._reconnecting &&
3580
+ this._reconnection &&
3581
+ this.backoff.attempts === 0) {
3582
+ // keeps reconnection from firing twice for the same reconnection loop
3583
+ this.reconnect();
3584
+ }
3585
+ }
3586
+ /**
3587
+ * Sets the current transport `socket`.
3588
+ *
3589
+ * @param {Function} fn - optional, callback
3590
+ * @return self
3591
+ * @public
3592
+ */
3593
+ open(fn) {
3594
+ if (~this._readyState.indexOf("open"))
3595
+ return this;
3596
+ this.engine = new Socket$1(this.uri, this.opts);
3597
+ const socket = this.engine;
3598
+ const self = this;
3599
+ this._readyState = "opening";
3600
+ this.skipReconnect = false;
3601
+ // emit `open`
3602
+ const openSubDestroy = on(socket, "open", function () {
3603
+ self.onopen();
3604
+ fn && fn();
3605
+ });
3606
+ const onError = (err) => {
3607
+ this.cleanup();
3608
+ this._readyState = "closed";
3609
+ this.emitReserved("error", err);
3610
+ if (fn) {
3611
+ fn(err);
3612
+ }
3613
+ else {
3614
+ // Only do this if there is no fn to handle the error
3615
+ this.maybeReconnectOnOpen();
3616
+ }
3617
+ };
3618
+ // emit `error`
3619
+ const errorSub = on(socket, "error", onError);
3620
+ if (false !== this._timeout) {
3621
+ const timeout = this._timeout;
3622
+ // set timer
3623
+ const timer = this.setTimeoutFn(() => {
3624
+ openSubDestroy();
3625
+ onError(new Error("timeout"));
3626
+ socket.close();
3627
+ }, timeout);
3628
+ if (this.opts.autoUnref) {
3629
+ timer.unref();
3630
+ }
3631
+ this.subs.push(() => {
3632
+ this.clearTimeoutFn(timer);
3633
+ });
3634
+ }
3635
+ this.subs.push(openSubDestroy);
3636
+ this.subs.push(errorSub);
3637
+ return this;
3638
+ }
3639
+ /**
3640
+ * Alias for open()
3641
+ *
3642
+ * @return self
3643
+ * @public
3644
+ */
3645
+ connect(fn) {
3646
+ return this.open(fn);
3647
+ }
3648
+ /**
3649
+ * Called upon transport open.
3650
+ *
3651
+ * @private
3652
+ */
3653
+ onopen() {
3654
+ // clear old subs
3655
+ this.cleanup();
3656
+ // mark as open
3657
+ this._readyState = "open";
3658
+ this.emitReserved("open");
3659
+ // add new subs
3660
+ const socket = this.engine;
3661
+ this.subs.push(on(socket, "ping", this.onping.bind(this)), on(socket, "data", this.ondata.bind(this)), on(socket, "error", this.onerror.bind(this)), on(socket, "close", this.onclose.bind(this)), on(this.decoder, "decoded", this.ondecoded.bind(this)));
3662
+ }
3663
+ /**
3664
+ * Called upon a ping.
3665
+ *
3666
+ * @private
3667
+ */
3668
+ onping() {
3669
+ this.emitReserved("ping");
3670
+ }
3671
+ /**
3672
+ * Called with data.
3673
+ *
3674
+ * @private
3675
+ */
3676
+ ondata(data) {
3677
+ try {
3678
+ this.decoder.add(data);
3679
+ }
3680
+ catch (e) {
3681
+ this.onclose("parse error", e);
3682
+ }
3683
+ }
3684
+ /**
3685
+ * Called when parser fully decodes a packet.
3686
+ *
3687
+ * @private
3688
+ */
3689
+ ondecoded(packet) {
3690
+ // the nextTick call prevents an exception in a user-provided event listener from triggering a disconnection due to a "parse error"
3691
+ nextTick(() => {
3692
+ this.emitReserved("packet", packet);
3693
+ }, this.setTimeoutFn);
3694
+ }
3695
+ /**
3696
+ * Called upon socket error.
3697
+ *
3698
+ * @private
3699
+ */
3700
+ onerror(err) {
3701
+ this.emitReserved("error", err);
3702
+ }
3703
+ /**
3704
+ * Creates a new socket for the given `nsp`.
3705
+ *
3706
+ * @return {Socket}
3707
+ * @public
3708
+ */
3709
+ socket(nsp, opts) {
3710
+ let socket = this.nsps[nsp];
3711
+ if (!socket) {
3712
+ socket = new Socket(this, nsp, opts);
3713
+ this.nsps[nsp] = socket;
3714
+ }
3715
+ else if (this._autoConnect && !socket.active) {
3716
+ socket.connect();
3717
+ }
3718
+ return socket;
3719
+ }
3720
+ /**
3721
+ * Called upon a socket close.
3722
+ *
3723
+ * @param socket
3724
+ * @private
3725
+ */
3726
+ _destroy(socket) {
3727
+ const nsps = Object.keys(this.nsps);
3728
+ for (const nsp of nsps) {
3729
+ const socket = this.nsps[nsp];
3730
+ if (socket.active) {
3731
+ return;
3732
+ }
3733
+ }
3734
+ this._close();
3735
+ }
3736
+ /**
3737
+ * Writes a packet.
3738
+ *
3739
+ * @param packet
3740
+ * @private
3741
+ */
3742
+ _packet(packet) {
3743
+ const encodedPackets = this.encoder.encode(packet);
3744
+ for (let i = 0; i < encodedPackets.length; i++) {
3745
+ this.engine.write(encodedPackets[i], packet.options);
3746
+ }
3747
+ }
3748
+ /**
3749
+ * Clean up transport subscriptions and packet buffer.
3750
+ *
3751
+ * @private
3752
+ */
3753
+ cleanup() {
3754
+ this.subs.forEach((subDestroy) => subDestroy());
3755
+ this.subs.length = 0;
3756
+ this.decoder.destroy();
3757
+ }
3758
+ /**
3759
+ * Close the current socket.
3760
+ *
3761
+ * @private
3762
+ */
3763
+ _close() {
3764
+ this.skipReconnect = true;
3765
+ this._reconnecting = false;
3766
+ this.onclose("forced close");
3767
+ if (this.engine)
3768
+ this.engine.close();
3769
+ }
3770
+ /**
3771
+ * Alias for close()
3772
+ *
3773
+ * @private
3774
+ */
3775
+ disconnect() {
3776
+ return this._close();
3777
+ }
3778
+ /**
3779
+ * Called upon engine close.
3780
+ *
3781
+ * @private
3782
+ */
3783
+ onclose(reason, description) {
3784
+ this.cleanup();
3785
+ this.backoff.reset();
3786
+ this._readyState = "closed";
3787
+ this.emitReserved("close", reason, description);
3788
+ if (this._reconnection && !this.skipReconnect) {
3789
+ this.reconnect();
3790
+ }
3791
+ }
3792
+ /**
3793
+ * Attempt a reconnection.
3794
+ *
3795
+ * @private
3796
+ */
3797
+ reconnect() {
3798
+ if (this._reconnecting || this.skipReconnect)
3799
+ return this;
3800
+ const self = this;
3801
+ if (this.backoff.attempts >= this._reconnectionAttempts) {
3802
+ this.backoff.reset();
3803
+ this.emitReserved("reconnect_failed");
3804
+ this._reconnecting = false;
3805
+ }
3806
+ else {
3807
+ const delay = this.backoff.duration();
3808
+ this._reconnecting = true;
3809
+ const timer = this.setTimeoutFn(() => {
3810
+ if (self.skipReconnect)
3811
+ return;
3812
+ this.emitReserved("reconnect_attempt", self.backoff.attempts);
3813
+ // check again for the case socket closed in above events
3814
+ if (self.skipReconnect)
3815
+ return;
3816
+ self.open((err) => {
3817
+ if (err) {
3818
+ self._reconnecting = false;
3819
+ self.reconnect();
3820
+ this.emitReserved("reconnect_error", err);
3821
+ }
3822
+ else {
3823
+ self.onreconnect();
3824
+ }
3825
+ });
3826
+ }, delay);
3827
+ if (this.opts.autoUnref) {
3828
+ timer.unref();
3829
+ }
3830
+ this.subs.push(() => {
3831
+ this.clearTimeoutFn(timer);
3832
+ });
3833
+ }
3834
+ }
3835
+ /**
3836
+ * Called upon successful reconnect.
3837
+ *
3838
+ * @private
3839
+ */
3840
+ onreconnect() {
3841
+ const attempt = this.backoff.attempts;
3842
+ this._reconnecting = false;
3843
+ this.backoff.reset();
3844
+ this.emitReserved("reconnect", attempt);
3845
+ }
3846
+ }
3847
+
3848
+ /**
3849
+ * Managers cache.
3850
+ */
3851
+ const cache = {};
3852
+ function lookup(uri, opts) {
3853
+ if (typeof uri === "object") {
3854
+ opts = uri;
3855
+ uri = undefined;
3856
+ }
3857
+ opts = opts || {};
3858
+ const parsed = url(uri, opts.path || "/socket.io");
3859
+ const source = parsed.source;
3860
+ const id = parsed.id;
3861
+ const path = parsed.path;
3862
+ const sameNamespace = cache[id] && path in cache[id]["nsps"];
3863
+ const newConnection = opts.forceNew ||
3864
+ opts["force new connection"] ||
3865
+ false === opts.multiplex ||
3866
+ sameNamespace;
3867
+ let io;
3868
+ if (newConnection) {
3869
+ io = new Manager(source, opts);
3870
+ }
3871
+ else {
3872
+ if (!cache[id]) {
3873
+ cache[id] = new Manager(source, opts);
3874
+ }
3875
+ io = cache[id];
3876
+ }
3877
+ if (parsed.query && !opts.query) {
3878
+ opts.query = parsed.queryKey;
3879
+ }
3880
+ return io.socket(parsed.path, opts);
3881
+ }
3882
+ // so that "lookup" can be used both as a function (e.g. `io(...)`) and as a
3883
+ // namespace (e.g. `io.connect(...)`), for backward compatibility
3884
+ Object.assign(lookup, {
3885
+ Manager,
3886
+ Socket,
3887
+ io: lookup,
3888
+ connect: lookup,
3889
+ });
3890
+
3891
+ const ClickOutsideOptionsDefaults = {
3892
+ triggerEvents: "click",
3893
+ exclude: ""
3894
+ };
3895
+ /**
3896
+ * Call this function as soon as the click outside of annotated method's host is done.
3897
+ * @example
3898
+ ```
3899
+ @ClickOutside()
3900
+ callback() {
3901
+ // this will run when click outside of element (host component) is done.
3902
+ }
3903
+ ```
3904
+ */
3905
+ function ClickOutside(opt = ClickOutsideOptionsDefaults) {
3906
+ return (proto, methodName) => {
3907
+ // this is to resolve the 'compiler optimization issue':
3908
+ // lifecycle events not being called when not explicitly declared in at least one of components from bundle
3909
+ Build.connectedCallback = true;
3910
+ Build.disconnectedCallback = true;
3911
+ const { connectedCallback, disconnectedCallback } = proto;
3912
+ proto.connectedCallback = function () {
3913
+ const host = getElement(this);
3914
+ const method = this[methodName];
3915
+ registerClickOutside(this, host, method, opt);
3916
+ return connectedCallback && connectedCallback.call(this);
3917
+ };
3918
+ proto.disconnectedCallback = function () {
3919
+ const host = getElement(this);
3920
+ const method = this[methodName];
3921
+ removeClickOutside(this, host, method, opt);
3922
+ return disconnectedCallback && disconnectedCallback.call(this);
3923
+ };
3924
+ };
3925
+ }
3926
+ /**
3927
+ * Register callback function for HTMLElement to be executed when user clicks outside of element.
3928
+ * @example
3929
+ ```
3930
+ <span
3931
+ ref={spanEl => registerClickOutside(this, spanEl, () => this.test())}>
3932
+ Hello, World!
3933
+ </span>;
3934
+ ```
3935
+ */
3936
+ function registerClickOutside(component, element, callback, opt = ClickOutsideOptionsDefaults) {
3937
+ const excludedNodes = getExcludedNodes(opt);
3938
+ getTriggerEvents(opt).forEach(triggerEvent => {
3939
+ window.addEventListener(triggerEvent, (e) => {
3940
+ initClickOutside(e, component, element, callback, excludedNodes);
3941
+ }, false);
3942
+ });
3943
+ }
3944
+ /**
3945
+ * Remove click outside callback function for HTMLElement.
3946
+ */
3947
+ function removeClickOutside(component, element, callback, opt = ClickOutsideOptionsDefaults) {
3948
+ getTriggerEvents(opt).forEach(triggerEvent => {
3949
+ window.removeEventListener(triggerEvent, (e) => {
3950
+ initClickOutside(e, component, element, callback);
3951
+ }, false);
3952
+ });
3953
+ }
3954
+ function initClickOutside(event, component, element, callback, excludedNodes) {
3955
+ const target = event.target;
3956
+ if (!element.contains(target) && !isExcluded(target, excludedNodes)) {
3957
+ callback.call(component);
3958
+ }
3959
+ }
3960
+ function getTriggerEvents(opt) {
3961
+ if (opt.triggerEvents) {
3962
+ return opt.triggerEvents.split(",").map(e => e.trim());
3963
+ }
3964
+ return ["click"];
3965
+ }
3966
+ function getExcludedNodes(opt) {
3967
+ if (opt.exclude) {
3968
+ try {
3969
+ return Array.from(document.querySelectorAll(opt.exclude));
3970
+ }
3971
+ catch (err) {
3972
+ console.warn(`@ClickOutside: Exclude: '${opt.exclude}' will not be evaluated. Check your exclude selector syntax.`, err);
3973
+ }
3974
+ }
3975
+ return;
3976
+ }
3977
+ function isExcluded(target, excudedNodes) {
3978
+ if (target && excudedNodes) {
3979
+ for (let excludedNode of excudedNodes) {
3980
+ if (excludedNode.contains(target)) {
3981
+ return true;
3982
+ }
3983
+ }
3984
+ }
3985
+ return false;
3986
+ }
3987
+
3988
+ const nutsInboxWidgetCss = ":host{display:block;font-family:\"Roboto\", \"Arial\", sans-serif}.BellIconWrapper{width:40px;height:40px}.BellIcon{width:40px;height:40px;display:flex}";
3989
+
3990
+ const NutsInboxWidget$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
3991
+ constructor() {
3992
+ super();
3993
+ this.__registerHost();
3994
+ this.__attachShadow();
3995
+ this.notificationFeed = createEvent(this, "notificationFeed", 7);
3996
+ this.newNotification = createEvent(this, "newNotification", 7);
3997
+ /**
3998
+ * Language of the widget
3999
+ */
4000
+ this.language = 'en';
4001
+ /**
4002
+ * Environment on which the widget is used (possible values: `stage`, `prod`)
4003
+ */
4004
+ this.environment = 'stage';
4005
+ /**
4006
+ * Client custom styling via inline styles
4007
+ */
4008
+ this.clientStyling = '';
4009
+ this.isLoading = true;
4010
+ this.popoverVisible = false;
4011
+ this.ntsEndpoint = 'https://nts.everymatrix.com/ss';
4012
+ this.token = null;
4013
+ this.setClientStyling = () => {
4014
+ let sheet = document.createElement('style');
4015
+ sheet.innerHTML = this.clientStyling;
4016
+ this.stylingContainer.prepend(sheet);
4017
+ };
4018
+ this.setClientStylingURL = () => {
4019
+ let url = new URL(this.clientStylingUrl);
4020
+ let cssFile = document.createElement('style');
4021
+ fetch(url.href)
4022
+ .then((res) => res.text())
4023
+ .then((data) => {
4024
+ cssFile.innerHTML = data;
4025
+ this.clientStyling = data;
4026
+ setTimeout(() => { this.stylingContainer.prepend(cssFile); }, 1);
4027
+ })
4028
+ .catch((err) => {
4029
+ console.log('error ', err);
4030
+ });
4031
+ };
4032
+ }
4033
+ paramChangeHandler(newValue, oldValue) {
4034
+ if (newValue != oldValue) {
4035
+ if (this.userId && this.sessionId && this.operatorId) {
4036
+ this.callSS();
4037
+ }
4038
+ }
4039
+ }
4040
+ initializeHandler(newValue, oldValue) {
4041
+ if (newValue != oldValue) {
4042
+ if (this.userId && this.operatorId && this.applicationIdentifier) {
4043
+ this.initializeSession();
4044
+ }
4045
+ }
4046
+ }
4047
+ clickOutsideHandle() {
4048
+ this.popoverVisible = false;
4049
+ }
4050
+ callSS() {
4051
+ const url = new URL(`${this.ntsEndpoint}/v1/${this.operatorId}/subscribers/${this.userId}`);
4052
+ if (this.deviceId) {
4053
+ url.searchParams.append('deviceToken', this.deviceId);
4054
+ }
4055
+ url.searchParams.append('language', this.language);
4056
+ const headers = new Headers();
4057
+ headers.append('authorization', this.sessionId);
4058
+ headers.append('Content-Type', 'application/json');
4059
+ const options = {
4060
+ method: 'GET',
4061
+ headers,
4062
+ };
4063
+ fetch(url.href, options)
4064
+ .then((res) => {
4065
+ if (res.status < 300) {
4066
+ return res.json();
4067
+ }
4068
+ })
4069
+ .catch((err) => {
4070
+ console.error('There was an error while trying to connect to the Notification System', err);
4071
+ })
4072
+ .finally(() => {
4073
+ this.isLoading = false;
4074
+ });
4075
+ }
4076
+ setupSocket() {
4077
+ if (this.token) {
4078
+ this.socketRef = lookup(this.socketUrl, {
4079
+ reconnectionDelayMax: 10000,
4080
+ transports: ['websocket'],
4081
+ auth: {
4082
+ token: `${this.token}`,
4083
+ },
4084
+ });
4085
+ this.socketRef.on('connect_error', (error) => {
4086
+ console.error('WebSocket error', error);
4087
+ });
4088
+ this.socketRef.on('notification_received', (data) => {
4089
+ this.newNotification.emit(data.message);
4090
+ });
4091
+ this.socketRef.on('unseen_count_changed', (data) => {
4092
+ this.unseenCount = data.unseenCount;
4093
+ });
4094
+ }
4095
+ }
4096
+ getUnseenCounter() {
4097
+ let url = new URL(`${this.backendUrl}/v1/widgets/notifications/unseen?limit=100`);
4098
+ const headers = new Headers();
4099
+ headers.append('Authorization', `Bearer ${this.token || ''}`);
4100
+ const options = {
4101
+ method: 'GET',
4102
+ headers,
4103
+ };
4104
+ fetch(url.href, options)
4105
+ .then((res) => res.json())
4106
+ .then((data) => {
4107
+ this.unseenCount = data.data.count;
4108
+ });
4109
+ }
4110
+ async initializeSession() {
4111
+ return new Promise((resolve, reject) => {
4112
+ let url = new URL(`${this.backendUrl}/v1/widgets/session/initialize`);
4113
+ const headers = new Headers();
4114
+ headers.append('Authorization', `Bearer ${this.token || ''}`);
4115
+ headers.append('Content-Type', 'application/json');
4116
+ const body = {
4117
+ applicationIdentifier: this.applicationIdentifier,
4118
+ subscriberId: `${this.operatorId}-${this.userId}`,
4119
+ hmacHash: null
4120
+ };
4121
+ const options = {
4122
+ method: 'POST',
4123
+ body: JSON.stringify(body),
4124
+ headers,
4125
+ };
4126
+ fetch(url.href, options)
4127
+ .then(res => res.json())
4128
+ .then((data) => {
4129
+ this.token = data.data.token;
4130
+ this.setupSocket();
4131
+ this.getUnseenCounter();
4132
+ resolve(data);
4133
+ })
4134
+ .catch((err) => {
4135
+ reject(err);
4136
+ });
4137
+ });
4138
+ }
4139
+ togglePopover() {
4140
+ this.popoverVisible = !this.popoverVisible;
4141
+ }
4142
+ async connectedCallback() {
4143
+ if (this.userId && this.operatorId && this.applicationIdentifier) {
4144
+ this.initializeSession();
4145
+ }
4146
+ if (this.userId && this.operatorId && this.sessionId) {
4147
+ this.callSS();
4148
+ }
4149
+ if (this.clientStylingUrl) {
4150
+ this.setClientStylingURL();
4151
+ }
4152
+ }
4153
+ renderBellIcon() {
4154
+ return (h("div", { onClick: () => this.togglePopover(), class: "BellIcon" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", fill: "currentColor", class: "bi bi-bell", viewBox: "0 0 16 16" }, " ", h("path", { d: "M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z" }), " "), this.unseenCount > 0 ? h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", class: "nc-bell-button-dot css-0 css-1eg2znq" }, h("rect", { x: "1.5", y: "1.5", width: "13", height: "13", rx: "6.5", fill: "url(#paint0_linear_1722_2699)", stroke: "#1E1E26", "stroke-width": "3" }), h("defs", null, h("linearGradient", { id: "paint0_linear_1722_2699", x1: "8", y1: "13", x2: "8", y2: "3", gradientUnits: "userSpaceOnUse" }, h("stop", { "stop-color": "#FF512F" }), h("stop", { offset: "1", "stop-color": "#DD2476" })))) : ''));
4155
+ }
4156
+ render() {
4157
+ return (h("div", { class: "BellIconWrapper", ref: el => this.stylingContainer = el }, !this.isLoading && this.renderBellIcon(), this.popoverVisible && h("nuts-popover", { "unseen-count": this.unseenCount, token: this.token, "backend-url": this.backendUrl, "operator-id": this.operatorId, "user-id": this.userId, language: this.language, "client-styling": this.clientStyling })));
4158
+ }
4159
+ static get watchers() { return {
4160
+ "userId": ["paramChangeHandler", "initializeHandler"],
4161
+ "sessionId": ["paramChangeHandler"],
4162
+ "operatorId": ["paramChangeHandler", "initializeHandler"],
4163
+ "deviceId": ["paramChangeHandler"],
4164
+ "applicationIdentifier": ["initializeHandler"]
4165
+ }; }
4166
+ static get style() { return nutsInboxWidgetCss; }
4167
+ }, [1, "nuts-inbox-widget", {
4168
+ "backendUrl": [513, "backend-url"],
4169
+ "socketUrl": [513, "socket-url"],
4170
+ "userId": [513, "user-id"],
4171
+ "sessionId": [513, "session-id"],
4172
+ "operatorId": [513, "operator-id"],
4173
+ "deviceId": [513, "device-id"],
4174
+ "language": [513],
4175
+ "environment": [513],
4176
+ "applicationIdentifier": [513, "application-identifier"],
4177
+ "clientStyling": [1537, "client-styling"],
4178
+ "clientStylingUrl": [513, "client-styling-url"],
4179
+ "isLoading": [32],
4180
+ "popoverVisible": [32],
4181
+ "unseenCount": [32]
4182
+ }]);
4183
+ __decorate([
4184
+ ClickOutside(),
4185
+ __metadata("design:type", Function),
4186
+ __metadata("design:paramtypes", []),
4187
+ __metadata("design:returntype", void 0)
4188
+ ], NutsInboxWidget$1.prototype, "clickOutsideHandle", null);
4189
+ function defineCustomElement$1() {
4190
+ if (typeof customElements === "undefined") {
4191
+ return;
4192
+ }
4193
+ const components = ["nuts-inbox-widget", "nuts-notification", "nuts-popover"];
4194
+ components.forEach(tagName => { switch (tagName) {
4195
+ case "nuts-inbox-widget":
4196
+ if (!customElements.get(tagName)) {
4197
+ customElements.define(tagName, NutsInboxWidget$1);
4198
+ }
4199
+ break;
4200
+ case "nuts-notification":
4201
+ if (!customElements.get(tagName)) {
4202
+ defineCustomElement$3();
4203
+ }
4204
+ break;
4205
+ case "nuts-popover":
4206
+ if (!customElements.get(tagName)) {
4207
+ defineCustomElement$2();
4208
+ }
4209
+ break;
4210
+ } });
4211
+ }
4212
+
4213
+ const NutsInboxWidget = NutsInboxWidget$1;
4214
+ const defineCustomElement = defineCustomElement$1;
4215
+
4216
+ export { NutsInboxWidget, defineCustomElement };