Commit Graph

733 Commits

Author SHA1 Message Date
Damien Arrachequesne
7c056889ee docs: add jsdoc for each public method 2022-10-15 06:54:56 +02:00
Damien Arrachequesne
2403b88057 fix: do not swallow user exceptions
Following [1], any exception in a user-provided event listener would
get caught in the try...catch of the decoder and result in the
reconnection of the socket.

[1]: c597023169

Related:

- https://github.com/socketio/socket.io-client/issues/1551
- https://github.com/socketio/socket.io-client/issues/1554
- https://github.com/socketio/socket.io-client/issues/1557
2022-10-13 16:26:35 +02:00
Damien Arrachequesne
c597023169 fix: handle ill-formatted packet from server
The decoder can throw an error when trying to decode an invalid payload
sent by the server, so the manager will now catch it, close the
connection and then reconnect instead of crashing.

Related:

- https://github.com/socketio/socket.io/issues/4392
- https://github.com/socketio/socket.io-client/issues/1551
2022-09-02 23:28:35 +01:00
Damien Arrachequesne
8c659bcccf chore: regenerate lockfile
For some reason, the lockfile was not in sync anymore with the
package.json file:

> `npm ci` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync.

That may be linked to a new version of Node.js (v16.15.1).
2022-06-26 08:19:46 +02:00
Damien Arrachequesne
e8590188ec refactor: replace the disconnected attribute by a getter 2022-04-24 00:13:56 +02:00
Damien Arrachequesne
74e3e601a4 feat: add support for catch-all listeners for outgoing packets
This is similar to `onAny()`, but for outgoing packets.

Syntax:

```js
socket.onAnyOutgoing((event, ...args) => {
  console.log(event);
});
```

Related: 531104d332
2022-04-23 23:57:03 +02:00
Damien Arrachequesne
6fdf3c9bfa refactor: import single-file 3rd party modules
This commit allows to:

- provide an ESM version of those modules ([1])
- reduce the attack surface in case of supply chain attacks
- reduce the size of the bundle with tree-shaking

As a downside, we won't receive security updates for those modules
anymore.

[1]: socketio/socket.io-client#1536

Related: df32277c3f
2022-04-23 22:55:39 +02:00
Damien Arrachequesne
b862924b7f feat: add details to the disconnect event
The "disconnect" event will now include additional details to help
debugging if anything has gone wrong.

Example when a payload is over the maxHttpBufferSize value in HTTP
long-polling mode:

```js
socket.on("disconnect", (reason, details) => {
  console.log(reason); // "transport error"

  // in that case, details is an error object
  console.log(details.message); "xhr post error"
  console.log(details.description); // 413 (the HTTP status of the response)

  // details.context refers to the XMLHttpRequest object
  console.log(details.context.status); // 413
  console.log(details.context.responseText); // ""
});
```

Related: b9252e2074
2022-04-23 00:57:23 +02:00
Damien Arrachequesne
522ffbe7a8 fix: prevent double ack with timeout
The ack was not properly removed upon timeout, and could be called
twice.

Related: ccf7998cc5
2021-11-18 13:40:46 +01:00
Damien Arrachequesne
99c2cb8421 fix: fix socket.disconnect().connect() usage
Previously, calling `socket.disconnect().connect()` could, if the
connection was upgraded to WebSocket, result in "disconnect" being
emitted twice, and an engine being leaked.

Here's what happened:

> socket.disconnect()

- calls `socket.destroy()` so the socket doesn't listen to the manager events anymore
- then calls `manager._close()` which closes the underlying engine but not the manager itself (it waits for the "close" event of the engine)

> socket.connect()

- calls `socket.subEvents()` so the socket does listen to the manager events
- calls `manager.open()` which creates a new engine

And then the first engine emits a "close" event, which is forwarded to
the socket, hence the second "disconnect" event.

Related: https://github.com/socketio/socket.io-client/issues/1014
2021-11-18 13:39:40 +01:00
Damien Arrachequesne
d54d12ce63 fix: prevent socket from reconnecting after middleware failure
Related: https://github.com/socketio/socket.io/discussions/4150
2021-11-16 19:57:47 +01:00
Damien Arrachequesne
ccf7998cc5 feat: add timeout feature
Usage:

