@xapp/chat-widget 1.75.0 → 1.76.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
@@ -3903,6 +3903,15 @@ Emitter.prototype.hasListeners = function(event){
3903
3903
  return !! this.listeners(event).length;
3904
3904
  };
3905
3905
 
3906
+ const nextTick = (() => {
3907
+ const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
3908
+ if (isPromiseAvailable) {
3909
+ return (cb) => Promise.resolve().then(cb);
3910
+ }
3911
+ else {
3912
+ return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
3913
+ }
3914
+ })();
3906
3915
  const globalThisShim = (() => {
3907
3916
  if (typeof self !== "undefined") {
3908
3917
  return self;
@@ -3914,6 +3923,8 @@ const globalThisShim = (() => {
3914
3923
  return Function("return this")();
3915
3924
  }
3916
3925
  })();
3926
+ const defaultBinaryType = "arraybuffer";
3927
+ function createCookieJar() { }
3917
3928
 
3918
3929
  function pick(obj, ...attr) {
3919
3930
  return attr.reduce((acc, k) => {
@@ -3966,6 +3977,13 @@ function utf8Length(str) {
3966
3977
  }
3967
3978
  return length;
3968
3979
  }
3980
+ /**
3981
+ * Generates a random 8-characters string.
3982
+ */
3983
+ function randomString$1() {
3984
+ return (Date.now().toString(36).substring(3) +
3985
+ Math.random().toString(36).substring(2, 5));
3986
+ }
3969
3987
 
3970
3988
  // imported from https://github.com/galkn/querystring
3971
3989
  /**
@@ -3975,7 +3993,7 @@ function utf8Length(str) {
3975
3993
  * @param {Object}
3976
3994
  * @api private
3977
3995
  */
3978
- function encode$1(obj) {
3996
+ function encode(obj) {
3979
3997
  let str = '';
3980
3998
  for (let i in obj) {
3981
3999
  if (obj.hasOwnProperty(i)) {
@@ -4024,6 +4042,7 @@ class Transport extends Emitter_1 {
4024
4042
  this.opts = opts;
4025
4043
  this.query = opts.query;
4026
4044
  this.socket = opts.socket;
4045
+ this.supportsBinary = !opts.forceBase64;
4027
4046
  }
4028
4047
  /**
4029
4048
  * Emits an error.
@@ -4132,115 +4151,15 @@ class Transport extends Emitter_1 {
4132
4151
  }
4133
4152
  }
4134
4153
  _query(query) {
4135
- const encodedQuery = encode$1(query);
4154
+ const encodedQuery = encode(query);
4136
4155
  return encodedQuery.length ? "?" + encodedQuery : "";
4137
4156
  }
4138
4157
  }
4139
4158
 
4140
- // imported from https://github.com/unshiftio/yeast
4141
- const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''), length = 64, map = {};
4142
- let seed = 0, i = 0, prev;
4143
- /**
4144
- * Return a string representing the specified number.
4145
- *
4146
- * @param {Number} num The number to convert.
4147
- * @returns {String} The string representation of the number.
4148
- * @api public
4149
- */
4150
- function encode(num) {
4151
- let encoded = '';
4152
- do {
4153
- encoded = alphabet[num % length] + encoded;
4154
- num = Math.floor(num / length);
4155
- } while (num > 0);
4156
- return encoded;
4157
- }
4158
- /**
4159
- * Yeast: A tiny growing id generator.
4160
- *
4161
- * @returns {String} A unique id.
4162
- * @api public
4163
- */
4164
- function yeast() {
4165
- const now = encode(+new Date());
4166
- if (now !== prev)
4167
- return seed = 0, prev = now;
4168
- return now + '.' + encode(seed++);
4169
- }
4170
- //
4171
- // Map each character to its index.
4172
- //
4173
- for (; i < length; i++)
4174
- map[alphabet[i]] = i;
4175
-
4176
- // imported from https://github.com/component/has-cors
4177
- let value = false;
4178
- try {
4179
- value = typeof XMLHttpRequest !== 'undefined' &&
4180
- 'withCredentials' in new XMLHttpRequest();
4181
- }
4182
- catch (err) {
4183
- // if XMLHttp support is disabled in IE then it will throw
4184
- // when trying to create
4185
- }
4186
- const hasCORS = value;
4187
-
4188
- // browser shim for xmlhttprequest module
4189
- function XHR(opts) {
4190
- const xdomain = opts.xdomain;
4191
- // XMLHttpRequest can be disabled on IE
4192
- try {
4193
- if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
4194
- return new XMLHttpRequest();
4195
- }
4196
- }
4197
- catch (e) { }
4198
- if (!xdomain) {
4199
- try {
4200
- return new globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
4201
- }
4202
- catch (e) { }
4203
- }
4204
- }
4205
- function createCookieJar() { }
4206
-
4207
- function empty$2() { }
4208
- const hasXHR2 = (function () {
4209
- const xhr = new XHR({
4210
- xdomain: false,
4211
- });
4212
- return null != xhr.responseType;
4213
- })();
4214
4159
  class Polling extends Transport {
4215
- /**
4216
- * XHR Polling constructor.
4217
- *
4218
- * @param {Object} opts
4219
- * @package
4220
- */
4221
- constructor(opts) {
4222
- super(opts);
4223
- this.polling = false;
4224
- if (typeof location !== "undefined") {
4225
- const isSSL = "https:" === location.protocol;
4226
- let port = location.port;
4227
- // some user agents have empty `location.port`
4228
- if (!port) {
4229
- port = isSSL ? "443" : "80";
4230
- }
4231
- this.xd =
4232
- (typeof location !== "undefined" &&
4233
- opts.hostname !== location.hostname) ||
4234
- port !== opts.port;
4235
- }
4236
- /**
4237
- * XHR supports binary
4238
- */
4239
- const forceBase64 = opts && opts.forceBase64;
4240
- this.supportsBinary = hasXHR2 && !forceBase64;
4241
- if (this.opts.withCredentials) {
4242
- this.cookieJar = createCookieJar();
4243
- }
4160
+ constructor() {
4161
+ super(...arguments);
4162
+ this._polling = false;
4244
4163
  }
4245
4164
  get name() {
4246
4165
  return "polling";
@@ -4252,7 +4171,7 @@ class Polling extends Transport {
4252
4171
  * @protected
4253
4172
  */
4254
4173
  doOpen() {
4255
- this.poll();
4174
+ this._poll();
4256
4175
  }
4257
4176
  /**
4258
4177
  * Pauses polling.
@@ -4266,9 +4185,9 @@ class Polling extends Transport {
4266
4185
  this.readyState = "paused";
4267
4186
  onPause();
4268
4187
  };
4269
- if (this.polling || !this.writable) {
4188
+ if (this._polling || !this.writable) {
4270
4189
  let total = 0;
4271
- if (this.polling) {
4190
+ if (this._polling) {
4272
4191
  total++;
4273
4192
  this.once("pollComplete", function () {
4274
4193
  --total || pause();
@@ -4290,8 +4209,8 @@ class Polling extends Transport {
4290
4209
  *
4291
4210
  * @private
4292
4211
  */
4293
- poll() {
4294
- this.polling = true;
4212
+ _poll() {
4213
+ this._polling = true;
4295
4214
  this.doPoll();
4296
4215
  this.emitReserved("poll");
4297
4216
  }
@@ -4319,10 +4238,10 @@ class Polling extends Transport {
4319
4238
  // if an event did not trigger closing
4320
4239
  if ("closed" !== this.readyState) {
4321
4240
  // if we got data we're not polling
4322
- this.polling = false;
4241
+ this._polling = false;
4323
4242
  this.emitReserved("pollComplete");
4324
4243
  if ("open" === this.readyState) {
4325
- this.poll();
4244
+ this._poll();
4326
4245
  }
4327
4246
  }
4328
4247
  }
@@ -4369,22 +4288,49 @@ class Polling extends Transport {
4369
4288
  const query = this.query || {};
4370
4289
  // cache busting is forced
4371
4290
  if (false !== this.opts.timestampRequests) {
4372
- query[this.opts.timestampParam] = yeast();
4291
+ query[this.opts.timestampParam] = randomString$1();
4373
4292
  }
4374
4293
  if (!this.supportsBinary && !query.sid) {
4375
4294
  query.b64 = 1;
4376
4295
  }
4377
4296
  return this.createUri(schema, query);
4378
4297
  }
4298
+ }
4299
+
4300
+ // imported from https://github.com/component/has-cors
4301
+ let value = false;
4302
+ try {
4303
+ value = typeof XMLHttpRequest !== 'undefined' &&
4304
+ 'withCredentials' in new XMLHttpRequest();
4305
+ }
4306
+ catch (err) {
4307
+ // if XMLHttp support is disabled in IE then it will throw
4308
+ // when trying to create
4309
+ }
4310
+ const hasCORS = value;
4311
+
4312
+ function empty$2() { }
4313
+ class BaseXHR extends Polling {
4379
4314
  /**
4380
- * Creates a request.
4315
+ * XHR Polling constructor.
4381
4316
  *
4382
- * @param {String} method
4383
- * @private
4317
+ * @param {Object} opts
4318
+ * @package
4384
4319
  */
4385
- request(opts = {}) {
4386
- Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
4387
- return new Request(this.uri(), opts);
4320
+ constructor(opts) {
4321
+ super(opts);
4322
+ if (typeof location !== "undefined") {
4323
+ const isSSL = "https:" === location.protocol;
4324
+ let port = location.port;
4325
+ // some user agents have empty `location.port`
4326
+ if (!port) {
4327
+ port = isSSL ? "443" : "80";
4328
+ }
4329
+ this.xd =
4330
+ (typeof location !== "undefined" &&
4331
+ opts.hostname !== location.hostname) ||
4332
+ port !== opts.port;
4333
+ }
4388
4334
  }
4389
4335
  /**
4390
4336
  * Sends data.
@@ -4424,39 +4370,41 @@ class Request extends Emitter_1 {
4424
4370
  * @param {Object} options
4425
4371
  * @package
4426
4372
  */
4427
- constructor(uri, opts) {
4373
+ constructor(createRequest, uri, opts) {
4428
4374
  super();
4375
+ this.createRequest = createRequest;
4429
4376
  installTimerFunctions(this, opts);
4430
- this.opts = opts;
4431
- this.method = opts.method || "GET";
4432
- this.uri = uri;
4433
- this.data = undefined !== opts.data ? opts.data : null;
4434
- this.create();
4377
+ this._opts = opts;
4378
+ this._method = opts.method || "GET";
4379
+ this._uri = uri;
4380
+ this._data = undefined !== opts.data ? opts.data : null;
4381
+ this._create();
4435
4382
  }
4436
4383
  /**
4437
4384
  * Creates the XHR object and sends the request.
4438
4385
  *
4439
4386
  * @private
4440
4387
  */
4441
- create() {
4388
+ _create() {
4442
4389
  var _a;
4443
- const opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4444
- opts.xdomain = !!this.opts.xd;
4445
- const xhr = (this.xhr = new XHR(opts));
4390
+ const opts = pick(this._opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4391
+ opts.xdomain = !!this._opts.xd;
4392
+ const xhr = (this._xhr = this.createRequest(opts));
4446
4393
  try {
4447
- xhr.open(this.method, this.uri, true);
4394
+ xhr.open(this._method, this._uri, true);
4448
4395
  try {
4449
- if (this.opts.extraHeaders) {
4396
+ if (this._opts.extraHeaders) {
4397
+ // @ts-ignore
4450
4398
  xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
4451
- for (let i in this.opts.extraHeaders) {
4452
- if (this.opts.extraHeaders.hasOwnProperty(i)) {
4453
- xhr.setRequestHeader(i, this.opts.extraHeaders[i]);
4399
+ for (let i in this._opts.extraHeaders) {
4400
+ if (this._opts.extraHeaders.hasOwnProperty(i)) {
4401
+ xhr.setRequestHeader(i, this._opts.extraHeaders[i]);
4454
4402
  }
4455
4403
  }
4456
4404
  }
4457
4405
  }
4458
4406
  catch (e) { }
4459
- if ("POST" === this.method) {
4407
+ if ("POST" === this._method) {
4460
4408
  try {
4461
4409
  xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
4462
4410
  }
@@ -4466,46 +4414,48 @@ class Request extends Emitter_1 {
4466
4414
  xhr.setRequestHeader("Accept", "*/*");
4467
4415
  }
4468
4416
  catch (e) { }
4469
- (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4417
+ (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4470
4418
  // ie6 check
4471
4419
  if ("withCredentials" in xhr) {
4472
- xhr.withCredentials = this.opts.withCredentials;
4420
+ xhr.withCredentials = this._opts.withCredentials;
4473
4421
  }
4474
- if (this.opts.requestTimeout) {
4475
- xhr.timeout = this.opts.requestTimeout;
4422
+ if (this._opts.requestTimeout) {
4423
+ xhr.timeout = this._opts.requestTimeout;
4476
4424
  }
4477
4425
  xhr.onreadystatechange = () => {
4478
4426
  var _a;
4479
4427
  if (xhr.readyState === 3) {
4480
- (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
4428
+ (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(
4429
+ // @ts-ignore
4430
+ xhr.getResponseHeader("set-cookie"));
4481
4431
  }
4482
4432
  if (4 !== xhr.readyState)
4483
4433
  return;
4484
4434
  if (200 === xhr.status || 1223 === xhr.status) {
4485
- this.onLoad();
4435
+ this._onLoad();
4486
4436
  }
4487
4437
  else {
4488
4438
  // make sure the `error` event handler that's user-set
4489
4439
  // does not throw in the same tick and gets caught here
4490
4440
  this.setTimeoutFn(() => {
4491
- this.onError(typeof xhr.status === "number" ? xhr.status : 0);
4441
+ this._onError(typeof xhr.status === "number" ? xhr.status : 0);
4492
4442
  }, 0);
4493
4443
  }
4494
4444
  };
4495
- xhr.send(this.data);
4445
+ xhr.send(this._data);
4496
4446
  }
4497
4447
  catch (e) {
4498
4448
  // Need to defer since .create() is called directly from the constructor
4499
4449
  // and thus the 'error' event can only be only bound *after* this exception
4500
4450
  // occurs. Therefore, also, we cannot throw here at all.
4501
4451
  this.setTimeoutFn(() => {
4502
- this.onError(e);
4452
+ this._onError(e);
4503
4453
  }, 0);
4504
4454
  return;
4505
4455
  }
4506
4456
  if (typeof document !== "undefined") {
4507
- this.index = Request.requestsCount++;
4508
- Request.requests[this.index] = this;
4457
+ this._index = Request.requestsCount++;
4458
+ Request.requests[this._index] = this;
4509
4459
  }
4510
4460
  }
4511
4461
  /**
@@ -4513,42 +4463,42 @@ class Request extends Emitter_1 {
4513
4463
  *
4514
4464
  * @private
4515
4465
  */
4516
- onError(err) {
4517
- this.emitReserved("error", err, this.xhr);
4518
- this.cleanup(true);
4466
+ _onError(err) {
4467
+ this.emitReserved("error", err, this._xhr);
4468
+ this._cleanup(true);
4519
4469
  }
4520
4470
  /**
4521
4471
  * Cleans up house.
4522
4472
  *
4523
4473
  * @private
4524
4474
  */
4525
- cleanup(fromError) {
4526
- if ("undefined" === typeof this.xhr || null === this.xhr) {
4475
+ _cleanup(fromError) {
4476
+ if ("undefined" === typeof this._xhr || null === this._xhr) {
4527
4477
  return;
4528
4478
  }
4529
- this.xhr.onreadystatechange = empty$2;
4479
+ this._xhr.onreadystatechange = empty$2;
4530
4480
  if (fromError) {
4531
4481
  try {
4532
- this.xhr.abort();
4482
+ this._xhr.abort();
4533
4483
  }
4534
4484
  catch (e) { }
4535
4485
  }
4536
4486
  if (typeof document !== "undefined") {
4537
- delete Request.requests[this.index];
4487
+ delete Request.requests[this._index];
4538
4488
  }
4539
- this.xhr = null;
4489
+ this._xhr = null;
4540
4490
  }
4541
4491
  /**
4542
4492
  * Called upon load.
4543
4493
  *
4544
4494
  * @private
4545
4495
  */
4546
- onLoad() {
4547
- const data = this.xhr.responseText;
4496
+ _onLoad() {
4497
+ const data = this._xhr.responseText;
4548
4498
  if (data !== null) {
4549
4499
  this.emitReserved("data", data);
4550
4500
  this.emitReserved("success");
4551
- this.cleanup();
4501
+ this._cleanup();
4552
4502
  }
4553
4503
  }
4554
4504
  /**
@@ -4557,7 +4507,7 @@ class Request extends Emitter_1 {
4557
4507
  * @package
4558
4508
  */
4559
4509
  abort() {
4560
- this.cleanup();
4510
+ this._cleanup();
4561
4511
  }
4562
4512
  }
4563
4513
  Request.requestsCount = 0;
@@ -4585,43 +4535,56 @@ function unloadHandler() {
4585
4535
  }
4586
4536
  }
4587
4537
  }
4588
-
4589
- const nextTick = (() => {
4590
- const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
4591
- if (isPromiseAvailable) {
4592
- return (cb) => Promise.resolve().then(cb);
4538
+ const hasXHR2 = (function () {
4539
+ const xhr = newRequest({
4540
+ xdomain: false,
4541
+ });
4542
+ return xhr && xhr.responseType !== null;
4543
+ })();
4544
+ /**
4545
+ * HTTP long-polling based on the built-in `XMLHttpRequest` object.
4546
+ *
4547
+ * Usage: browser
4548
+ *
4549
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
4550
+ */
4551
+ class XHR extends BaseXHR {
4552
+ constructor(opts) {
4553
+ super(opts);
4554
+ const forceBase64 = opts && opts.forceBase64;
4555
+ this.supportsBinary = hasXHR2 && !forceBase64;
4593
4556
  }
4594
- else {
4595
- return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
4557
+ request(opts = {}) {
4558
+ Object.assign(opts, { xd: this.xd }, this.opts);
4559
+ return new Request(newRequest, this.uri(), opts);
4596
4560
  }
4597
- })();
4598
- const WebSocket$1 = globalThisShim.WebSocket || globalThisShim.MozWebSocket;
4599
- const usingBrowserWebSocket = true;
4600
- const defaultBinaryType = "arraybuffer";
4561
+ }
4562
+ function newRequest(opts) {
4563
+ const xdomain = opts.xdomain;
4564
+ // XMLHttpRequest can be disabled on IE
4565
+ try {
4566
+ if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
4567
+ return new XMLHttpRequest();
4568
+ }
4569
+ }
4570
+ catch (e) { }
4571
+ if (!xdomain) {
4572
+ try {
4573
+ return new globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
4574
+ }
4575
+ catch (e) { }
4576
+ }
4577
+ }
4601
4578
 
4602
4579
  // detect ReactNative environment
4603
4580
  const isReactNative = typeof navigator !== "undefined" &&
4604
4581
  typeof navigator.product === "string" &&
4605
4582
  navigator.product.toLowerCase() === "reactnative";
4606
- class WS extends Transport {
4607
- /**
4608
- * WebSocket transport constructor.
4609
- *
4610
- * @param {Object} opts - connection options
4611
- * @protected
4612
- */
4613
- constructor(opts) {
4614
- super(opts);
4615
- this.supportsBinary = !opts.forceBase64;
4616
- }
4583
+ class BaseWS extends Transport {
4617
4584
  get name() {
4618
4585
  return "websocket";
4619
4586
  }
4620
4587
  doOpen() {
4621
- if (!this.check()) {
4622
- // let probe timeout
4623
- return;
4624
- }
4625
4588
  const uri = this.uri();
4626
4589
  const protocols = this.opts.protocols;
4627
4590
  // React Native only supports the 'headers' option, and will print a warning if anything else is passed
@@ -4632,12 +4595,7 @@ class WS extends Transport {
4632
4595
  opts.headers = this.opts.extraHeaders;
4633
4596
  }
4634
4597
  try {
4635
- this.ws =
4636
- usingBrowserWebSocket && !isReactNative
4637
- ? protocols
4638
- ? new WebSocket$1(uri, protocols)
4639
- : new WebSocket$1(uri)
4640
- : new WebSocket$1(uri, protocols, opts);
4598
+ this.ws = this.createSocket(uri, protocols, opts);
4641
4599
  }
4642
4600
  catch (err) {
4643
4601
  return this.emitReserved("error", err);
@@ -4672,16 +4630,11 @@ class WS extends Transport {
4672
4630
  const packet = packets[i];
4673
4631
  const lastPacket = i === packets.length - 1;
4674
4632
  encodePacket(packet, this.supportsBinary, (data) => {
4675
- // always create a new object (GH-437)
4676
- const opts = {};
4677
4633
  // Sometimes the websocket has already been closed but the browser didn't
4678
4634
  // have a chance of informing us about it yet, in that case send will
4679
4635
  // throw an error
4680
4636
  try {
4681
- if (usingBrowserWebSocket) {
4682
- // TypeError is thrown when passing the second argument on Safari
4683
- this.ws.send(data);
4684
- }
4637
+ this.doWrite(packet, data);
4685
4638
  }
4686
4639
  catch (e) {
4687
4640
  }
@@ -4698,6 +4651,7 @@ class WS extends Transport {
4698
4651
  }
4699
4652
  doClose() {
4700
4653
  if (typeof this.ws !== "undefined") {
4654
+ this.ws.onerror = () => { };
4701
4655
  this.ws.close();
4702
4656
  this.ws = null;
4703
4657
  }
@@ -4712,7 +4666,7 @@ class WS extends Transport {
4712
4666
  const query = this.query || {};
4713
4667
  // append timestamp to URI
4714
4668
  if (this.opts.timestampRequests) {
4715
- query[this.opts.timestampParam] = yeast();
4669
+ query[this.opts.timestampParam] = randomString$1();
4716
4670
  }
4717
4671
  // communicate binary support capabilities
4718
4672
  if (!this.supportsBinary) {
@@ -4720,29 +4674,51 @@ class WS extends Transport {
4720
4674
  }
4721
4675
  return this.createUri(schema, query);
4722
4676
  }
4723
- /**
4724
- * Feature detection for WebSocket.
4725
- *
4726
- * @return {Boolean} whether this transport is available.
4727
- * @private
4728
- */
4729
- check() {
4730
- return !!WebSocket$1;
4677
+ }
4678
+ const WebSocketCtor = globalThisShim.WebSocket || globalThisShim.MozWebSocket;
4679
+ /**
4680
+ * WebSocket transport based on the built-in `WebSocket` object.
4681
+ *
4682
+ * Usage: browser, Node.js (since v21), Deno, Bun
4683
+ *
4684
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
4685
+ * @see https://caniuse.com/mdn-api_websocket
4686
+ * @see https://nodejs.org/api/globals.html#websocket
4687
+ */
4688
+ class WS extends BaseWS {
4689
+ createSocket(uri, protocols, opts) {
4690
+ return !isReactNative
4691
+ ? protocols
4692
+ ? new WebSocketCtor(uri, protocols)
4693
+ : new WebSocketCtor(uri)
4694
+ : new WebSocketCtor(uri, protocols, opts);
4695
+ }
4696
+ doWrite(_packet, data) {
4697
+ this.ws.send(data);
4731
4698
  }
4732
4699
  }
4733
4700
 
4701
+ /**
4702
+ * WebTransport transport based on the built-in `WebTransport` object.
4703
+ *
4704
+ * Usage: browser, Node.js (with the `@fails-components/webtransport` package)
4705
+ *
4706
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
4707
+ * @see https://caniuse.com/webtransport
4708
+ */
4734
4709
  class WT extends Transport {
4735
4710
  get name() {
4736
4711
  return "webtransport";
4737
4712
  }
4738
4713
  doOpen() {
4739
- // @ts-ignore
4740
- if (typeof WebTransport !== "function") {
4741
- return;
4714
+ try {
4715
+ // @ts-ignore
4716
+ this._transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4742
4717
  }
4743
- // @ts-ignore
4744
- this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4745
- this.transport.closed
4718
+ catch (err) {
4719
+ return this.emitReserved("error", err);
4720
+ }
4721
+ this._transport.closed
4746
4722
  .then(() => {
4747
4723
  this.onClose();
4748
4724
  })
@@ -4750,13 +4726,13 @@ class WT extends Transport {
4750
4726
  this.onError("webtransport error", err);
4751
4727
  });
4752
4728
  // note: we could have used async/await, but that would require some additional polyfills
4753
- this.transport.ready.then(() => {
4754
- this.transport.createBidirectionalStream().then((stream) => {
4729
+ this._transport.ready.then(() => {
4730
+ this._transport.createBidirectionalStream().then((stream) => {
4755
4731
  const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
4756
4732
  const reader = stream.readable.pipeThrough(decoderStream).getReader();
4757
4733
  const encoderStream = createPacketEncoderStream();
4758
4734
  encoderStream.readable.pipeTo(stream.writable);
4759
- this.writer = encoderStream.writable.getWriter();
4735
+ this._writer = encoderStream.writable.getWriter();
4760
4736
  const read = () => {
4761
4737
  reader
4762
4738
  .read()
@@ -4775,7 +4751,7 @@ class WT extends Transport {
4775
4751
  if (this.query.sid) {
4776
4752
  packet.data = `{"sid":"${this.query.sid}"}`;
4777
4753
  }
4778
- this.writer.write(packet).then(() => this.onOpen());
4754
+ this._writer.write(packet).then(() => this.onOpen());
4779
4755
  });
4780
4756
  });
4781
4757
  }
@@ -4784,7 +4760,7 @@ class WT extends Transport {
4784
4760
  for (let i = 0; i < packets.length; i++) {
4785
4761
  const packet = packets[i];
4786
4762
  const lastPacket = i === packets.length - 1;
4787
- this.writer.write(packet).then(() => {
4763
+ this._writer.write(packet).then(() => {
4788
4764
  if (lastPacket) {
4789
4765
  nextTick(() => {
4790
4766
  this.writable = true;
@@ -4796,14 +4772,14 @@ class WT extends Transport {
4796
4772
  }
4797
4773
  doClose() {
4798
4774
  var _a;
4799
- (_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
4775
+ (_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();
4800
4776
  }
4801
4777
  }
4802
4778
 
4803
4779
  const transports = {
4804
4780
  websocket: WS,
4805
4781
  webtransport: WT,
4806
- polling: Polling,
4782
+ polling: XHR,
4807
4783
  };
4808
4784
 
4809
4785
  // imported from https://github.com/galkn/parseuri
@@ -4830,7 +4806,7 @@ const parts = [
4830
4806
  'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
4831
4807
  ];
4832
4808
  function parse$2(str) {
4833
- if (str.length > 2000) {
4809
+ if (str.length > 8000) {
4834
4810
  throw "URI too long";
4835
4811
  }
4836
4812
  const src = str, b = str.indexOf('['), e = str.indexOf(']');
@@ -4871,28 +4847,71 @@ function queryKey(uri, query) {
4871
4847
  return data;
4872
4848
  }
4873
4849
 
4874
- let Socket$1 = class Socket extends Emitter_1 {
4850
+ const withEventListeners = typeof addEventListener === "function" &&
4851
+ typeof removeEventListener === "function";
4852
+ const OFFLINE_EVENT_LISTENERS = [];
4853
+ if (withEventListeners) {
4854
+ // within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the
4855
+ // script, so we create one single event listener here which will forward the event to the socket instances
4856
+ addEventListener("offline", () => {
4857
+ OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());
4858
+ }, false);
4859
+ }
4860
+ /**
4861
+ * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
4862
+ * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
4863
+ *
4864
+ * This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
4865
+ * successfully establishes the connection.
4866
+ *
4867
+ * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
4868
+ *
4869
+ * @example
4870
+ * import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
4871
+ *
4872
+ * const socket = new SocketWithoutUpgrade({
4873
+ * transports: [WebSocket]
4874
+ * });
4875
+ *
4876
+ * socket.on("open", () => {
4877
+ * socket.send("hello");
4878
+ * });
4879
+ *
4880
+ * @see SocketWithUpgrade
4881
+ * @see Socket
4882
+ */
4883
+ class SocketWithoutUpgrade extends Emitter_1 {
4875
4884
  /**
4876
4885
  * Socket constructor.
4877
4886
  *
4878
4887
  * @param {String|Object} uri - uri or options
4879
4888
  * @param {Object} opts - options
4880
4889
  */
4881
- constructor(uri, opts = {}) {
4890
+ constructor(uri, opts) {
4882
4891
  super();
4883
4892
  this.binaryType = defaultBinaryType;
4884
4893
  this.writeBuffer = [];
4894
+ this._prevBufferLen = 0;
4895
+ this._pingInterval = -1;
4896
+ this._pingTimeout = -1;
4897
+ this._maxPayload = -1;
4898
+ /**
4899
+ * The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
4900
+ * callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
4901
+ */
4902
+ this._pingTimeoutTime = Infinity;
4885
4903
  if (uri && "object" === typeof uri) {
4886
4904
  opts = uri;
4887
4905
  uri = null;
4888
4906
  }
4889
4907
  if (uri) {
4890
- uri = parse$2(uri);
4891
- opts.hostname = uri.host;
4892
- opts.secure = uri.protocol === "https" || uri.protocol === "wss";
4893
- opts.port = uri.port;
4894
- if (uri.query)
4895
- opts.query = uri.query;
4908
+ const parsedUri = parse$2(uri);
4909
+ opts.hostname = parsedUri.host;
4910
+ opts.secure =
4911
+ parsedUri.protocol === "https" || parsedUri.protocol === "wss";
4912
+ opts.port = parsedUri.port;
4913
+ if (parsedUri.query)
4914
+ opts.query = parsedUri.query;
4896
4915
  }
4897
4916
  else if (opts.host) {
4898
4917
  opts.hostname = parse$2(opts.host).host;
@@ -4916,13 +4935,13 @@ let Socket$1 = class Socket extends Emitter_1 {
4916
4935
  : this.secure
4917
4936
  ? "443"
4918
4937
  : "80");
4919
- this.transports = opts.transports || [
4920
- "polling",
4921
- "websocket",
4922
- "webtransport",
4923
- ];
4924
- this.writeBuffer = [];
4925
- this.prevBufferLen = 0;
4938
+ this.transports = [];
4939
+ this._transportsByName = {};
4940
+ opts.transports.forEach((t) => {
4941
+ const transportName = t.prototype.name;
4942
+ this.transports.push(transportName);
4943
+ this._transportsByName[transportName] = t;
4944
+ });
4926
4945
  this.opts = Object.assign({
4927
4946
  path: "/engine.io",
4928
4947
  agent: false,
@@ -4944,37 +4963,33 @@ let Socket$1 = class Socket extends Emitter_1 {
4944
4963
  if (typeof this.opts.query === "string") {
4945
4964
  this.opts.query = decode(this.opts.query);
4946
4965
  }
4947
- // set on handshake
4948
- this.id = null;
4949
- this.upgrades = null;
4950
- this.pingInterval = null;
4951
- this.pingTimeout = null;
4952
- // set on heartbeat
4953
- this.pingTimeoutTimer = null;
4954
- if (typeof addEventListener === "function") {
4966
+ if (withEventListeners) {
4955
4967
  if (this.opts.closeOnBeforeunload) {
4956
4968
  // Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
4957
4969
  // ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
4958
4970
  // closed/reloaded)
4959
- this.beforeunloadEventListener = () => {
4971
+ this._beforeunloadEventListener = () => {
4960
4972
  if (this.transport) {
4961
4973
  // silently close the transport
4962
4974
  this.transport.removeAllListeners();
4963
4975
  this.transport.close();
4964
4976
  }
4965
4977
  };
4966
- addEventListener("beforeunload", this.beforeunloadEventListener, false);
4978
+ addEventListener("beforeunload", this._beforeunloadEventListener, false);
4967
4979
  }
4968
4980
  if (this.hostname !== "localhost") {
4969
- this.offlineEventListener = () => {
4970
- this.onClose("transport close", {
4981
+ this._offlineEventListener = () => {
4982
+ this._onClose("transport close", {
4971
4983
  description: "network connection lost",
4972
4984
  });
4973
4985
  };
4974
- addEventListener("offline", this.offlineEventListener, false);
4986
+ OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);
4975
4987
  }
4976
4988
  }
4977
- this.open();
4989
+ if (this.opts.withCredentials) {
4990
+ this._cookieJar = createCookieJar();
4991
+ }
4992
+ this._open();
4978
4993
  }
4979
4994
  /**
4980
4995
  * Creates transport of the given type.
@@ -4999,40 +5014,28 @@ let Socket$1 = class Socket extends Emitter_1 {
4999
5014
  secure: this.secure,
5000
5015
  port: this.port,
5001
5016
  }, this.opts.transportOptions[name]);
5002
- return new transports[name](opts);
5017
+ return new this._transportsByName[name](opts);
5003
5018
  }
5004
5019
  /**
5005
5020
  * Initializes transport to use and starts probe.
5006
5021
  *
5007
5022
  * @private
5008
5023
  */
5009
- open() {
5010
- let transport;
5011
- if (this.opts.rememberUpgrade &&
5012
- Socket.priorWebsocketSuccess &&
5013
- this.transports.indexOf("websocket") !== -1) {
5014
- transport = "websocket";
5015
- }
5016
- else if (0 === this.transports.length) {
5024
+ _open() {
5025
+ if (this.transports.length === 0) {
5017
5026
  // Emit error on next tick so it can be listened to
5018
5027
  this.setTimeoutFn(() => {
5019
5028
  this.emitReserved("error", "No transports available");
5020
5029
  }, 0);
5021
5030
  return;
5022
5031
  }
5023
- else {
5024
- transport = this.transports[0];
5025
- }
5032
+ const transportName = this.opts.rememberUpgrade &&
5033
+ SocketWithoutUpgrade.priorWebsocketSuccess &&
5034
+ this.transports.indexOf("websocket") !== -1
5035
+ ? "websocket"
5036
+ : this.transports[0];
5026
5037
  this.readyState = "opening";
5027
- // Retry with the next transport if the transport is disabled (jsonp: false)
5028
- try {
5029
- transport = this.createTransport(transport);
5030
- }
5031
- catch (e) {
5032
- this.transports.shift();
5033
- this.open();
5034
- return;
5035
- }
5038
+ const transport = this.createTransport(transportName);
5036
5039
  transport.open();
5037
5040
  this.setTransport(transport);
5038
5041
  }
@@ -5049,111 +5052,10 @@ let Socket$1 = class Socket extends Emitter_1 {
5049
5052
  this.transport = transport;
5050
5053
  // set up transport listeners
5051
5054
  transport
5052
- .on("drain", this.onDrain.bind(this))
5053
- .on("packet", this.onPacket.bind(this))
5054
- .on("error", this.onError.bind(this))
5055
- .on("close", (reason) => this.onClose("transport close", reason));
5056
- }
5057
- /**
5058
- * Probes a transport.
5059
- *
5060
- * @param {String} name - transport name
5061
- * @private
5062
- */
5063
- probe(name) {
5064
- let transport = this.createTransport(name);
5065
- let failed = false;
5066
- Socket.priorWebsocketSuccess = false;
5067
- const onTransportOpen = () => {
5068
- if (failed)
5069
- return;
5070
- transport.send([{ type: "ping", data: "probe" }]);
5071
- transport.once("packet", (msg) => {
5072
- if (failed)
5073
- return;
5074
- if ("pong" === msg.type && "probe" === msg.data) {
5075
- this.upgrading = true;
5076
- this.emitReserved("upgrading", transport);
5077
- if (!transport)
5078
- return;
5079
- Socket.priorWebsocketSuccess = "websocket" === transport.name;
5080
- this.transport.pause(() => {
5081
- if (failed)
5082
- return;
5083
- if ("closed" === this.readyState)
5084
- return;
5085
- cleanup();
5086
- this.setTransport(transport);
5087
- transport.send([{ type: "upgrade" }]);
5088
- this.emitReserved("upgrade", transport);
5089
- transport = null;
5090
- this.upgrading = false;
5091
- this.flush();
5092
- });
5093
- }
5094
- else {
5095
- const err = new Error("probe error");
5096
- // @ts-ignore
5097
- err.transport = transport.name;
5098
- this.emitReserved("upgradeError", err);
5099
- }
5100
- });
5101
- };
5102
- function freezeTransport() {
5103
- if (failed)
5104
- return;
5105
- // Any callback called by transport should be ignored since now
5106
- failed = true;
5107
- cleanup();
5108
- transport.close();
5109
- transport = null;
5110
- }
5111
- // Handle any error that happens while probing
5112
- const onerror = (err) => {
5113
- const error = new Error("probe error: " + err);
5114
- // @ts-ignore
5115
- error.transport = transport.name;
5116
- freezeTransport();
5117
- this.emitReserved("upgradeError", error);
5118
- };
5119
- function onTransportClose() {
5120
- onerror("transport closed");
5121
- }
5122
- // When the socket is closed while we're probing
5123
- function onclose() {
5124
- onerror("socket closed");
5125
- }
5126
- // When the socket is upgraded while we're probing
5127
- function onupgrade(to) {
5128
- if (transport && to.name !== transport.name) {
5129
- freezeTransport();
5130
- }
5131
- }
5132
- // Remove all listeners on the transport and on self
5133
- const cleanup = () => {
5134
- transport.removeListener("open", onTransportOpen);
5135
- transport.removeListener("error", onerror);
5136
- transport.removeListener("close", onTransportClose);
5137
- this.off("close", onclose);
5138
- this.off("upgrading", onupgrade);
5139
- };
5140
- transport.once("open", onTransportOpen);
5141
- transport.once("error", onerror);
5142
- transport.once("close", onTransportClose);
5143
- this.once("close", onclose);
5144
- this.once("upgrading", onupgrade);
5145
- if (this.upgrades.indexOf("webtransport") !== -1 &&
5146
- name !== "webtransport") {
5147
- // favor WebTransport
5148
- this.setTimeoutFn(() => {
5149
- if (!failed) {
5150
- transport.open();
5151
- }
5152
- }, 200);
5153
- }
5154
- else {
5155
- transport.open();
5156
- }
5055
+ .on("drain", this._onDrain.bind(this))
5056
+ .on("packet", this._onPacket.bind(this))
5057
+ .on("error", this._onError.bind(this))
5058
+ .on("close", (reason) => this._onClose("transport close", reason));
5157
5059
  }
5158
5060
  /**
5159
5061
  * Called when connection is deemed open.
@@ -5162,46 +5064,38 @@ let Socket$1 = class Socket extends Emitter_1 {
5162
5064
  */
5163
5065
  onOpen() {
5164
5066
  this.readyState = "open";
5165
- Socket.priorWebsocketSuccess = "websocket" === this.transport.name;
5067
+ SocketWithoutUpgrade.priorWebsocketSuccess =
5068
+ "websocket" === this.transport.name;
5166
5069
  this.emitReserved("open");
5167
5070
  this.flush();
5168
- // we check for `readyState` in case an `open`
5169
- // listener already closed the socket
5170
- if ("open" === this.readyState && this.opts.upgrade) {
5171
- let i = 0;
5172
- const l = this.upgrades.length;
5173
- for (; i < l; i++) {
5174
- this.probe(this.upgrades[i]);
5175
- }
5176
- }
5177
5071
  }
5178
5072
  /**
5179
5073
  * Handles a packet.
5180
5074
  *
5181
5075
  * @private
5182
5076
  */
5183
- onPacket(packet) {
5077
+ _onPacket(packet) {
5184
5078
  if ("opening" === this.readyState ||
5185
5079
  "open" === this.readyState ||
5186
5080
  "closing" === this.readyState) {
5187
5081
  this.emitReserved("packet", packet);
5188
5082
  // Socket is live - any packet counts
5189
5083
  this.emitReserved("heartbeat");
5190
- this.resetPingTimeout();
5191
5084
  switch (packet.type) {
5192
5085
  case "open":
5193
5086
  this.onHandshake(JSON.parse(packet.data));
5194
5087
  break;
5195
5088
  case "ping":
5196
- this.sendPacket("pong");
5089
+ this._sendPacket("pong");
5197
5090
  this.emitReserved("ping");
5198
5091
  this.emitReserved("pong");
5092
+ this._resetPingTimeout();
5199
5093
  break;
5200
5094
  case "error":
5201
5095
  const err = new Error("server error");
5202
5096
  // @ts-ignore
5203
5097
  err.code = packet.data;
5204
- this.onError(err);
5098
+ this._onError(err);
5205
5099
  break;
5206
5100
  case "message":
5207
5101
  this.emitReserved("data", packet.data);
@@ -5220,28 +5114,29 @@ let Socket$1 = class Socket extends Emitter_1 {
5220
5114
  this.emitReserved("handshake", data);
5221
5115
  this.id = data.sid;
5222
5116
  this.transport.query.sid = data.sid;
5223
- this.upgrades = this.filterUpgrades(data.upgrades);
5224
- this.pingInterval = data.pingInterval;
5225
- this.pingTimeout = data.pingTimeout;
5226
- this.maxPayload = data.maxPayload;
5117
+ this._pingInterval = data.pingInterval;
5118
+ this._pingTimeout = data.pingTimeout;
5119
+ this._maxPayload = data.maxPayload;
5227
5120
  this.onOpen();
5228
5121
  // In case open handler closes socket
5229
5122
  if ("closed" === this.readyState)
5230
5123
  return;
5231
- this.resetPingTimeout();
5124
+ this._resetPingTimeout();
5232
5125
  }
5233
5126
  /**
5234
5127
  * Sets and resets ping timeout timer based on server pings.
5235
5128
  *
5236
5129
  * @private
5237
5130
  */
5238
- resetPingTimeout() {
5239
- this.clearTimeoutFn(this.pingTimeoutTimer);
5240
- this.pingTimeoutTimer = this.setTimeoutFn(() => {
5241
- this.onClose("ping timeout");
5242
- }, this.pingInterval + this.pingTimeout);
5131
+ _resetPingTimeout() {
5132
+ this.clearTimeoutFn(this._pingTimeoutTimer);
5133
+ const delay = this._pingInterval + this._pingTimeout;
5134
+ this._pingTimeoutTime = Date.now() + delay;
5135
+ this._pingTimeoutTimer = this.setTimeoutFn(() => {
5136
+ this._onClose("ping timeout");
5137
+ }, delay);
5243
5138
  if (this.opts.autoUnref) {
5244
- this.pingTimeoutTimer.unref();
5139
+ this._pingTimeoutTimer.unref();
5245
5140
  }
5246
5141
  }
5247
5142
  /**
@@ -5249,12 +5144,12 @@ let Socket$1 = class Socket extends Emitter_1 {
5249
5144
  *
5250
5145
  * @private
5251
5146
  */
5252
- onDrain() {
5253
- this.writeBuffer.splice(0, this.prevBufferLen);
5147
+ _onDrain() {
5148
+ this.writeBuffer.splice(0, this._prevBufferLen);
5254
5149
  // setting prevBufferLen = 0 is very important
5255
5150
  // for example, when upgrading, upgrade packet is sent over,
5256
5151
  // and a nonzero prevBufferLen could cause problems on `drain`
5257
- this.prevBufferLen = 0;
5152
+ this._prevBufferLen = 0;
5258
5153
  if (0 === this.writeBuffer.length) {
5259
5154
  this.emitReserved("drain");
5260
5155
  }
@@ -5272,11 +5167,11 @@ let Socket$1 = class Socket extends Emitter_1 {
5272
5167
  this.transport.writable &&
5273
5168
  !this.upgrading &&
5274
5169
  this.writeBuffer.length) {
5275
- const packets = this.getWritablePackets();
5170
+ const packets = this._getWritablePackets();
5276
5171
  this.transport.send(packets);
5277
5172
  // keep track of current length of writeBuffer
5278
5173
  // splice writeBuffer and callbackBuffer on `drain`
5279
- this.prevBufferLen = packets.length;
5174
+ this._prevBufferLen = packets.length;
5280
5175
  this.emitReserved("flush");
5281
5176
  }
5282
5177
  }
@@ -5286,8 +5181,8 @@ let Socket$1 = class Socket extends Emitter_1 {
5286
5181
  *
5287
5182
  * @private
5288
5183
  */
5289
- getWritablePackets() {
5290
- const shouldCheckPayloadSize = this.maxPayload &&
5184
+ _getWritablePackets() {
5185
+ const shouldCheckPayloadSize = this._maxPayload &&
5291
5186
  this.transport.name === "polling" &&
5292
5187
  this.writeBuffer.length > 1;
5293
5188
  if (!shouldCheckPayloadSize) {
@@ -5299,27 +5194,56 @@ let Socket$1 = class Socket extends Emitter_1 {
5299
5194
  if (data) {
5300
5195
  payloadSize += byteLength(data);
5301
5196
  }
5302
- if (i > 0 && payloadSize > this.maxPayload) {
5197
+ if (i > 0 && payloadSize > this._maxPayload) {
5303
5198
  return this.writeBuffer.slice(0, i);
5304
5199
  }
5305
5200
  payloadSize += 2; // separator + packet type
5306
5201
  }
5307
5202
  return this.writeBuffer;
5308
5203
  }
5204
+ /**
5205
+ * Checks whether the heartbeat timer has expired but the socket has not yet been notified.
5206
+ *
5207
+ * Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
5208
+ * `write()` method then the message would not be buffered by the Socket.IO client.
5209
+ *
5210
+ * @return {boolean}
5211
+ * @private
5212
+ */
5213
+ /* private */ _hasPingExpired() {
5214
+ if (!this._pingTimeoutTime)
5215
+ return true;
5216
+ const hasExpired = Date.now() > this._pingTimeoutTime;
5217
+ if (hasExpired) {
5218
+ this._pingTimeoutTime = 0;
5219
+ nextTick(() => {
5220
+ this._onClose("ping timeout");
5221
+ }, this.setTimeoutFn);
5222
+ }
5223
+ return hasExpired;
5224
+ }
5309
5225
  /**
5310
5226
  * Sends a message.
5311
5227
  *
5312
5228
  * @param {String} msg - message.
5313
5229
  * @param {Object} options.
5314
- * @param {Function} callback function.
5230
+ * @param {Function} fn - callback function.
5315
5231
  * @return {Socket} for chaining.
5316
5232
  */
5317
5233
  write(msg, options, fn) {
5318
- this.sendPacket("message", msg, options, fn);
5234
+ this._sendPacket("message", msg, options, fn);
5319
5235
  return this;
5320
5236
  }
5237
+ /**
5238
+ * Sends a message. Alias of {@link Socket#write}.
5239
+ *
5240
+ * @param {String} msg - message.
5241
+ * @param {Object} options.
5242
+ * @param {Function} fn - callback function.
5243
+ * @return {Socket} for chaining.
5244
+ */
5321
5245
  send(msg, options, fn) {
5322
- this.sendPacket("message", msg, options, fn);
5246
+ this._sendPacket("message", msg, options, fn);
5323
5247
  return this;
5324
5248
  }
5325
5249
  /**
@@ -5331,7 +5255,7 @@ let Socket$1 = class Socket extends Emitter_1 {
5331
5255
  * @param {Function} fn - callback function.
5332
5256
  * @private
5333
5257
  */
5334
- sendPacket(type, data, options, fn) {
5258
+ _sendPacket(type, data, options, fn) {
5335
5259
  if ("function" === typeof data) {
5336
5260
  fn = data;
5337
5261
  data = undefined;
@@ -5361,7 +5285,7 @@ let Socket$1 = class Socket extends Emitter_1 {
5361
5285
  */
5362
5286
  close() {
5363
5287
  const close = () => {
5364
- this.onClose("forced close");
5288
+ this._onClose("forced close");
5365
5289
  this.transport.close();
5366
5290
  };
5367
5291
  const cleanupAndClose = () => {
@@ -5400,31 +5324,44 @@ let Socket$1 = class Socket extends Emitter_1 {
5400
5324
  *
5401
5325
  * @private
5402
5326
  */
5403
- onError(err) {
5404
- Socket.priorWebsocketSuccess = false;
5327
+ _onError(err) {
5328
+ SocketWithoutUpgrade.priorWebsocketSuccess = false;
5329
+ if (this.opts.tryAllTransports &&
5330
+ this.transports.length > 1 &&
5331
+ this.readyState === "opening") {
5332
+ this.transports.shift();
5333
+ return this._open();
5334
+ }
5405
5335
  this.emitReserved("error", err);
5406
- this.onClose("transport error", err);
5336
+ this._onClose("transport error", err);
5407
5337
  }
5408
5338
  /**
5409
5339
  * Called upon transport close.
5410
5340
  *
5411
5341
  * @private
5412
5342
  */
5413
- onClose(reason, description) {
5343
+ _onClose(reason, description) {
5414
5344
  if ("opening" === this.readyState ||
5415
5345
  "open" === this.readyState ||
5416
5346
  "closing" === this.readyState) {
5417
5347
  // clear timers
5418
- this.clearTimeoutFn(this.pingTimeoutTimer);
5348
+ this.clearTimeoutFn(this._pingTimeoutTimer);
5419
5349
  // stop event from firing again for transport
5420
5350
  this.transport.removeAllListeners("close");
5421
5351
  // ensure transport won't stay open
5422
5352
  this.transport.close();
5423
5353
  // ignore further transport communication
5424
5354
  this.transport.removeAllListeners();
5425
- if (typeof removeEventListener === "function") {
5426
- removeEventListener("beforeunload", this.beforeunloadEventListener, false);
5427
- removeEventListener("offline", this.offlineEventListener, false);
5355
+ if (withEventListeners) {
5356
+ if (this._beforeunloadEventListener) {
5357
+ removeEventListener("beforeunload", this._beforeunloadEventListener, false);
5358
+ }
5359
+ if (this._offlineEventListener) {
5360
+ const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);
5361
+ if (i !== -1) {
5362
+ OFFLINE_EVENT_LISTENERS.splice(i, 1);
5363
+ }
5364
+ }
5428
5365
  }
5429
5366
  // set ready state
5430
5367
  this.readyState = "closed";
@@ -5435,27 +5372,199 @@ let Socket$1 = class Socket extends Emitter_1 {
5435
5372
  // clean buffers after, so users can still
5436
5373
  // grab the buffers on `close` event
5437
5374
  this.writeBuffer = [];
5438
- this.prevBufferLen = 0;
5375
+ this._prevBufferLen = 0;
5376
+ }
5377
+ }
5378
+ }
5379
+ SocketWithoutUpgrade.protocol = protocol$1;
5380
+ /**
5381
+ * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
5382
+ * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
5383
+ *
5384
+ * This class comes with an upgrade mechanism, which means that once the connection is established with the first
5385
+ * low-level transport, it will try to upgrade to a better transport.
5386
+ *
5387
+ * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
5388
+ *
5389
+ * @example
5390
+ * import { SocketWithUpgrade, WebSocket } from "engine.io-client";
5391
+ *
5392
+ * const socket = new SocketWithUpgrade({
5393
+ * transports: [WebSocket]
5394
+ * });
5395
+ *
5396
+ * socket.on("open", () => {
5397
+ * socket.send("hello");
5398
+ * });
5399
+ *
5400
+ * @see SocketWithoutUpgrade
5401
+ * @see Socket
5402
+ */
5403
+ class SocketWithUpgrade extends SocketWithoutUpgrade {
5404
+ constructor() {
5405
+ super(...arguments);
5406
+ this._upgrades = [];
5407
+ }
5408
+ onOpen() {
5409
+ super.onOpen();
5410
+ if ("open" === this.readyState && this.opts.upgrade) {
5411
+ for (let i = 0; i < this._upgrades.length; i++) {
5412
+ this._probe(this._upgrades[i]);
5413
+ }
5439
5414
  }
5440
5415
  }
5416
+ /**
5417
+ * Probes a transport.
5418
+ *
5419
+ * @param {String} name - transport name
5420
+ * @private
5421
+ */
5422
+ _probe(name) {
5423
+ let transport = this.createTransport(name);
5424
+ let failed = false;
5425
+ SocketWithoutUpgrade.priorWebsocketSuccess = false;
5426
+ const onTransportOpen = () => {
5427
+ if (failed)
5428
+ return;
5429
+ transport.send([{ type: "ping", data: "probe" }]);
5430
+ transport.once("packet", (msg) => {
5431
+ if (failed)
5432
+ return;
5433
+ if ("pong" === msg.type && "probe" === msg.data) {
5434
+ this.upgrading = true;
5435
+ this.emitReserved("upgrading", transport);
5436
+ if (!transport)
5437
+ return;
5438
+ SocketWithoutUpgrade.priorWebsocketSuccess =
5439
+ "websocket" === transport.name;
5440
+ this.transport.pause(() => {
5441
+ if (failed)
5442
+ return;
5443
+ if ("closed" === this.readyState)
5444
+ return;
5445
+ cleanup();
5446
+ this.setTransport(transport);
5447
+ transport.send([{ type: "upgrade" }]);
5448
+ this.emitReserved("upgrade", transport);
5449
+ transport = null;
5450
+ this.upgrading = false;
5451
+ this.flush();
5452
+ });
5453
+ }
5454
+ else {
5455
+ const err = new Error("probe error");
5456
+ // @ts-ignore
5457
+ err.transport = transport.name;
5458
+ this.emitReserved("upgradeError", err);
5459
+ }
5460
+ });
5461
+ };
5462
+ function freezeTransport() {
5463
+ if (failed)
5464
+ return;
5465
+ // Any callback called by transport should be ignored since now
5466
+ failed = true;
5467
+ cleanup();
5468
+ transport.close();
5469
+ transport = null;
5470
+ }
5471
+ // Handle any error that happens while probing
5472
+ const onerror = (err) => {
5473
+ const error = new Error("probe error: " + err);
5474
+ // @ts-ignore
5475
+ error.transport = transport.name;
5476
+ freezeTransport();
5477
+ this.emitReserved("upgradeError", error);
5478
+ };
5479
+ function onTransportClose() {
5480
+ onerror("transport closed");
5481
+ }
5482
+ // When the socket is closed while we're probing
5483
+ function onclose() {
5484
+ onerror("socket closed");
5485
+ }
5486
+ // When the socket is upgraded while we're probing
5487
+ function onupgrade(to) {
5488
+ if (transport && to.name !== transport.name) {
5489
+ freezeTransport();
5490
+ }
5491
+ }
5492
+ // Remove all listeners on the transport and on self
5493
+ const cleanup = () => {
5494
+ transport.removeListener("open", onTransportOpen);
5495
+ transport.removeListener("error", onerror);
5496
+ transport.removeListener("close", onTransportClose);
5497
+ this.off("close", onclose);
5498
+ this.off("upgrading", onupgrade);
5499
+ };
5500
+ transport.once("open", onTransportOpen);
5501
+ transport.once("error", onerror);
5502
+ transport.once("close", onTransportClose);
5503
+ this.once("close", onclose);
5504
+ this.once("upgrading", onupgrade);
5505
+ if (this._upgrades.indexOf("webtransport") !== -1 &&
5506
+ name !== "webtransport") {
5507
+ // favor WebTransport
5508
+ this.setTimeoutFn(() => {
5509
+ if (!failed) {
5510
+ transport.open();
5511
+ }
5512
+ }, 200);
5513
+ }
5514
+ else {
5515
+ transport.open();
5516
+ }
5517
+ }
5518
+ onHandshake(data) {
5519
+ this._upgrades = this._filterUpgrades(data.upgrades);
5520
+ super.onHandshake(data);
5521
+ }
5441
5522
  /**
5442
5523
  * Filters upgrades, returning only those matching client transports.
5443
5524
  *
5444
5525
  * @param {Array} upgrades - server upgrades
5445
5526
  * @private
5446
5527
  */
5447
- filterUpgrades(upgrades) {
5528
+ _filterUpgrades(upgrades) {
5448
5529
  const filteredUpgrades = [];
5449
- let i = 0;
5450
- const j = upgrades.length;
5451
- for (; i < j; i++) {
5530
+ for (let i = 0; i < upgrades.length; i++) {
5452
5531
  if (~this.transports.indexOf(upgrades[i]))
5453
5532
  filteredUpgrades.push(upgrades[i]);
5454
5533
  }
5455
5534
  return filteredUpgrades;
5456
5535
  }
5536
+ }
5537
+ /**
5538
+ * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
5539
+ * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
5540
+ *
5541
+ * This class comes with an upgrade mechanism, which means that once the connection is established with the first
5542
+ * low-level transport, it will try to upgrade to a better transport.
5543
+ *
5544
+ * @example
5545
+ * import { Socket } from "engine.io-client";
5546
+ *
5547
+ * const socket = new Socket();
5548
+ *
5549
+ * socket.on("open", () => {
5550
+ * socket.send("hello");
5551
+ * });
5552
+ *
5553
+ * @see SocketWithoutUpgrade
5554
+ * @see SocketWithUpgrade
5555
+ */
5556
+ let Socket$1 = class Socket extends SocketWithUpgrade {
5557
+ constructor(uri, opts = {}) {
5558
+ const o = typeof uri === "object" ? uri : opts;
5559
+ if (!o.transports ||
5560
+ (o.transports && typeof o.transports[0] === "string")) {
5561
+ o.transports = (o.transports || ["polling", "websocket", "webtransport"])
5562
+ .map((transportName) => transports[transportName])
5563
+ .filter((t) => !!t);
5564
+ }
5565
+ super(uri, o);
5566
+ }
5457
5567
  };
5458
- Socket$1.protocol = protocol$1;
5459
5568
 
5460
5569
  Socket$1.protocol;
5461
5570
 
@@ -6211,6 +6320,7 @@ class Socket extends Emitter_1 {
6211
6320
  * @return self
6212
6321
  */
6213
6322
  emit(ev, ...args) {
6323
+ var _a, _b, _c;
6214
6324
  if (RESERVED_EVENTS.hasOwnProperty(ev)) {
6215
6325
  throw new Error('"' + ev.toString() + '" is a reserved event name');
6216
6326
  }
@@ -6232,12 +6342,11 @@ class Socket extends Emitter_1 {
6232
6342
  this._registerAckCallback(id, ack);
6233
6343
  packet.id = id;
6234
6344
  }
6235
- const isTransportWritable = this.io.engine &&
6236
- this.io.engine.transport &&
6237
- this.io.engine.transport.writable;
6238
- const discardPacket = this.flags.volatile && (!isTransportWritable || !this.connected);
6345
+ const isTransportWritable = (_b = (_a = this.io.engine) === null || _a === void 0 ? void 0 : _a.transport) === null || _b === void 0 ? void 0 : _b.writable;
6346
+ const isConnected = this.connected && !((_c = this.io.engine) === null || _c === void 0 ? void 0 : _c._hasPingExpired());
6347
+ const discardPacket = this.flags.volatile && !isTransportWritable;
6239
6348
  if (discardPacket) ;
6240
- else if (this.connected) {
6349
+ else if (isConnected) {
6241
6350
  this.notifyOutgoingListeners(packet);
6242
6351
  this.packet(packet);
6243
6352
  }
@@ -6960,6 +7069,9 @@ class Manager extends Emitter_1 {
6960
7069
  if (!arguments.length)
6961
7070
  return this._reconnection;
6962
7071
  this._reconnection = !!v;
7072
+ if (!v) {
7073
+ this.skipReconnect = true;
7074
+ }
6963
7075
  return this;
6964
7076
  }
6965
7077
  reconnectionAttempts(v) {
@@ -7088,7 +7200,9 @@ class Manager extends Emitter_1 {
7088
7200
  this.emitReserved("open");
7089
7201
  // add new subs
7090
7202
  const socket = this.engine;
7091
- this.subs.push(on(socket, "ping", this.onping.bind(this)), on(socket, "data", this.ondata.bind(this)), on(socket, "error", this.onerror.bind(this)), on(socket, "close", this.onclose.bind(this)), on(this.decoder, "decoded", this.ondecoded.bind(this)));
7203
+ this.subs.push(on(socket, "ping", this.onping.bind(this)), on(socket, "data", this.ondata.bind(this)), on(socket, "error", this.onerror.bind(this)), on(socket, "close", this.onclose.bind(this)),
7204
+ // @ts-ignore
7205
+ on(this.decoder, "decoded", this.ondecoded.bind(this)));
7092
7206
  }
7093
7207
  /**
7094
7208
  * Called upon a ping.
@@ -7194,8 +7308,6 @@ class Manager extends Emitter_1 {
7194
7308
  this.skipReconnect = true;
7195
7309
  this._reconnecting = false;
7196
7310
  this.onclose("forced close");
7197
- if (this.engine)
7198
- this.engine.close();
7199
7311
  }
7200
7312
  /**
7201
7313
  * Alias for close()
@@ -7206,12 +7318,18 @@ class Manager extends Emitter_1 {
7206
7318
  return this._close();
7207
7319
  }
7208
7320
  /**
7209
- * Called upon engine close.
7321
+ * Called when:
7322
+ *
7323
+ * - the low-level engine is closed
7324
+ * - the parser encountered a badly formatted packet
7325
+ * - all sockets are disconnected
7210
7326
  *
7211
7327
  * @private
7212
7328
  */
7213
7329
  onclose(reason, description) {
7330
+ var _a;
7214
7331
  this.cleanup();
7332
+ (_a = this.engine) === null || _a === void 0 ? void 0 : _a.close();
7215
7333
  this.backoff.reset();
7216
7334
  this._readyState = "closed";
7217
7335
  this.emitReserved("close", reason, description);