@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.js CHANGED
@@ -2304,9 +2304,9 @@ var StentorDirectChat = /** @class */ (function () {
2304
2304
  return __assign(__assign({}, user), { nick: user.nick || bot.nick || "Bot", displayName: user.displayName || bot.displayName || "Bot", avatarPath: user.avatarPath || bot.avatarPath });
2305
2305
  };
2306
2306
  StentorDirectChat.prototype.sendChatMsgRequest = function (serviceRequest, cb) {
2307
- var _a;
2308
2307
  return __awaiter$1(this, void 0, void 0, function () {
2309
2308
  var agentResponse;
2309
+ var _a;
2310
2310
  return __generator$1(this, function (_b) {
2311
2311
  switch (_b.label) {
2312
2312
  case 0: return [4 /*yield*/, this.postMessage(serviceRequest)];
@@ -2362,10 +2362,10 @@ var StentorDirectChat = /** @class */ (function () {
2362
2362
  StentorDirectChat.prototype.wakeup = function () {
2363
2363
  };
2364
2364
  StentorDirectChat.prototype.postMessage = function (message) {
2365
- var _a, _b, _c, _d, _e;
2366
2365
  return __awaiter$1(this, void 0, void 0, function () {
2367
- var request, userId, sessionId, accessToken, attributes, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
2366
+ var request, userId, sessionId, accessToken, attributes, rwgToken, merchantId, environment, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
2368
2367
  var _this = this;
2368
+ var _a, _b, _c, _d, _e;
2369
2369
  return __generator$1(this, function (_f) {
2370
2370
  switch (_f.label) {
2371
2371
  case 0:
@@ -2373,6 +2373,18 @@ var StentorDirectChat = /** @class */ (function () {
2373
2373
  sessionId = this._sessionId;
2374
2374
  accessToken = this._accessToken;
2375
2375
  attributes = this._attributes || {};
2376
+ rwgToken = localStorage.getItem("xa_rwg_token");
2377
+ if (rwgToken) {
2378
+ attributes["rwg_token"] = rwgToken;
2379
+ }
2380
+ merchantId = localStorage.getItem("xa_merchant_id");
2381
+ if (merchantId) {
2382
+ attributes["merchant_id"] = merchantId;
2383
+ }
2384
+ environment = localStorage.getItem("xa_environment");
2385
+ if (environment) {
2386
+ attributes["environment"] = environment;
2387
+ }
2376
2388
  now = new Date().getTime();
2377
2389
  if (this.isNewSession && !((_a = message === null || message === void 0 ? void 0 : message.msg) === null || _a === void 0 ? void 0 : _a.text)) {
2378
2390
  request = {
@@ -2832,7 +2844,7 @@ var StentorRouterChat = /** @class */ (function () {
2832
2844
  _this.dispatch(setConnectionStatus("offline"));
2833
2845
  }
2834
2846
  };
2835
- // Server ping (not sent peroidically - at least not for now)
2847
+ // Server ping (not sent periodically - at least not for now)
2836
2848
  this.handlers["account status"] = function (_data, _sender, ts) {
2837
2849
  dispatch({
2838
2850
  type: "account_status",
@@ -3162,9 +3174,11 @@ var StentorRouterChat = /** @class */ (function () {
3162
3174
  nick: senderToNick(serverInfo),
3163
3175
  avatarPath: serverInfo.avatarPath
3164
3176
  },
3165
- msg: { text: this.noOfServerErrors === 0 ?
3177
+ msg: {
3178
+ text: this.noOfServerErrors === 0 ?
3166
3179
  "I cannot connect to the server. Please try later." :
3167
- "Nope. Still no luck. I still cannot connect to the server. Please don't give up." },
3180
+ "Nope. Still no luck. I still cannot connect to the server. Please don't give up."
3181
+ },
3168
3182
  timestamp: new Date().getTime(),
3169
3183
  }
3170
3184
  });
@@ -3287,12 +3301,24 @@ var StentorRouterChat = /** @class */ (function () {
3287
3301
  };
3288
3302
  StentorRouterChat.prototype.postMessage = function (message) {
3289
3303
  return __awaiter$1(this, void 0, void 0, function () {
3290
- var userId, sessionId, accessToken, attributes, request;
3304
+ var userId, sessionId, accessToken, attributes, rwgToken, merchantId, environment, request;
3291
3305
  return __generator$1(this, function (_a) {
3292
3306
  userId = this._userId;
3293
3307
  sessionId = this._sessionId;
3294
3308
  accessToken = this.accessToken;
3295
3309
  attributes = this.attributes || {};
3310
+ rwgToken = localStorage.getItem("xa_rwg_token");
3311
+ if (rwgToken) {
3312
+ attributes["rwg_token"] = rwgToken;
3313
+ }
3314
+ merchantId = localStorage.getItem("xa_merchant_id");
3315
+ if (merchantId) {
3316
+ attributes["merchant_id"] = merchantId;
3317
+ }
3318
+ environment = localStorage.getItem("xa_environment");
3319
+ if (environment) {
3320
+ attributes["environment"] = environment;
3321
+ }
3296
3322
  request = requestFromMessage(message, userId, this.isNewSession, sessionId, accessToken, attributes, this.visitorInfo);
3297
3323
  this.emit("new message", request);
3298
3324
  return [2 /*return*/];
@@ -3375,7 +3401,7 @@ PACKET_TYPES["message"] = "4";
3375
3401
  PACKET_TYPES["upgrade"] = "5";
3376
3402
  PACKET_TYPES["noop"] = "6";
3377
3403
  const PACKET_TYPES_REVERSE = Object.create(null);
3378
- Object.keys(PACKET_TYPES).forEach(key => {
3404
+ Object.keys(PACKET_TYPES).forEach((key) => {
3379
3405
  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
3380
3406
  });
3381
3407
  const ERROR_PACKET = { type: "error", data: "parser error" };
@@ -3385,7 +3411,7 @@ const withNativeBlob$1 = typeof Blob === "function" ||
3385
3411
  Object.prototype.toString.call(Blob) === "[object BlobConstructor]");
3386
3412
  const withNativeArrayBuffer$2 = typeof ArrayBuffer === "function";
3387
3413
  // ArrayBuffer.isView method is not defined in IE10
3388
- const isView$1 = obj => {
3414
+ const isView$1 = (obj) => {
3389
3415
  return typeof ArrayBuffer.isView === "function"
3390
3416
  ? ArrayBuffer.isView(obj)
3391
3417
  : obj && obj.buffer instanceof ArrayBuffer;
@@ -3419,6 +3445,33 @@ const encodeBlobAsBase64 = (data, callback) => {
3419
3445
  };
3420
3446
  return fileReader.readAsDataURL(data);
3421
3447
  };
3448
+ function toArray(data) {
3449
+ if (data instanceof Uint8Array) {
3450
+ return data;
3451
+ }
3452
+ else if (data instanceof ArrayBuffer) {
3453
+ return new Uint8Array(data);
3454
+ }
3455
+ else {
3456
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
3457
+ }
3458
+ }
3459
+ let TEXT_ENCODER;
3460
+ function encodePacketToBinary(packet, callback) {
3461
+ if (withNativeBlob$1 && packet.data instanceof Blob) {
3462
+ return packet.data.arrayBuffer().then(toArray).then(callback);
3463
+ }
3464
+ else if (withNativeArrayBuffer$2 &&
3465
+ (packet.data instanceof ArrayBuffer || isView$1(packet.data))) {
3466
+ return callback(toArray(packet.data));
3467
+ }
3468
+ encodePacket(packet, false, (encoded) => {
3469
+ if (!TEXT_ENCODER) {
3470
+ TEXT_ENCODER = new TextEncoder();
3471
+ }
3472
+ callback(TEXT_ENCODER.encode(encoded));
3473
+ });
3474
+ }
3422
3475
 
3423
3476
  // imported from https://github.com/socketio/base64-arraybuffer
3424
3477
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -3453,14 +3506,14 @@ const decodePacket = (encodedPacket, binaryType) => {
3453
3506
  if (typeof encodedPacket !== "string") {
3454
3507
  return {
3455
3508
  type: "message",
3456
- data: mapBinary(encodedPacket, binaryType)
3509
+ data: mapBinary(encodedPacket, binaryType),
3457
3510
  };
3458
3511
  }
3459
3512
  const type = encodedPacket.charAt(0);
3460
3513
  if (type === "b") {
3461
3514
  return {
3462
3515
  type: "message",
3463
- data: decodeBase64Packet(encodedPacket.substring(1), binaryType)
3516
+ data: decodeBase64Packet(encodedPacket.substring(1), binaryType),
3464
3517
  };
3465
3518
  }
3466
3519
  const packetType = PACKET_TYPES_REVERSE[type];
@@ -3470,10 +3523,10 @@ const decodePacket = (encodedPacket, binaryType) => {
3470
3523
  return encodedPacket.length > 1
3471
3524
  ? {
3472
3525
  type: PACKET_TYPES_REVERSE[type],
3473
- data: encodedPacket.substring(1)
3526
+ data: encodedPacket.substring(1),
3474
3527
  }
3475
3528
  : {
3476
- type: PACKET_TYPES_REVERSE[type]
3529
+ type: PACKET_TYPES_REVERSE[type],
3477
3530
  };
3478
3531
  };
3479
3532
  const decodeBase64Packet = (data, binaryType) => {
@@ -3488,10 +3541,24 @@ const decodeBase64Packet = (data, binaryType) => {
3488
3541
  const mapBinary = (data, binaryType) => {
3489
3542
  switch (binaryType) {
3490
3543
  case "blob":
3491
- return data instanceof ArrayBuffer ? new Blob([data]) : data;
3544
+ if (data instanceof Blob) {
3545
+ // from WebSocket + binaryType "blob"
3546
+ return data;
3547
+ }
3548
+ else {
3549
+ // from HTTP long-polling or WebTransport
3550
+ return new Blob([data]);
3551
+ }
3492
3552
  case "arraybuffer":
3493
3553
  default:
3494
- return data; // assuming the data is already an ArrayBuffer
3554
+ if (data instanceof ArrayBuffer) {
3555
+ // from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
3556
+ return data;
3557
+ }
3558
+ else {
3559
+ // from WebTransport (Uint8Array)
3560
+ return data.buffer;
3561
+ }
3495
3562
  }
3496
3563
  };
3497
3564
 
@@ -3503,7 +3570,7 @@ const encodePayload = (packets, callback) => {
3503
3570
  let count = 0;
3504
3571
  packets.forEach((packet, i) => {
3505
3572
  // force base64 encoding for binary packets
3506
- encodePacket(packet, false, encodedPacket => {
3573
+ encodePacket(packet, false, (encodedPacket) => {
3507
3574
  encodedPackets[i] = encodedPacket;
3508
3575
  if (++count === length) {
3509
3576
  callback(encodedPackets.join(SEPARATOR));
@@ -3523,6 +3590,131 @@ const decodePayload = (encodedPayload, binaryType) => {
3523
3590
  }
3524
3591
  return packets;
3525
3592
  };
3593
+ function createPacketEncoderStream() {
3594
+ // @ts-expect-error
3595
+ return new TransformStream({
3596
+ transform(packet, controller) {
3597
+ encodePacketToBinary(packet, (encodedPacket) => {
3598
+ const payloadLength = encodedPacket.length;
3599
+ let header;
3600
+ // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
3601
+ if (payloadLength < 126) {
3602
+ header = new Uint8Array(1);
3603
+ new DataView(header.buffer).setUint8(0, payloadLength);
3604
+ }
3605
+ else if (payloadLength < 65536) {
3606
+ header = new Uint8Array(3);
3607
+ const view = new DataView(header.buffer);
3608
+ view.setUint8(0, 126);
3609
+ view.setUint16(1, payloadLength);
3610
+ }
3611
+ else {
3612
+ header = new Uint8Array(9);
3613
+ const view = new DataView(header.buffer);
3614
+ view.setUint8(0, 127);
3615
+ view.setBigUint64(1, BigInt(payloadLength));
3616
+ }
3617
+ // first bit indicates whether the payload is plain text (0) or binary (1)
3618
+ if (packet.data && typeof packet.data !== "string") {
3619
+ header[0] |= 0x80;
3620
+ }
3621
+ controller.enqueue(header);
3622
+ controller.enqueue(encodedPacket);
3623
+ });
3624
+ },
3625
+ });
3626
+ }
3627
+ let TEXT_DECODER;
3628
+ function totalLength(chunks) {
3629
+ return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
3630
+ }
3631
+ function concatChunks(chunks, size) {
3632
+ if (chunks[0].length === size) {
3633
+ return chunks.shift();
3634
+ }
3635
+ const buffer = new Uint8Array(size);
3636
+ let j = 0;
3637
+ for (let i = 0; i < size; i++) {
3638
+ buffer[i] = chunks[0][j++];
3639
+ if (j === chunks[0].length) {
3640
+ chunks.shift();
3641
+ j = 0;
3642
+ }
3643
+ }
3644
+ if (chunks.length && j < chunks[0].length) {
3645
+ chunks[0] = chunks[0].slice(j);
3646
+ }
3647
+ return buffer;
3648
+ }
3649
+ function createPacketDecoderStream(maxPayload, binaryType) {
3650
+ if (!TEXT_DECODER) {
3651
+ TEXT_DECODER = new TextDecoder();
3652
+ }
3653
+ const chunks = [];
3654
+ let state = 0 /* READ_HEADER */;
3655
+ let expectedLength = -1;
3656
+ let isBinary = false;
3657
+ // @ts-expect-error
3658
+ return new TransformStream({
3659
+ transform(chunk, controller) {
3660
+ chunks.push(chunk);
3661
+ while (true) {
3662
+ if (state === 0 /* READ_HEADER */) {
3663
+ if (totalLength(chunks) < 1) {
3664
+ break;
3665
+ }
3666
+ const header = concatChunks(chunks, 1);
3667
+ isBinary = (header[0] & 0x80) === 0x80;
3668
+ expectedLength = header[0] & 0x7f;
3669
+ if (expectedLength < 126) {
3670
+ state = 3 /* READ_PAYLOAD */;
3671
+ }
3672
+ else if (expectedLength === 126) {
3673
+ state = 1 /* READ_EXTENDED_LENGTH_16 */;
3674
+ }
3675
+ else {
3676
+ state = 2 /* READ_EXTENDED_LENGTH_64 */;
3677
+ }
3678
+ }
3679
+ else if (state === 1 /* READ_EXTENDED_LENGTH_16 */) {
3680
+ if (totalLength(chunks) < 2) {
3681
+ break;
3682
+ }
3683
+ const headerArray = concatChunks(chunks, 2);
3684
+ expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
3685
+ state = 3 /* READ_PAYLOAD */;
3686
+ }
3687
+ else if (state === 2 /* READ_EXTENDED_LENGTH_64 */) {
3688
+ if (totalLength(chunks) < 8) {
3689
+ break;
3690
+ }
3691
+ const headerArray = concatChunks(chunks, 8);
3692
+ const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
3693
+ const n = view.getUint32(0);
3694
+ if (n > Math.pow(2, 53 - 32) - 1) {
3695
+ // the maximum safe integer in JavaScript is 2^53 - 1
3696
+ controller.enqueue(ERROR_PACKET);
3697
+ break;
3698
+ }
3699
+ expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
3700
+ state = 3 /* READ_PAYLOAD */;
3701
+ }
3702
+ else {
3703
+ if (totalLength(chunks) < expectedLength) {
3704
+ break;
3705
+ }
3706
+ const data = concatChunks(chunks, expectedLength);
3707
+ controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
3708
+ state = 0 /* READ_HEADER */;
3709
+ }
3710
+ if (expectedLength === 0 || expectedLength > maxPayload) {
3711
+ controller.enqueue(ERROR_PACKET);
3712
+ break;
3713
+ }
3714
+ }
3715
+ },
3716
+ });
3717
+ }
3526
3718
  const protocol$1 = 4;
3527
3719
 
3528
3720
  /**
@@ -3722,16 +3914,16 @@ function pick(obj, ...attr) {
3722
3914
  }, {});
3723
3915
  }
3724
3916
  // Keep a reference to the real timeout functions so they can be used when overridden
3725
- const NATIVE_SET_TIMEOUT = setTimeout;
3726
- const NATIVE_CLEAR_TIMEOUT = clearTimeout;
3917
+ const NATIVE_SET_TIMEOUT = globalThisShim.setTimeout;
3918
+ const NATIVE_CLEAR_TIMEOUT = globalThisShim.clearTimeout;
3727
3919
  function installTimerFunctions(obj, opts) {
3728
3920
  if (opts.useNativeTimers) {
3729
3921
  obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThisShim);
3730
3922
  obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThisShim);
3731
3923
  }
3732
3924
  else {
3733
- obj.setTimeoutFn = setTimeout.bind(globalThisShim);
3734
- obj.clearTimeoutFn = clearTimeout.bind(globalThisShim);
3925
+ obj.setTimeoutFn = globalThisShim.setTimeout.bind(globalThisShim);
3926
+ obj.clearTimeoutFn = globalThisShim.clearTimeout.bind(globalThisShim);
3735
3927
  }
3736
3928
  }
3737
3929
  // base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
@@ -3765,6 +3957,41 @@ function utf8Length(str) {
3765
3957
  return length;
3766
3958
  }
3767
3959
 
3960
+ // imported from https://github.com/galkn/querystring
3961
+ /**
3962
+ * Compiles a querystring
3963
+ * Returns string representation of the object
3964
+ *
3965
+ * @param {Object}
3966
+ * @api private
3967
+ */
3968
+ function encode$1(obj) {
3969
+ let str = '';
3970
+ for (let i in obj) {
3971
+ if (obj.hasOwnProperty(i)) {
3972
+ if (str.length)
3973
+ str += '&';
3974
+ str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3975
+ }
3976
+ }
3977
+ return str;
3978
+ }
3979
+ /**
3980
+ * Parses a simple querystring into an object
3981
+ *
3982
+ * @param {String} qs
3983
+ * @api private
3984
+ */
3985
+ function decode(qs) {
3986
+ let qry = {};
3987
+ let pairs = qs.split('&');
3988
+ for (let i = 0, l = pairs.length; i < l; i++) {
3989
+ let pair = pairs[i].split('=');
3990
+ qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3991
+ }
3992
+ return qry;
3993
+ }
3994
+
3768
3995
  class TransportError extends Error {
3769
3996
  constructor(reason, description, context) {
3770
3997
  super(reason);
@@ -3777,8 +4004,8 @@ class Transport extends Emitter_1 {
3777
4004
  /**
3778
4005
  * Transport abstract constructor.
3779
4006
  *
3780
- * @param {Object} options.
3781
- * @api private
4007
+ * @param {Object} opts - options
4008
+ * @protected
3782
4009
  */
3783
4010
  constructor(opts) {
3784
4011
  super();
@@ -3786,7 +4013,6 @@ class Transport extends Emitter_1 {
3786
4013
  installTimerFunctions(this, opts);
3787
4014
  this.opts = opts;
3788
4015
  this.query = opts.query;
3789
- this.readyState = "";
3790
4016
  this.socket = opts.socket;
3791
4017
  }
3792
4018
  /**
@@ -3796,7 +4022,7 @@ class Transport extends Emitter_1 {
3796
4022
  * @param description
3797
4023
  * @param context - the error context
3798
4024
  * @return {Transport} for chaining
3799
- * @api protected
4025
+ * @protected
3800
4026
  */
3801
4027
  onError(reason, description, context) {
3802
4028
  super.emitReserved("error", new TransportError(reason, description, context));
@@ -3804,23 +4030,17 @@ class Transport extends Emitter_1 {
3804
4030
  }
3805
4031
  /**
3806
4032
  * Opens the transport.
3807
- *
3808
- * @api public
3809
4033
  */
3810
4034
  open() {
3811
- if ("closed" === this.readyState || "" === this.readyState) {
3812
- this.readyState = "opening";
3813
- this.doOpen();
3814
- }
4035
+ this.readyState = "opening";
4036
+ this.doOpen();
3815
4037
  return this;
3816
4038
  }
3817
4039
  /**
3818
4040
  * Closes the transport.
3819
- *
3820
- * @api public
3821
4041
  */
3822
4042
  close() {
3823
- if ("opening" === this.readyState || "open" === this.readyState) {
4043
+ if (this.readyState === "opening" || this.readyState === "open") {
3824
4044
  this.doClose();
3825
4045
  this.onClose();
3826
4046
  }
@@ -3830,17 +4050,16 @@ class Transport extends Emitter_1 {
3830
4050
  * Sends multiple packets.
3831
4051
  *
3832
4052
  * @param {Array} packets
3833
- * @api public
3834
4053
  */
3835
4054
  send(packets) {
3836
- if ("open" === this.readyState) {
4055
+ if (this.readyState === "open") {
3837
4056
  this.write(packets);
3838
4057
  }
3839
4058
  }
3840
4059
  /**
3841
4060
  * Called upon open
3842
4061
  *
3843
- * @api protected
4062
+ * @protected
3844
4063
  */
3845
4064
  onOpen() {
3846
4065
  this.readyState = "open";
@@ -3851,7 +4070,7 @@ class Transport extends Emitter_1 {
3851
4070
  * Called with data.
3852
4071
  *
3853
4072
  * @param {String} data
3854
- * @api protected
4073
+ * @protected
3855
4074
  */
3856
4075
  onData(data) {
3857
4076
  const packet = decodePacket(data, this.socket.binaryType);
@@ -3860,7 +4079,7 @@ class Transport extends Emitter_1 {
3860
4079
  /**
3861
4080
  * Called with a decoded packet.
3862
4081
  *
3863
- * @api protected
4082
+ * @protected
3864
4083
  */
3865
4084
  onPacket(packet) {
3866
4085
  super.emitReserved("packet", packet);
@@ -3868,12 +4087,44 @@ class Transport extends Emitter_1 {
3868
4087
  /**
3869
4088
  * Called upon close.
3870
4089
  *
3871
- * @api protected
4090
+ * @protected
3872
4091
  */
3873
4092
  onClose(details) {
3874
4093
  this.readyState = "closed";
3875
4094
  super.emitReserved("close", details);
3876
4095
  }
4096
+ /**
4097
+ * Pauses the transport, in order not to lose packets during an upgrade.
4098
+ *
4099
+ * @param onPause
4100
+ */
4101
+ pause(onPause) { }
4102
+ createUri(schema, query = {}) {
4103
+ return (schema +
4104
+ "://" +
4105
+ this._hostname() +
4106
+ this._port() +
4107
+ this.opts.path +
4108
+ this._query(query));
4109
+ }
4110
+ _hostname() {
4111
+ const hostname = this.opts.hostname;
4112
+ return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
4113
+ }
4114
+ _port() {
4115
+ if (this.opts.port &&
4116
+ ((this.opts.secure && Number(this.opts.port !== 443)) ||
4117
+ (!this.opts.secure && Number(this.opts.port) !== 80))) {
4118
+ return ":" + this.opts.port;
4119
+ }
4120
+ else {
4121
+ return "";
4122
+ }
4123
+ }
4124
+ _query(query) {
4125
+ const encodedQuery = encode$1(query);
4126
+ return encodedQuery.length ? "?" + encodedQuery : "";
4127
+ }
3877
4128
  }
3878
4129
 
3879
4130
  // imported from https://github.com/unshiftio/yeast
@@ -3886,7 +4137,7 @@ let seed = 0, i = 0, prev;
3886
4137
  * @returns {String} The string representation of the number.
3887
4138
  * @api public
3888
4139
  */
3889
- function encode$1(num) {
4140
+ function encode(num) {
3890
4141
  let encoded = '';
3891
4142
  do {
3892
4143
  encoded = alphabet[num % length] + encoded;
@@ -3901,10 +4152,10 @@ function encode$1(num) {
3901
4152
  * @api public
3902
4153
  */
3903
4154
  function yeast() {
3904
- const now = encode$1(+new Date());
4155
+ const now = encode(+new Date());
3905
4156
  if (now !== prev)
3906
4157
  return seed = 0, prev = now;
3907
- return now + '.' + encode$1(seed++);
4158
+ return now + '.' + encode(seed++);
3908
4159
  }
3909
4160
  //
3910
4161
  // Map each character to its index.
@@ -3912,41 +4163,6 @@ function yeast() {
3912
4163
  for (; i < length; i++)
3913
4164
  map[alphabet[i]] = i;
3914
4165
 
3915
- // imported from https://github.com/galkn/querystring
3916
- /**
3917
- * Compiles a querystring
3918
- * Returns string representation of the object
3919
- *
3920
- * @param {Object}
3921
- * @api private
3922
- */
3923
- function encode(obj) {
3924
- let str = '';
3925
- for (let i in obj) {
3926
- if (obj.hasOwnProperty(i)) {
3927
- if (str.length)
3928
- str += '&';
3929
- str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3930
- }
3931
- }
3932
- return str;
3933
- }
3934
- /**
3935
- * Parses a simple querystring into an object
3936
- *
3937
- * @param {String} qs
3938
- * @api private
3939
- */
3940
- function decode(qs) {
3941
- let qry = {};
3942
- let pairs = qs.split('&');
3943
- for (let i = 0, l = pairs.length; i < l; i++) {
3944
- let pair = pairs[i].split('=');
3945
- qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3946
- }
3947
- return qry;
3948
- }
3949
-
3950
4166
  // imported from https://github.com/component/has-cors
3951
4167
  let value = false;
3952
4168
  try {
@@ -3976,11 +4192,12 @@ function XHR(opts) {
3976
4192
  catch (e) { }
3977
4193
  }
3978
4194
  }
4195
+ function createCookieJar() { }
3979
4196
 
3980
4197
  function empty$2() { }
3981
4198
  const hasXHR2 = (function () {
3982
4199
  const xhr = new XHR({
3983
- xdomain: false
4200
+ xdomain: false,
3984
4201
  });
3985
4202
  return null != xhr.responseType;
3986
4203
  })();
@@ -3989,7 +4206,7 @@ class Polling extends Transport {
3989
4206
  * XHR Polling constructor.
3990
4207
  *
3991
4208
  * @param {Object} opts
3992
- * @api public
4209
+ * @package
3993
4210
  */
3994
4211
  constructor(opts) {
3995
4212
  super(opts);
@@ -4005,17 +4222,16 @@ class Polling extends Transport {
4005
4222
  (typeof location !== "undefined" &&
4006
4223
  opts.hostname !== location.hostname) ||
4007
4224
  port !== opts.port;
4008
- this.xs = opts.secure !== isSSL;
4009
4225
  }
4010
4226
  /**
4011
4227
  * XHR supports binary
4012
4228
  */
4013
4229
  const forceBase64 = opts && opts.forceBase64;
4014
4230
  this.supportsBinary = hasXHR2 && !forceBase64;
4231
+ if (this.opts.withCredentials) {
4232
+ this.cookieJar = createCookieJar();
4233
+ }
4015
4234
  }
4016
- /**
4017
- * Transport name.
4018
- */
4019
4235
  get name() {
4020
4236
  return "polling";
4021
4237
  }
@@ -4023,7 +4239,7 @@ class Polling extends Transport {
4023
4239
  * Opens the socket (triggers polling). We write a PING message to determine
4024
4240
  * when the transport is open.
4025
4241
  *
4026
- * @api private
4242
+ * @protected
4027
4243
  */
4028
4244
  doOpen() {
4029
4245
  this.poll();
@@ -4031,8 +4247,8 @@ class Polling extends Transport {
4031
4247
  /**
4032
4248
  * Pauses polling.
4033
4249
  *
4034
- * @param {Function} callback upon buffers are flushed and transport is paused
4035
- * @api private
4250
+ * @param {Function} onPause - callback upon buffers are flushed and transport is paused
4251
+ * @package
4036
4252
  */
4037
4253
  pause(onPause) {
4038
4254
  this.readyState = "pausing";
@@ -4062,7 +4278,7 @@ class Polling extends Transport {
4062
4278
  /**
4063
4279
  * Starts polling cycle.
4064
4280
  *
4065
- * @api public
4281
+ * @private
4066
4282
  */
4067
4283
  poll() {
4068
4284
  this.polling = true;
@@ -4072,10 +4288,10 @@ class Polling extends Transport {
4072
4288
  /**
4073
4289
  * Overloads onData to detect payloads.
4074
4290
  *
4075
- * @api private
4291
+ * @protected
4076
4292
  */
4077
4293
  onData(data) {
4078
- const callback = packet => {
4294
+ const callback = (packet) => {
4079
4295
  // if its the first message we consider the transport open
4080
4296
  if ("opening" === this.readyState && packet.type === "open") {
4081
4297
  this.onOpen();
@@ -4103,7 +4319,7 @@ class Polling extends Transport {
4103
4319
  /**
4104
4320
  * For polling, send a close packet.
4105
4321
  *
4106
- * @api private
4322
+ * @protected
4107
4323
  */
4108
4324
  doClose() {
4109
4325
  const close = () => {
@@ -4121,13 +4337,12 @@ class Polling extends Transport {
4121
4337
  /**
4122
4338
  * Writes a packets payload.
4123
4339
  *
4124
- * @param {Array} data packets
4125
- * @param {Function} drain callback
4126
- * @api private
4340
+ * @param {Array} packets - data packets
4341
+ * @protected
4127
4342
  */
4128
4343
  write(packets) {
4129
4344
  this.writable = false;
4130
- encodePayload(packets, data => {
4345
+ encodePayload(packets, (data) => {
4131
4346
  this.doWrite(data, () => {
4132
4347
  this.writable = true;
4133
4348
  this.emitReserved("drain");
@@ -4137,12 +4352,11 @@ class Polling extends Transport {
4137
4352
  /**
4138
4353
  * Generates uri for connection.
4139
4354
  *
4140
- * @api private
4355
+ * @private
4141
4356
  */
4142
4357
  uri() {
4143
- let query = this.query || {};
4144
4358
  const schema = this.opts.secure ? "https" : "http";
4145
- let port = "";
4359
+ const query = this.query || {};
4146
4360
  // cache busting is forced
4147
4361
  if (false !== this.opts.timestampRequests) {
4148
4362
  query[this.opts.timestampParam] = yeast();
@@ -4150,29 +4364,16 @@ class Polling extends Transport {
4150
4364
  if (!this.supportsBinary && !query.sid) {
4151
4365
  query.b64 = 1;
4152
4366
  }
4153
- // avoid port if default for schema
4154
- if (this.opts.port &&
4155
- (("https" === schema && Number(this.opts.port) !== 443) ||
4156
- ("http" === schema && Number(this.opts.port) !== 80))) {
4157
- port = ":" + this.opts.port;
4158
- }
4159
- const encodedQuery = encode(query);
4160
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4161
- return (schema +
4162
- "://" +
4163
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4164
- port +
4165
- this.opts.path +
4166
- (encodedQuery.length ? "?" + encodedQuery : ""));
4367
+ return this.createUri(schema, query);
4167
4368
  }
4168
4369
  /**
4169
4370
  * Creates a request.
4170
4371
  *
4171
4372
  * @param {String} method
4172
- * @api private
4373
+ * @private
4173
4374
  */
4174
4375
  request(opts = {}) {
4175
- Object.assign(opts, { xd: this.xd, xs: this.xs }, this.opts);
4376
+ Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
4176
4377
  return new Request(this.uri(), opts);
4177
4378
  }
4178
4379
  /**
@@ -4180,12 +4381,12 @@ class Polling extends Transport {
4180
4381
  *
4181
4382
  * @param {String} data to send.
4182
4383
  * @param {Function} called upon flush.
4183
- * @api private
4384
+ * @private
4184
4385
  */
4185
4386
  doWrite(data, fn) {
4186
4387
  const req = this.request({
4187
4388
  method: "POST",
4188
- data: data
4389
+ data: data,
4189
4390
  });
4190
4391
  req.on("success", fn);
4191
4392
  req.on("error", (xhrStatus, context) => {
@@ -4195,7 +4396,7 @@ class Polling extends Transport {
4195
4396
  /**
4196
4397
  * Starts a poll cycle.
4197
4398
  *
4198
- * @api private
4399
+ * @private
4199
4400
  */
4200
4401
  doPoll() {
4201
4402
  const req = this.request();
@@ -4211,7 +4412,7 @@ class Request extends Emitter_1 {
4211
4412
  * Request constructor
4212
4413
  *
4213
4414
  * @param {Object} options
4214
- * @api public
4415
+ * @package
4215
4416
  */
4216
4417
  constructor(uri, opts) {
4217
4418
  super();
@@ -4219,22 +4420,21 @@ class Request extends Emitter_1 {
4219
4420
  this.opts = opts;
4220
4421
  this.method = opts.method || "GET";
4221
4422
  this.uri = uri;
4222
- this.async = false !== opts.async;
4223
4423
  this.data = undefined !== opts.data ? opts.data : null;
4224
4424
  this.create();
4225
4425
  }
4226
4426
  /**
4227
4427
  * Creates the XHR object and sends the request.
4228
4428
  *
4229
- * @api private
4429
+ * @private
4230
4430
  */
4231
4431
  create() {
4432
+ var _a;
4232
4433
  const opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4233
4434
  opts.xdomain = !!this.opts.xd;
4234
- opts.xscheme = !!this.opts.xs;
4235
4435
  const xhr = (this.xhr = new XHR(opts));
4236
4436
  try {
4237
- xhr.open(this.method, this.uri, this.async);
4437
+ xhr.open(this.method, this.uri, true);
4238
4438
  try {
4239
4439
  if (this.opts.extraHeaders) {
4240
4440
  xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
@@ -4256,6 +4456,7 @@ class Request extends Emitter_1 {
4256
4456
  xhr.setRequestHeader("Accept", "*/*");
4257
4457
  }
4258
4458
  catch (e) { }
4459
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4259
4460
  // ie6 check
4260
4461
  if ("withCredentials" in xhr) {
4261
4462
  xhr.withCredentials = this.opts.withCredentials;
@@ -4264,6 +4465,10 @@ class Request extends Emitter_1 {
4264
4465
  xhr.timeout = this.opts.requestTimeout;
4265
4466
  }
4266
4467
  xhr.onreadystatechange = () => {
4468
+ var _a;
4469
+ if (xhr.readyState === 3) {
4470
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
4471
+ }
4267
4472
  if (4 !== xhr.readyState)
4268
4473
  return;
4269
4474
  if (200 === xhr.status || 1223 === xhr.status) {
@@ -4296,7 +4501,7 @@ class Request extends Emitter_1 {
4296
4501
  /**
4297
4502
  * Called upon error.
4298
4503
  *
4299
- * @api private
4504
+ * @private
4300
4505
  */
4301
4506
  onError(err) {
4302
4507
  this.emitReserved("error", err, this.xhr);
@@ -4305,7 +4510,7 @@ class Request extends Emitter_1 {
4305
4510
  /**
4306
4511
  * Cleans up house.
4307
4512
  *
4308
- * @api private
4513
+ * @private
4309
4514
  */
4310
4515
  cleanup(fromError) {
4311
4516
  if ("undefined" === typeof this.xhr || null === this.xhr) {
@@ -4326,7 +4531,7 @@ class Request extends Emitter_1 {
4326
4531
  /**
4327
4532
  * Called upon load.
4328
4533
  *
4329
- * @api private
4534
+ * @private
4330
4535
  */
4331
4536
  onLoad() {
4332
4537
  const data = this.xhr.responseText;
@@ -4339,7 +4544,7 @@ class Request extends Emitter_1 {
4339
4544
  /**
4340
4545
  * Aborts the request.
4341
4546
  *
4342
- * @api public
4547
+ * @package
4343
4548
  */
4344
4549
  abort() {
4345
4550
  this.cleanup();
@@ -4374,7 +4579,7 @@ function unloadHandler() {
4374
4579
  const nextTick = (() => {
4375
4580
  const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
4376
4581
  if (isPromiseAvailable) {
4377
- return cb => Promise.resolve().then(cb);
4582
+ return (cb) => Promise.resolve().then(cb);
4378
4583
  }
4379
4584
  else {
4380
4585
  return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
@@ -4392,26 +4597,16 @@ class WS extends Transport {
4392
4597
  /**
4393
4598
  * WebSocket transport constructor.
4394
4599
  *
4395
- * @api {Object} connection options
4396
- * @api public
4600
+ * @param {Object} opts - connection options
4601
+ * @protected
4397
4602
  */
4398
4603
  constructor(opts) {
4399
4604
  super(opts);
4400
4605
  this.supportsBinary = !opts.forceBase64;
4401
4606
  }
4402
- /**
4403
- * Transport name.
4404
- *
4405
- * @api public
4406
- */
4407
4607
  get name() {
4408
4608
  return "websocket";
4409
4609
  }
4410
- /**
4411
- * Opens socket.
4412
- *
4413
- * @api private
4414
- */
4415
4610
  doOpen() {
4416
4611
  if (!this.check()) {
4417
4612
  // let probe timeout
@@ -4437,13 +4632,13 @@ class WS extends Transport {
4437
4632
  catch (err) {
4438
4633
  return this.emitReserved("error", err);
4439
4634
  }
4440
- this.ws.binaryType = this.socket.binaryType || defaultBinaryType;
4635
+ this.ws.binaryType = this.socket.binaryType;
4441
4636
  this.addEventListeners();
4442
4637
  }
4443
4638
  /**
4444
4639
  * Adds event listeners to the socket
4445
4640
  *
4446
- * @api private
4641
+ * @private
4447
4642
  */
4448
4643
  addEventListeners() {
4449
4644
  this.ws.onopen = () => {
@@ -4452,19 +4647,13 @@ class WS extends Transport {
4452
4647
  }
4453
4648
  this.onOpen();
4454
4649
  };
4455
- this.ws.onclose = closeEvent => this.onClose({
4650
+ this.ws.onclose = (closeEvent) => this.onClose({
4456
4651
  description: "websocket connection closed",
4457
- context: closeEvent
4652
+ context: closeEvent,
4458
4653
  });
4459
- this.ws.onmessage = ev => this.onData(ev.data);
4460
- this.ws.onerror = e => this.onError("websocket error", e);
4654
+ this.ws.onmessage = (ev) => this.onData(ev.data);
4655
+ this.ws.onerror = (e) => this.onError("websocket error", e);
4461
4656
  }
4462
- /**
4463
- * Writes data to socket.
4464
- *
4465
- * @param {Array} array of packets.
4466
- * @api private
4467
- */
4468
4657
  write(packets) {
4469
4658
  this.writable = false;
4470
4659
  // encodePacket efficient as it uses WS framing
@@ -4472,7 +4661,7 @@ class WS extends Transport {
4472
4661
  for (let i = 0; i < packets.length; i++) {
4473
4662
  const packet = packets[i];
4474
4663
  const lastPacket = i === packets.length - 1;
4475
- encodePacket(packet, this.supportsBinary, data => {
4664
+ encodePacket(packet, this.supportsBinary, (data) => {
4476
4665
  // always create a new object (GH-437)
4477
4666
  const opts = {};
4478
4667
  // Sometimes the websocket has already been closed but the browser didn't
@@ -4497,11 +4686,6 @@ class WS extends Transport {
4497
4686
  });
4498
4687
  }
4499
4688
  }
4500
- /**
4501
- * Closes socket.
4502
- *
4503
- * @api private
4504
- */
4505
4689
  doClose() {
4506
4690
  if (typeof this.ws !== "undefined") {
4507
4691
  this.ws.close();
@@ -4511,18 +4695,11 @@ class WS extends Transport {
4511
4695
  /**
4512
4696
  * Generates uri for connection.
4513
4697
  *
4514
- * @api private
4698
+ * @private
4515
4699
  */
4516
4700
  uri() {
4517
- let query = this.query || {};
4518
4701
  const schema = this.opts.secure ? "wss" : "ws";
4519
- let port = "";
4520
- // avoid port if default for schema
4521
- if (this.opts.port &&
4522
- (("wss" === schema && Number(this.opts.port) !== 443) ||
4523
- ("ws" === schema && Number(this.opts.port) !== 80))) {
4524
- port = ":" + this.opts.port;
4525
- }
4702
+ const query = this.query || {};
4526
4703
  // append timestamp to URI
4527
4704
  if (this.opts.timestampRequests) {
4528
4705
  query[this.opts.timestampParam] = yeast();
@@ -4531,43 +4708,121 @@ class WS extends Transport {
4531
4708
  if (!this.supportsBinary) {
4532
4709
  query.b64 = 1;
4533
4710
  }
4534
- const encodedQuery = encode(query);
4535
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4536
- return (schema +
4537
- "://" +
4538
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4539
- port +
4540
- this.opts.path +
4541
- (encodedQuery.length ? "?" + encodedQuery : ""));
4711
+ return this.createUri(schema, query);
4542
4712
  }
4543
4713
  /**
4544
4714
  * Feature detection for WebSocket.
4545
4715
  *
4546
4716
  * @return {Boolean} whether this transport is available.
4547
- * @api public
4717
+ * @private
4548
4718
  */
4549
4719
  check() {
4550
4720
  return !!WebSocket$1;
4551
4721
  }
4552
4722
  }
4553
4723
 
4724
+ class WT extends Transport {
4725
+ get name() {
4726
+ return "webtransport";
4727
+ }
4728
+ doOpen() {
4729
+ // @ts-ignore
4730
+ if (typeof WebTransport !== "function") {
4731
+ return;
4732
+ }
4733
+ // @ts-ignore
4734
+ this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4735
+ this.transport.closed
4736
+ .then(() => {
4737
+ this.onClose();
4738
+ })
4739
+ .catch((err) => {
4740
+ this.onError("webtransport error", err);
4741
+ });
4742
+ // note: we could have used async/await, but that would require some additional polyfills
4743
+ this.transport.ready.then(() => {
4744
+ this.transport.createBidirectionalStream().then((stream) => {
4745
+ const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
4746
+ const reader = stream.readable.pipeThrough(decoderStream).getReader();
4747
+ const encoderStream = createPacketEncoderStream();
4748
+ encoderStream.readable.pipeTo(stream.writable);
4749
+ this.writer = encoderStream.writable.getWriter();
4750
+ const read = () => {
4751
+ reader
4752
+ .read()
4753
+ .then(({ done, value }) => {
4754
+ if (done) {
4755
+ return;
4756
+ }
4757
+ this.onPacket(value);
4758
+ read();
4759
+ })
4760
+ .catch((err) => {
4761
+ });
4762
+ };
4763
+ read();
4764
+ const packet = { type: "open" };
4765
+ if (this.query.sid) {
4766
+ packet.data = `{"sid":"${this.query.sid}"}`;
4767
+ }
4768
+ this.writer.write(packet).then(() => this.onOpen());
4769
+ });
4770
+ });
4771
+ }
4772
+ write(packets) {
4773
+ this.writable = false;
4774
+ for (let i = 0; i < packets.length; i++) {
4775
+ const packet = packets[i];
4776
+ const lastPacket = i === packets.length - 1;
4777
+ this.writer.write(packet).then(() => {
4778
+ if (lastPacket) {
4779
+ nextTick(() => {
4780
+ this.writable = true;
4781
+ this.emitReserved("drain");
4782
+ }, this.setTimeoutFn);
4783
+ }
4784
+ });
4785
+ }
4786
+ }
4787
+ doClose() {
4788
+ var _a;
4789
+ (_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
4790
+ }
4791
+ }
4792
+
4554
4793
  const transports = {
4555
4794
  websocket: WS,
4556
- polling: Polling
4795
+ webtransport: WT,
4796
+ polling: Polling,
4557
4797
  };
4558
4798
 
4559
4799
  // imported from https://github.com/galkn/parseuri
4560
4800
  /**
4561
- * Parses an URI
4801
+ * Parses a URI
4802
+ *
4803
+ * Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
4804
+ *
4805
+ * See:
4806
+ * - https://developer.mozilla.org/en-US/docs/Web/API/URL
4807
+ * - https://caniuse.com/url
4808
+ * - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
4809
+ *
4810
+ * History of the parse() method:
4811
+ * - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
4812
+ * - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
4813
+ * - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
4562
4814
  *
4563
4815
  * @author Steven Levithan <stevenlevithan.com> (MIT license)
4564
4816
  * @api private
4565
4817
  */
4566
- const re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4818
+ const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4567
4819
  const parts = [
4568
4820
  'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
4569
4821
  ];
4570
4822
  function parse$2(str) {
4823
+ if (str.length > 2000) {
4824
+ throw "URI too long";
4825
+ }
4571
4826
  const src = str, b = str.indexOf('['), e = str.indexOf(']');
4572
4827
  if (b != -1 && e != -1) {
4573
4828
  str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
@@ -4610,12 +4865,13 @@ class Socket$1 extends Emitter_1 {
4610
4865
  /**
4611
4866
  * Socket constructor.
4612
4867
  *
4613
- * @param {String|Object} uri or options
4868
+ * @param {String|Object} uri - uri or options
4614
4869
  * @param {Object} opts - options
4615
- * @api public
4616
4870
  */
4617
4871
  constructor(uri, opts = {}) {
4618
4872
  super();
4873
+ this.binaryType = defaultBinaryType;
4874
+ this.writeBuffer = [];
4619
4875
  if (uri && "object" === typeof uri) {
4620
4876
  opts = uri;
4621
4877
  uri = null;
@@ -4650,8 +4906,11 @@ class Socket$1 extends Emitter_1 {
4650
4906
  : this.secure
4651
4907
  ? "443"
4652
4908
  : "80");
4653
- this.transports = opts.transports || ["polling", "websocket"];
4654
- this.readyState = "";
4909
+ this.transports = opts.transports || [
4910
+ "polling",
4911
+ "websocket",
4912
+ "webtransport",
4913
+ ];
4655
4914
  this.writeBuffer = [];
4656
4915
  this.prevBufferLen = 0;
4657
4916
  this.opts = Object.assign({
@@ -4661,14 +4920,17 @@ class Socket$1 extends Emitter_1 {
4661
4920
  upgrade: true,
4662
4921
  timestampParam: "t",
4663
4922
  rememberUpgrade: false,
4923
+ addTrailingSlash: true,
4664
4924
  rejectUnauthorized: true,
4665
4925
  perMessageDeflate: {
4666
- threshold: 1024
4926
+ threshold: 1024,
4667
4927
  },
4668
4928
  transportOptions: {},
4669
- closeOnBeforeunload: true
4929
+ closeOnBeforeunload: false,
4670
4930
  }, opts);
4671
- this.opts.path = this.opts.path.replace(/\/$/, "") + "/";
4931
+ this.opts.path =
4932
+ this.opts.path.replace(/\/$/, "") +
4933
+ (this.opts.addTrailingSlash ? "/" : "");
4672
4934
  if (typeof this.opts.query === "string") {
4673
4935
  this.opts.query = decode(this.opts.query);
4674
4936
  }
@@ -4696,7 +4958,7 @@ class Socket$1 extends Emitter_1 {
4696
4958
  if (this.hostname !== "localhost") {
4697
4959
  this.offlineEventListener = () => {
4698
4960
  this.onClose("transport close", {
4699
- description: "network connection lost"
4961
+ description: "network connection lost",
4700
4962
  });
4701
4963
  };
4702
4964
  addEventListener("offline", this.offlineEventListener, false);
@@ -4707,9 +4969,9 @@ class Socket$1 extends Emitter_1 {
4707
4969
  /**
4708
4970
  * Creates transport of the given type.
4709
4971
  *
4710
- * @param {String} transport name
4972
+ * @param {String} name - transport name
4711
4973
  * @return {Transport}
4712
- * @api private
4974
+ * @private
4713
4975
  */
4714
4976
  createTransport(name) {
4715
4977
  const query = Object.assign({}, this.opts.query);
@@ -4720,19 +4982,19 @@ class Socket$1 extends Emitter_1 {
4720
4982
  // session id if we already have one
4721
4983
  if (this.id)
4722
4984
  query.sid = this.id;
4723
- const opts = Object.assign({}, this.opts.transportOptions[name], this.opts, {
4985
+ const opts = Object.assign({}, this.opts, {
4724
4986
  query,
4725
4987
  socket: this,
4726
4988
  hostname: this.hostname,
4727
4989
  secure: this.secure,
4728
- port: this.port
4729
- });
4990
+ port: this.port,
4991
+ }, this.opts.transportOptions[name]);
4730
4992
  return new transports[name](opts);
4731
4993
  }
4732
4994
  /**
4733
4995
  * Initializes transport to use and starts probe.
4734
4996
  *
4735
- * @api private
4997
+ * @private
4736
4998
  */
4737
4999
  open() {
4738
5000
  let transport;
@@ -4767,7 +5029,7 @@ class Socket$1 extends Emitter_1 {
4767
5029
  /**
4768
5030
  * Sets the current transport. Disables the existing one (if any).
4769
5031
  *
4770
- * @api private
5032
+ * @private
4771
5033
  */
4772
5034
  setTransport(transport) {
4773
5035
  if (this.transport) {
@@ -4780,13 +5042,13 @@ class Socket$1 extends Emitter_1 {
4780
5042
  .on("drain", this.onDrain.bind(this))
4781
5043
  .on("packet", this.onPacket.bind(this))
4782
5044
  .on("error", this.onError.bind(this))
4783
- .on("close", reason => this.onClose("transport close", reason));
5045
+ .on("close", (reason) => this.onClose("transport close", reason));
4784
5046
  }
4785
5047
  /**
4786
5048
  * Probes a transport.
4787
5049
  *
4788
- * @param {String} transport name
4789
- * @api private
5050
+ * @param {String} name - transport name
5051
+ * @private
4790
5052
  */
4791
5053
  probe(name) {
4792
5054
  let transport = this.createTransport(name);
@@ -4796,7 +5058,7 @@ class Socket$1 extends Emitter_1 {
4796
5058
  if (failed)
4797
5059
  return;
4798
5060
  transport.send([{ type: "ping", data: "probe" }]);
4799
- transport.once("packet", msg => {
5061
+ transport.once("packet", (msg) => {
4800
5062
  if (failed)
4801
5063
  return;
4802
5064
  if ("pong" === msg.type && "probe" === msg.data) {
@@ -4837,7 +5099,7 @@ class Socket$1 extends Emitter_1 {
4837
5099
  transport = null;
4838
5100
  }
4839
5101
  // Handle any error that happens while probing
4840
- const onerror = err => {
5102
+ const onerror = (err) => {
4841
5103
  const error = new Error("probe error: " + err);
4842
5104
  // @ts-ignore
4843
5105
  error.transport = transport.name;
@@ -4870,12 +5132,23 @@ class Socket$1 extends Emitter_1 {
4870
5132
  transport.once("close", onTransportClose);
4871
5133
  this.once("close", onclose);
4872
5134
  this.once("upgrading", onupgrade);
4873
- transport.open();
5135
+ if (this.upgrades.indexOf("webtransport") !== -1 &&
5136
+ name !== "webtransport") {
5137
+ // favor WebTransport
5138
+ this.setTimeoutFn(() => {
5139
+ if (!failed) {
5140
+ transport.open();
5141
+ }
5142
+ }, 200);
5143
+ }
5144
+ else {
5145
+ transport.open();
5146
+ }
4874
5147
  }
4875
5148
  /**
4876
5149
  * Called when connection is deemed open.
4877
5150
  *
4878
- * @api private
5151
+ * @private
4879
5152
  */
4880
5153
  onOpen() {
4881
5154
  this.readyState = "open";
@@ -4884,9 +5157,7 @@ class Socket$1 extends Emitter_1 {
4884
5157
  this.flush();
4885
5158
  // we check for `readyState` in case an `open`
4886
5159
  // listener already closed the socket
4887
- if ("open" === this.readyState &&
4888
- this.opts.upgrade &&
4889
- this.transport.pause) {
5160
+ if ("open" === this.readyState && this.opts.upgrade) {
4890
5161
  let i = 0;
4891
5162
  const l = this.upgrades.length;
4892
5163
  for (; i < l; i++) {
@@ -4897,7 +5168,7 @@ class Socket$1 extends Emitter_1 {
4897
5168
  /**
4898
5169
  * Handles a packet.
4899
5170
  *
4900
- * @api private
5171
+ * @private
4901
5172
  */
4902
5173
  onPacket(packet) {
4903
5174
  if ("opening" === this.readyState ||
@@ -4906,12 +5177,12 @@ class Socket$1 extends Emitter_1 {
4906
5177
  this.emitReserved("packet", packet);
4907
5178
  // Socket is live - any packet counts
4908
5179
  this.emitReserved("heartbeat");
5180
+ this.resetPingTimeout();
4909
5181
  switch (packet.type) {
4910
5182
  case "open":
4911
5183
  this.onHandshake(JSON.parse(packet.data));
4912
5184
  break;
4913
5185
  case "ping":
4914
- this.resetPingTimeout();
4915
5186
  this.sendPacket("pong");
4916
5187
  this.emitReserved("ping");
4917
5188
  this.emitReserved("pong");
@@ -4933,7 +5204,7 @@ class Socket$1 extends Emitter_1 {
4933
5204
  * Called upon handshake completion.
4934
5205
  *
4935
5206
  * @param {Object} data - handshake obj
4936
- * @api private
5207
+ * @private
4937
5208
  */
4938
5209
  onHandshake(data) {
4939
5210
  this.emitReserved("handshake", data);
@@ -4952,7 +5223,7 @@ class Socket$1 extends Emitter_1 {
4952
5223
  /**
4953
5224
  * Sets and resets ping timeout timer based on server pings.
4954
5225
  *
4955
- * @api private
5226
+ * @private
4956
5227
  */
4957
5228
  resetPingTimeout() {
4958
5229
  this.clearTimeoutFn(this.pingTimeoutTimer);
@@ -4966,7 +5237,7 @@ class Socket$1 extends Emitter_1 {
4966
5237
  /**
4967
5238
  * Called on `drain` event
4968
5239
  *
4969
- * @api private
5240
+ * @private
4970
5241
  */
4971
5242
  onDrain() {
4972
5243
  this.writeBuffer.splice(0, this.prevBufferLen);
@@ -4984,7 +5255,7 @@ class Socket$1 extends Emitter_1 {
4984
5255
  /**
4985
5256
  * Flush write buffers.
4986
5257
  *
4987
- * @api private
5258
+ * @private
4988
5259
  */
4989
5260
  flush() {
4990
5261
  if ("closed" !== this.readyState &&
@@ -5028,11 +5299,10 @@ class Socket$1 extends Emitter_1 {
5028
5299
  /**
5029
5300
  * Sends a message.
5030
5301
  *
5031
- * @param {String} message.
5032
- * @param {Function} callback function.
5302
+ * @param {String} msg - message.
5033
5303
  * @param {Object} options.
5304
+ * @param {Function} callback function.
5034
5305
  * @return {Socket} for chaining.
5035
- * @api public
5036
5306
  */
5037
5307
  write(msg, options, fn) {
5038
5308
  this.sendPacket("message", msg, options, fn);
@@ -5045,11 +5315,11 @@ class Socket$1 extends Emitter_1 {
5045
5315
  /**
5046
5316
  * Sends a packet.
5047
5317
  *
5048
- * @param {String} packet type.
5318
+ * @param {String} type: packet type.
5049
5319
  * @param {String} data.
5050
5320
  * @param {Object} options.
5051
- * @param {Function} callback function.
5052
- * @api private
5321
+ * @param {Function} fn - callback function.
5322
+ * @private
5053
5323
  */
5054
5324
  sendPacket(type, data, options, fn) {
5055
5325
  if ("function" === typeof data) {
@@ -5068,7 +5338,7 @@ class Socket$1 extends Emitter_1 {
5068
5338
  const packet = {
5069
5339
  type: type,
5070
5340
  data: data,
5071
- options: options
5341
+ options: options,
5072
5342
  };
5073
5343
  this.emitReserved("packetCreate", packet);
5074
5344
  this.writeBuffer.push(packet);
@@ -5078,8 +5348,6 @@ class Socket$1 extends Emitter_1 {
5078
5348
  }
5079
5349
  /**
5080
5350
  * Closes the connection.
5081
- *
5082
- * @api public
5083
5351
  */
5084
5352
  close() {
5085
5353
  const close = () => {
@@ -5120,7 +5388,7 @@ class Socket$1 extends Emitter_1 {
5120
5388
  /**
5121
5389
  * Called upon transport error
5122
5390
  *
5123
- * @api private
5391
+ * @private
5124
5392
  */
5125
5393
  onError(err) {
5126
5394
  Socket$1.priorWebsocketSuccess = false;
@@ -5130,7 +5398,7 @@ class Socket$1 extends Emitter_1 {
5130
5398
  /**
5131
5399
  * Called upon transport close.
5132
5400
  *
5133
- * @api private
5401
+ * @private
5134
5402
  */
5135
5403
  onClose(reason, description) {
5136
5404
  if ("opening" === this.readyState ||
@@ -5163,9 +5431,8 @@ class Socket$1 extends Emitter_1 {
5163
5431
  /**
5164
5432
  * Filters upgrades, returning only those matching client transports.
5165
5433
  *
5166
- * @param {Array} server upgrades
5167
- * @api private
5168
- *
5434
+ * @param {Array} upgrades - server upgrades
5435
+ * @private
5169
5436
  */
5170
5437
  filterUpgrades(upgrades) {
5171
5438
  const filteredUpgrades = [];
@@ -5375,6 +5642,17 @@ function _reconstructPacket(data, buffers) {
5375
5642
  return data;
5376
5643
  }
5377
5644
 
5645
+ /**
5646
+ * These strings must not be used as event names, as they have a special meaning.
5647
+ */
5648
+ const RESERVED_EVENTS$1 = [
5649
+ "connect",
5650
+ "connect_error",
5651
+ "disconnect",
5652
+ "disconnecting",
5653
+ "newListener",
5654
+ "removeListener", // used by the Node.js EventEmitter
5655
+ ];
5378
5656
  /**
5379
5657
  * Protocol version.
5380
5658
  *
@@ -5463,6 +5741,10 @@ class Encoder {
5463
5741
  return buffers; // write all the buffers
5464
5742
  }
5465
5743
  }
5744
+ // see https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
5745
+ function isObject(value) {
5746
+ return Object.prototype.toString.call(value) === "[object Object]";
5747
+ }
5466
5748
  /**
5467
5749
  * A socket.io Decoder instance
5468
5750
  *
@@ -5602,14 +5884,17 @@ class Decoder extends Emitter_1 {
5602
5884
  static isPayloadValid(type, payload) {
5603
5885
  switch (type) {
5604
5886
  case PacketType.CONNECT:
5605
- return typeof payload === "object";
5887
+ return isObject(payload);
5606
5888
  case PacketType.DISCONNECT:
5607
5889
  return payload === undefined;
5608
5890
  case PacketType.CONNECT_ERROR:
5609
- return typeof payload === "string" || typeof payload === "object";
5891
+ return typeof payload === "string" || isObject(payload);
5610
5892
  case PacketType.EVENT:
5611
5893
  case PacketType.BINARY_EVENT:
5612
- return Array.isArray(payload) && payload.length > 0;
5894
+ return (Array.isArray(payload) &&
5895
+ (typeof payload[0] === "number" ||
5896
+ (typeof payload[0] === "string" &&
5897
+ RESERVED_EVENTS$1.indexOf(payload[0]) === -1)));
5613
5898
  case PacketType.ACK:
5614
5899
  case PacketType.BINARY_ACK:
5615
5900
  return Array.isArray(payload);
@@ -5694,18 +5979,100 @@ const RESERVED_EVENTS = Object.freeze({
5694
5979
  newListener: 1,
5695
5980
  removeListener: 1,
5696
5981
  });
5982
+ /**
5983
+ * A Socket is the fundamental class for interacting with the server.
5984
+ *
5985
+ * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.
5986
+ *
5987
+ * @example
5988
+ * const socket = io();
5989
+ *
5990
+ * socket.on("connect", () => {
5991
+ * console.log("connected");
5992
+ * });
5993
+ *
5994
+ * // send an event to the server
5995
+ * socket.emit("foo", "bar");
5996
+ *
5997
+ * socket.on("foobar", () => {
5998
+ * // an event was received from the server
5999
+ * });
6000
+ *
6001
+ * // upon disconnection
6002
+ * socket.on("disconnect", (reason) => {
6003
+ * console.log(`disconnected due to ${reason}`);
6004
+ * });
6005
+ */
5697
6006
  class Socket extends Emitter_1 {
5698
6007
  /**
5699
6008
  * `Socket` constructor.
5700
- *
5701
- * @public
5702
6009
  */
5703
6010
  constructor(io, nsp, opts) {
5704
6011
  super();
6012
+ /**
6013
+ * Whether the socket is currently connected to the server.
6014
+ *
6015
+ * @example
6016
+ * const socket = io();
6017
+ *
6018
+ * socket.on("connect", () => {
6019
+ * console.log(socket.connected); // true
6020
+ * });
6021
+ *
6022
+ * socket.on("disconnect", () => {
6023
+ * console.log(socket.connected); // false
6024
+ * });
6025
+ */
5705
6026
  this.connected = false;
6027
+ /**
6028
+ * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
6029
+ * be transmitted by the server.
6030
+ */
6031
+ this.recovered = false;
6032
+ /**
6033
+ * Buffer for packets received before the CONNECT packet
6034
+ */
5706
6035
  this.receiveBuffer = [];
6036
+ /**
6037
+ * Buffer for packets that will be sent once the socket is connected
6038
+ */
5707
6039
  this.sendBuffer = [];
6040
+ /**
6041
+ * The queue of packets to be sent with retry in case of failure.
6042
+ *
6043
+ * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.
6044
+ * @private
6045
+ */
6046
+ this._queue = [];
6047
+ /**
6048
+ * A sequence to generate the ID of the {@link QueuedPacket}.
6049
+ * @private
6050
+ */
6051
+ this._queueSeq = 0;
5708
6052
  this.ids = 0;
6053
+ /**
6054
+ * A map containing acknowledgement handlers.
6055
+ *
6056
+ * The `withError` attribute is used to differentiate handlers that accept an error as first argument:
6057
+ *
6058
+ * - `socket.emit("test", (err, value) => { ... })` with `ackTimeout` option
6059
+ * - `socket.timeout(5000).emit("test", (err, value) => { ... })`
6060
+ * - `const value = await socket.emitWithAck("test")`
6061
+ *
6062
+ * From those that don't:
6063
+ *
6064
+ * - `socket.emit("test", (value) => { ... });`
6065
+ *
6066
+ * In the first case, the handlers will be called with an error when:
6067
+ *
6068
+ * - the timeout is reached
6069
+ * - the socket gets disconnected
6070
+ *
6071
+ * In the second case, the handlers will be simply discarded upon disconnection, since the client will never receive
6072
+ * an acknowledgement from the server.
6073
+ *
6074
+ * @private
6075
+ */
5709
6076
  this.acks = {};
5710
6077
  this.flags = {};
5711
6078
  this.io = io;
@@ -5713,11 +6080,23 @@ class Socket extends Emitter_1 {
5713
6080
  if (opts && opts.auth) {
5714
6081
  this.auth = opts.auth;
5715
6082
  }
6083
+ this._opts = Object.assign({}, opts);
5716
6084
  if (this.io._autoConnect)
5717
6085
  this.open();
5718
6086
  }
5719
6087
  /**
5720
6088
  * Whether the socket is currently disconnected
6089
+ *
6090
+ * @example
6091
+ * const socket = io();
6092
+ *
6093
+ * socket.on("connect", () => {
6094
+ * console.log(socket.disconnected); // false
6095
+ * });
6096
+ *
6097
+ * socket.on("disconnect", () => {
6098
+ * console.log(socket.disconnected); // true
6099
+ * });
5721
6100
  */
5722
6101
  get disconnected() {
5723
6102
  return !this.connected;
@@ -5739,7 +6118,21 @@ class Socket extends Emitter_1 {
5739
6118
  ];
5740
6119
  }
5741
6120
  /**
5742
- * Whether the Socket will try to reconnect when its Manager connects or reconnects
6121
+ * Whether the Socket will try to reconnect when its Manager connects or reconnects.
6122
+ *
6123
+ * @example
6124
+ * const socket = io();
6125
+ *
6126
+ * console.log(socket.active); // true
6127
+ *
6128
+ * socket.on("disconnect", (reason) => {
6129
+ * if (reason === "io server disconnect") {
6130
+ * // the disconnection was initiated by the server, you need to manually reconnect
6131
+ * console.log(socket.active); // false
6132
+ * }
6133
+ * // else the socket will automatically try to reconnect
6134
+ * console.log(socket.active); // true
6135
+ * });
5743
6136
  */
5744
6137
  get active() {
5745
6138
  return !!this.subs;
@@ -5747,7 +6140,12 @@ class Socket extends Emitter_1 {
5747
6140
  /**
5748
6141
  * "Opens" the socket.
5749
6142
  *
5750
- * @public
6143
+ * @example
6144
+ * const socket = io({
6145
+ * autoConnect: false
6146
+ * });
6147
+ *
6148
+ * socket.connect();
5751
6149
  */
5752
6150
  connect() {
5753
6151
  if (this.connected)
@@ -5760,7 +6158,7 @@ class Socket extends Emitter_1 {
5760
6158
  return this;
5761
6159
  }
5762
6160
  /**
5763
- * Alias for connect()
6161
+ * Alias for {@link connect()}.
5764
6162
  */
5765
6163
  open() {
5766
6164
  return this.connect();
@@ -5768,8 +6166,17 @@ class Socket extends Emitter_1 {
5768
6166
  /**
5769
6167
  * Sends a `message` event.
5770
6168
  *
6169
+ * This method mimics the WebSocket.send() method.
6170
+ *
6171
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
6172
+ *
6173
+ * @example
6174
+ * socket.send("hello");
6175
+ *
6176
+ * // this is equivalent to
6177
+ * socket.emit("message", "hello");
6178
+ *
5771
6179
  * @return self
5772
- * @public
5773
6180
  */
5774
6181
  send(...args) {
5775
6182
  args.unshift("message");
@@ -5780,14 +6187,28 @@ class Socket extends Emitter_1 {
5780
6187
  * Override `emit`.
5781
6188
  * If the event is in `events`, it's emitted normally.
5782
6189
  *
6190
+ * @example
6191
+ * socket.emit("hello", "world");
6192
+ *
6193
+ * // all serializable datastructures are supported (no need to call JSON.stringify)
6194
+ * socket.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
6195
+ *
6196
+ * // with an acknowledgement from the server
6197
+ * socket.emit("hello", "world", (val) => {
6198
+ * // ...
6199
+ * });
6200
+ *
5783
6201
  * @return self
5784
- * @public
5785
6202
  */
5786
6203
  emit(ev, ...args) {
5787
6204
  if (RESERVED_EVENTS.hasOwnProperty(ev)) {
5788
- throw new Error('"' + ev + '" is a reserved event name');
6205
+ throw new Error('"' + ev.toString() + '" is a reserved event name');
5789
6206
  }
5790
6207
  args.unshift(ev);
6208
+ if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {
6209
+ this._addToQueue(args);
6210
+ return this;
6211
+ }
5791
6212
  const packet = {
5792
6213
  type: PacketType.EVENT,
5793
6214
  data: args,
@@ -5820,7 +6241,8 @@ class Socket extends Emitter_1 {
5820
6241
  * @private
5821
6242
  */
5822
6243
  _registerAckCallback(id, ack) {
5823
- const timeout = this.flags.timeout;
6244
+ var _a;
6245
+ const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;
5824
6246
  if (timeout === undefined) {
5825
6247
  this.acks[id] = ack;
5826
6248
  return;
@@ -5835,11 +6257,101 @@ class Socket extends Emitter_1 {
5835
6257
  }
5836
6258
  ack.call(this, new Error("operation has timed out"));
5837
6259
  }, timeout);
5838
- this.acks[id] = (...args) => {
6260
+ const fn = (...args) => {
5839
6261
  // @ts-ignore
5840
6262
  this.io.clearTimeoutFn(timer);
5841
- ack.apply(this, [null, ...args]);
6263
+ ack.apply(this, args);
6264
+ };
6265
+ fn.withError = true;
6266
+ this.acks[id] = fn;
6267
+ }
6268
+ /**
6269
+ * Emits an event and waits for an acknowledgement
6270
+ *
6271
+ * @example
6272
+ * // without timeout
6273
+ * const response = await socket.emitWithAck("hello", "world");
6274
+ *
6275
+ * // with a specific timeout
6276
+ * try {
6277
+ * const response = await socket.timeout(1000).emitWithAck("hello", "world");
6278
+ * } catch (err) {
6279
+ * // the server did not acknowledge the event in the given delay
6280
+ * }
6281
+ *
6282
+ * @return a Promise that will be fulfilled when the server acknowledges the event
6283
+ */
6284
+ emitWithAck(ev, ...args) {
6285
+ return new Promise((resolve, reject) => {
6286
+ const fn = (arg1, arg2) => {
6287
+ return arg1 ? reject(arg1) : resolve(arg2);
6288
+ };
6289
+ fn.withError = true;
6290
+ args.push(fn);
6291
+ this.emit(ev, ...args);
6292
+ });
6293
+ }
6294
+ /**
6295
+ * Add the packet to the queue.
6296
+ * @param args
6297
+ * @private
6298
+ */
6299
+ _addToQueue(args) {
6300
+ let ack;
6301
+ if (typeof args[args.length - 1] === "function") {
6302
+ ack = args.pop();
6303
+ }
6304
+ const packet = {
6305
+ id: this._queueSeq++,
6306
+ tryCount: 0,
6307
+ pending: false,
6308
+ args,
6309
+ flags: Object.assign({ fromQueue: true }, this.flags),
5842
6310
  };
6311
+ args.push((err, ...responseArgs) => {
6312
+ if (packet !== this._queue[0]) {
6313
+ // the packet has already been acknowledged
6314
+ return;
6315
+ }
6316
+ const hasError = err !== null;
6317
+ if (hasError) {
6318
+ if (packet.tryCount > this._opts.retries) {
6319
+ this._queue.shift();
6320
+ if (ack) {
6321
+ ack(err);
6322
+ }
6323
+ }
6324
+ }
6325
+ else {
6326
+ this._queue.shift();
6327
+ if (ack) {
6328
+ ack(null, ...responseArgs);
6329
+ }
6330
+ }
6331
+ packet.pending = false;
6332
+ return this._drainQueue();
6333
+ });
6334
+ this._queue.push(packet);
6335
+ this._drainQueue();
6336
+ }
6337
+ /**
6338
+ * Send the first packet of the queue, and wait for an acknowledgement from the server.
6339
+ * @param force - whether to resend a packet that has not been acknowledged yet
6340
+ *
6341
+ * @private
6342
+ */
6343
+ _drainQueue(force = false) {
6344
+ if (!this.connected || this._queue.length === 0) {
6345
+ return;
6346
+ }
6347
+ const packet = this._queue[0];
6348
+ if (packet.pending && !force) {
6349
+ return;
6350
+ }
6351
+ packet.pending = true;
6352
+ packet.tryCount++;
6353
+ this.flags = packet.flags;
6354
+ this.emit.apply(this, packet.args);
5843
6355
  }
5844
6356
  /**
5845
6357
  * Sends a packet.
@@ -5859,13 +6371,27 @@ class Socket extends Emitter_1 {
5859
6371
  onopen() {
5860
6372
  if (typeof this.auth == "function") {
5861
6373
  this.auth((data) => {
5862
- this.packet({ type: PacketType.CONNECT, data });
6374
+ this._sendConnectPacket(data);
5863
6375
  });
5864
6376
  }
5865
6377
  else {
5866
- this.packet({ type: PacketType.CONNECT, data: this.auth });
6378
+ this._sendConnectPacket(this.auth);
5867
6379
  }
5868
6380
  }
6381
+ /**
6382
+ * Sends a CONNECT packet to initiate the Socket.IO session.
6383
+ *
6384
+ * @param data
6385
+ * @private
6386
+ */
6387
+ _sendConnectPacket(data) {
6388
+ this.packet({
6389
+ type: PacketType.CONNECT,
6390
+ data: this._pid
6391
+ ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)
6392
+ : data,
6393
+ });
6394
+ }
5869
6395
  /**
5870
6396
  * Called upon engine or manager `error`.
5871
6397
  *
@@ -5888,6 +6414,26 @@ class Socket extends Emitter_1 {
5888
6414
  this.connected = false;
5889
6415
  delete this.id;
5890
6416
  this.emitReserved("disconnect", reason, description);
6417
+ this._clearAcks();
6418
+ }
6419
+ /**
6420
+ * Clears the acknowledgement handlers upon disconnection, since the client will never receive an acknowledgement from
6421
+ * the server.
6422
+ *
6423
+ * @private
6424
+ */
6425
+ _clearAcks() {
6426
+ Object.keys(this.acks).forEach((id) => {
6427
+ const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id);
6428
+ if (!isBuffered) {
6429
+ // note: handlers that do not accept an error as first argument are ignored here
6430
+ const ack = this.acks[id];
6431
+ delete this.acks[id];
6432
+ if (ack.withError) {
6433
+ ack.call(this, new Error("socket has been disconnected"));
6434
+ }
6435
+ }
6436
+ });
5891
6437
  }
5892
6438
  /**
5893
6439
  * Called with socket packet.
@@ -5902,8 +6448,7 @@ class Socket extends Emitter_1 {
5902
6448
  switch (packet.type) {
5903
6449
  case PacketType.CONNECT:
5904
6450
  if (packet.data && packet.data.sid) {
5905
- const id = packet.data.sid;
5906
- this.onconnect(id);
6451
+ this.onconnect(packet.data.sid, packet.data.pid);
5907
6452
  }
5908
6453
  else {
5909
6454
  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/)"));
@@ -5955,6 +6500,9 @@ class Socket extends Emitter_1 {
5955
6500
  }
5956
6501
  }
5957
6502
  super.emit.apply(this, args);
6503
+ if (this._pid && args.length && typeof args[args.length - 1] === "string") {
6504
+ this._lastOffset = args[args.length - 1];
6505
+ }
5958
6506
  }
5959
6507
  /**
5960
6508
  * Produces an ack callback to emit with an event.
@@ -5977,28 +6525,37 @@ class Socket extends Emitter_1 {
5977
6525
  };
5978
6526
  }
5979
6527
  /**
5980
- * Called upon a server acknowlegement.
6528
+ * Called upon a server acknowledgement.
5981
6529
  *
5982
6530
  * @param packet
5983
6531
  * @private
5984
6532
  */
5985
6533
  onack(packet) {
5986
6534
  const ack = this.acks[packet.id];
5987
- if ("function" === typeof ack) {
5988
- ack.apply(this, packet.data);
5989
- delete this.acks[packet.id];
6535
+ if (typeof ack !== "function") {
6536
+ return;
6537
+ }
6538
+ delete this.acks[packet.id];
6539
+ // @ts-ignore FIXME ack is incorrectly inferred as 'never'
6540
+ if (ack.withError) {
6541
+ packet.data.unshift(null);
5990
6542
  }
6543
+ // @ts-ignore
6544
+ ack.apply(this, packet.data);
5991
6545
  }
5992
6546
  /**
5993
6547
  * Called upon server connect.
5994
6548
  *
5995
6549
  * @private
5996
6550
  */
5997
- onconnect(id) {
6551
+ onconnect(id, pid) {
5998
6552
  this.id = id;
6553
+ this.recovered = pid && this._pid === pid;
6554
+ this._pid = pid; // defined only if connection state recovery is enabled
5999
6555
  this.connected = true;
6000
6556
  this.emitBuffered();
6001
6557
  this.emitReserved("connect");
6558
+ this._drainQueue(true);
6002
6559
  }
6003
6560
  /**
6004
6561
  * Emit buffered events (received and emitted).
@@ -6039,10 +6596,20 @@ class Socket extends Emitter_1 {
6039
6596
  this.io["_destroy"](this);
6040
6597
  }
6041
6598
  /**
6042
- * Disconnects the socket manually.
6599
+ * Disconnects the socket manually. In that case, the socket will not try to reconnect.
6600
+ *
6601
+ * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.
6602
+ *
6603
+ * @example
6604
+ * const socket = io();
6605
+ *
6606
+ * socket.on("disconnect", (reason) => {
6607
+ * // console.log(reason); prints "io client disconnect"
6608
+ * });
6609
+ *
6610
+ * socket.disconnect();
6043
6611
  *
6044
6612
  * @return self
6045
- * @public
6046
6613
  */
6047
6614
  disconnect() {
6048
6615
  if (this.connected) {
@@ -6057,10 +6624,9 @@ class Socket extends Emitter_1 {
6057
6624
  return this;
6058
6625
  }
6059
6626
  /**
6060
- * Alias for disconnect()
6627
+ * Alias for {@link disconnect()}.
6061
6628
  *
6062
6629
  * @return self
6063
- * @public
6064
6630
  */
6065
6631
  close() {
6066
6632
  return this.disconnect();
@@ -6068,9 +6634,11 @@ class Socket extends Emitter_1 {
6068
6634
  /**
6069
6635
  * Sets the compress flag.
6070
6636
  *
6637
+ * @example
6638
+ * socket.compress(false).emit("hello");
6639
+ *
6071
6640
  * @param compress - if `true`, compresses the sending data
6072
6641
  * @return self
6073
- * @public
6074
6642
  */
6075
6643
  compress(compress) {
6076
6644
  this.flags.compress = compress;
@@ -6080,8 +6648,10 @@ class Socket extends Emitter_1 {
6080
6648
  * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
6081
6649
  * ready to send messages.
6082
6650
  *
6651
+ * @example
6652
+ * socket.volatile.emit("hello"); // the server may or may not receive it
6653
+ *
6083
6654
  * @returns self
6084
- * @public
6085
6655
  */
6086
6656
  get volatile() {
6087
6657
  this.flags.volatile = true;
@@ -6091,16 +6661,14 @@ class Socket extends Emitter_1 {
6091
6661
  * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
6092
6662
  * given number of milliseconds have elapsed without an acknowledgement from the server:
6093
6663
  *
6094
- * ```
6664
+ * @example
6095
6665
  * socket.timeout(5000).emit("my-event", (err) => {
6096
6666
  * if (err) {
6097
6667
  * // the server did not acknowledge the event in the given delay
6098
6668
  * }
6099
6669
  * });
6100
- * ```
6101
6670
  *
6102
6671
  * @returns self
6103
- * @public
6104
6672
  */
6105
6673
  timeout(timeout) {
6106
6674
  this.flags.timeout = timeout;
@@ -6110,8 +6678,12 @@ class Socket extends Emitter_1 {
6110
6678
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6111
6679
  * callback.
6112
6680
  *
6681
+ * @example
6682
+ * socket.onAny((event, ...args) => {
6683
+ * console.log(`got ${event}`);
6684
+ * });
6685
+ *
6113
6686
  * @param listener
6114
- * @public
6115
6687
  */
6116
6688
  onAny(listener) {
6117
6689
  this._anyListeners = this._anyListeners || [];
@@ -6122,8 +6694,12 @@ class Socket extends Emitter_1 {
6122
6694
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6123
6695
  * callback. The listener is added to the beginning of the listeners array.
6124
6696
  *
6697
+ * @example
6698
+ * socket.prependAny((event, ...args) => {
6699
+ * console.log(`got event ${event}`);
6700
+ * });
6701
+ *
6125
6702
  * @param listener
6126
- * @public
6127
6703
  */
6128
6704
  prependAny(listener) {
6129
6705
  this._anyListeners = this._anyListeners || [];
@@ -6133,8 +6709,20 @@ class Socket extends Emitter_1 {
6133
6709
  /**
6134
6710
  * Removes the listener that will be fired when any event is emitted.
6135
6711
  *
6712
+ * @example
6713
+ * const catchAllListener = (event, ...args) => {
6714
+ * console.log(`got event ${event}`);
6715
+ * }
6716
+ *
6717
+ * socket.onAny(catchAllListener);
6718
+ *
6719
+ * // remove a specific listener
6720
+ * socket.offAny(catchAllListener);
6721
+ *
6722
+ * // or remove all listeners
6723
+ * socket.offAny();
6724
+ *
6136
6725
  * @param listener
6137
- * @public
6138
6726
  */
6139
6727
  offAny(listener) {
6140
6728
  if (!this._anyListeners) {
@@ -6157,8 +6745,6 @@ class Socket extends Emitter_1 {
6157
6745
  /**
6158
6746
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6159
6747
  * e.g. to remove listeners.
6160
- *
6161
- * @public
6162
6748
  */
6163
6749
  listenersAny() {
6164
6750
  return this._anyListeners || [];
@@ -6167,17 +6753,14 @@ class Socket extends Emitter_1 {
6167
6753
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6168
6754
  * callback.
6169
6755
  *
6170
- * @param listener
6171
- *
6172
- * <pre><code>
6756
+ * Note: acknowledgements sent to the server are not included.
6173
6757
  *
6758
+ * @example
6174
6759
  * socket.onAnyOutgoing((event, ...args) => {
6175
- * console.log(event);
6760
+ * console.log(`sent event ${event}`);
6176
6761
  * });
6177
6762
  *
6178
- * </pre></code>
6179
- *
6180
- * @public
6763
+ * @param listener
6181
6764
  */
6182
6765
  onAnyOutgoing(listener) {
6183
6766
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6188,17 +6771,14 @@ class Socket extends Emitter_1 {
6188
6771
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6189
6772
  * callback. The listener is added to the beginning of the listeners array.
6190
6773
  *
6191
- * @param listener
6192
- *
6193
- * <pre><code>
6774
+ * Note: acknowledgements sent to the server are not included.
6194
6775
  *
6776
+ * @example
6195
6777
  * socket.prependAnyOutgoing((event, ...args) => {
6196
- * console.log(event);
6778
+ * console.log(`sent event ${event}`);
6197
6779
  * });
6198
6780
  *
6199
- * </pre></code>
6200
- *
6201
- * @public
6781
+ * @param listener
6202
6782
  */
6203
6783
  prependAnyOutgoing(listener) {
6204
6784
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6208,22 +6788,20 @@ class Socket extends Emitter_1 {
6208
6788
  /**
6209
6789
  * Removes the listener that will be fired when any event is emitted.
6210
6790
  *
6211
- * @param listener
6212
- *
6213
- * <pre><code>
6214
- *
6215
- * const handler = (event, ...args) => {
6216
- * console.log(event);
6791
+ * @example
6792
+ * const catchAllListener = (event, ...args) => {
6793
+ * console.log(`sent event ${event}`);
6217
6794
  * }
6218
6795
  *
6219
- * socket.onAnyOutgoing(handler);
6796
+ * socket.onAnyOutgoing(catchAllListener);
6220
6797
  *
6221
- * // then later
6222
- * socket.offAnyOutgoing(handler);
6798
+ * // remove a specific listener
6799
+ * socket.offAnyOutgoing(catchAllListener);
6223
6800
  *
6224
- * </pre></code>
6801
+ * // or remove all listeners
6802
+ * socket.offAnyOutgoing();
6225
6803
  *
6226
- * @public
6804
+ * @param [listener] - the catch-all listener (optional)
6227
6805
  */
6228
6806
  offAnyOutgoing(listener) {
6229
6807
  if (!this._anyOutgoingListeners) {
@@ -6246,8 +6824,6 @@ class Socket extends Emitter_1 {
6246
6824
  /**
6247
6825
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6248
6826
  * e.g. to remove listeners.
6249
- *
6250
- * @public
6251
6827
  */
6252
6828
  listenersAnyOutgoing() {
6253
6829
  return this._anyOutgoingListeners || [];
@@ -6447,36 +7023,33 @@ class Manager extends Emitter_1 {
6447
7023
  self.onopen();
6448
7024
  fn && fn();
6449
7025
  });
6450
- // emit `error`
6451
- const errorSub = on(socket, "error", (err) => {
6452
- self.cleanup();
6453
- self._readyState = "closed";
7026
+ const onError = (err) => {
7027
+ this.cleanup();
7028
+ this._readyState = "closed";
6454
7029
  this.emitReserved("error", err);
6455
7030
  if (fn) {
6456
7031
  fn(err);
6457
7032
  }
6458
7033
  else {
6459
7034
  // Only do this if there is no fn to handle the error
6460
- self.maybeReconnectOnOpen();
7035
+ this.maybeReconnectOnOpen();
6461
7036
  }
6462
- });
7037
+ };
7038
+ // emit `error`
7039
+ const errorSub = on(socket, "error", onError);
6463
7040
  if (false !== this._timeout) {
6464
7041
  const timeout = this._timeout;
6465
- if (timeout === 0) {
6466
- openSubDestroy(); // prevents a race condition with the 'open' event
6467
- }
6468
7042
  // set timer
6469
7043
  const timer = this.setTimeoutFn(() => {
6470
7044
  openSubDestroy();
7045
+ onError(new Error("timeout"));
6471
7046
  socket.close();
6472
- // @ts-ignore
6473
- socket.emit("error", new Error("timeout"));
6474
7047
  }, timeout);
6475
7048
  if (this.opts.autoUnref) {
6476
7049
  timer.unref();
6477
7050
  }
6478
- this.subs.push(function subDestroy() {
6479
- clearTimeout(timer);
7051
+ this.subs.push(() => {
7052
+ this.clearTimeoutFn(timer);
6480
7053
  });
6481
7054
  }
6482
7055
  this.subs.push(openSubDestroy);
@@ -6521,7 +7094,12 @@ class Manager extends Emitter_1 {
6521
7094
  * @private
6522
7095
  */
6523
7096
  ondata(data) {
6524
- this.decoder.add(data);
7097
+ try {
7098
+ this.decoder.add(data);
7099
+ }
7100
+ catch (e) {
7101
+ this.onclose("parse error", e);
7102
+ }
6525
7103
  }
6526
7104
  /**
6527
7105
  * Called when parser fully decodes a packet.
@@ -6529,7 +7107,10 @@ class Manager extends Emitter_1 {
6529
7107
  * @private
6530
7108
  */
6531
7109
  ondecoded(packet) {
6532
- this.emitReserved("packet", packet);
7110
+ // the nextTick call prevents an exception in a user-provided event listener from triggering a disconnection due to a "parse error"
7111
+ nextTick(() => {
7112
+ this.emitReserved("packet", packet);
7113
+ }, this.setTimeoutFn);
6533
7114
  }
6534
7115
  /**
6535
7116
  * Called upon socket error.
@@ -6551,6 +7132,9 @@ class Manager extends Emitter_1 {
6551
7132
  socket = new Socket(this, nsp, opts);
6552
7133
  this.nsps[nsp] = socket;
6553
7134
  }
7135
+ else if (this._autoConnect && !socket.active) {
7136
+ socket.connect();
7137
+ }
6554
7138
  return socket;
6555
7139
  }
6556
7140
  /**
@@ -6663,8 +7247,8 @@ class Manager extends Emitter_1 {
6663
7247
  if (this.opts.autoUnref) {
6664
7248
  timer.unref();
6665
7249
  }
6666
- this.subs.push(function subDestroy() {
6667
- clearTimeout(timer);
7250
+ this.subs.push(() => {
7251
+ this.clearTimeoutFn(timer);
6668
7252
  });
6669
7253
  }
6670
7254
  }