```js
socket.timeout(5000).emit("my-event", (err) => {
  if (err) {
    // the server did not acknowledge the event in the given delay
  }
});
```
2021-11-16 19:56:44 +01:00
Damien Arrachequesne
6780f29624 fix: restore the default export (bis)
The previous commit, while successfully restoring support for:

```js
const socket = require("socket.io-client")(...);
```

breaks for some other cases:

- https://github.com/socketio/socket.io/issues/4128
- https://github.com/socketio/socket.io-client/issues/1509

According to [1], we should use `export = `, but this is not supported
by module "esnext":

> Export assignment cannot be used when targeting ECMAScript modules

So we'll go for this ugly workaround, at least until we remove the
default export in the next major release.

[1]: https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require
2021-10-17 01:00:28 +02:00
Damien Arrachequesne
f0aae8457a fix: restore the default export
The default export was accidentally removed in [1].

Note: that being said, users are encouraged to use the named exports,
because the default export has a different meaning for CommonJS and ES
modules users.

```js
// BAD
import io from "socket.io-client";

// GOOD
import { io } from "socket.io-client";
```

Related:

- https://github.com/socketio/socket.io-client/issues/1505
- https://github.com/socketio/socket.io-client/issues/1507
- https://github.com/socketio/socket.io-client/issues/1508

[1]: 16b65698ae
2021-10-16 01:09:43 +02:00
Chris Krycho
8737d0ae6f fix: restore the namespace export
This restores the previous behavior, where the "io" object available in
the browser could be used as a function (`io()`) or as a namespace
(`io.connect()`).

The breaking change was introduced in [1].

Related: https://github.com/socketio/socket.io/issues/4121

[1]: 16b65698ae
2021-10-16 00:52:31 +02:00
Damien Arrachequesne
91b948b860 refactor: move the typed events to @socket.io/component-emitter
The typed events have been moved to [1] in order to remove the
intermediary class and reduce the bundle size.

Diff: https://github.com/socketio/emitter/compare/2.0.0...3.0.0

