@nktkas/hyperliquid 0.13.1 → 0.13.2
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/LICENSE +20 -20
- package/README.md +33 -17
- package/esm/deps/jsr.io/@std/bytes/1.0.5/_types.d.ts +9 -0
- package/esm/deps/jsr.io/@std/bytes/1.0.5/_types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/bytes/1.0.5/_types.js +2 -0
- package/esm/deps/jsr.io/@std/bytes/{1.0.4 → 1.0.5}/concat.d.ts +3 -1
- package/esm/deps/jsr.io/@std/bytes/1.0.5/concat.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/bytes/{1.0.4 → 1.0.5}/concat.js +1 -1
- package/esm/deps/jsr.io/@std/encoding/1.0.7/_types.d.ts +9 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.7/_types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.7/_types.js +2 -0
- package/esm/deps/jsr.io/@std/encoding/{1.0.6 → 1.0.7}/_validate_binary_like.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/encoding/{1.0.6 → 1.0.7}/_validate_binary_like.js +1 -1
- package/{script/deps/jsr.io/@std/encoding/1.0.6 → esm/deps/jsr.io/@std/encoding/1.0.7}/hex.d.ts +3 -1
- package/esm/deps/jsr.io/@std/encoding/1.0.7/hex.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/encoding/{1.0.6 → 1.0.7}/hex.js +1 -1
- package/esm/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts +9 -0
- package/esm/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/msgpack/1.0.3/_types.js +2 -0
- package/esm/deps/jsr.io/@std/msgpack/{1.0.2 → 1.0.3}/encode.d.ts +3 -1
- package/esm/deps/jsr.io/@std/msgpack/1.0.3/encode.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/msgpack/{1.0.2 → 1.0.3}/encode.js +2 -2
- package/esm/mod.d.ts +1 -0
- package/esm/mod.d.ts.map +1 -1
- package/esm/src/clients/event.d.ts +57 -16
- package/esm/src/clients/event.d.ts.map +1 -1
- package/esm/src/clients/event.js +72 -16
- package/esm/src/clients/public.d.ts +241 -49
- package/esm/src/clients/public.d.ts.map +1 -1
- package/esm/src/clients/public.js +243 -47
- package/esm/src/clients/wallet.d.ts +120 -51
- package/esm/src/clients/wallet.d.ts.map +1 -1
- package/esm/src/clients/wallet.js +192 -58
- package/esm/src/transports/websocket/hyperliquid_event_target.d.ts +27 -21
- package/esm/src/transports/websocket/hyperliquid_event_target.d.ts.map +1 -1
- package/esm/src/transports/websocket/hyperliquid_event_target.js +37 -0
- package/esm/src/transports/websocket/websocket_request_dispatcher.js +3 -3
- package/esm/src/transports/websocket/websocket_transport.d.ts +7 -10
- package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/esm/src/transports/websocket/websocket_transport.js +41 -35
- package/esm/src/types/exchange/common.d.ts +6 -6
- package/esm/src/types/exchange/common.d.ts.map +1 -1
- package/esm/src/types/exchange/requests.d.ts +131 -64
- package/esm/src/types/exchange/requests.d.ts.map +1 -1
- package/esm/src/types/exchange/responses.d.ts +7 -7
- package/esm/src/types/exchange/responses.d.ts.map +1 -1
- package/esm/src/types/explorer/common.d.ts +15 -15
- package/esm/src/types/explorer/common.d.ts.map +1 -1
- package/esm/src/types/explorer/requests.d.ts +19 -6
- package/esm/src/types/explorer/requests.d.ts.map +1 -1
- package/esm/src/types/explorer/responses.d.ts +9 -2
- package/esm/src/types/explorer/responses.d.ts.map +1 -1
- package/esm/src/types/info/accounts.d.ts +189 -124
- package/esm/src/types/info/accounts.d.ts.map +1 -1
- package/esm/src/types/info/assets.d.ts +82 -78
- package/esm/src/types/info/assets.d.ts.map +1 -1
- package/esm/src/types/info/delegations.d.ts +117 -0
- package/esm/src/types/info/delegations.d.ts.map +1 -0
- package/esm/src/types/info/delegations.js +1 -0
- package/esm/src/types/info/orders.d.ts +67 -67
- package/esm/src/types/info/orders.d.ts.map +1 -1
- package/esm/src/types/info/requests.d.ts +128 -63
- package/esm/src/types/info/requests.d.ts.map +1 -1
- package/esm/src/types/info/vaults.d.ts +41 -84
- package/esm/src/types/info/vaults.d.ts.map +1 -1
- package/esm/src/types/subscriptions/common.d.ts +3 -0
- package/esm/src/types/subscriptions/common.d.ts.map +1 -1
- package/esm/src/types/subscriptions/requests.d.ts +10 -0
- package/esm/src/types/subscriptions/requests.d.ts.map +1 -1
- package/esm/src/utils/key_sort.d.ts +2 -2
- package/esm/src/utils/key_sort.d.ts.map +1 -1
- package/esm/src/utils/signing.d.ts +1 -1
- package/esm/src/utils/signing.js +2 -2
- package/package.json +1 -1
- package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/mod.js +13 -3
- package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/src/TypedEventTarget.js +23 -13
- package/script/deps/jsr.io/@noble/hashes/1.7.1/src/_assert.js +55 -45
- package/script/deps/jsr.io/@noble/hashes/1.7.1/src/_u64.js +97 -87
- package/script/deps/jsr.io/@noble/hashes/1.7.1/src/crypto.js +14 -4
- package/script/deps/jsr.io/@noble/hashes/1.7.1/src/sha3.js +288 -278
- package/script/deps/jsr.io/@noble/hashes/1.7.1/src/utils.js +238 -228
- package/script/deps/jsr.io/@std/bytes/1.0.5/_types.d.ts +9 -0
- package/script/deps/jsr.io/@std/bytes/1.0.5/_types.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/bytes/1.0.5/_types.js +13 -0
- package/script/deps/jsr.io/@std/bytes/{1.0.4 → 1.0.5}/concat.d.ts +3 -1
- package/script/deps/jsr.io/@std/bytes/1.0.5/concat.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/bytes/1.0.5/concat.js +45 -0
- package/script/deps/jsr.io/@std/encoding/1.0.7/_types.d.ts +9 -0
- package/script/deps/jsr.io/@std/encoding/1.0.7/_types.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/encoding/1.0.7/_types.js +13 -0
- package/script/deps/jsr.io/@std/encoding/{1.0.6 → 1.0.7}/_validate_binary_like.d.ts.map +1 -1
- package/script/deps/jsr.io/@std/encoding/1.0.7/_validate_binary_like.js +39 -0
- package/{esm/deps/jsr.io/@std/encoding/1.0.6 → script/deps/jsr.io/@std/encoding/1.0.7}/hex.d.ts +3 -1
- package/script/deps/jsr.io/@std/encoding/1.0.7/hex.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/encoding/1.0.7/hex.js +123 -0
- package/script/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts +9 -0
- package/script/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/msgpack/1.0.3/_types.js +13 -0
- package/script/deps/jsr.io/@std/msgpack/{1.0.2 → 1.0.3}/encode.d.ts +3 -1
- package/script/deps/jsr.io/@std/msgpack/1.0.3/encode.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/msgpack/1.0.3/encode.js +250 -0
- package/script/mod.d.ts +1 -0
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +23 -13
- package/script/src/clients/event.d.ts +57 -16
- package/script/src/clients/event.d.ts.map +1 -1
- package/script/src/clients/event.js +551 -485
- package/script/src/clients/public.d.ts +241 -49
- package/script/src/clients/public.d.ts.map +1 -1
- package/script/src/clients/public.js +914 -708
- package/script/src/clients/wallet.d.ts +120 -51
- package/script/src/clients/wallet.d.ts.map +1 -1
- package/script/src/clients/wallet.js +1121 -977
- package/script/src/transports/base.js +25 -15
- package/script/src/transports/http/http_transport.js +174 -164
- package/script/src/transports/websocket/hyperliquid_event_target.d.ts +27 -21
- package/script/src/transports/websocket/hyperliquid_event_target.d.ts.map +1 -1
- package/script/src/transports/websocket/hyperliquid_event_target.js +80 -33
- package/script/src/transports/websocket/reconnecting_websocket.js +364 -354
- package/script/src/transports/websocket/websocket_request_dispatcher.js +196 -186
- package/script/src/transports/websocket/websocket_transport.d.ts +7 -10
- package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/script/src/transports/websocket/websocket_transport.js +236 -220
- package/script/src/types/common.js +12 -2
- package/script/src/types/exchange/common.d.ts +6 -6
- package/script/src/types/exchange/common.d.ts.map +1 -1
- package/script/src/types/exchange/common.js +12 -2
- package/script/src/types/exchange/requests.d.ts +131 -64
- package/script/src/types/exchange/requests.d.ts.map +1 -1
- package/script/src/types/exchange/requests.js +12 -2
- package/script/src/types/exchange/responses.d.ts +7 -7
- package/script/src/types/exchange/responses.d.ts.map +1 -1
- package/script/src/types/exchange/responses.js +12 -2
- package/script/src/types/explorer/common.d.ts +15 -15
- package/script/src/types/explorer/common.d.ts.map +1 -1
- package/script/src/types/explorer/common.js +12 -2
- package/script/src/types/explorer/requests.d.ts +19 -6
- package/script/src/types/explorer/requests.d.ts.map +1 -1
- package/script/src/types/explorer/requests.js +12 -2
- package/script/src/types/explorer/responses.d.ts +9 -2
- package/script/src/types/explorer/responses.d.ts.map +1 -1
- package/script/src/types/explorer/responses.js +12 -2
- package/script/src/types/info/accounts.d.ts +189 -124
- package/script/src/types/info/accounts.d.ts.map +1 -1
- package/script/src/types/info/accounts.js +12 -2
- package/script/src/types/info/assets.d.ts +82 -78
- package/script/src/types/info/assets.d.ts.map +1 -1
- package/script/src/types/info/assets.js +12 -2
- package/script/src/types/info/delegations.d.ts +117 -0
- package/script/src/types/info/delegations.d.ts.map +1 -0
- package/script/src/types/info/delegations.js +12 -0
- package/script/src/types/info/orders.d.ts +67 -67
- package/script/src/types/info/orders.d.ts.map +1 -1
- package/script/src/types/info/orders.js +12 -2
- package/script/src/types/info/requests.d.ts +128 -63
- package/script/src/types/info/requests.d.ts.map +1 -1
- package/script/src/types/info/requests.js +12 -2
- package/script/src/types/info/vaults.d.ts +41 -84
- package/script/src/types/info/vaults.d.ts.map +1 -1
- package/script/src/types/info/vaults.js +12 -2
- package/script/src/types/subscriptions/common.d.ts +3 -0
- package/script/src/types/subscriptions/common.d.ts.map +1 -1
- package/script/src/types/subscriptions/common.js +12 -2
- package/script/src/types/subscriptions/requests.d.ts +10 -0
- package/script/src/types/subscriptions/requests.d.ts.map +1 -1
- package/script/src/types/subscriptions/requests.js +12 -2
- package/script/src/utils/key_sort.d.ts +2 -2
- package/script/src/utils/key_sort.d.ts.map +1 -1
- package/script/src/utils/key_sort.js +133 -123
- package/script/src/utils/signing.d.ts +1 -1
- package/script/src/utils/signing.js +172 -162
- package/esm/deps/jsr.io/@std/bytes/1.0.4/concat.d.ts.map +0 -1
- package/esm/deps/jsr.io/@std/encoding/1.0.6/hex.d.ts.map +0 -1
- package/esm/deps/jsr.io/@std/msgpack/1.0.2/encode.d.ts.map +0 -1
- package/script/deps/jsr.io/@std/bytes/1.0.4/concat.d.ts.map +0 -1
- package/script/deps/jsr.io/@std/bytes/1.0.4/concat.js +0 -35
- package/script/deps/jsr.io/@std/encoding/1.0.6/_validate_binary_like.js +0 -29
- package/script/deps/jsr.io/@std/encoding/1.0.6/hex.d.ts.map +0 -1
- package/script/deps/jsr.io/@std/encoding/1.0.6/hex.js +0 -113
- package/script/deps/jsr.io/@std/msgpack/1.0.2/encode.d.ts.map +0 -1
- package/script/deps/jsr.io/@std/msgpack/1.0.2/encode.js +0 -240
- /package/esm/deps/jsr.io/@std/encoding/{1.0.6 → 1.0.7}/_validate_binary_like.d.ts +0 -0
- /package/script/deps/jsr.io/@std/encoding/{1.0.6 → 1.0.7}/_validate_binary_like.d.ts +0 -0
|
@@ -1,374 +1,384 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// deno-lint-ignore-file no-explicit-any
|
|
3
|
-
|
|
4
|
-
exports
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
class FIFOMessageBuffer {
|
|
9
|
-
constructor() {
|
|
10
|
-
Object.defineProperty(this, "messages", {
|
|
11
|
-
enumerable: true,
|
|
12
|
-
configurable: true,
|
|
13
|
-
writable: true,
|
|
14
|
-
value: []
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
push(data) {
|
|
18
|
-
this.messages.push(data);
|
|
19
|
-
}
|
|
20
|
-
shift() {
|
|
21
|
-
return this.messages.shift();
|
|
2
|
+
(function (factory) {
|
|
3
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
4
|
+
var v = factory(require, exports);
|
|
5
|
+
if (v !== undefined) module.exports = v;
|
|
22
6
|
}
|
|
23
|
-
|
|
24
|
-
|
|
7
|
+
else if (typeof define === "function" && define.amd) {
|
|
8
|
+
define(["require", "exports"], factory);
|
|
25
9
|
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*/
|
|
31
|
-
class ReconnectingWebSocket {
|
|
10
|
+
})(function (require, exports) {
|
|
11
|
+
"use strict";
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.ReconnectingWebSocket = void 0;
|
|
32
14
|
/**
|
|
33
|
-
*
|
|
34
|
-
* @param url - The WebSocket URL to connect to.
|
|
35
|
-
* @param protocols - The WebSocket protocols to use.
|
|
36
|
-
* @param options - The configuration options.
|
|
15
|
+
* Simple FIFO (First In, First Out) buffer implementation.
|
|
37
16
|
*/
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
configurable: true,
|
|
57
|
-
writable: true,
|
|
58
|
-
value: void 0
|
|
59
|
-
});
|
|
60
|
-
/** Current number of reconnection attempts */
|
|
61
|
-
Object.defineProperty(this, "reconnectCount", {
|
|
62
|
-
enumerable: true,
|
|
63
|
-
configurable: true,
|
|
64
|
-
writable: true,
|
|
65
|
-
value: 0
|
|
66
|
-
});
|
|
67
|
-
/** Array of registered event listeners */
|
|
68
|
-
Object.defineProperty(this, "eventListeners", {
|
|
69
|
-
enumerable: true,
|
|
70
|
-
configurable: true,
|
|
71
|
-
writable: true,
|
|
72
|
-
value: []
|
|
73
|
-
});
|
|
74
|
-
/** Configuration options */
|
|
75
|
-
Object.defineProperty(this, "reconnectOptions", {
|
|
76
|
-
enumerable: true,
|
|
77
|
-
configurable: true,
|
|
78
|
-
writable: true,
|
|
79
|
-
value: void 0
|
|
80
|
-
});
|
|
81
|
-
/** An AbortSignal that is triggered when the connection is permanently closed */
|
|
82
|
-
Object.defineProperty(this, "terminationSignal", {
|
|
83
|
-
enumerable: true,
|
|
84
|
-
configurable: true,
|
|
85
|
-
writable: true,
|
|
86
|
-
value: this.terminationController.signal
|
|
87
|
-
});
|
|
88
|
-
Object.defineProperty(this, "CLOSED", {
|
|
89
|
-
enumerable: true,
|
|
90
|
-
configurable: true,
|
|
91
|
-
writable: true,
|
|
92
|
-
value: WebSocket.CLOSED
|
|
93
|
-
});
|
|
94
|
-
Object.defineProperty(this, "CLOSING", {
|
|
95
|
-
enumerable: true,
|
|
96
|
-
configurable: true,
|
|
97
|
-
writable: true,
|
|
98
|
-
value: WebSocket.CLOSING
|
|
99
|
-
});
|
|
100
|
-
Object.defineProperty(this, "CONNECTING", {
|
|
101
|
-
enumerable: true,
|
|
102
|
-
configurable: true,
|
|
103
|
-
writable: true,
|
|
104
|
-
value: WebSocket.CONNECTING
|
|
105
|
-
});
|
|
106
|
-
Object.defineProperty(this, "OPEN", {
|
|
107
|
-
enumerable: true,
|
|
108
|
-
configurable: true,
|
|
109
|
-
writable: true,
|
|
110
|
-
value: WebSocket.OPEN
|
|
111
|
-
});
|
|
112
|
-
this.reconnectOptions = {
|
|
113
|
-
maxRetries: options?.maxRetries ?? 3,
|
|
114
|
-
connectionTimeout: options?.connectionTimeout === undefined ? 10_000 : options.connectionTimeout,
|
|
115
|
-
connectionDelay: options?.connectionDelay ?? ((attempt) => Math.min(~~(1 << attempt) * 150, 10_000)),
|
|
116
|
-
shouldReconnect: options?.shouldReconnect ?? (() => true),
|
|
117
|
-
messageBuffer: options?.messageBuffer ?? new FIFOMessageBuffer(),
|
|
118
|
-
WebSocketConstructor: options?.WebSocketConstructor ?? WebSocket,
|
|
119
|
-
};
|
|
120
|
-
this.protocols = protocols;
|
|
121
|
-
this.socket = this.reconnectOptions.connectionTimeout
|
|
122
|
-
? this.connectWithTimeout(url, this.protocols, this.reconnectOptions.connectionTimeout)
|
|
123
|
-
: new this.reconnectOptions.WebSocketConstructor(url, this.protocols);
|
|
124
|
-
this.initEventListeners();
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Creates a WebSocket connection with timeout.
|
|
128
|
-
* @param url - The WebSocket URL to connect to.
|
|
129
|
-
* @param protocols - The WebSocket protocols to use.
|
|
130
|
-
* @param timeout - The connection timeout in ms.
|
|
131
|
-
* @returns A new WebSocket instance.
|
|
132
|
-
*/
|
|
133
|
-
connectWithTimeout(url, protocols, timeout) {
|
|
134
|
-
const socket = new this.reconnectOptions.WebSocketConstructor(url, protocols);
|
|
135
|
-
const timeoutId = setTimeout(() => {
|
|
136
|
-
socket.removeEventListener("open", openHandler);
|
|
137
|
-
socket.removeEventListener("close", closeHandler);
|
|
138
|
-
socket.close(3008, "Timeout"); // https://www.iana.org/assignments/websocket/websocket.xml#close-code-number
|
|
139
|
-
}, timeout);
|
|
140
|
-
const openHandler = () => {
|
|
141
|
-
socket.removeEventListener("close", closeHandler);
|
|
142
|
-
clearTimeout(timeoutId);
|
|
143
|
-
};
|
|
144
|
-
const closeHandler = () => {
|
|
145
|
-
socket.removeEventListener("open", openHandler);
|
|
146
|
-
clearTimeout(timeoutId);
|
|
147
|
-
};
|
|
148
|
-
socket.addEventListener("open", openHandler, { once: true });
|
|
149
|
-
socket.addEventListener("close", closeHandler, { once: true });
|
|
150
|
-
return socket;
|
|
17
|
+
class FIFOMessageBuffer {
|
|
18
|
+
constructor() {
|
|
19
|
+
Object.defineProperty(this, "messages", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: []
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
push(data) {
|
|
27
|
+
this.messages.push(data);
|
|
28
|
+
}
|
|
29
|
+
shift() {
|
|
30
|
+
return this.messages.shift();
|
|
31
|
+
}
|
|
32
|
+
clear() {
|
|
33
|
+
this.messages = [];
|
|
34
|
+
}
|
|
151
35
|
}
|
|
152
36
|
/**
|
|
153
|
-
*
|
|
37
|
+
* A WebSocket that automatically reconnects when disconnected.
|
|
38
|
+
* Fully compatible with standard WebSocket API.
|
|
154
39
|
*/
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
40
|
+
class ReconnectingWebSocket {
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new reconnecting WebSocket.
|
|
43
|
+
* @param url - The WebSocket URL to connect to.
|
|
44
|
+
* @param protocols - The WebSocket protocols to use.
|
|
45
|
+
* @param options - The configuration options.
|
|
46
|
+
*/
|
|
47
|
+
constructor(url, protocols, options) {
|
|
48
|
+
/** Controller for handling connection termination */
|
|
49
|
+
Object.defineProperty(this, "terminationController", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: new AbortController()
|
|
54
|
+
});
|
|
55
|
+
/** WebSocket protocols */
|
|
56
|
+
Object.defineProperty(this, "protocols", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
configurable: true,
|
|
59
|
+
writable: true,
|
|
60
|
+
value: void 0
|
|
61
|
+
});
|
|
62
|
+
/** The underlying WebSocket instance */
|
|
63
|
+
Object.defineProperty(this, "socket", {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
configurable: true,
|
|
66
|
+
writable: true,
|
|
67
|
+
value: void 0
|
|
68
|
+
});
|
|
69
|
+
/** Current number of reconnection attempts */
|
|
70
|
+
Object.defineProperty(this, "reconnectCount", {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
configurable: true,
|
|
73
|
+
writable: true,
|
|
74
|
+
value: 0
|
|
75
|
+
});
|
|
76
|
+
/** Array of registered event listeners */
|
|
77
|
+
Object.defineProperty(this, "eventListeners", {
|
|
78
|
+
enumerable: true,
|
|
79
|
+
configurable: true,
|
|
80
|
+
writable: true,
|
|
81
|
+
value: []
|
|
82
|
+
});
|
|
83
|
+
/** Configuration options */
|
|
84
|
+
Object.defineProperty(this, "reconnectOptions", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
configurable: true,
|
|
87
|
+
writable: true,
|
|
88
|
+
value: void 0
|
|
89
|
+
});
|
|
90
|
+
/** An AbortSignal that is triggered when the connection is permanently closed */
|
|
91
|
+
Object.defineProperty(this, "terminationSignal", {
|
|
92
|
+
enumerable: true,
|
|
93
|
+
configurable: true,
|
|
94
|
+
writable: true,
|
|
95
|
+
value: this.terminationController.signal
|
|
96
|
+
});
|
|
97
|
+
Object.defineProperty(this, "CLOSED", {
|
|
98
|
+
enumerable: true,
|
|
99
|
+
configurable: true,
|
|
100
|
+
writable: true,
|
|
101
|
+
value: WebSocket.CLOSED
|
|
102
|
+
});
|
|
103
|
+
Object.defineProperty(this, "CLOSING", {
|
|
104
|
+
enumerable: true,
|
|
105
|
+
configurable: true,
|
|
106
|
+
writable: true,
|
|
107
|
+
value: WebSocket.CLOSING
|
|
108
|
+
});
|
|
109
|
+
Object.defineProperty(this, "CONNECTING", {
|
|
110
|
+
enumerable: true,
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: true,
|
|
113
|
+
value: WebSocket.CONNECTING
|
|
114
|
+
});
|
|
115
|
+
Object.defineProperty(this, "OPEN", {
|
|
116
|
+
enumerable: true,
|
|
117
|
+
configurable: true,
|
|
118
|
+
writable: true,
|
|
119
|
+
value: WebSocket.OPEN
|
|
120
|
+
});
|
|
121
|
+
this.reconnectOptions = {
|
|
122
|
+
maxRetries: options?.maxRetries ?? 3,
|
|
123
|
+
connectionTimeout: options?.connectionTimeout === undefined ? 10_000 : options.connectionTimeout,
|
|
124
|
+
connectionDelay: options?.connectionDelay ?? ((attempt) => Math.min(~~(1 << attempt) * 150, 10_000)),
|
|
125
|
+
shouldReconnect: options?.shouldReconnect ?? (() => true),
|
|
126
|
+
messageBuffer: options?.messageBuffer ?? new FIFOMessageBuffer(),
|
|
127
|
+
WebSocketConstructor: options?.WebSocketConstructor ?? WebSocket,
|
|
128
|
+
};
|
|
129
|
+
this.protocols = protocols;
|
|
130
|
+
this.socket = this.reconnectOptions.connectionTimeout
|
|
131
|
+
? this.connectWithTimeout(url, this.protocols, this.reconnectOptions.connectionTimeout)
|
|
132
|
+
: new this.reconnectOptions.WebSocketConstructor(url, this.protocols);
|
|
133
|
+
this.initEventListeners();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Creates a WebSocket connection with timeout.
|
|
137
|
+
* @param url - The WebSocket URL to connect to.
|
|
138
|
+
* @param protocols - The WebSocket protocols to use.
|
|
139
|
+
* @param timeout - The connection timeout in ms.
|
|
140
|
+
* @returns A new WebSocket instance.
|
|
141
|
+
*/
|
|
142
|
+
connectWithTimeout(url, protocols, timeout) {
|
|
143
|
+
const socket = new this.reconnectOptions.WebSocketConstructor(url, protocols);
|
|
144
|
+
const timeoutId = setTimeout(() => {
|
|
145
|
+
socket.removeEventListener("open", openHandler);
|
|
146
|
+
socket.removeEventListener("close", closeHandler);
|
|
147
|
+
socket.close(3008, "Timeout"); // https://www.iana.org/assignments/websocket/websocket.xml#close-code-number
|
|
148
|
+
}, timeout);
|
|
149
|
+
const openHandler = () => {
|
|
150
|
+
socket.removeEventListener("close", closeHandler);
|
|
151
|
+
clearTimeout(timeoutId);
|
|
152
|
+
};
|
|
153
|
+
const closeHandler = () => {
|
|
154
|
+
socket.removeEventListener("open", openHandler);
|
|
155
|
+
clearTimeout(timeoutId);
|
|
156
|
+
};
|
|
157
|
+
socket.addEventListener("open", openHandler, { once: true });
|
|
158
|
+
socket.addEventListener("close", closeHandler, { once: true });
|
|
159
|
+
return socket;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Initializes the internal event listeners for the WebSocket.
|
|
163
|
+
*/
|
|
164
|
+
initEventListeners() {
|
|
165
|
+
this.socket.addEventListener("open", () => {
|
|
166
|
+
// Reset reconnection count
|
|
167
|
+
this.reconnectCount = 0;
|
|
168
|
+
// Send all buffered messages
|
|
169
|
+
let message;
|
|
170
|
+
while ((message = this.reconnectOptions.messageBuffer.shift()) !== undefined) {
|
|
171
|
+
this.socket.send(message);
|
|
172
|
+
}
|
|
173
|
+
}, { once: true });
|
|
174
|
+
this.socket.addEventListener("close", async (event) => {
|
|
175
|
+
try {
|
|
176
|
+
// If the termination signal is already aborted, do not attempt to reconnect
|
|
177
|
+
if (this.terminationSignal.aborted)
|
|
178
|
+
return;
|
|
179
|
+
// Check if reconnection should be attempted
|
|
180
|
+
if (++this.reconnectCount > this.reconnectOptions.maxRetries) {
|
|
181
|
+
this.cleanup(new Error("RECONNECTION_LIMIT_REACHED", { cause: event }));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const userDecision = await this.reconnectOptions.shouldReconnect(event);
|
|
185
|
+
if (this.terminationSignal.aborted)
|
|
186
|
+
return; // Check again after the await
|
|
187
|
+
if (!userDecision) {
|
|
188
|
+
this.cleanup(new Error("RECONNECTION_STOPPED_BY_USER", { cause: event }));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
// Delay before reconnecting
|
|
192
|
+
const delay = typeof this.reconnectOptions.connectionDelay === "number"
|
|
193
|
+
? this.reconnectOptions.connectionDelay
|
|
194
|
+
: await this.reconnectOptions.connectionDelay(this.reconnectCount);
|
|
195
|
+
if (this.terminationSignal.aborted)
|
|
196
|
+
return; // Check again after the await
|
|
197
|
+
await sleep(delay, this.terminationSignal);
|
|
198
|
+
// Reconnect the socket
|
|
199
|
+
this.socket = this.reconnectOptions.connectionTimeout
|
|
200
|
+
? this.connectWithTimeout(this.url, this.protocols, this.reconnectOptions.connectionTimeout)
|
|
201
|
+
: new this.reconnectOptions.WebSocketConstructor(this.url, this.protocols);
|
|
202
|
+
// Reconnect all listeners
|
|
203
|
+
this.initEventListeners();
|
|
204
|
+
this.eventListeners.forEach(({ type, listenerProxy, options }) => {
|
|
205
|
+
this.socket.addEventListener(type, listenerProxy, options);
|
|
206
|
+
});
|
|
174
207
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return; // Check again after the await
|
|
178
|
-
if (!userDecision) {
|
|
179
|
-
this.cleanup(new Error("RECONNECTION_STOPPED_BY_USER", { cause: event }));
|
|
180
|
-
return;
|
|
208
|
+
catch (error) {
|
|
209
|
+
this.cleanup(new Error("RECONNECTION_ERROR", { cause: { error, event } }));
|
|
181
210
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
211
|
+
}, { once: true });
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Clean up internal resources.
|
|
215
|
+
* @param reason - The reason for cleanup.
|
|
216
|
+
*/
|
|
217
|
+
cleanup(reason) {
|
|
218
|
+
this.terminationController.abort(reason);
|
|
219
|
+
this.reconnectOptions.messageBuffer.clear();
|
|
220
|
+
this.eventListeners = [];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Check if two event listeners are the same (just like EventTarget).
|
|
224
|
+
* @param a - First event listener configuration.
|
|
225
|
+
* @param b - Second event listener configuration.
|
|
226
|
+
* @returns True if the listeners match.
|
|
227
|
+
*/
|
|
228
|
+
isListenerMatch(a, b) {
|
|
229
|
+
const aCapture = Boolean(typeof a.options === "object" ? a.options.capture : a.options);
|
|
230
|
+
const bCapture = Boolean(typeof b.options === "object" ? b.options.capture : b.options);
|
|
231
|
+
return a.type === b.type && a.listener === b.listener && aCapture === bCapture;
|
|
232
|
+
}
|
|
233
|
+
// WebSocket property implementations
|
|
234
|
+
get url() {
|
|
235
|
+
return this.socket.url;
|
|
236
|
+
}
|
|
237
|
+
get readyState() {
|
|
238
|
+
return this.socket.readyState;
|
|
239
|
+
}
|
|
240
|
+
get bufferedAmount() {
|
|
241
|
+
return this.socket.bufferedAmount;
|
|
242
|
+
}
|
|
243
|
+
get extensions() {
|
|
244
|
+
return this.socket.extensions;
|
|
245
|
+
}
|
|
246
|
+
get protocol() {
|
|
247
|
+
return this.socket.protocol;
|
|
248
|
+
}
|
|
249
|
+
get binaryType() {
|
|
250
|
+
return this.socket.binaryType;
|
|
251
|
+
}
|
|
252
|
+
set binaryType(value) {
|
|
253
|
+
this.socket.binaryType = value;
|
|
254
|
+
}
|
|
255
|
+
get onclose() {
|
|
256
|
+
return this.socket.onclose;
|
|
257
|
+
}
|
|
258
|
+
set onclose(value) {
|
|
259
|
+
this.socket.onclose = value;
|
|
260
|
+
}
|
|
261
|
+
get onerror() {
|
|
262
|
+
return this.socket.onerror;
|
|
263
|
+
}
|
|
264
|
+
set onerror(value) {
|
|
265
|
+
this.socket.onerror = value;
|
|
266
|
+
}
|
|
267
|
+
get onmessage() {
|
|
268
|
+
return this.socket.onmessage;
|
|
269
|
+
}
|
|
270
|
+
set onmessage(value) {
|
|
271
|
+
this.socket.onmessage = value;
|
|
272
|
+
}
|
|
273
|
+
get onopen() {
|
|
274
|
+
return this.socket.onopen;
|
|
275
|
+
}
|
|
276
|
+
set onopen(value) {
|
|
277
|
+
this.socket.onopen = value;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* @param permanently - If true, the connection will be permanently closed. Default is true.
|
|
281
|
+
*/
|
|
282
|
+
close(code, reason, permanently = true) {
|
|
283
|
+
if (permanently)
|
|
284
|
+
this.cleanup(new Error("USER_INITIATED_CLOSE"));
|
|
285
|
+
this.socket.close(code, reason);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* @note If the connection is not open, the data will be buffered and sent when the connection is established.
|
|
289
|
+
*/
|
|
290
|
+
send(data) {
|
|
291
|
+
if (this.socket.readyState !== WebSocket.OPEN && !this.terminationSignal.aborted) {
|
|
292
|
+
this.reconnectOptions.messageBuffer.push(data);
|
|
198
293
|
}
|
|
199
|
-
|
|
200
|
-
this.
|
|
294
|
+
else {
|
|
295
|
+
this.socket.send(data);
|
|
201
296
|
}
|
|
202
|
-
}, { once: true });
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Clean up internal resources.
|
|
206
|
-
* @param reason - The reason for cleanup.
|
|
207
|
-
*/
|
|
208
|
-
cleanup(reason) {
|
|
209
|
-
this.terminationController.abort(reason);
|
|
210
|
-
this.reconnectOptions.messageBuffer.clear();
|
|
211
|
-
this.eventListeners = [];
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Check if two event listeners are the same (just like EventTarget).
|
|
215
|
-
* @param a - First event listener configuration.
|
|
216
|
-
* @param b - Second event listener configuration.
|
|
217
|
-
* @returns True if the listeners match.
|
|
218
|
-
*/
|
|
219
|
-
isListenerMatch(a, b) {
|
|
220
|
-
const aCapture = Boolean(typeof a.options === "object" ? a.options.capture : a.options);
|
|
221
|
-
const bCapture = Boolean(typeof b.options === "object" ? b.options.capture : b.options);
|
|
222
|
-
return a.type === b.type && a.listener === b.listener && aCapture === bCapture;
|
|
223
|
-
}
|
|
224
|
-
// WebSocket property implementations
|
|
225
|
-
get url() {
|
|
226
|
-
return this.socket.url;
|
|
227
|
-
}
|
|
228
|
-
get readyState() {
|
|
229
|
-
return this.socket.readyState;
|
|
230
|
-
}
|
|
231
|
-
get bufferedAmount() {
|
|
232
|
-
return this.socket.bufferedAmount;
|
|
233
|
-
}
|
|
234
|
-
get extensions() {
|
|
235
|
-
return this.socket.extensions;
|
|
236
|
-
}
|
|
237
|
-
get protocol() {
|
|
238
|
-
return this.socket.protocol;
|
|
239
|
-
}
|
|
240
|
-
get binaryType() {
|
|
241
|
-
return this.socket.binaryType;
|
|
242
|
-
}
|
|
243
|
-
set binaryType(value) {
|
|
244
|
-
this.socket.binaryType = value;
|
|
245
|
-
}
|
|
246
|
-
get onclose() {
|
|
247
|
-
return this.socket.onclose;
|
|
248
|
-
}
|
|
249
|
-
set onclose(value) {
|
|
250
|
-
this.socket.onclose = value;
|
|
251
|
-
}
|
|
252
|
-
get onerror() {
|
|
253
|
-
return this.socket.onerror;
|
|
254
|
-
}
|
|
255
|
-
set onerror(value) {
|
|
256
|
-
this.socket.onerror = value;
|
|
257
|
-
}
|
|
258
|
-
get onmessage() {
|
|
259
|
-
return this.socket.onmessage;
|
|
260
|
-
}
|
|
261
|
-
set onmessage(value) {
|
|
262
|
-
this.socket.onmessage = value;
|
|
263
|
-
}
|
|
264
|
-
get onopen() {
|
|
265
|
-
return this.socket.onopen;
|
|
266
|
-
}
|
|
267
|
-
set onopen(value) {
|
|
268
|
-
this.socket.onopen = value;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* @param permanently - If true, the connection will be permanently closed. Default is true.
|
|
272
|
-
*/
|
|
273
|
-
close(code, reason, permanently = true) {
|
|
274
|
-
if (permanently)
|
|
275
|
-
this.cleanup(new Error("USER_INITIATED_CLOSE"));
|
|
276
|
-
this.socket.close(code, reason);
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* @note If the connection is not open, the data will be buffered and sent when the connection is established.
|
|
280
|
-
*/
|
|
281
|
-
send(data) {
|
|
282
|
-
if (this.socket.readyState !== WebSocket.OPEN && !this.terminationSignal.aborted) {
|
|
283
|
-
this.reconnectOptions.messageBuffer.push(data);
|
|
284
|
-
}
|
|
285
|
-
else {
|
|
286
|
-
this.socket.send(data);
|
|
287
297
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
298
|
+
addEventListener(type, listener, options) {
|
|
299
|
+
// Check if the listener is already added
|
|
300
|
+
const exists = this.eventListeners.some((e) => this.isListenerMatch(e, { type, listener, options }));
|
|
301
|
+
if (exists)
|
|
302
|
+
return;
|
|
303
|
+
// Wrap the original listener to follow the once option when reconnecting
|
|
304
|
+
const listenerProxy = (event) => {
|
|
305
|
+
try {
|
|
306
|
+
if (typeof listener === "function") {
|
|
307
|
+
listener.call(this, event);
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
listener.handleEvent(event);
|
|
311
|
+
}
|
|
302
312
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
313
|
+
finally {
|
|
314
|
+
if (typeof options === "object" && options.once === true) {
|
|
315
|
+
const index = this.eventListeners.findIndex((e) => this.isListenerMatch(e, { type, listener, options }));
|
|
316
|
+
if (index !== -1)
|
|
317
|
+
this.eventListeners.splice(index, 1);
|
|
318
|
+
}
|
|
309
319
|
}
|
|
320
|
+
};
|
|
321
|
+
this.eventListeners.push({ type, listener, options, listenerProxy });
|
|
322
|
+
this.socket.addEventListener(type, listenerProxy, options);
|
|
323
|
+
}
|
|
324
|
+
removeEventListener(type, listener, options) {
|
|
325
|
+
const index = this.eventListeners.findIndex((e) => this.isListenerMatch(e, { type, listener, options }));
|
|
326
|
+
if (index !== -1) {
|
|
327
|
+
const { listenerProxy } = this.eventListeners[index];
|
|
328
|
+
this.socket.removeEventListener(type, listenerProxy, options);
|
|
329
|
+
this.eventListeners.splice(index, 1);
|
|
310
330
|
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
removeEventListener(type, listener, options) {
|
|
316
|
-
const index = this.eventListeners.findIndex((e) => this.isListenerMatch(e, { type, listener, options }));
|
|
317
|
-
if (index !== -1) {
|
|
318
|
-
const { listenerProxy } = this.eventListeners[index];
|
|
319
|
-
this.socket.removeEventListener(type, listenerProxy, options);
|
|
320
|
-
this.eventListeners.splice(index, 1);
|
|
331
|
+
}
|
|
332
|
+
dispatchEvent(event) {
|
|
333
|
+
return this.socket.dispatchEvent(event);
|
|
321
334
|
}
|
|
322
335
|
}
|
|
323
|
-
|
|
324
|
-
|
|
336
|
+
exports.ReconnectingWebSocket = ReconnectingWebSocket;
|
|
337
|
+
Object.defineProperty(ReconnectingWebSocket, "CLOSED", {
|
|
338
|
+
enumerable: true,
|
|
339
|
+
configurable: true,
|
|
340
|
+
writable: true,
|
|
341
|
+
value: WebSocket.CLOSED
|
|
342
|
+
});
|
|
343
|
+
Object.defineProperty(ReconnectingWebSocket, "CLOSING", {
|
|
344
|
+
enumerable: true,
|
|
345
|
+
configurable: true,
|
|
346
|
+
writable: true,
|
|
347
|
+
value: WebSocket.CLOSING
|
|
348
|
+
});
|
|
349
|
+
Object.defineProperty(ReconnectingWebSocket, "CONNECTING", {
|
|
350
|
+
enumerable: true,
|
|
351
|
+
configurable: true,
|
|
352
|
+
writable: true,
|
|
353
|
+
value: WebSocket.CONNECTING
|
|
354
|
+
});
|
|
355
|
+
Object.defineProperty(ReconnectingWebSocket, "OPEN", {
|
|
356
|
+
enumerable: true,
|
|
357
|
+
configurable: true,
|
|
358
|
+
writable: true,
|
|
359
|
+
value: WebSocket.OPEN
|
|
360
|
+
});
|
|
361
|
+
/**
|
|
362
|
+
* Returns a promise that resolves after the specified number of ms,
|
|
363
|
+
* or rejects as soon as the given signal is aborted.
|
|
364
|
+
* @param ms - The number of ms to sleep.
|
|
365
|
+
* @param signal - An optional abort signal.
|
|
366
|
+
* @returns A promise that resolves after the specified delay.
|
|
367
|
+
*/
|
|
368
|
+
function sleep(ms, signal) {
|
|
369
|
+
return new Promise((resolve, reject) => {
|
|
370
|
+
if (signal?.aborted) {
|
|
371
|
+
return reject(signal.reason);
|
|
372
|
+
}
|
|
373
|
+
const onAbort = function () {
|
|
374
|
+
clearTimeout(timer);
|
|
375
|
+
reject(this.reason);
|
|
376
|
+
};
|
|
377
|
+
const timer = setTimeout(() => {
|
|
378
|
+
signal?.removeEventListener("abort", onAbort);
|
|
379
|
+
resolve();
|
|
380
|
+
}, ms);
|
|
381
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
382
|
+
});
|
|
325
383
|
}
|
|
326
|
-
}
|
|
327
|
-
exports.ReconnectingWebSocket = ReconnectingWebSocket;
|
|
328
|
-
Object.defineProperty(ReconnectingWebSocket, "CLOSED", {
|
|
329
|
-
enumerable: true,
|
|
330
|
-
configurable: true,
|
|
331
|
-
writable: true,
|
|
332
|
-
value: WebSocket.CLOSED
|
|
333
384
|
});
|
|
334
|
-
Object.defineProperty(ReconnectingWebSocket, "CLOSING", {
|
|
335
|
-
enumerable: true,
|
|
336
|
-
configurable: true,
|
|
337
|
-
writable: true,
|
|
338
|
-
value: WebSocket.CLOSING
|
|
339
|
-
});
|
|
340
|
-
Object.defineProperty(ReconnectingWebSocket, "CONNECTING", {
|
|
341
|
-
enumerable: true,
|
|
342
|
-
configurable: true,
|
|
343
|
-
writable: true,
|
|
344
|
-
value: WebSocket.CONNECTING
|
|
345
|
-
});
|
|
346
|
-
Object.defineProperty(ReconnectingWebSocket, "OPEN", {
|
|
347
|
-
enumerable: true,
|
|
348
|
-
configurable: true,
|
|
349
|
-
writable: true,
|
|
350
|
-
value: WebSocket.OPEN
|
|
351
|
-
});
|
|
352
|
-
/**
|
|
353
|
-
* Returns a promise that resolves after the specified number of ms,
|
|
354
|
-
* or rejects as soon as the given signal is aborted.
|
|
355
|
-
* @param ms - The number of ms to sleep.
|
|
356
|
-
* @param signal - An optional abort signal.
|
|
357
|
-
* @returns A promise that resolves after the specified delay.
|
|
358
|
-
*/
|
|
359
|
-
function sleep(ms, signal) {
|
|
360
|
-
return new Promise((resolve, reject) => {
|
|
361
|
-
if (signal?.aborted) {
|
|
362
|
-
return reject(signal.reason);
|
|
363
|
-
}
|
|
364
|
-
const onAbort = function () {
|
|
365
|
-
clearTimeout(timer);
|
|
366
|
-
reject(this.reason);
|
|
367
|
-
};
|
|
368
|
-
const timer = setTimeout(() => {
|
|
369
|
-
signal?.removeEventListener("abort", onAbort);
|
|
370
|
-
resolve();
|
|
371
|
-
}, ms);
|
|
372
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
373
|
-
});
|
|
374
|
-
}
|