@xapp/chat-widget 1.70.2 → 1.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -2296,9 +2296,9 @@ var StentorDirectChat = /** @class */ (function () {
2296
2296
  return __assign(__assign({}, user), { nick: user.nick || bot.nick || "Bot", displayName: user.displayName || bot.displayName || "Bot", avatarPath: user.avatarPath || bot.avatarPath });
2297
2297
  };
2298
2298
  StentorDirectChat.prototype.sendChatMsgRequest = function (serviceRequest, cb) {
2299
- var _a;
2300
2299
  return __awaiter$1(this, void 0, void 0, function () {
2301
2300
  var agentResponse;
2301
+ var _a;
2302
2302
  return __generator$1(this, function (_b) {
2303
2303
  switch (_b.label) {
2304
2304
  case 0: return [4 /*yield*/, this.postMessage(serviceRequest)];
@@ -2354,10 +2354,10 @@ var StentorDirectChat = /** @class */ (function () {
2354
2354
  StentorDirectChat.prototype.wakeup = function () {
2355
2355
  };
2356
2356
  StentorDirectChat.prototype.postMessage = function (message) {
2357
- var _a, _b, _c, _d, _e;
2358
2357
  return __awaiter$1(this, void 0, void 0, function () {
2359
- var request, userId, sessionId, accessToken, attributes, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
2358
+ var request, userId, sessionId, accessToken, attributes, rwgToken, merchantId, environment, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
2360
2359
  var _this = this;
2360
+ var _a, _b, _c, _d, _e;
2361
2361
  return __generator$1(this, function (_f) {
2362
2362
  switch (_f.label) {
2363
2363
  case 0:
@@ -2365,6 +2365,18 @@ var StentorDirectChat = /** @class */ (function () {
2365
2365
  sessionId = this._sessionId;
2366
2366
  accessToken = this._accessToken;
2367
2367
  attributes = this._attributes || {};
2368
+ rwgToken = localStorage.getItem("xa_rwg_token");
2369
+ if (rwgToken) {
2370
+ attributes["rwg_token"] = rwgToken;
2371
+ }
2372
+ merchantId = localStorage.getItem("xa_merchant_id");
2373
+ if (merchantId) {
2374
+ attributes["merchant_id"] = merchantId;
2375
+ }
2376
+ environment = localStorage.getItem("xa_environment");
2377
+ if (environment) {
2378
+ attributes["environment"] = environment;
2379
+ }
2368
2380
  now = new Date().getTime();
2369
2381
  if (this.isNewSession && !((_a = message === null || message === void 0 ? void 0 : message.msg) === null || _a === void 0 ? void 0 : _a.text)) {
2370
2382
  request = {
@@ -2824,7 +2836,7 @@ var StentorRouterChat = /** @class */ (function () {
2824
2836
  _this.dispatch(setConnectionStatus("offline"));
2825
2837
  }
2826
2838
  };
2827
- // Server ping (not sent peroidically - at least not for now)
2839
+ // Server ping (not sent periodically - at least not for now)
2828
2840
  this.handlers["account status"] = function (_data, _sender, ts) {
2829
2841
  dispatch({
2830
2842
  type: "account_status",
@@ -3154,9 +3166,11 @@ var StentorRouterChat = /** @class */ (function () {
3154
3166
  nick: senderToNick(serverInfo),
3155
3167
  avatarPath: serverInfo.avatarPath
3156
3168
  },
3157
- msg: { text: this.noOfServerErrors === 0 ?
3169
+ msg: {
3170
+ text: this.noOfServerErrors === 0 ?
3158
3171
  "I cannot connect to the server. Please try later." :
3159
- "Nope. Still no luck. I still cannot connect to the server. Please don't give up." },
3172
+ "Nope. Still no luck. I still cannot connect to the server. Please don't give up."
3173
+ },
3160
3174
  timestamp: new Date().getTime(),
3161
3175
  }
3162
3176
  });
@@ -3279,12 +3293,24 @@ var StentorRouterChat = /** @class */ (function () {
3279
3293
  };
3280
3294
  StentorRouterChat.prototype.postMessage = function (message) {
3281
3295
  return __awaiter$1(this, void 0, void 0, function () {
3282
- var userId, sessionId, accessToken, attributes, request;
3296
+ var userId, sessionId, accessToken, attributes, rwgToken, merchantId, environment, request;
3283
3297
  return __generator$1(this, function (_a) {
3284
3298
  userId = this._userId;
3285
3299
  sessionId = this._sessionId;
3286
3300
  accessToken = this.accessToken;
3287
3301
  attributes = this.attributes || {};
3302
+ rwgToken = localStorage.getItem("xa_rwg_token");
3303
+ if (rwgToken) {
3304
+ attributes["rwg_token"] = rwgToken;
3305
+ }
3306
+ merchantId = localStorage.getItem("xa_merchant_id");
3307
+ if (merchantId) {
3308
+ attributes["merchant_id"] = merchantId;
3309
+ }
3310
+ environment = localStorage.getItem("xa_environment");
3311
+ if (environment) {
3312
+ attributes["environment"] = environment;
3313
+ }
3288
3314
  request = requestFromMessage(message, userId, this.isNewSession, sessionId, accessToken, attributes, this.visitorInfo);
3289
3315
  this.emit("new message", request);
3290
3316
  return [2 /*return*/];
@@ -3367,7 +3393,7 @@ PACKET_TYPES["message"] = "4";
3367
3393
  PACKET_TYPES["upgrade"] = "5";
3368
3394
  PACKET_TYPES["noop"] = "6";
3369
3395
  const PACKET_TYPES_REVERSE = Object.create(null);
3370
- Object.keys(PACKET_TYPES).forEach(key => {
3396
+ Object.keys(PACKET_TYPES).forEach((key) => {
3371
3397
  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
3372
3398
  });
3373
3399
  const ERROR_PACKET = { type: "error", data: "parser error" };
@@ -3377,7 +3403,7 @@ const withNativeBlob$1 = typeof Blob === "function" ||
3377
3403
  Object.prototype.toString.call(Blob) === "[object BlobConstructor]");
3378
3404
  const withNativeArrayBuffer$2 = typeof ArrayBuffer === "function";
3379
3405
  // ArrayBuffer.isView method is not defined in IE10
3380
- const isView$1 = obj => {
3406
+ const isView$1 = (obj) => {
3381
3407
  return typeof ArrayBuffer.isView === "function"
3382
3408
  ? ArrayBuffer.isView(obj)
3383
3409
  : obj && obj.buffer instanceof ArrayBuffer;
@@ -3411,6 +3437,33 @@ const encodeBlobAsBase64 = (data, callback) => {
3411
3437
  };
3412
3438
  return fileReader.readAsDataURL(data);
3413
3439
  };
3440
+ function toArray(data) {
3441
+ if (data instanceof Uint8Array) {
3442
+ return data;
3443
+ }
3444
+ else if (data instanceof ArrayBuffer) {
3445
+ return new Uint8Array(data);
3446
+ }
3447
+ else {
3448
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
3449
+ }
3450
+ }
3451
+ let TEXT_ENCODER;
3452
+ function encodePacketToBinary(packet, callback) {
3453
+ if (withNativeBlob$1 && packet.data instanceof Blob) {
3454
+ return packet.data.arrayBuffer().then(toArray).then(callback);
3455
+ }
3456
+ else if (withNativeArrayBuffer$2 &&
3457
+ (packet.data instanceof ArrayBuffer || isView$1(packet.data))) {
3458
+ return callback(toArray(packet.data));
3459
+ }
3460
+ encodePacket(packet, false, (encoded) => {
3461
+ if (!TEXT_ENCODER) {
3462
+ TEXT_ENCODER = new TextEncoder();
3463
+ }
3464
+ callback(TEXT_ENCODER.encode(encoded));
3465
+ });
3466
+ }
3414
3467
 
3415
3468
  // imported from https://github.com/socketio/base64-arraybuffer
3416
3469
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -3445,14 +3498,14 @@ const decodePacket = (encodedPacket, binaryType) => {
3445
3498
  if (typeof encodedPacket !== "string") {
3446
3499
  return {
3447
3500
  type: "message",
3448
- data: mapBinary(encodedPacket, binaryType)
3501
+ data: mapBinary(encodedPacket, binaryType),
3449
3502
  };
3450
3503
  }
3451
3504
  const type = encodedPacket.charAt(0);
3452
3505
  if (type === "b") {
3453
3506
  return {
3454
3507
  type: "message",
3455
- data: decodeBase64Packet(encodedPacket.substring(1), binaryType)
3508
+ data: decodeBase64Packet(encodedPacket.substring(1), binaryType),
3456
3509
  };
3457
3510
  }
3458
3511
  const packetType = PACKET_TYPES_REVERSE[type];
@@ -3462,10 +3515,10 @@ const decodePacket = (encodedPacket, binaryType) => {
3462
3515
  return encodedPacket.length > 1
3463
3516
  ? {
3464
3517
  type: PACKET_TYPES_REVERSE[type],
3465
- data: encodedPacket.substring(1)
3518
+ data: encodedPacket.substring(1),
3466
3519
  }
3467
3520
  : {
3468
- type: PACKET_TYPES_REVERSE[type]
3521
+ type: PACKET_TYPES_REVERSE[type],
3469
3522
  };
3470
3523
  };
3471
3524
  const decodeBase64Packet = (data, binaryType) => {
@@ -3480,10 +3533,24 @@ const decodeBase64Packet = (data, binaryType) => {
3480
3533
  const mapBinary = (data, binaryType) => {
3481
3534
  switch (binaryType) {
3482
3535
  case "blob":
3483
- return data instanceof ArrayBuffer ? new Blob([data]) : data;
3536
+ if (data instanceof Blob) {
3537
+ // from WebSocket + binaryType "blob"
3538
+ return data;
3539
+ }
3540
+ else {
3541
+ // from HTTP long-polling or WebTransport
3542
+ return new Blob([data]);
3543
+ }
3484
3544
  case "arraybuffer":
3485
3545
  default:
3486
- return data; // assuming the data is already an ArrayBuffer
3546
+ if (data instanceof ArrayBuffer) {
3547
+ // from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
3548
+ return data;
3549
+ }
3550
+ else {
3551
+ // from WebTransport (Uint8Array)
3552
+ return data.buffer;
3553
+ }
3487
3554
  }
3488
3555
  };
3489
3556
 
@@ -3495,7 +3562,7 @@ const encodePayload = (packets, callback) => {
3495
3562
  let count = 0;
3496
3563
  packets.forEach((packet, i) => {
3497
3564
  // force base64 encoding for binary packets
3498
- encodePacket(packet, false, encodedPacket => {
3565
+ encodePacket(packet, false, (encodedPacket) => {
3499
3566
  encodedPackets[i] = encodedPacket;
3500
3567
  if (++count === length) {
3501
3568
  callback(encodedPackets.join(SEPARATOR));
@@ -3515,6 +3582,131 @@ const decodePayload = (encodedPayload, binaryType) => {
3515
3582
  }
3516
3583
  return packets;
3517
3584
  };
3585
+ function createPacketEncoderStream() {
3586
+ // @ts-expect-error
3587
+ return new TransformStream({
3588
+ transform(packet, controller) {
3589
+ encodePacketToBinary(packet, (encodedPacket) => {
3590
+ const payloadLength = encodedPacket.length;
3591
+ let header;
3592
+ // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
3593
+ if (payloadLength < 126) {
3594
+ header = new Uint8Array(1);
3595
+ new DataView(header.buffer).setUint8(0, payloadLength);
3596
+ }
3597
+ else if (payloadLength < 65536) {
3598
+ header = new Uint8Array(3);
3599
+ const view = new DataView(header.buffer);
3600
+ view.setUint8(0, 126);
3601
+ view.setUint16(1, payloadLength);
3602
+ }
3603
+ else {
3604
+ header = new Uint8Array(9);
3605
+ const view = new DataView(header.buffer);
3606
+ view.setUint8(0, 127);
3607
+ view.setBigUint64(1, BigInt(payloadLength));
3608
+ }
3609
+ // first bit indicates whether the payload is plain text (0) or binary (1)
3610
+ if (packet.data && typeof packet.data !== "string") {
3611
+ header[0] |= 0x80;
3612
+ }
3613
+ controller.enqueue(header);
3614
+ controller.enqueue(encodedPacket);
3615
+ });
3616
+ },
3617
+ });
3618
+ }
3619
+ let TEXT_DECODER;
3620
+ function totalLength(chunks) {
3621
+ return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
3622
+ }
3623
+ function concatChunks(chunks, size) {
3624
+ if (chunks[0].length === size) {
3625
+ return chunks.shift();
3626
+ }
3627
+ const buffer = new Uint8Array(size);
3628
+ let j = 0;
3629
+ for (let i = 0; i < size; i++) {
3630
+ buffer[i] = chunks[0][j++];
3631
+ if (j === chunks[0].length) {
3632
+ chunks.shift();
3633
+ j = 0;
3634
+ }
3635
+ }
3636
+ if (chunks.length && j < chunks[0].length) {
3637
+ chunks[0] = chunks[0].slice(j);
3638
+ }
3639
+ return buffer;
3640
+ }
3641
+ function createPacketDecoderStream(maxPayload, binaryType) {
3642
+ if (!TEXT_DECODER) {
3643
+ TEXT_DECODER = new TextDecoder();
3644
+ }
3645
+ const chunks = [];
3646
+ let state = 0 /* READ_HEADER */;
3647
+ let expectedLength = -1;
3648
+ let isBinary = false;
3649
+ // @ts-expect-error
3650
+ return new TransformStream({
3651
+ transform(chunk, controller) {
3652
+ chunks.push(chunk);
3653
+ while (true) {
3654
+ if (state === 0 /* READ_HEADER */) {
3655
+ if (totalLength(chunks) < 1) {
3656
+ break;
3657
+ }
3658
+ const header = concatChunks(chunks, 1);
3659
+ isBinary = (header[0] & 0x80) === 0x80;
3660
+ expectedLength = header[0] & 0x7f;
3661
+ if (expectedLength < 126) {
3662
+ state = 3 /* READ_PAYLOAD */;
3663
+ }
3664
+ else if (expectedLength === 126) {
3665
+ state = 1 /* READ_EXTENDED_LENGTH_16 */;
3666
+ }
3667
+ else {
3668
+ state = 2 /* READ_EXTENDED_LENGTH_64 */;
3669
+ }
3670
+ }
3671
+ else if (state === 1 /* READ_EXTENDED_LENGTH_16 */) {
3672
+ if (totalLength(chunks) < 2) {
3673
+ break;
3674
+ }
3675
+ const headerArray = concatChunks(chunks, 2);
3676
+ expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
3677
+ state = 3 /* READ_PAYLOAD */;
3678
+ }
3679
+ else if (state === 2 /* READ_EXTENDED_LENGTH_64 */) {
3680
+ if (totalLength(chunks) < 8) {
3681
+ break;
3682
+ }
3683
+ const headerArray = concatChunks(chunks, 8);
3684
+ const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
3685
+ const n = view.getUint32(0);
3686
+ if (n > Math.pow(2, 53 - 32) - 1) {
3687
+ // the maximum safe integer in JavaScript is 2^53 - 1
3688
+ controller.enqueue(ERROR_PACKET);
3689
+ break;
3690
+ }
3691
+ expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
3692
+ state = 3 /* READ_PAYLOAD */;
3693
+ }
3694
+ else {
3695
+ if (totalLength(chunks) < expectedLength) {
3696
+ break;
3697
+ }
3698
+ const data = concatChunks(chunks, expectedLength);
3699
+ controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
3700
+ state = 0 /* READ_HEADER */;
3701
+ }
3702
+ if (expectedLength === 0 || expectedLength > maxPayload) {
3703
+ controller.enqueue(ERROR_PACKET);
3704
+ break;
3705
+ }
3706
+ }
3707
+ },
3708
+ });
3709
+ }
3518
3710
  const protocol$1 = 4;
3519
3711
 
3520
3712
  /**
@@ -3714,16 +3906,16 @@ function pick(obj, ...attr) {
3714
3906
  }, {});
3715
3907
  }
3716
3908
  // Keep a reference to the real timeout functions so they can be used when overridden
3717
- const NATIVE_SET_TIMEOUT = setTimeout;
3718
- const NATIVE_CLEAR_TIMEOUT = clearTimeout;
3909
+ const NATIVE_SET_TIMEOUT = globalThisShim.setTimeout;
3910
+ const NATIVE_CLEAR_TIMEOUT = globalThisShim.clearTimeout;
3719
3911
  function installTimerFunctions(obj, opts) {
3720
3912
  if (opts.useNativeTimers) {
3721
3913
  obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThisShim);
3722
3914
  obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThisShim);
3723
3915
  }
3724
3916
  else {
3725
- obj.setTimeoutFn = setTimeout.bind(globalThisShim);
3726
- obj.clearTimeoutFn = clearTimeout.bind(globalThisShim);
3917
+ obj.setTimeoutFn = globalThisShim.setTimeout.bind(globalThisShim);
3918
+ obj.clearTimeoutFn = globalThisShim.clearTimeout.bind(globalThisShim);
3727
3919
  }
3728
3920
  }
3729
3921
  // base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
@@ -3757,6 +3949,41 @@ function utf8Length(str) {
3757
3949
  return length;
3758
3950
  }
3759
3951
 
3952
+ // imported from https://github.com/galkn/querystring
3953
+ /**
3954
+ * Compiles a querystring
3955
+ * Returns string representation of the object
3956
+ *
3957
+ * @param {Object}
3958
+ * @api private
3959
+ */
3960
+ function encode$1(obj) {
3961
+ let str = '';
3962
+ for (let i in obj) {
3963
+ if (obj.hasOwnProperty(i)) {
3964
+ if (str.length)
3965
+ str += '&';
3966
+ str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3967
+ }
3968
+ }
3969
+ return str;
3970
+ }
3971
+ /**
3972
+ * Parses a simple querystring into an object
3973
+ *
3974
+ * @param {String} qs
3975
+ * @api private
3976
+ */
3977
+ function decode(qs) {
3978
+ let qry = {};
3979
+ let pairs = qs.split('&');
3980
+ for (let i = 0, l = pairs.length; i < l; i++) {
3981
+ let pair = pairs[i].split('=');
3982
+ qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3983
+ }
3984
+ return qry;
3985
+ }
3986
+
3760
3987
  class TransportError extends Error {
3761
3988
  constructor(reason, description, context) {
3762
3989
  super(reason);
@@ -3769,8 +3996,8 @@ class Transport extends Emitter_1 {
3769
3996
  /**
3770
3997
  * Transport abstract constructor.
3771
3998
  *
3772
- * @param {Object} options.
3773
- * @api private
3999
+ * @param {Object} opts - options
4000
+ * @protected
3774
4001
  */
3775
4002
  constructor(opts) {
3776
4003
  super();
@@ -3778,7 +4005,6 @@ class Transport extends Emitter_1 {
3778
4005
  installTimerFunctions(this, opts);
3779
4006
  this.opts = opts;
3780
4007
  this.query = opts.query;
3781
- this.readyState = "";
3782
4008
  this.socket = opts.socket;
3783
4009
  }
3784
4010
  /**
@@ -3788,7 +4014,7 @@ class Transport extends Emitter_1 {
3788
4014
  * @param description
3789
4015
  * @param context - the error context
3790
4016
  * @return {Transport} for chaining
3791
- * @api protected
4017
+ * @protected
3792
4018
  */
3793
4019
  onError(reason, description, context) {
3794
4020
  super.emitReserved("error", new TransportError(reason, description, context));
@@ -3796,23 +4022,17 @@ class Transport extends Emitter_1 {
3796
4022
  }
3797
4023
  /**
3798
4024
  * Opens the transport.
3799
- *
3800
- * @api public
3801
4025
  */
3802
4026
  open() {
3803
- if ("closed" === this.readyState || "" === this.readyState) {
3804
- this.readyState = "opening";
3805
- this.doOpen();
3806
- }
4027
+ this.readyState = "opening";
4028
+ this.doOpen();
3807
4029
  return this;
3808
4030
  }
3809
4031
  /**
3810
4032
  * Closes the transport.
3811
- *
3812
- * @api public
3813
4033
  */
3814
4034
  close() {
3815
- if ("opening" === this.readyState || "open" === this.readyState) {
4035
+ if (this.readyState === "opening" || this.readyState === "open") {
3816
4036
  this.doClose();
3817
4037
  this.onClose();
3818
4038
  }
@@ -3822,17 +4042,16 @@ class Transport extends Emitter_1 {
3822
4042
  * Sends multiple packets.
3823
4043
  *
3824
4044
  * @param {Array} packets
3825
- * @api public
3826
4045
  */
3827
4046
  send(packets) {
3828
- if ("open" === this.readyState) {
4047
+ if (this.readyState === "open") {
3829
4048
  this.write(packets);
3830
4049
  }
3831
4050
  }
3832
4051
  /**
3833
4052
  * Called upon open
3834
4053
  *
3835
- * @api protected
4054
+ * @protected
3836
4055
  */
3837
4056
  onOpen() {
3838
4057
  this.readyState = "open";
@@ -3843,7 +4062,7 @@ class Transport extends Emitter_1 {
3843
4062
  * Called with data.
3844
4063
  *
3845
4064
  * @param {String} data
3846
- * @api protected
4065
+ * @protected
3847
4066
  */
3848
4067
  onData(data) {
3849
4068
  const packet = decodePacket(data, this.socket.binaryType);
@@ -3852,7 +4071,7 @@ class Transport extends Emitter_1 {
3852
4071
  /**
3853
4072
  * Called with a decoded packet.
3854
4073
  *
3855
- * @api protected
4074
+ * @protected
3856
4075
  */
3857
4076
  onPacket(packet) {
3858
4077
  super.emitReserved("packet", packet);
@@ -3860,12 +4079,44 @@ class Transport extends Emitter_1 {
3860
4079
  /**
3861
4080
  * Called upon close.
3862
4081
  *
3863
- * @api protected
4082
+ * @protected
3864
4083
  */
3865
4084
  onClose(details) {
3866
4085
  this.readyState = "closed";
3867
4086
  super.emitReserved("close", details);
3868
4087
  }
4088
+ /**
4089
+ * Pauses the transport, in order not to lose packets during an upgrade.
4090
+ *
4091
+ * @param onPause
4092
+ */
4093
+ pause(onPause) { }
4094
+ createUri(schema, query = {}) {
4095
+ return (schema +
4096
+ "://" +
4097
+ this._hostname() +
4098
+ this._port() +
4099
+ this.opts.path +
4100
+ this._query(query));
4101
+ }
4102
+ _hostname() {
4103
+ const hostname = this.opts.hostname;
4104
+ return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
4105
+ }
4106
+ _port() {
4107
+ if (this.opts.port &&
4108
+ ((this.opts.secure && Number(this.opts.port !== 443)) ||
4109
+ (!this.opts.secure && Number(this.opts.port) !== 80))) {
4110
+ return ":" + this.opts.port;
4111
+ }
4112
+ else {
4113
+ return "";
4114
+ }
4115
+ }
4116
+ _query(query) {
4117
+ const encodedQuery = encode$1(query);
4118
+ return encodedQuery.length ? "?" + encodedQuery : "";
4119
+ }
3869
4120
  }
3870
4121
 
3871
4122
  // imported from https://github.com/unshiftio/yeast
@@ -3878,7 +4129,7 @@ let seed = 0, i = 0, prev;
3878
4129
  * @returns {String} The string representation of the number.
3879
4130
  * @api public
3880
4131
  */
3881
- function encode$1(num) {
4132
+ function encode(num) {
3882
4133
  let encoded = '';
3883
4134
  do {
3884
4135
  encoded = alphabet[num % length] + encoded;
@@ -3893,10 +4144,10 @@ function encode$1(num) {
3893
4144
  * @api public
3894
4145
  */
3895
4146
  function yeast() {
3896
- const now = encode$1(+new Date());
4147
+ const now = encode(+new Date());
3897
4148
  if (now !== prev)
3898
4149
  return seed = 0, prev = now;
3899
- return now + '.' + encode$1(seed++);
4150
+ return now + '.' + encode(seed++);
3900
4151
  }
3901
4152
  //
3902
4153
  // Map each character to its index.
@@ -3904,41 +4155,6 @@ function yeast() {
3904
4155
  for (; i < length; i++)
3905
4156
  map[alphabet[i]] = i;
3906
4157
 
3907
- // imported from https://github.com/galkn/querystring
3908
- /**
3909
- * Compiles a querystring
3910
- * Returns string representation of the object
3911
- *
3912
- * @param {Object}
3913
- * @api private
3914
- */
3915
- function encode(obj) {
3916
- let str = '';
3917
- for (let i in obj) {
3918
- if (obj.hasOwnProperty(i)) {
3919
- if (str.length)
3920
- str += '&';
3921
- str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3922
- }
3923
- }
3924
- return str;
3925
- }
3926
- /**
3927
- * Parses a simple querystring into an object
3928
- *
3929
- * @param {String} qs
3930
- * @api private
3931
- */
3932
- function decode(qs) {
3933
- let qry = {};
3934
- let pairs = qs.split('&');
3935
- for (let i = 0, l = pairs.length; i < l; i++) {
3936
- let pair = pairs[i].split('=');
3937
- qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3938
- }
3939
- return qry;
3940
- }
3941
-
3942
4158
  // imported from https://github.com/component/has-cors
3943
4159
  let value = false;
3944
4160
  try {
@@ -3968,11 +4184,12 @@ function XHR(opts) {
3968
4184
  catch (e) { }
3969
4185
  }
3970
4186
  }
4187
+ function createCookieJar() { }
3971
4188
 
3972
4189
  function empty$2() { }
3973
4190
  const hasXHR2 = (function () {
3974
4191
  const xhr = new XHR({
3975
- xdomain: false
4192
+ xdomain: false,
3976
4193
  });
3977
4194
  return null != xhr.responseType;
3978
4195
  })();
@@ -3981,7 +4198,7 @@ class Polling extends Transport {
3981
4198
  * XHR Polling constructor.
3982
4199
  *
3983
4200
  * @param {Object} opts
3984
- * @api public
4201
+ * @package
3985
4202
  */
3986
4203
  constructor(opts) {
3987
4204
  super(opts);
@@ -3997,17 +4214,16 @@ class Polling extends Transport {
3997
4214
  (typeof location !== "undefined" &&
3998
4215
  opts.hostname !== location.hostname) ||
3999
4216
  port !== opts.port;
4000
- this.xs = opts.secure !== isSSL;
4001
4217
  }
4002
4218
  /**
4003
4219
  * XHR supports binary
4004
4220
  */
4005
4221
  const forceBase64 = opts && opts.forceBase64;
4006
4222
  this.supportsBinary = hasXHR2 && !forceBase64;
4223
+ if (this.opts.withCredentials) {
4224
+ this.cookieJar = createCookieJar();
4225
+ }
4007
4226
  }
4008
- /**
4009
- * Transport name.
4010
- */
4011
4227
  get name() {
4012
4228
  return "polling";
4013
4229
  }
@@ -4015,7 +4231,7 @@ class Polling extends Transport {
4015
4231
  * Opens the socket (triggers polling). We write a PING message to determine
4016
4232
  * when the transport is open.
4017
4233
  *
4018
- * @api private
4234
+ * @protected
4019
4235
  */
4020
4236
  doOpen() {
4021
4237
  this.poll();
@@ -4023,8 +4239,8 @@ class Polling extends Transport {
4023
4239
  /**
4024
4240
  * Pauses polling.
4025
4241
  *
4026
- * @param {Function} callback upon buffers are flushed and transport is paused
4027
- * @api private
4242
+ * @param {Function} onPause - callback upon buffers are flushed and transport is paused
4243
+ * @package
4028
4244
  */
4029
4245
  pause(onPause) {
4030
4246
  this.readyState = "pausing";
@@ -4054,7 +4270,7 @@ class Polling extends Transport {
4054
4270
  /**
4055
4271
  * Starts polling cycle.
4056
4272
  *
4057
- * @api public
4273
+ * @private
4058
4274
  */
4059
4275
  poll() {
4060
4276
  this.polling = true;
@@ -4064,10 +4280,10 @@ class Polling extends Transport {
4064
4280
  /**
4065
4281
  * Overloads onData to detect payloads.
4066
4282
  *
4067
- * @api private
4283
+ * @protected
4068
4284
  */
4069
4285
  onData(data) {
4070
- const callback = packet => {
4286
+ const callback = (packet) => {
4071
4287
  // if its the first message we consider the transport open
4072
4288
  if ("opening" === this.readyState && packet.type === "open") {
4073
4289
  this.onOpen();
@@ -4095,7 +4311,7 @@ class Polling extends Transport {
4095
4311
  /**
4096
4312
  * For polling, send a close packet.
4097
4313
  *
4098
- * @api private
4314
+ * @protected
4099
4315
  */
4100
4316
  doClose() {
4101
4317
  const close = () => {
@@ -4113,13 +4329,12 @@ class Polling extends Transport {
4113
4329
  /**
4114
4330
  * Writes a packets payload.
4115
4331
  *
4116
- * @param {Array} data packets
4117
- * @param {Function} drain callback
4118
- * @api private
4332
+ * @param {Array} packets - data packets
4333
+ * @protected
4119
4334
  */
4120
4335
  write(packets) {
4121
4336
  this.writable = false;
4122
- encodePayload(packets, data => {
4337
+ encodePayload(packets, (data) => {
4123
4338
  this.doWrite(data, () => {
4124
4339
  this.writable = true;
4125
4340
  this.emitReserved("drain");
@@ -4129,12 +4344,11 @@ class Polling extends Transport {
4129
4344
  /**
4130
4345
  * Generates uri for connection.
4131
4346
  *
4132
- * @api private
4347
+ * @private
4133
4348
  */
4134
4349
  uri() {
4135
- let query = this.query || {};
4136
4350
  const schema = this.opts.secure ? "https" : "http";
4137
- let port = "";
4351
+ const query = this.query || {};
4138
4352
  // cache busting is forced
4139
4353
  if (false !== this.opts.timestampRequests) {
4140
4354
  query[this.opts.timestampParam] = yeast();
@@ -4142,29 +4356,16 @@ class Polling extends Transport {
4142
4356
  if (!this.supportsBinary && !query.sid) {
4143
4357
  query.b64 = 1;
4144
4358
  }
4145
- // avoid port if default for schema
4146
- if (this.opts.port &&
4147
- (("https" === schema && Number(this.opts.port) !== 443) ||
4148
- ("http" === schema && Number(this.opts.port) !== 80))) {
4149
- port = ":" + this.opts.port;
4150
- }
4151
- const encodedQuery = encode(query);
4152
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4153
- return (schema +
4154
- "://" +
4155
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4156
- port +
4157
- this.opts.path +
4158
- (encodedQuery.length ? "?" + encodedQuery : ""));
4359
+ return this.createUri(schema, query);
4159
4360
  }
4160
4361
  /**
4161
4362
  * Creates a request.
4162
4363
  *
4163
4364
  * @param {String} method
4164
- * @api private
4365
+ * @private
4165
4366
  */
4166
4367
  request(opts = {}) {
4167
- Object.assign(opts, { xd: this.xd, xs: this.xs }, this.opts);
4368
+ Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
4168
4369
  return new Request(this.uri(), opts);
4169
4370
  }
4170
4371
  /**
@@ -4172,12 +4373,12 @@ class Polling extends Transport {
4172
4373
  *
4173
4374
  * @param {String} data to send.
4174
4375
  * @param {Function} called upon flush.
4175
- * @api private
4376
+ * @private
4176
4377
  */
4177
4378
  doWrite(data, fn) {
4178
4379
  const req = this.request({
4179
4380
  method: "POST",
4180
- data: data
4381
+ data: data,
4181
4382
  });
4182
4383
  req.on("success", fn);
4183
4384
  req.on("error", (xhrStatus, context) => {
@@ -4187,7 +4388,7 @@ class Polling extends Transport {
4187
4388
  /**
4188
4389
  * Starts a poll cycle.
4189
4390
  *
4190
- * @api private
4391
+ * @private
4191
4392
  */
4192
4393
  doPoll() {
4193
4394
  const req = this.request();
@@ -4203,7 +4404,7 @@ class Request extends Emitter_1 {
4203
4404
  * Request constructor
4204
4405
  *
4205
4406
  * @param {Object} options
4206
- * @api public
4407
+ * @package
4207
4408
  */
4208
4409
  constructor(uri, opts) {
4209
4410
  super();
@@ -4211,22 +4412,21 @@ class Request extends Emitter_1 {
4211
4412
  this.opts = opts;
4212
4413
  this.method = opts.method || "GET";
4213
4414
  this.uri = uri;
4214
- this.async = false !== opts.async;
4215
4415
  this.data = undefined !== opts.data ? opts.data : null;
4216
4416
  this.create();
4217
4417
  }
4218
4418
  /**
4219
4419
  * Creates the XHR object and sends the request.
4220
4420
  *
4221
- * @api private
4421
+ * @private
4222
4422
  */
4223
4423
  create() {
4424
+ var _a;
4224
4425
  const opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4225
4426
  opts.xdomain = !!this.opts.xd;
4226
- opts.xscheme = !!this.opts.xs;
4227
4427
  const xhr = (this.xhr = new XHR(opts));
4228
4428
  try {
4229
- xhr.open(this.method, this.uri, this.async);
4429
+ xhr.open(this.method, this.uri, true);
4230
4430
  try {
4231
4431
  if (this.opts.extraHeaders) {
4232
4432
  xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
@@ -4248,6 +4448,7 @@ class Request extends Emitter_1 {
4248
4448
  xhr.setRequestHeader("Accept", "*/*");
4249
4449
  }
4250
4450
  catch (e) { }
4451
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4251
4452
  // ie6 check
4252
4453
  if ("withCredentials" in xhr) {
4253
4454
  xhr.withCredentials = this.opts.withCredentials;
@@ -4256,6 +4457,10 @@ class Request extends Emitter_1 {
4256
4457
  xhr.timeout = this.opts.requestTimeout;
4257
4458
  }
4258
4459
  xhr.onreadystatechange = () => {
4460
+ var _a;
4461
+ if (xhr.readyState === 3) {
4462
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
4463
+ }
4259
4464
  if (4 !== xhr.readyState)
4260
4465
  return;
4261
4466
  if (200 === xhr.status || 1223 === xhr.status) {
@@ -4288,7 +4493,7 @@ class Request extends Emitter_1 {
4288
4493
  /**
4289
4494
  * Called upon error.
4290
4495
  *
4291
- * @api private
4496
+ * @private
4292
4497
  */
4293
4498
  onError(err) {
4294
4499
  this.emitReserved("error", err, this.xhr);
@@ -4297,7 +4502,7 @@ class Request extends Emitter_1 {
4297
4502
  /**
4298
4503
  * Cleans up house.
4299
4504
  *
4300
- * @api private
4505
+ * @private
4301
4506
  */
4302
4507
  cleanup(fromError) {
4303
4508
  if ("undefined" === typeof this.xhr || null === this.xhr) {
@@ -4318,7 +4523,7 @@ class Request extends Emitter_1 {
4318
4523
  /**
4319
4524
  * Called upon load.
4320
4525
  *
4321
- * @api private
4526
+ * @private
4322
4527
  */
4323
4528
  onLoad() {
4324
4529
  const data = this.xhr.responseText;
@@ -4331,7 +4536,7 @@ class Request extends Emitter_1 {
4331
4536
  /**
4332
4537
  * Aborts the request.
4333
4538
  *
4334
- * @api public
4539
+ * @package
4335
4540
  */
4336
4541
  abort() {
4337
4542
  this.cleanup();
@@ -4366,7 +4571,7 @@ function unloadHandler() {
4366
4571
  const nextTick = (() => {
4367
4572
  const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
4368
4573
  if (isPromiseAvailable) {
4369
- return cb => Promise.resolve().then(cb);
4574
+ return (cb) => Promise.resolve().then(cb);
4370
4575
  }
4371
4576
  else {
4372
4577
  return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
@@ -4384,26 +4589,16 @@ class WS extends Transport {
4384
4589
  /**
4385
4590
  * WebSocket transport constructor.
4386
4591
  *
4387
- * @api {Object} connection options
4388
- * @api public
4592
+ * @param {Object} opts - connection options
4593
+ * @protected
4389
4594
  */
4390
4595
  constructor(opts) {
4391
4596
  super(opts);
4392
4597
  this.supportsBinary = !opts.forceBase64;
4393
4598
  }
4394
- /**
4395
- * Transport name.
4396
- *
4397
- * @api public
4398
- */
4399
4599
  get name() {
4400
4600
  return "websocket";
4401
4601
  }
4402
- /**
4403
- * Opens socket.
4404
- *
4405
- * @api private
4406
- */
4407
4602
  doOpen() {
4408
4603
  if (!this.check()) {
4409
4604
  // let probe timeout
@@ -4429,13 +4624,13 @@ class WS extends Transport {
4429
4624
  catch (err) {
4430
4625
  return this.emitReserved("error", err);
4431
4626
  }
4432
- this.ws.binaryType = this.socket.binaryType || defaultBinaryType;
4627
+ this.ws.binaryType = this.socket.binaryType;
4433
4628
  this.addEventListeners();
4434
4629
  }
4435
4630
  /**
4436
4631
  * Adds event listeners to the socket
4437
4632
  *
4438
- * @api private
4633
+ * @private
4439
4634
  */
4440
4635
  addEventListeners() {
4441
4636
  this.ws.onopen = () => {
@@ -4444,19 +4639,13 @@ class WS extends Transport {
4444
4639
  }
4445
4640
  this.onOpen();
4446
4641
  };
4447
- this.ws.onclose = closeEvent => this.onClose({
4642
+ this.ws.onclose = (closeEvent) => this.onClose({
4448
4643
  description: "websocket connection closed",
4449
- context: closeEvent
4644
+ context: closeEvent,
4450
4645
  });
4451
- this.ws.onmessage = ev => this.onData(ev.data);
4452
- this.ws.onerror = e => this.onError("websocket error", e);
4646
+ this.ws.onmessage = (ev) => this.onData(ev.data);
4647
+ this.ws.onerror = (e) => this.onError("websocket error", e);
4453
4648
  }
4454
- /**
4455
- * Writes data to socket.
4456
- *
4457
- * @param {Array} array of packets.
4458
- * @api private
4459
- */
4460
4649
  write(packets) {
4461
4650
  this.writable = false;
4462
4651
  // encodePacket efficient as it uses WS framing
@@ -4464,7 +4653,7 @@ class WS extends Transport {
4464
4653
  for (let i = 0; i < packets.length; i++) {
4465
4654
  const packet = packets[i];
4466
4655
  const lastPacket = i === packets.length - 1;
4467
- encodePacket(packet, this.supportsBinary, data => {
4656
+ encodePacket(packet, this.supportsBinary, (data) => {
4468
4657
  // always create a new object (GH-437)
4469
4658
  const opts = {};
4470
4659
  // Sometimes the websocket has already been closed but the browser didn't
@@ -4489,11 +4678,6 @@ class WS extends Transport {
4489
4678
  });
4490
4679
  }
4491
4680
  }
4492
- /**
4493
- * Closes socket.
4494
- *
4495
- * @api private
4496
- */
4497
4681
  doClose() {
4498
4682
  if (typeof this.ws !== "undefined") {
4499
4683
  this.ws.close();
@@ -4503,18 +4687,11 @@ class WS extends Transport {
4503
4687
  /**
4504
4688
  * Generates uri for connection.
4505
4689
  *
4506
- * @api private
4690
+ * @private
4507
4691
  */
4508
4692
  uri() {
4509
- let query = this.query || {};
4510
4693
  const schema = this.opts.secure ? "wss" : "ws";
4511
- let port = "";
4512
- // avoid port if default for schema
4513
- if (this.opts.port &&
4514
- (("wss" === schema && Number(this.opts.port) !== 443) ||
4515
- ("ws" === schema && Number(this.opts.port) !== 80))) {
4516
- port = ":" + this.opts.port;
4517
- }
4694
+ const query = this.query || {};
4518
4695
  // append timestamp to URI
4519
4696
  if (this.opts.timestampRequests) {
4520
4697
  query[this.opts.timestampParam] = yeast();
@@ -4523,43 +4700,121 @@ class WS extends Transport {
4523
4700
  if (!this.supportsBinary) {
4524
4701
  query.b64 = 1;
4525
4702
  }
4526
- const encodedQuery = encode(query);
4527
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4528
- return (schema +
4529
- "://" +
4530
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4531
- port +
4532
- this.opts.path +
4533
- (encodedQuery.length ? "?" + encodedQuery : ""));
4703
+ return this.createUri(schema, query);
4534
4704
  }
4535
4705
  /**
4536
4706
  * Feature detection for WebSocket.
4537
4707
  *
4538
4708
  * @return {Boolean} whether this transport is available.
4539
- * @api public
4709
+ * @private
4540
4710
  */
4541
4711
  check() {
4542
4712
  return !!WebSocket$1;
4543
4713
  }
4544
4714
  }
4545
4715
 
4716
+ class WT extends Transport {
4717
+ get name() {
4718
+ return "webtransport";
4719
+ }
4720
+ doOpen() {
4721
+ // @ts-ignore
4722
+ if (typeof WebTransport !== "function") {
4723
+ return;
4724
+ }
4725
+ // @ts-ignore
4726
+ this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4727
+ this.transport.closed
4728
+ .then(() => {
4729
+ this.onClose();
4730
+ })
4731
+ .catch((err) => {
4732
+ this.onError("webtransport error", err);
4733
+ });
4734
+ // note: we could have used async/await, but that would require some additional polyfills
4735
+ this.transport.ready.then(() => {
4736
+ this.transport.createBidirectionalStream().then((stream) => {
4737
+ const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
4738
+ const reader = stream.readable.pipeThrough(decoderStream).getReader();
4739
+ const encoderStream = createPacketEncoderStream();
4740
+ encoderStream.readable.pipeTo(stream.writable);
4741
+ this.writer = encoderStream.writable.getWriter();
4742
+ const read = () => {
4743
+ reader
4744
+ .read()
4745
+ .then(({ done, value }) => {
4746
+ if (done) {
4747
+ return;
4748
+ }
4749
+ this.onPacket(value);
4750
+ read();
4751
+ })
4752
+ .catch((err) => {
4753
+ });
4754
+ };
4755
+ read();
4756
+ const packet = { type: "open" };
4757
+ if (this.query.sid) {
4758
+ packet.data = `{"sid":"${this.query.sid}"}`;
4759
+ }
4760
+ this.writer.write(packet).then(() => this.onOpen());
4761
+ });
4762
+ });
4763
+ }
4764
+ write(packets) {
4765
+ this.writable = false;
4766
+ for (let i = 0; i < packets.length; i++) {
4767
+ const packet = packets[i];
4768
+ const lastPacket = i === packets.length - 1;
4769
+ this.writer.write(packet).then(() => {
4770
+ if (lastPacket) {
4771
+ nextTick(() => {
4772
+ this.writable = true;
4773
+ this.emitReserved("drain");
4774
+ }, this.setTimeoutFn);
4775
+ }
4776
+ });
4777
+ }
4778
+ }
4779
+ doClose() {
4780
+ var _a;
4781
+ (_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
4782
+ }
4783
+ }
4784
+
4546
4785
  const transports = {
4547
4786
  websocket: WS,
4548
- polling: Polling
4787
+ webtransport: WT,
4788
+ polling: Polling,
4549
4789
  };
4550
4790
 
4551
4791
  // imported from https://github.com/galkn/parseuri
4552
4792
  /**
4553
- * Parses an URI
4793
+ * Parses a URI
4794
+ *
4795
+ * Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
4796
+ *
4797
+ * See:
4798
+ * - https://developer.mozilla.org/en-US/docs/Web/API/URL
4799
+ * - https://caniuse.com/url
4800
+ * - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
4801
+ *
4802
+ * History of the parse() method:
4803
+ * - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
4804
+ * - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
4805
+ * - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
4554
4806
  *
4555
4807
  * @author Steven Levithan <stevenlevithan.com> (MIT license)
4556
4808
  * @api private
4557
4809
  */
4558
- const re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4810
+ const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4559
4811
  const parts = [
4560
4812
  'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
4561
4813
  ];
4562
4814
  function parse$2(str) {
4815
+ if (str.length > 2000) {
4816
+ throw "URI too long";
4817
+ }
4563
4818
  const src = str, b = str.indexOf('['), e = str.indexOf(']');
4564
4819
  if (b != -1 && e != -1) {
4565
4820
  str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
@@ -4602,12 +4857,13 @@ class Socket$1 extends Emitter_1 {
4602
4857
  /**
4603
4858
  * Socket constructor.
4604
4859
  *
4605
- * @param {String|Object} uri or options
4860
+ * @param {String|Object} uri - uri or options
4606
4861
  * @param {Object} opts - options
4607
- * @api public
4608
4862
  */
4609
4863
  constructor(uri, opts = {}) {
4610
4864
  super();
4865
+ this.binaryType = defaultBinaryType;
4866
+ this.writeBuffer = [];
4611
4867
  if (uri && "object" === typeof uri) {
4612
4868
  opts = uri;
4613
4869
  uri = null;
@@ -4642,8 +4898,11 @@ class Socket$1 extends Emitter_1 {
4642
4898
  : this.secure
4643
4899
  ? "443"
4644
4900
  : "80");
4645
- this.transports = opts.transports || ["polling", "websocket"];
4646
- this.readyState = "";
4901
+ this.transports = opts.transports || [
4902
+ "polling",
4903
+ "websocket",
4904
+ "webtransport",
4905
+ ];
4647
4906
  this.writeBuffer = [];
4648
4907
  this.prevBufferLen = 0;
4649
4908
  this.opts = Object.assign({
@@ -4653,14 +4912,17 @@ class Socket$1 extends Emitter_1 {
4653
4912
  upgrade: true,
4654
4913
  timestampParam: "t",
4655
4914
  rememberUpgrade: false,
4915
+ addTrailingSlash: true,
4656
4916
  rejectUnauthorized: true,
4657
4917
  perMessageDeflate: {
4658
- threshold: 1024
4918
+ threshold: 1024,
4659
4919
  },
4660
4920
  transportOptions: {},
4661
- closeOnBeforeunload: true
4921
+ closeOnBeforeunload: false,
4662
4922
  }, opts);
4663
- this.opts.path = this.opts.path.replace(/\/$/, "") + "/";
4923
+ this.opts.path =
4924
+ this.opts.path.replace(/\/$/, "") +
4925
+ (this.opts.addTrailingSlash ? "/" : "");
4664
4926
  if (typeof this.opts.query === "string") {
4665
4927
  this.opts.query = decode(this.opts.query);
4666
4928
  }
@@ -4688,7 +4950,7 @@ class Socket$1 extends Emitter_1 {
4688
4950
  if (this.hostname !== "localhost") {
4689
4951
  this.offlineEventListener = () => {
4690
4952
  this.onClose("transport close", {
4691
- description: "network connection lost"
4953
+ description: "network connection lost",
4692
4954
  });
4693
4955
  };
4694
4956
  addEventListener("offline", this.offlineEventListener, false);
@@ -4699,9 +4961,9 @@ class Socket$1 extends Emitter_1 {
4699
4961
  /**
4700
4962
  * Creates transport of the given type.
4701
4963
  *
4702
- * @param {String} transport name
4964
+ * @param {String} name - transport name
4703
4965
  * @return {Transport}
4704
- * @api private
4966
+ * @private
4705
4967
  */
4706
4968
  createTransport(name) {
4707
4969
  const query = Object.assign({}, this.opts.query);
@@ -4712,19 +4974,19 @@ class Socket$1 extends Emitter_1 {
4712
4974
  // session id if we already have one
4713
4975
  if (this.id)
4714
4976
  query.sid = this.id;
4715
- const opts = Object.assign({}, this.opts.transportOptions[name], this.opts, {
4977
+ const opts = Object.assign({}, this.opts, {
4716
4978
  query,
4717
4979
  socket: this,
4718
4980
  hostname: this.hostname,
4719
4981
  secure: this.secure,
4720
- port: this.port
4721
- });
4982
+ port: this.port,
4983
+ }, this.opts.transportOptions[name]);
4722
4984
  return new transports[name](opts);
4723
4985
  }
4724
4986
  /**
4725
4987
  * Initializes transport to use and starts probe.
4726
4988
  *
4727
- * @api private
4989
+ * @private
4728
4990
  */
4729
4991
  open() {
4730
4992
  let transport;
@@ -4759,7 +5021,7 @@ class Socket$1 extends Emitter_1 {
4759
5021
  /**
4760
5022
  * Sets the current transport. Disables the existing one (if any).
4761
5023
  *
4762
- * @api private
5024
+ * @private
4763
5025
  */
4764
5026
  setTransport(transport) {
4765
5027
  if (this.transport) {
@@ -4772,13 +5034,13 @@ class Socket$1 extends Emitter_1 {
4772
5034
  .on("drain", this.onDrain.bind(this))
4773
5035
  .on("packet", this.onPacket.bind(this))
4774
5036
  .on("error", this.onError.bind(this))
4775
- .on("close", reason => this.onClose("transport close", reason));
5037
+ .on("close", (reason) => this.onClose("transport close", reason));
4776
5038
  }
4777
5039
  /**
4778
5040
  * Probes a transport.
4779
5041
  *
4780
- * @param {String} transport name
4781
- * @api private
5042
+ * @param {String} name - transport name
5043
+ * @private
4782
5044
  */
4783
5045
  probe(name) {
4784
5046
  let transport = this.createTransport(name);
@@ -4788,7 +5050,7 @@ class Socket$1 extends Emitter_1 {
4788
5050
  if (failed)
4789
5051
  return;
4790
5052
  transport.send([{ type: "ping", data: "probe" }]);
4791
- transport.once("packet", msg => {
5053
+ transport.once("packet", (msg) => {
4792
5054
  if (failed)
4793
5055
  return;
4794
5056
  if ("pong" === msg.type && "probe" === msg.data) {
@@ -4829,7 +5091,7 @@ class Socket$1 extends Emitter_1 {
4829
5091
  transport = null;
4830
5092
  }
4831
5093
  // Handle any error that happens while probing
4832
- const onerror = err => {
5094
+ const onerror = (err) => {
4833
5095
  const error = new Error("probe error: " + err);
4834
5096
  // @ts-ignore
4835
5097
  error.transport = transport.name;
@@ -4862,12 +5124,23 @@ class Socket$1 extends Emitter_1 {
4862
5124
  transport.once("close", onTransportClose);
4863
5125
  this.once("close", onclose);
4864
5126
  this.once("upgrading", onupgrade);
4865
- transport.open();
5127
+ if (this.upgrades.indexOf("webtransport") !== -1 &&
5128
+ name !== "webtransport") {
5129
+ // favor WebTransport
5130
+ this.setTimeoutFn(() => {
5131
+ if (!failed) {
5132
+ transport.open();
5133
+ }
5134
+ }, 200);
5135
+ }
5136
+ else {
5137
+ transport.open();
5138
+ }
4866
5139
  }
4867
5140
  /**
4868
5141
  * Called when connection is deemed open.
4869
5142
  *
4870
- * @api private
5143
+ * @private
4871
5144
  */
4872
5145
  onOpen() {
4873
5146
  this.readyState = "open";
@@ -4876,9 +5149,7 @@ class Socket$1 extends Emitter_1 {
4876
5149
  this.flush();
4877
5150
  // we check for `readyState` in case an `open`
4878
5151
  // listener already closed the socket
4879
- if ("open" === this.readyState &&
4880
- this.opts.upgrade &&
4881
- this.transport.pause) {
5152
+ if ("open" === this.readyState && this.opts.upgrade) {
4882
5153
  let i = 0;
4883
5154
  const l = this.upgrades.length;
4884
5155
  for (; i < l; i++) {
@@ -4889,7 +5160,7 @@ class Socket$1 extends Emitter_1 {
4889
5160
  /**
4890
5161
  * Handles a packet.
4891
5162
  *
4892
- * @api private
5163
+ * @private
4893
5164
  */
4894
5165
  onPacket(packet) {
4895
5166
  if ("opening" === this.readyState ||
@@ -4898,12 +5169,12 @@ class Socket$1 extends Emitter_1 {
4898
5169
  this.emitReserved("packet", packet);
4899
5170
  // Socket is live - any packet counts
4900
5171
  this.emitReserved("heartbeat");
5172
+ this.resetPingTimeout();
4901
5173
  switch (packet.type) {
4902
5174
  case "open":
4903
5175
  this.onHandshake(JSON.parse(packet.data));
4904
5176
  break;
4905
5177
  case "ping":
4906
- this.resetPingTimeout();
4907
5178
  this.sendPacket("pong");
4908
5179
  this.emitReserved("ping");
4909
5180
  this.emitReserved("pong");
@@ -4925,7 +5196,7 @@ class Socket$1 extends Emitter_1 {
4925
5196
  * Called upon handshake completion.
4926
5197
  *
4927
5198
  * @param {Object} data - handshake obj
4928
- * @api private
5199
+ * @private
4929
5200
  */
4930
5201
  onHandshake(data) {
4931
5202
  this.emitReserved("handshake", data);
@@ -4944,7 +5215,7 @@ class Socket$1 extends Emitter_1 {
4944
5215
  /**
4945
5216
  * Sets and resets ping timeout timer based on server pings.
4946
5217
  *
4947
- * @api private
5218
+ * @private
4948
5219
  */
4949
5220
  resetPingTimeout() {
4950
5221
  this.clearTimeoutFn(this.pingTimeoutTimer);
@@ -4958,7 +5229,7 @@ class Socket$1 extends Emitter_1 {
4958
5229
  /**
4959
5230
  * Called on `drain` event
4960
5231
  *
4961
- * @api private
5232
+ * @private
4962
5233
  */
4963
5234
  onDrain() {
4964
5235
  this.writeBuffer.splice(0, this.prevBufferLen);
@@ -4976,7 +5247,7 @@ class Socket$1 extends Emitter_1 {
4976
5247
  /**
4977
5248
  * Flush write buffers.
4978
5249
  *
4979
- * @api private
5250
+ * @private
4980
5251
  */
4981
5252
  flush() {
4982
5253
  if ("closed" !== this.readyState &&
@@ -5020,11 +5291,10 @@ class Socket$1 extends Emitter_1 {
5020
5291
  /**
5021
5292
  * Sends a message.
5022
5293
  *
5023
- * @param {String} message.
5024
- * @param {Function} callback function.
5294
+ * @param {String} msg - message.
5025
5295
  * @param {Object} options.
5296
+ * @param {Function} callback function.
5026
5297
  * @return {Socket} for chaining.
5027
- * @api public
5028
5298
  */
5029
5299
  write(msg, options, fn) {
5030
5300
  this.sendPacket("message", msg, options, fn);
@@ -5037,11 +5307,11 @@ class Socket$1 extends Emitter_1 {
5037
5307
  /**
5038
5308
  * Sends a packet.
5039
5309
  *
5040
- * @param {String} packet type.
5310
+ * @param {String} type: packet type.
5041
5311
  * @param {String} data.
5042
5312
  * @param {Object} options.
5043
- * @param {Function} callback function.
5044
- * @api private
5313
+ * @param {Function} fn - callback function.
5314
+ * @private
5045
5315
  */
5046
5316
  sendPacket(type, data, options, fn) {
5047
5317
  if ("function" === typeof data) {
@@ -5060,7 +5330,7 @@ class Socket$1 extends Emitter_1 {
5060
5330
  const packet = {
5061
5331
  type: type,
5062
5332
  data: data,
5063
- options: options
5333
+ options: options,
5064
5334
  };
5065
5335
  this.emitReserved("packetCreate", packet);
5066
5336
  this.writeBuffer.push(packet);
@@ -5070,8 +5340,6 @@ class Socket$1 extends Emitter_1 {
5070
5340
  }
5071
5341
  /**
5072
5342
  * Closes the connection.
5073
- *
5074
- * @api public
5075
5343
  */
5076
5344
  close() {
5077
5345
  const close = () => {
@@ -5112,7 +5380,7 @@ class Socket$1 extends Emitter_1 {
5112
5380
  /**
5113
5381
  * Called upon transport error
5114
5382
  *
5115
- * @api private
5383
+ * @private
5116
5384
  */
5117
5385
  onError(err) {
5118
5386
  Socket$1.priorWebsocketSuccess = false;
@@ -5122,7 +5390,7 @@ class Socket$1 extends Emitter_1 {
5122
5390
  /**
5123
5391
  * Called upon transport close.
5124
5392
  *
5125
- * @api private
5393
+ * @private
5126
5394
  */
5127
5395
  onClose(reason, description) {
5128
5396
  if ("opening" === this.readyState ||
@@ -5155,9 +5423,8 @@ class Socket$1 extends Emitter_1 {
5155
5423
  /**
5156
5424
  * Filters upgrades, returning only those matching client transports.
5157
5425
  *
5158
- * @param {Array} server upgrades
5159
- * @api private
5160
- *
5426
+ * @param {Array} upgrades - server upgrades
5427
+ * @private
5161
5428
  */
5162
5429
  filterUpgrades(upgrades) {
5163
5430
  const filteredUpgrades = [];
@@ -5367,6 +5634,17 @@ function _reconstructPacket(data, buffers) {
5367
5634
  return data;
5368
5635
  }
5369
5636
 
5637
+ /**
5638
+ * These strings must not be used as event names, as they have a special meaning.
5639
+ */
5640
+ const RESERVED_EVENTS$1 = [
5641
+ "connect",
5642
+ "connect_error",
5643
+ "disconnect",
5644
+ "disconnecting",
5645
+ "newListener",
5646
+ "removeListener", // used by the Node.js EventEmitter
5647
+ ];
5370
5648
  /**
5371
5649
  * Protocol version.
5372
5650
  *
@@ -5455,6 +5733,10 @@ class Encoder {
5455
5733
  return buffers; // write all the buffers
5456
5734
  }
5457
5735
  }
5736
+ // see https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
5737
+ function isObject(value) {
5738
+ return Object.prototype.toString.call(value) === "[object Object]";
5739
+ }
5458
5740
  /**
5459
5741
  * A socket.io Decoder instance
5460
5742
  *
@@ -5594,14 +5876,17 @@ class Decoder extends Emitter_1 {
5594
5876
  static isPayloadValid(type, payload) {
5595
5877
  switch (type) {
5596
5878
  case PacketType.CONNECT:
5597
- return typeof payload === "object";
5879
+ return isObject(payload);
5598
5880
  case PacketType.DISCONNECT:
5599
5881
  return payload === undefined;
5600
5882
  case PacketType.CONNECT_ERROR:
5601
- return typeof payload === "string" || typeof payload === "object";
5883
+ return typeof payload === "string" || isObject(payload);
5602
5884
  case PacketType.EVENT:
5603
5885
  case PacketType.BINARY_EVENT:
5604
- return Array.isArray(payload) && payload.length > 0;
5886
+ return (Array.isArray(payload) &&
5887
+ (typeof payload[0] === "number" ||
5888
+ (typeof payload[0] === "string" &&
5889
+ RESERVED_EVENTS$1.indexOf(payload[0]) === -1)));
5605
5890
  case PacketType.ACK:
5606
5891
  case PacketType.BINARY_ACK:
5607
5892
  return Array.isArray(payload);
@@ -5686,18 +5971,100 @@ const RESERVED_EVENTS = Object.freeze({
5686
5971
  newListener: 1,
5687
5972
  removeListener: 1,
5688
5973
  });
5974
+ /**
5975
+ * A Socket is the fundamental class for interacting with the server.
5976
+ *
5977
+ * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.
5978
+ *
5979
+ * @example
5980
+ * const socket = io();
5981
+ *
5982
+ * socket.on("connect", () => {
5983
+ * console.log("connected");
5984
+ * });
5985
+ *
5986
+ * // send an event to the server
5987
+ * socket.emit("foo", "bar");
5988
+ *
5989
+ * socket.on("foobar", () => {
5990
+ * // an event was received from the server
5991
+ * });
5992
+ *
5993
+ * // upon disconnection
5994
+ * socket.on("disconnect", (reason) => {
5995
+ * console.log(`disconnected due to ${reason}`);
5996
+ * });
5997
+ */
5689
5998
  class Socket extends Emitter_1 {
5690
5999
  /**
5691
6000
  * `Socket` constructor.
5692
- *
5693
- * @public
5694
6001
  */
5695
6002
  constructor(io, nsp, opts) {
5696
6003
  super();
6004
+ /**
6005
+ * Whether the socket is currently connected to the server.
6006
+ *
6007
+ * @example
6008
+ * const socket = io();
6009
+ *
6010
+ * socket.on("connect", () => {
6011
+ * console.log(socket.connected); // true
6012
+ * });
6013
+ *
6014
+ * socket.on("disconnect", () => {
6015
+ * console.log(socket.connected); // false
6016
+ * });
6017
+ */
5697
6018
  this.connected = false;
6019
+ /**
6020
+ * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
6021
+ * be transmitted by the server.
6022
+ */
6023
+ this.recovered = false;
6024
+ /**
6025
+ * Buffer for packets received before the CONNECT packet
6026
+ */
5698
6027
  this.receiveBuffer = [];
6028
+ /**
6029
+ * Buffer for packets that will be sent once the socket is connected
6030
+ */
5699
6031
  this.sendBuffer = [];
6032
+ /**
6033
+ * The queue of packets to be sent with retry in case of failure.
6034
+ *
6035
+ * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.
6036
+ * @private
6037
+ */
6038
+ this._queue = [];
6039
+ /**
6040
+ * A sequence to generate the ID of the {@link QueuedPacket}.
6041
+ * @private
6042
+ */
6043
+ this._queueSeq = 0;
5700
6044
  this.ids = 0;
6045
+ /**
6046
+ * A map containing acknowledgement handlers.
6047
+ *
6048
+ * The `withError` attribute is used to differentiate handlers that accept an error as first argument:
6049
+ *
6050
+ * - `socket.emit("test", (err, value) => { ... })` with `ackTimeout` option
6051
+ * - `socket.timeout(5000).emit("test", (err, value) => { ... })`
6052
+ * - `const value = await socket.emitWithAck("test")`
6053
+ *
6054
+ * From those that don't:
6055
+ *
6056
+ * - `socket.emit("test", (value) => { ... });`
6057
+ *
6058
+ * In the first case, the handlers will be called with an error when:
6059
+ *
6060
+ * - the timeout is reached
6061
+ * - the socket gets disconnected
6062
+ *
6063
+ * In the second case, the handlers will be simply discarded upon disconnection, since the client will never receive
6064
+ * an acknowledgement from the server.
6065
+ *
6066
+ * @private
6067
+ */
5701
6068
  this.acks = {};
5702
6069
  this.flags = {};
5703
6070
  this.io = io;
@@ -5705,11 +6072,23 @@ class Socket extends Emitter_1 {
5705
6072
  if (opts && opts.auth) {
5706
6073
  this.auth = opts.auth;
5707
6074
  }
6075
+ this._opts = Object.assign({}, opts);
5708
6076
  if (this.io._autoConnect)
5709
6077
  this.open();
5710
6078
  }
5711
6079
  /**
5712
6080
  * Whether the socket is currently disconnected
6081
+ *
6082
+ * @example
6083
+ * const socket = io();
6084
+ *
6085
+ * socket.on("connect", () => {
6086
+ * console.log(socket.disconnected); // false
6087
+ * });
6088
+ *
6089
+ * socket.on("disconnect", () => {
6090
+ * console.log(socket.disconnected); // true
6091
+ * });
5713
6092
  */
5714
6093
  get disconnected() {
5715
6094
  return !this.connected;
@@ -5731,7 +6110,21 @@ class Socket extends Emitter_1 {
5731
6110
  ];
5732
6111
  }
5733
6112
  /**
5734
- * Whether the Socket will try to reconnect when its Manager connects or reconnects
6113
+ * Whether the Socket will try to reconnect when its Manager connects or reconnects.
6114
+ *
6115
+ * @example
6116
+ * const socket = io();
6117
+ *
6118
+ * console.log(socket.active); // true
6119
+ *
6120
+ * socket.on("disconnect", (reason) => {
6121
+ * if (reason === "io server disconnect") {
6122
+ * // the disconnection was initiated by the server, you need to manually reconnect
6123
+ * console.log(socket.active); // false
6124
+ * }
6125
+ * // else the socket will automatically try to reconnect
6126
+ * console.log(socket.active); // true
6127
+ * });
5735
6128
  */
5736
6129
  get active() {
5737
6130
  return !!this.subs;
@@ -5739,7 +6132,12 @@ class Socket extends Emitter_1 {
5739
6132
  /**
5740
6133
  * "Opens" the socket.
5741
6134
  *
5742
- * @public
6135
+ * @example
6136
+ * const socket = io({
6137
+ * autoConnect: false
6138
+ * });
6139
+ *
6140
+ * socket.connect();
5743
6141
  */
5744
6142
  connect() {
5745
6143
  if (this.connected)
@@ -5752,7 +6150,7 @@ class Socket extends Emitter_1 {
5752
6150
  return this;
5753
6151
  }
5754
6152
  /**
5755
- * Alias for connect()
6153
+ * Alias for {@link connect()}.
5756
6154
  */
5757
6155
  open() {
5758
6156
  return this.connect();
@@ -5760,8 +6158,17 @@ class Socket extends Emitter_1 {
5760
6158
  /**
5761
6159
  * Sends a `message` event.
5762
6160
  *
6161
+ * This method mimics the WebSocket.send() method.
6162
+ *
6163
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
6164
+ *
6165
+ * @example
6166
+ * socket.send("hello");
6167
+ *
6168
+ * // this is equivalent to
6169
+ * socket.emit("message", "hello");
6170
+ *
5763
6171
  * @return self
5764
- * @public
5765
6172
  */
5766
6173
  send(...args) {
5767
6174
  args.unshift("message");
@@ -5772,14 +6179,28 @@ class Socket extends Emitter_1 {
5772
6179
  * Override `emit`.
5773
6180
  * If the event is in `events`, it's emitted normally.
5774
6181
  *
6182
+ * @example
6183
+ * socket.emit("hello", "world");
6184
+ *
6185
+ * // all serializable datastructures are supported (no need to call JSON.stringify)
6186
+ * socket.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
6187
+ *
6188
+ * // with an acknowledgement from the server
6189
+ * socket.emit("hello", "world", (val) => {
6190
+ * // ...
6191
+ * });
6192
+ *
5775
6193
  * @return self
5776
- * @public
5777
6194
  */
5778
6195
  emit(ev, ...args) {
5779
6196
  if (RESERVED_EVENTS.hasOwnProperty(ev)) {
5780
- throw new Error('"' + ev + '" is a reserved event name');
6197
+ throw new Error('"' + ev.toString() + '" is a reserved event name');
5781
6198
  }
5782
6199
  args.unshift(ev);
6200
+ if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {
6201
+ this._addToQueue(args);
6202
+ return this;
6203
+ }
5783
6204
  const packet = {
5784
6205
  type: PacketType.EVENT,
5785
6206
  data: args,
@@ -5812,7 +6233,8 @@ class Socket extends Emitter_1 {
5812
6233
  * @private
5813
6234
  */
5814
6235
  _registerAckCallback(id, ack) {
5815
- const timeout = this.flags.timeout;
6236
+ var _a;
6237
+ const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;
5816
6238
  if (timeout === undefined) {
5817
6239
  this.acks[id] = ack;
5818
6240
  return;
@@ -5827,11 +6249,101 @@ class Socket extends Emitter_1 {
5827
6249
  }
5828
6250
  ack.call(this, new Error("operation has timed out"));
5829
6251
  }, timeout);
5830
- this.acks[id] = (...args) => {
6252
+ const fn = (...args) => {
5831
6253
  // @ts-ignore
5832
6254
  this.io.clearTimeoutFn(timer);
5833
- ack.apply(this, [null, ...args]);
6255
+ ack.apply(this, args);
6256
+ };
6257
+ fn.withError = true;
6258
+ this.acks[id] = fn;
6259
+ }
6260
+ /**
6261
+ * Emits an event and waits for an acknowledgement
6262
+ *
6263
+ * @example
6264
+ * // without timeout
6265
+ * const response = await socket.emitWithAck("hello", "world");
6266
+ *
6267
+ * // with a specific timeout
6268
+ * try {
6269
+ * const response = await socket.timeout(1000).emitWithAck("hello", "world");
6270
+ * } catch (err) {
6271
+ * // the server did not acknowledge the event in the given delay
6272
+ * }
6273
+ *
6274
+ * @return a Promise that will be fulfilled when the server acknowledges the event
6275
+ */
6276
+ emitWithAck(ev, ...args) {
6277
+ return new Promise((resolve, reject) => {
6278
+ const fn = (arg1, arg2) => {
6279
+ return arg1 ? reject(arg1) : resolve(arg2);
6280
+ };
6281
+ fn.withError = true;
6282
+ args.push(fn);
6283
+ this.emit(ev, ...args);
6284
+ });
6285
+ }
6286
+ /**
6287
+ * Add the packet to the queue.
6288
+ * @param args
6289
+ * @private
6290
+ */
6291
+ _addToQueue(args) {
6292
+ let ack;
6293
+ if (typeof args[args.length - 1] === "function") {
6294
+ ack = args.pop();
6295
+ }
6296
+ const packet = {
6297
+ id: this._queueSeq++,
6298
+ tryCount: 0,
6299
+ pending: false,
6300
+ args,
6301
+ flags: Object.assign({ fromQueue: true }, this.flags),
5834
6302
  };
6303
+ args.push((err, ...responseArgs) => {
6304
+ if (packet !== this._queue[0]) {
6305
+ // the packet has already been acknowledged
6306
+ return;
6307
+ }
6308
+ const hasError = err !== null;
6309
+ if (hasError) {
6310
+ if (packet.tryCount > this._opts.retries) {
6311
+ this._queue.shift();
6312
+ if (ack) {
6313
+ ack(err);
6314
+ }
6315
+ }
6316
+ }
6317
+ else {
6318
+ this._queue.shift();
6319
+ if (ack) {
6320
+ ack(null, ...responseArgs);
6321
+ }
6322
+ }
6323
+ packet.pending = false;
6324
+ return this._drainQueue();
6325
+ });
6326
+ this._queue.push(packet);
6327
+ this._drainQueue();
6328
+ }
6329
+ /**
6330
+ * Send the first packet of the queue, and wait for an acknowledgement from the server.
6331
+ * @param force - whether to resend a packet that has not been acknowledged yet
6332
+ *
6333
+ * @private
6334
+ */
6335
+ _drainQueue(force = false) {
6336
+ if (!this.connected || this._queue.length === 0) {
6337
+ return;
6338
+ }
6339
+ const packet = this._queue[0];
6340
+ if (packet.pending && !force) {
6341
+ return;
6342
+ }
6343
+ packet.pending = true;
6344
+ packet.tryCount++;
6345
+ this.flags = packet.flags;
6346
+ this.emit.apply(this, packet.args);
5835
6347
  }
5836
6348
  /**
5837
6349
  * Sends a packet.
@@ -5851,13 +6363,27 @@ class Socket extends Emitter_1 {
5851
6363
  onopen() {
5852
6364
  if (typeof this.auth == "function") {
5853
6365
  this.auth((data) => {
5854
- this.packet({ type: PacketType.CONNECT, data });
6366
+ this._sendConnectPacket(data);
5855
6367
  });
5856
6368
  }
5857
6369
  else {
5858
- this.packet({ type: PacketType.CONNECT, data: this.auth });
6370
+ this._sendConnectPacket(this.auth);
5859
6371
  }
5860
6372
  }
6373
+ /**
6374
+ * Sends a CONNECT packet to initiate the Socket.IO session.
6375
+ *
6376
+ * @param data
6377
+ * @private
6378
+ */
6379
+ _sendConnectPacket(data) {
6380
+ this.packet({
6381
+ type: PacketType.CONNECT,
6382
+ data: this._pid
6383
+ ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)
6384
+ : data,
6385
+ });
6386
+ }
5861
6387
  /**
5862
6388
  * Called upon engine or manager `error`.
5863
6389
  *
@@ -5880,6 +6406,26 @@ class Socket extends Emitter_1 {
5880
6406
  this.connected = false;
5881
6407
  delete this.id;
5882
6408
  this.emitReserved("disconnect", reason, description);
6409
+ this._clearAcks();
6410
+ }
6411
+ /**
6412
+ * Clears the acknowledgement handlers upon disconnection, since the client will never receive an acknowledgement from
6413
+ * the server.
6414
+ *
6415
+ * @private
6416
+ */
6417
+ _clearAcks() {
6418
+ Object.keys(this.acks).forEach((id) => {
6419
+ const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id);
6420
+ if (!isBuffered) {
6421
+ // note: handlers that do not accept an error as first argument are ignored here
6422
+ const ack = this.acks[id];
6423
+ delete this.acks[id];
6424
+ if (ack.withError) {
6425
+ ack.call(this, new Error("socket has been disconnected"));
6426
+ }
6427
+ }
6428
+ });
5883
6429
  }
5884
6430
  /**
5885
6431
  * Called with socket packet.
@@ -5894,8 +6440,7 @@ class Socket extends Emitter_1 {
5894
6440
  switch (packet.type) {
5895
6441
  case PacketType.CONNECT:
5896
6442
  if (packet.data && packet.data.sid) {
5897
- const id = packet.data.sid;
5898
- this.onconnect(id);
6443
+ this.onconnect(packet.data.sid, packet.data.pid);
5899
6444
  }
5900
6445
  else {
5901
6446
  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/)"));
@@ -5947,6 +6492,9 @@ class Socket extends Emitter_1 {
5947
6492
  }
5948
6493
  }
5949
6494
  super.emit.apply(this, args);
6495
+ if (this._pid && args.length && typeof args[args.length - 1] === "string") {
6496
+ this._lastOffset = args[args.length - 1];
6497
+ }
5950
6498
  }
5951
6499
  /**
5952
6500
  * Produces an ack callback to emit with an event.
@@ -5969,28 +6517,37 @@ class Socket extends Emitter_1 {
5969
6517
  };
5970
6518
  }
5971
6519
  /**
5972
- * Called upon a server acknowlegement.
6520
+ * Called upon a server acknowledgement.
5973
6521
  *
5974
6522
  * @param packet
5975
6523
  * @private
5976
6524
  */
5977
6525
  onack(packet) {
5978
6526
  const ack = this.acks[packet.id];
5979
- if ("function" === typeof ack) {
5980
- ack.apply(this, packet.data);
5981
- delete this.acks[packet.id];
6527
+ if (typeof ack !== "function") {
6528
+ return;
6529
+ }
6530
+ delete this.acks[packet.id];
6531
+ // @ts-ignore FIXME ack is incorrectly inferred as 'never'
6532
+ if (ack.withError) {
6533
+ packet.data.unshift(null);
5982
6534
  }
6535
+ // @ts-ignore
6536
+ ack.apply(this, packet.data);
5983
6537
  }
5984
6538
  /**
5985
6539
  * Called upon server connect.
5986
6540
  *
5987
6541
  * @private
5988
6542
  */
5989
- onconnect(id) {
6543
+ onconnect(id, pid) {
5990
6544
  this.id = id;
6545
+ this.recovered = pid && this._pid === pid;
6546
+ this._pid = pid; // defined only if connection state recovery is enabled
5991
6547
  this.connected = true;
5992
6548
  this.emitBuffered();
5993
6549
  this.emitReserved("connect");
6550
+ this._drainQueue(true);
5994
6551
  }
5995
6552
  /**
5996
6553
  * Emit buffered events (received and emitted).
@@ -6031,10 +6588,20 @@ class Socket extends Emitter_1 {
6031
6588
  this.io["_destroy"](this);
6032
6589
  }
6033
6590
  /**
6034
- * Disconnects the socket manually.
6591
+ * Disconnects the socket manually. In that case, the socket will not try to reconnect.
6592
+ *
6593
+ * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.
6594
+ *
6595
+ * @example
6596
+ * const socket = io();
6597
+ *
6598
+ * socket.on("disconnect", (reason) => {
6599
+ * // console.log(reason); prints "io client disconnect"
6600
+ * });
6601
+ *
6602
+ * socket.disconnect();
6035
6603
  *
6036
6604
  * @return self
6037
- * @public
6038
6605
  */
6039
6606
  disconnect() {
6040
6607
  if (this.connected) {
@@ -6049,10 +6616,9 @@ class Socket extends Emitter_1 {
6049
6616
  return this;
6050
6617
  }
6051
6618
  /**
6052
- * Alias for disconnect()
6619
+ * Alias for {@link disconnect()}.
6053
6620
  *
6054
6621
  * @return self
6055
- * @public
6056
6622
  */
6057
6623
  close() {
6058
6624
  return this.disconnect();
@@ -6060,9 +6626,11 @@ class Socket extends Emitter_1 {
6060
6626
  /**
6061
6627
  * Sets the compress flag.
6062
6628
  *
6629
+ * @example
6630
+ * socket.compress(false).emit("hello");
6631
+ *
6063
6632
  * @param compress - if `true`, compresses the sending data
6064
6633
  * @return self
6065
- * @public
6066
6634
  */
6067
6635
  compress(compress) {
6068
6636
  this.flags.compress = compress;
@@ -6072,8 +6640,10 @@ class Socket extends Emitter_1 {
6072
6640
  * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
6073
6641
  * ready to send messages.
6074
6642
  *
6643
+ * @example
6644
+ * socket.volatile.emit("hello"); // the server may or may not receive it
6645
+ *
6075
6646
  * @returns self
6076
- * @public
6077
6647
  */
6078
6648
  get volatile() {
6079
6649
  this.flags.volatile = true;
@@ -6083,16 +6653,14 @@ class Socket extends Emitter_1 {
6083
6653
  * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
6084
6654
  * given number of milliseconds have elapsed without an acknowledgement from the server:
6085
6655
  *
6086
- * ```
6656
+ * @example
6087
6657
  * socket.timeout(5000).emit("my-event", (err) => {
6088
6658
  * if (err) {
6089
6659
  * // the server did not acknowledge the event in the given delay
6090
6660
  * }
6091
6661
  * });
6092
- * ```
6093
6662
  *
6094
6663
  * @returns self
6095
- * @public
6096
6664
  */
6097
6665
  timeout(timeout) {
6098
6666
  this.flags.timeout = timeout;
@@ -6102,8 +6670,12 @@ class Socket extends Emitter_1 {
6102
6670
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6103
6671
  * callback.
6104
6672
  *
6673
+ * @example
6674
+ * socket.onAny((event, ...args) => {
6675
+ * console.log(`got ${event}`);
6676
+ * });
6677
+ *
6105
6678
  * @param listener
6106
- * @public
6107
6679
  */
6108
6680
  onAny(listener) {
6109
6681
  this._anyListeners = this._anyListeners || [];
@@ -6114,8 +6686,12 @@ class Socket extends Emitter_1 {
6114
6686
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6115
6687
  * callback. The listener is added to the beginning of the listeners array.
6116
6688
  *
6689
+ * @example
6690
+ * socket.prependAny((event, ...args) => {
6691
+ * console.log(`got event ${event}`);
6692
+ * });
6693
+ *
6117
6694
  * @param listener
6118
- * @public
6119
6695
  */
6120
6696
  prependAny(listener) {
6121
6697
  this._anyListeners = this._anyListeners || [];
@@ -6125,8 +6701,20 @@ class Socket extends Emitter_1 {
6125
6701
  /**
6126
6702
  * Removes the listener that will be fired when any event is emitted.
6127
6703
  *
6704
+ * @example
6705
+ * const catchAllListener = (event, ...args) => {
6706
+ * console.log(`got event ${event}`);
6707
+ * }
6708
+ *
6709
+ * socket.onAny(catchAllListener);
6710
+ *
6711
+ * // remove a specific listener
6712
+ * socket.offAny(catchAllListener);
6713
+ *
6714
+ * // or remove all listeners
6715
+ * socket.offAny();
6716
+ *
6128
6717
  * @param listener
6129
- * @public
6130
6718
  */
6131
6719
  offAny(listener) {
6132
6720
  if (!this._anyListeners) {
@@ -6149,8 +6737,6 @@ class Socket extends Emitter_1 {
6149
6737
  /**
6150
6738
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6151
6739
  * e.g. to remove listeners.
6152
- *
6153
- * @public
6154
6740
  */
6155
6741
  listenersAny() {
6156
6742
  return this._anyListeners || [];
@@ -6159,17 +6745,14 @@ class Socket extends Emitter_1 {
6159
6745
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6160
6746
  * callback.
6161
6747
  *
6162
- * @param listener
6163
- *
6164
- * <pre><code>
6748
+ * Note: acknowledgements sent to the server are not included.
6165
6749
  *
6750
+ * @example
6166
6751
  * socket.onAnyOutgoing((event, ...args) => {
6167
- * console.log(event);
6752
+ * console.log(`sent event ${event}`);
6168
6753
  * });
6169
6754
  *
6170
- * </pre></code>
6171
- *
6172
- * @public
6755
+ * @param listener
6173
6756
  */
6174
6757
  onAnyOutgoing(listener) {
6175
6758
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6180,17 +6763,14 @@ class Socket extends Emitter_1 {
6180
6763
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6181
6764
  * callback. The listener is added to the beginning of the listeners array.
6182
6765
  *
6183
- * @param listener
6184
- *
6185
- * <pre><code>
6766
+ * Note: acknowledgements sent to the server are not included.
6186
6767
  *
6768
+ * @example
6187
6769
  * socket.prependAnyOutgoing((event, ...args) => {
6188
- * console.log(event);
6770
+ * console.log(`sent event ${event}`);
6189
6771
  * });
6190
6772
  *
6191
- * </pre></code>
6192
- *
6193
- * @public
6773
+ * @param listener
6194
6774
  */
6195
6775
  prependAnyOutgoing(listener) {
6196
6776
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6200,22 +6780,20 @@ class Socket extends Emitter_1 {
6200
6780
  /**
6201
6781
  * Removes the listener that will be fired when any event is emitted.
6202
6782
  *
6203
- * @param listener
6204
- *
6205
- * <pre><code>
6206
- *
6207
- * const handler = (event, ...args) => {
6208
- * console.log(event);
6783
+ * @example
6784
+ * const catchAllListener = (event, ...args) => {
6785
+ * console.log(`sent event ${event}`);
6209
6786
  * }
6210
6787
  *
6211
- * socket.onAnyOutgoing(handler);
6788
+ * socket.onAnyOutgoing(catchAllListener);
6212
6789
  *
6213
- * // then later
6214
- * socket.offAnyOutgoing(handler);
6790
+ * // remove a specific listener
6791
+ * socket.offAnyOutgoing(catchAllListener);
6215
6792
  *
6216
- * </pre></code>
6793
+ * // or remove all listeners
6794
+ * socket.offAnyOutgoing();
6217
6795
  *
6218
- * @public
6796
+ * @param [listener] - the catch-all listener (optional)
6219
6797
  */
6220
6798
  offAnyOutgoing(listener) {
6221
6799
  if (!this._anyOutgoingListeners) {
@@ -6238,8 +6816,6 @@ class Socket extends Emitter_1 {
6238
6816
  /**
6239
6817
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6240
6818
  * e.g. to remove listeners.
6241
- *
6242
- * @public
6243
6819
  */
6244
6820
  listenersAnyOutgoing() {
6245
6821
  return this._anyOutgoingListeners || [];
@@ -6439,36 +7015,33 @@ class Manager extends Emitter_1 {
6439
7015
  self.onopen();
6440
7016
  fn && fn();
6441
7017
  });
6442
- // emit `error`
6443
- const errorSub = on(socket, "error", (err) => {
6444
- self.cleanup();
6445
- self._readyState = "closed";
7018
+ const onError = (err) => {
7019
+ this.cleanup();
7020
+ this._readyState = "closed";
6446
7021
  this.emitReserved("error", err);
6447
7022
  if (fn) {
6448
7023
  fn(err);
6449
7024
  }
6450
7025
  else {
6451
7026
  // Only do this if there is no fn to handle the error
6452
- self.maybeReconnectOnOpen();
7027
+ this.maybeReconnectOnOpen();
6453
7028
  }
6454
- });
7029
+ };
7030
+ // emit `error`
7031
+ const errorSub = on(socket, "error", onError);
6455
7032
  if (false !== this._timeout) {
6456
7033
  const timeout = this._timeout;
6457
- if (timeout === 0) {
6458
- openSubDestroy(); // prevents a race condition with the 'open' event
6459
- }
6460
7034
  // set timer
6461
7035
  const timer = this.setTimeoutFn(() => {
6462
7036
  openSubDestroy();
7037
+ onError(new Error("timeout"));
6463
7038
  socket.close();
6464
- // @ts-ignore
6465
- socket.emit("error", new Error("timeout"));
6466
7039
  }, timeout);
6467
7040
  if (this.opts.autoUnref) {
6468
7041
  timer.unref();
6469
7042
  }
6470
- this.subs.push(function subDestroy() {
6471
- clearTimeout(timer);
7043
+ this.subs.push(() => {
7044
+ this.clearTimeoutFn(timer);
6472
7045
  });
6473
7046
  }
6474
7047
  this.subs.push(openSubDestroy);
@@ -6513,7 +7086,12 @@ class Manager extends Emitter_1 {
6513
7086
  * @private
6514
7087
  */
6515
7088
  ondata(data) {
6516
- this.decoder.add(data);
7089
+ try {
7090
+ this.decoder.add(data);
7091
+ }
7092
+ catch (e) {
7093
+ this.onclose("parse error", e);
7094
+ }
6517
7095
  }
6518
7096
  /**
6519
7097
  * Called when parser fully decodes a packet.
@@ -6521,7 +7099,10 @@ class Manager extends Emitter_1 {
6521
7099
  * @private
6522
7100
  */
6523
7101
  ondecoded(packet) {
6524
- this.emitReserved("packet", packet);
7102
+ // the nextTick call prevents an exception in a user-provided event listener from triggering a disconnection due to a "parse error"
7103
+ nextTick(() => {
7104
+ this.emitReserved("packet", packet);
7105
+ }, this.setTimeoutFn);
6525
7106
  }
6526
7107
  /**
6527
7108
  * Called upon socket error.
@@ -6543,6 +7124,9 @@ class Manager extends Emitter_1 {
6543
7124
  socket = new Socket(this, nsp, opts);
6544
7125
  this.nsps[nsp] = socket;
6545
7126
  }
7127
+ else if (this._autoConnect && !socket.active) {
7128
+ socket.connect();
7129
+ }
6546
7130
  return socket;
6547
7131
  }
6548
7132
  /**
@@ -6655,8 +7239,8 @@ class Manager extends Emitter_1 {
6655
7239
  if (this.opts.autoUnref) {
6656
7240
  timer.unref();
6657
7241
  }
6658
- this.subs.push(function subDestroy() {
6659
- clearTimeout(timer);
7242
+ this.subs.push(() => {
7243
+ this.clearTimeoutFn(timer);
6660
7244
  });
6661
7245
  }
6662
7246
  }