[1]: https://github.com/socketio/emitter/
2021-10-14 14:09:23 +02:00
Abd Ul-Hameed Maree
a9e5b85580 feat(typings): add missing types for some emitter methods (#1502)
Co-authored-by: Abd UlHameed Maree <abd.maree@scandinaviatech.com>
2021-10-14 10:58:32 +02:00
Damien Arrachequesne
0661564dc2 chore: migrate to rollup
This change allows us to:

- reduce the size of the bundle
- provide an ESM bundle (for usage in <script type="module">)

Related: https://github.com/socketio/socket.io-client/issues/1198
2021-10-13 18:09:41 +02:00
Damien Arrachequesne
16b65698ae feat: provide an ESM build with and without debug
See also: 00d7e7d7ee

Related:

- https://github.com/socketio/socket.io-client/issues/1188
- https://github.com/socketio/socket.io-client/issues/1378
2021-10-13 18:09:41 +02:00
Damien Arrachequesne
91fbd47e1e chore: bump engine.io-client to version 6.0.0
Release notes: https://github.com/socketio/engine.io-client/releases/6.0.0
Diff: https://github.com/socketio/engine.io-client/compare/5.2.0...6.0.0
2021-10-11 23:19:51 +02:00
Damien Arrachequesne
66e00b7dd7 fix(typings): allow async listener in typed events
So that:

```ts
socket.on("my-event", async () => {
  // ...
});
```

is valid under the @typescript-eslint/no-misused-promises rule.

Related: https://github.com/socketio/socket.io-client/issues/1486
2021-08-30 08:21:47 +02:00
Michael Vartan
4e1b65699d feat: add an option to use native timer functions (#1479)
This allows to control the behavior of mocked timers (@sinonjs/fake-timers),
depending on the value of the "useNativeTimers" option:

- true: use native setTimeout function
- false (default): use classic timers, that may be mocked

Related: 5d1d5bea11
2021-08-29 09:31:25 +02:00
anshul singh
f3acddf997 refactor: remove duplicate initilializations (#1489)
The attributes were already initialized, resulting in duplicate lines
in the final bundle.

Related: https://github.com/socketio/socket.io/issues/4063
2021-08-28 09:25:36 +02:00
vks-jrobertson
dfb46b55a5 fix: allow to set randomizationFactor to 0 (#1447)
Documentation: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing

Related: https://github.com/socketio/socket.io-client/issues/1231
2021-07-29 09:59:03 +02:00
javiergonzalezGenially
35d27df2ae fix(typings): add missing closeOnBeforeunload option (#1469) 2021-05-17 22:01:39 +02:00
Poyan Nabati
c8dfbb1c1d fix(typings): add missing requestTimeout option (#1467) 2021-05-17 00:39:29 +02:00
Damien Arrachequesne
5394669488 fix(typings): add fallback to untyped event listener
See also: a11152f42b

Related:

- https://github.com/socketio/socket.io/issues/3885
- https://github.com/socketio/socket.io/issues/3872
- https://github.com/socketio/socket.io/issues/3833
2021-05-06 14:24:48 +02:00
Damien Arrachequesne
e20d487ac0 fix: properly export the Socket class
Before this change, `require("socket.io-client").Socket` would return
"undefined".

Note: having access to the Socket class allows users to modify its
prototype.

Related: https://github.com/socketio/socket.io/issues/3726
2021-05-06 14:24:08 +02:00
Damien Arrachequesne
34f822f783 fix: ensure buffered events are sent in order
Before this commit, an event sent in the "connect" handler could be
sent before the events that were buffered while disconnected.

```js
socket.on("connect", () => {
  socket.emit("bar");
});

socket.emit("foo"); // buffered while disconnected
```

In the example above, the "bar" event was sent first, which is not
correct.

Related: https://github.com/socketio/socket.io-client/issues/1458
2021-05-06 14:23:25 +02:00
Damien Arrachequesne
dd2a8fce00 fix: ensure connections are properly multiplexed
When passing the same `options` argument for two distinct Socket
instances, a new Manager was created:

```js
const opts = {};

const socket1 = io("/foo", opts);
const socket2 = io("/bar", opts);

console.log(socket1.io === socket2.io); // false
```

This bug was introduced by [1].

Note: the `options` argument is modified at the `socket.io-client`
level (path, query) and at the `engine.io-client` level (host, port),
which may not be optimal.

[1]: 7a0c2b504f

Related: https://github.com/socketio/socket.io/issues/3898
2021-05-06 14:22:54 +02:00
divlo
c15022347c fix(typings): make auth property public (#1455)
Related: https://github.com/socketio/socket.io-client/issues/1453
2021-04-01 00:32:21 +02:00
alex.zeng
48f573f6f6 fix(typings): update definition to match wrapper.mjs (#1456) 2021-04-01 00:31:43 +02:00
KC Erb
6abfa1fa4c feat: add autoUnref option
With autoUnref set to true (default: false), the Socket.IO client will
allow the program to exit if there is no other active timer/socket in
the event system.

```js
const socket = io({
  autoUnref: true
});
```

Note: this option only applies to Node.js clients.

Related: https://github.com/socketio/socket.io-client/issues/1446
2021-03-10 12:16:12 +01:00
Damien Arrachequesne
59023657a0 feat: add support for typed events
Syntax:

```ts
interface ServerToClientEvents {
  "my-event": (a: number, b: string, c: number[]) => void;
}

interface ClientToServerEvents {
  hello: (message: string) => void;
}

const socket: Socket<ServerToClientEvents, ClientToServerEvents> = io();

socket.emit("hello", "world");

socket.on("my-event", (a, b, c) => {
  // ...
});
```

The events are not typed by default (inferred as any), so this change
is backward compatible.

Related: https://github.com/socketio/socket.io/issues/3742
2021-03-10 01:24:56 +01:00
Damien Arrachequesne
7a0c2b504f fix: include the path in the manager ID
Previously, the following code:

```js
const socket1 = io({
  path: "/test1"
});
const socket2 = io({
  path: "/test2"
});
```

would result in one single Manager, with the "/test2" path being
silently ignored.

Two distinct Manager instances will now be created.

Related: https://github.com/socketio/socket.io-client/issues/1225
2021-02-03 22:31:01 +01:00
david-fong
47f917afdd fix(typings): add return types and general-case overload signatures (#1440) 2021-02-02 11:29:08 +01:00
Mick Lawitzke
f02ab3bc96 fix(typings): fix the type of the "query" option (#1439)
Having type `Object` it was not possible to set values, e.g.:

```ts
if (!this.socket.io.opts.query) {
  this.socket.io.opts.query = {};
}
this.socket.io.opts.query.token = 'abc123';
```

Results in error:

> Element implicitly has an 'any' type because expression of type '"token"' can't be used to index type 'Object'.
2021-02-02 11:26:33 +01:00
Damien Arrachequesne
0a63a17f63 refactor: remove unused line
In Socket.IO v2, the Socket `query` option was sent when connecting to
a custom namespace (but not for the main namespace).

This was fixed in Socket.IO v3 ([1]), so this line is now useless.

[1]: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/#Add-a-clear-distinction-between-the-Manager-query-option-and-the-Socket-query-option
2021-01-28 12:27:02 +01:00
Mick Lawitzke
fe97243fab fix(typings): make Manager#opts public (#1437)
As stated in the [documentation][1], the query option can be set by
setting `socket.io.opts` but `opts` was private and readonly.

[1]: https://socket.io/docs/v3/client-api/#With-query-option
2021-01-11 22:47:28 +01:00
Damien Arrachequesne
53c73749a8 fix: emit a connect_error event upon connection failure
Related: https://github.com/socketio/socket.io/issues/3734
2021-01-05 11:42:54 +01:00
Damien Arrachequesne
b83f89c901 fix(typings): make sendBuffer and receiveBuffer public
See also: https://socket.io/docs/v3/client-offline-behavior/#Buffered-events
2021-01-05 10:17:58 +01:00
david-fong
7bc7a7b624 refactor: switch to native javascript bind (#1423)
The polyfill for the bind() method was necessary for IE6/7/8, which we
do not support anymore.

Related: https://caniuse.com/mdn-javascript_builtins_function_bind
2020-12-11 11:55:57 +01:00
Damien Arrachequesne
f8f60fc860 fix: keep track of active sockets
When a given socket was disconnected, either by the server-side or by the client-side, the manager was closed too, regardless of the other connected sockets.

```js
const socket1 = io({
  autoConnect: false
});
const socket2 = io("/test");

socket1.disconnect(); // also disconnect socket2
```

This bug was introduced in [1].

[1]: b60e909039
2020-12-07 11:24:15 +01:00
Damien Arrachequesne
ec1f8c3474 fix: emit an error when reaching a v2.x server
A WebSocket-only v3.x client is able to reach a v2.x server, as the
Engine.IO handshake are compatible, but the v2.x server does not send
a sid in the Socket.IO handshake, which resulted in:

> Uncaught TypeError: Cannot read property 'sid' of undefined

A 'connect_error' event will now be emitted.

References:

- https://github.com/socketio/engine.io-protocol#difference-between-v3-and-v4
- https://github.com/socketio/socket.io-protocol#difference-between-v5-and-v4
- https://socket.io/docs/v3/migrating-from-2-x-to-3-0/
2020-12-07 11:18:55 +01:00
david-fong
226b491846 refactor(typings): make typing information more specific (#1418) 2020-12-07 09:06:57 +01:00
Luiz Pereira
b3de861a92 fix(typings): export extraHeaders option (#1410) 2020-11-20 23:09:27 +01:00
Damien Arrachequesne
719307801a fix(typings): export withCredentials option
Related: https://github.com/socketio/socket.io-client/issues/1405
2020-11-17 23:54:57 +01:00
Yusuke Sakurai
96cd2c9ae4 fix(typings): export ManagerOptions (#1398) 2020-11-17 00:03:22 +01:00
Avi Vahl
19ab1e9e4e fix(typings): export Socket and SocketOptions types (#1394)
These were exposed by @types/socket.io-client.
2020-11-09 09:00:07 +01:00
Damien Arrachequesne
09393952e3 feat: emit an Error object upon middleware error
See 54bf4a44e9
2020-10-30 22:54:13 +01:00