@inkeep/agents-work-apps 0.50.0 → 0.50.3
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/_virtual/rolldown_runtime.js +32 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.js +1 -0
- package/dist/github/mcp/auth.d.ts +2 -2
- package/dist/github/mcp/index.d.ts +2 -2
- package/dist/github/mcp/schemas.d.ts +1 -1
- package/dist/github/routes/tokenExchange.d.ts +2 -2
- package/dist/github/routes/webhooks.d.ts +2 -2
- package/dist/node_modules/.pnpm/@slack_logger@4.0.0/node_modules/@slack/logger/dist/index.js +89 -0
- package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/package.js +85 -0
- package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.js +223 -0
- package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/SocketModeClient.js +367 -0
- package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/UnrecoverableSocketModeStartError.js +20 -0
- package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/errors.js +71 -0
- package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/index.js +44 -0
- package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/logger.js +32 -0
- package/dist/node_modules/.pnpm/eventemitter3@5.0.1/node_modules/eventemitter3/index.js +241 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/index.js +23 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/buffer-util.js +107 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/constants.js +29 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/event-target.js +226 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/extension.js +150 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/limiter.js +57 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js +342 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/receiver.js +457 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/sender.js +505 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/stream.js +123 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/subprotocol.js +46 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/validation.js +203 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js +385 -0
- package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js +985 -0
- package/dist/slack/dispatcher.d.ts +16 -0
- package/dist/slack/dispatcher.js +335 -0
- package/dist/slack/i18n/strings.d.ts +5 -5
- package/dist/slack/i18n/strings.js +9 -9
- package/dist/slack/index.d.ts +3 -1
- package/dist/slack/index.js +4 -2
- package/dist/slack/middleware/permissions.js +120 -107
- package/dist/slack/routes/events.js +10 -328
- package/dist/slack/routes/oauth.js +6 -3
- package/dist/slack/routes/users.js +12 -6
- package/dist/slack/routes/workspaces.js +31 -36
- package/dist/slack/services/blocks/index.js +7 -11
- package/dist/slack/services/commands/index.js +2 -2
- package/dist/slack/services/dev-config.d.ts +23 -0
- package/dist/slack/services/dev-config.js +91 -0
- package/dist/slack/services/events/app-mention.js +6 -17
- package/dist/slack/services/events/modal-submission.js +5 -5
- package/dist/slack/services/events/streaming.js +4 -3
- package/dist/slack/services/events/utils.js +8 -8
- package/dist/slack/services/index.js +1 -1
- package/dist/slack/services/modals.js +4 -4
- package/dist/slack/services/nango.d.ts +2 -0
- package/dist/slack/services/nango.js +84 -2
- package/dist/slack/socket-mode.d.ts +4 -0
- package/dist/slack/socket-mode.js +130 -0
- package/package.json +3 -2
|
@@ -0,0 +1,985 @@
|
|
|
1
|
+
import { __commonJSMin, __require } from "../../../../../../_virtual/rolldown_runtime.js";
|
|
2
|
+
import { require_constants } from "./constants.js";
|
|
3
|
+
import { require_buffer_util } from "./buffer-util.js";
|
|
4
|
+
import { require_permessage_deflate } from "./permessage-deflate.js";
|
|
5
|
+
import { require_validation } from "./validation.js";
|
|
6
|
+
import { require_receiver } from "./receiver.js";
|
|
7
|
+
import { require_sender } from "./sender.js";
|
|
8
|
+
import { require_event_target } from "./event-target.js";
|
|
9
|
+
import { require_extension } from "./extension.js";
|
|
10
|
+
|
|
11
|
+
//#region ../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js
|
|
12
|
+
var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
13
|
+
const EventEmitter = __require("events");
|
|
14
|
+
const https = __require("https");
|
|
15
|
+
const http = __require("http");
|
|
16
|
+
const net = __require("net");
|
|
17
|
+
const tls = __require("tls");
|
|
18
|
+
const { randomBytes, createHash } = __require("crypto");
|
|
19
|
+
const { Duplex, Readable } = __require("stream");
|
|
20
|
+
const { URL } = __require("url");
|
|
21
|
+
const PerMessageDeflate = require_permessage_deflate();
|
|
22
|
+
const Receiver = require_receiver();
|
|
23
|
+
const Sender = require_sender();
|
|
24
|
+
const { isBlob } = require_validation();
|
|
25
|
+
const { BINARY_TYPES, CLOSE_TIMEOUT, EMPTY_BUFFER, GUID, kForOnEventAttribute, kListener, kStatusCode, kWebSocket, NOOP } = require_constants();
|
|
26
|
+
const { EventTarget: { addEventListener, removeEventListener } } = require_event_target();
|
|
27
|
+
const { format, parse } = require_extension();
|
|
28
|
+
const { toBuffer } = require_buffer_util();
|
|
29
|
+
const kAborted = Symbol("kAborted");
|
|
30
|
+
const protocolVersions = [8, 13];
|
|
31
|
+
const readyStates = [
|
|
32
|
+
"CONNECTING",
|
|
33
|
+
"OPEN",
|
|
34
|
+
"CLOSING",
|
|
35
|
+
"CLOSED"
|
|
36
|
+
];
|
|
37
|
+
const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
38
|
+
/**
|
|
39
|
+
* Class representing a WebSocket.
|
|
40
|
+
*
|
|
41
|
+
* @extends EventEmitter
|
|
42
|
+
*/
|
|
43
|
+
var WebSocket = class WebSocket extends EventEmitter {
|
|
44
|
+
/**
|
|
45
|
+
* Create a new `WebSocket`.
|
|
46
|
+
*
|
|
47
|
+
* @param {(String|URL)} address The URL to which to connect
|
|
48
|
+
* @param {(String|String[])} [protocols] The subprotocols
|
|
49
|
+
* @param {Object} [options] Connection options
|
|
50
|
+
*/
|
|
51
|
+
constructor(address, protocols, options) {
|
|
52
|
+
super();
|
|
53
|
+
this._binaryType = BINARY_TYPES[0];
|
|
54
|
+
this._closeCode = 1006;
|
|
55
|
+
this._closeFrameReceived = false;
|
|
56
|
+
this._closeFrameSent = false;
|
|
57
|
+
this._closeMessage = EMPTY_BUFFER;
|
|
58
|
+
this._closeTimer = null;
|
|
59
|
+
this._errorEmitted = false;
|
|
60
|
+
this._extensions = {};
|
|
61
|
+
this._paused = false;
|
|
62
|
+
this._protocol = "";
|
|
63
|
+
this._readyState = WebSocket.CONNECTING;
|
|
64
|
+
this._receiver = null;
|
|
65
|
+
this._sender = null;
|
|
66
|
+
this._socket = null;
|
|
67
|
+
if (address !== null) {
|
|
68
|
+
this._bufferedAmount = 0;
|
|
69
|
+
this._isServer = false;
|
|
70
|
+
this._redirects = 0;
|
|
71
|
+
if (protocols === void 0) protocols = [];
|
|
72
|
+
else if (!Array.isArray(protocols)) if (typeof protocols === "object" && protocols !== null) {
|
|
73
|
+
options = protocols;
|
|
74
|
+
protocols = [];
|
|
75
|
+
} else protocols = [protocols];
|
|
76
|
+
initAsClient(this, address, protocols, options);
|
|
77
|
+
} else {
|
|
78
|
+
this._autoPong = options.autoPong;
|
|
79
|
+
this._closeTimeout = options.closeTimeout;
|
|
80
|
+
this._isServer = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* For historical reasons, the custom "nodebuffer" type is used by the default
|
|
85
|
+
* instead of "blob".
|
|
86
|
+
*
|
|
87
|
+
* @type {String}
|
|
88
|
+
*/
|
|
89
|
+
get binaryType() {
|
|
90
|
+
return this._binaryType;
|
|
91
|
+
}
|
|
92
|
+
set binaryType(type) {
|
|
93
|
+
if (!BINARY_TYPES.includes(type)) return;
|
|
94
|
+
this._binaryType = type;
|
|
95
|
+
if (this._receiver) this._receiver._binaryType = type;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* @type {Number}
|
|
99
|
+
*/
|
|
100
|
+
get bufferedAmount() {
|
|
101
|
+
if (!this._socket) return this._bufferedAmount;
|
|
102
|
+
return this._socket._writableState.length + this._sender._bufferedBytes;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* @type {String}
|
|
106
|
+
*/
|
|
107
|
+
get extensions() {
|
|
108
|
+
return Object.keys(this._extensions).join();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* @type {Boolean}
|
|
112
|
+
*/
|
|
113
|
+
get isPaused() {
|
|
114
|
+
return this._paused;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @type {Function}
|
|
118
|
+
*/
|
|
119
|
+
/* istanbul ignore next */
|
|
120
|
+
get onclose() {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* @type {Function}
|
|
125
|
+
*/
|
|
126
|
+
/* istanbul ignore next */
|
|
127
|
+
get onerror() {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* @type {Function}
|
|
132
|
+
*/
|
|
133
|
+
/* istanbul ignore next */
|
|
134
|
+
get onopen() {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* @type {Function}
|
|
139
|
+
*/
|
|
140
|
+
/* istanbul ignore next */
|
|
141
|
+
get onmessage() {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @type {String}
|
|
146
|
+
*/
|
|
147
|
+
get protocol() {
|
|
148
|
+
return this._protocol;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* @type {Number}
|
|
152
|
+
*/
|
|
153
|
+
get readyState() {
|
|
154
|
+
return this._readyState;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* @type {String}
|
|
158
|
+
*/
|
|
159
|
+
get url() {
|
|
160
|
+
return this._url;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Set up the socket and the internal resources.
|
|
164
|
+
*
|
|
165
|
+
* @param {Duplex} socket The network socket between the server and client
|
|
166
|
+
* @param {Buffer} head The first packet of the upgraded stream
|
|
167
|
+
* @param {Object} options Options object
|
|
168
|
+
* @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
|
|
169
|
+
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
|
|
170
|
+
* multiple times in the same tick
|
|
171
|
+
* @param {Function} [options.generateMask] The function used to generate the
|
|
172
|
+
* masking key
|
|
173
|
+
* @param {Number} [options.maxPayload=0] The maximum allowed message size
|
|
174
|
+
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
175
|
+
* not to skip UTF-8 validation for text and close messages
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
setSocket(socket, head, options) {
|
|
179
|
+
const receiver = new Receiver({
|
|
180
|
+
allowSynchronousEvents: options.allowSynchronousEvents,
|
|
181
|
+
binaryType: this.binaryType,
|
|
182
|
+
extensions: this._extensions,
|
|
183
|
+
isServer: this._isServer,
|
|
184
|
+
maxPayload: options.maxPayload,
|
|
185
|
+
skipUTF8Validation: options.skipUTF8Validation
|
|
186
|
+
});
|
|
187
|
+
const sender = new Sender(socket, this._extensions, options.generateMask);
|
|
188
|
+
this._receiver = receiver;
|
|
189
|
+
this._sender = sender;
|
|
190
|
+
this._socket = socket;
|
|
191
|
+
receiver[kWebSocket] = this;
|
|
192
|
+
sender[kWebSocket] = this;
|
|
193
|
+
socket[kWebSocket] = this;
|
|
194
|
+
receiver.on("conclude", receiverOnConclude);
|
|
195
|
+
receiver.on("drain", receiverOnDrain);
|
|
196
|
+
receiver.on("error", receiverOnError);
|
|
197
|
+
receiver.on("message", receiverOnMessage);
|
|
198
|
+
receiver.on("ping", receiverOnPing);
|
|
199
|
+
receiver.on("pong", receiverOnPong);
|
|
200
|
+
sender.onerror = senderOnError;
|
|
201
|
+
if (socket.setTimeout) socket.setTimeout(0);
|
|
202
|
+
if (socket.setNoDelay) socket.setNoDelay();
|
|
203
|
+
if (head.length > 0) socket.unshift(head);
|
|
204
|
+
socket.on("close", socketOnClose);
|
|
205
|
+
socket.on("data", socketOnData);
|
|
206
|
+
socket.on("end", socketOnEnd);
|
|
207
|
+
socket.on("error", socketOnError);
|
|
208
|
+
this._readyState = WebSocket.OPEN;
|
|
209
|
+
this.emit("open");
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Emit the `'close'` event.
|
|
213
|
+
*
|
|
214
|
+
* @private
|
|
215
|
+
*/
|
|
216
|
+
emitClose() {
|
|
217
|
+
if (!this._socket) {
|
|
218
|
+
this._readyState = WebSocket.CLOSED;
|
|
219
|
+
this.emit("close", this._closeCode, this._closeMessage);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (this._extensions[PerMessageDeflate.extensionName]) this._extensions[PerMessageDeflate.extensionName].cleanup();
|
|
223
|
+
this._receiver.removeAllListeners();
|
|
224
|
+
this._readyState = WebSocket.CLOSED;
|
|
225
|
+
this.emit("close", this._closeCode, this._closeMessage);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Start a closing handshake.
|
|
229
|
+
*
|
|
230
|
+
* +----------+ +-----------+ +----------+
|
|
231
|
+
* - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
|
|
232
|
+
* | +----------+ +-----------+ +----------+ |
|
|
233
|
+
* +----------+ +-----------+ |
|
|
234
|
+
* CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING
|
|
235
|
+
* +----------+ +-----------+ |
|
|
236
|
+
* | | | +---+ |
|
|
237
|
+
* +------------------------+-->|fin| - - - -
|
|
238
|
+
* | +---+ | +---+
|
|
239
|
+
* - - - - -|fin|<---------------------+
|
|
240
|
+
* +---+
|
|
241
|
+
*
|
|
242
|
+
* @param {Number} [code] Status code explaining why the connection is closing
|
|
243
|
+
* @param {(String|Buffer)} [data] The reason why the connection is
|
|
244
|
+
* closing
|
|
245
|
+
* @public
|
|
246
|
+
*/
|
|
247
|
+
close(code, data) {
|
|
248
|
+
if (this.readyState === WebSocket.CLOSED) return;
|
|
249
|
+
if (this.readyState === WebSocket.CONNECTING) {
|
|
250
|
+
abortHandshake(this, this._req, "WebSocket was closed before the connection was established");
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (this.readyState === WebSocket.CLOSING) {
|
|
254
|
+
if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) this._socket.end();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this._readyState = WebSocket.CLOSING;
|
|
258
|
+
this._sender.close(code, data, !this._isServer, (err) => {
|
|
259
|
+
if (err) return;
|
|
260
|
+
this._closeFrameSent = true;
|
|
261
|
+
if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) this._socket.end();
|
|
262
|
+
});
|
|
263
|
+
setCloseTimer(this);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Pause the socket.
|
|
267
|
+
*
|
|
268
|
+
* @public
|
|
269
|
+
*/
|
|
270
|
+
pause() {
|
|
271
|
+
if (this.readyState === WebSocket.CONNECTING || this.readyState === WebSocket.CLOSED) return;
|
|
272
|
+
this._paused = true;
|
|
273
|
+
this._socket.pause();
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Send a ping.
|
|
277
|
+
*
|
|
278
|
+
* @param {*} [data] The data to send
|
|
279
|
+
* @param {Boolean} [mask] Indicates whether or not to mask `data`
|
|
280
|
+
* @param {Function} [cb] Callback which is executed when the ping is sent
|
|
281
|
+
* @public
|
|
282
|
+
*/
|
|
283
|
+
ping(data, mask, cb) {
|
|
284
|
+
if (this.readyState === WebSocket.CONNECTING) throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
|
|
285
|
+
if (typeof data === "function") {
|
|
286
|
+
cb = data;
|
|
287
|
+
data = mask = void 0;
|
|
288
|
+
} else if (typeof mask === "function") {
|
|
289
|
+
cb = mask;
|
|
290
|
+
mask = void 0;
|
|
291
|
+
}
|
|
292
|
+
if (typeof data === "number") data = data.toString();
|
|
293
|
+
if (this.readyState !== WebSocket.OPEN) {
|
|
294
|
+
sendAfterClose(this, data, cb);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (mask === void 0) mask = !this._isServer;
|
|
298
|
+
this._sender.ping(data || EMPTY_BUFFER, mask, cb);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Send a pong.
|
|
302
|
+
*
|
|
303
|
+
* @param {*} [data] The data to send
|
|
304
|
+
* @param {Boolean} [mask] Indicates whether or not to mask `data`
|
|
305
|
+
* @param {Function} [cb] Callback which is executed when the pong is sent
|
|
306
|
+
* @public
|
|
307
|
+
*/
|
|
308
|
+
pong(data, mask, cb) {
|
|
309
|
+
if (this.readyState === WebSocket.CONNECTING) throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
|
|
310
|
+
if (typeof data === "function") {
|
|
311
|
+
cb = data;
|
|
312
|
+
data = mask = void 0;
|
|
313
|
+
} else if (typeof mask === "function") {
|
|
314
|
+
cb = mask;
|
|
315
|
+
mask = void 0;
|
|
316
|
+
}
|
|
317
|
+
if (typeof data === "number") data = data.toString();
|
|
318
|
+
if (this.readyState !== WebSocket.OPEN) {
|
|
319
|
+
sendAfterClose(this, data, cb);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (mask === void 0) mask = !this._isServer;
|
|
323
|
+
this._sender.pong(data || EMPTY_BUFFER, mask, cb);
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Resume the socket.
|
|
327
|
+
*
|
|
328
|
+
* @public
|
|
329
|
+
*/
|
|
330
|
+
resume() {
|
|
331
|
+
if (this.readyState === WebSocket.CONNECTING || this.readyState === WebSocket.CLOSED) return;
|
|
332
|
+
this._paused = false;
|
|
333
|
+
if (!this._receiver._writableState.needDrain) this._socket.resume();
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Send a data message.
|
|
337
|
+
*
|
|
338
|
+
* @param {*} data The message to send
|
|
339
|
+
* @param {Object} [options] Options object
|
|
340
|
+
* @param {Boolean} [options.binary] Specifies whether `data` is binary or
|
|
341
|
+
* text
|
|
342
|
+
* @param {Boolean} [options.compress] Specifies whether or not to compress
|
|
343
|
+
* `data`
|
|
344
|
+
* @param {Boolean} [options.fin=true] Specifies whether the fragment is the
|
|
345
|
+
* last one
|
|
346
|
+
* @param {Boolean} [options.mask] Specifies whether or not to mask `data`
|
|
347
|
+
* @param {Function} [cb] Callback which is executed when data is written out
|
|
348
|
+
* @public
|
|
349
|
+
*/
|
|
350
|
+
send(data, options, cb) {
|
|
351
|
+
if (this.readyState === WebSocket.CONNECTING) throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
|
|
352
|
+
if (typeof options === "function") {
|
|
353
|
+
cb = options;
|
|
354
|
+
options = {};
|
|
355
|
+
}
|
|
356
|
+
if (typeof data === "number") data = data.toString();
|
|
357
|
+
if (this.readyState !== WebSocket.OPEN) {
|
|
358
|
+
sendAfterClose(this, data, cb);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const opts = {
|
|
362
|
+
binary: typeof data !== "string",
|
|
363
|
+
mask: !this._isServer,
|
|
364
|
+
compress: true,
|
|
365
|
+
fin: true,
|
|
366
|
+
...options
|
|
367
|
+
};
|
|
368
|
+
if (!this._extensions[PerMessageDeflate.extensionName]) opts.compress = false;
|
|
369
|
+
this._sender.send(data || EMPTY_BUFFER, opts, cb);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Forcibly close the connection.
|
|
373
|
+
*
|
|
374
|
+
* @public
|
|
375
|
+
*/
|
|
376
|
+
terminate() {
|
|
377
|
+
if (this.readyState === WebSocket.CLOSED) return;
|
|
378
|
+
if (this.readyState === WebSocket.CONNECTING) {
|
|
379
|
+
abortHandshake(this, this._req, "WebSocket was closed before the connection was established");
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (this._socket) {
|
|
383
|
+
this._readyState = WebSocket.CLOSING;
|
|
384
|
+
this._socket.destroy();
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
/**
|
|
389
|
+
* @constant {Number} CONNECTING
|
|
390
|
+
* @memberof WebSocket
|
|
391
|
+
*/
|
|
392
|
+
Object.defineProperty(WebSocket, "CONNECTING", {
|
|
393
|
+
enumerable: true,
|
|
394
|
+
value: readyStates.indexOf("CONNECTING")
|
|
395
|
+
});
|
|
396
|
+
/**
|
|
397
|
+
* @constant {Number} CONNECTING
|
|
398
|
+
* @memberof WebSocket.prototype
|
|
399
|
+
*/
|
|
400
|
+
Object.defineProperty(WebSocket.prototype, "CONNECTING", {
|
|
401
|
+
enumerable: true,
|
|
402
|
+
value: readyStates.indexOf("CONNECTING")
|
|
403
|
+
});
|
|
404
|
+
/**
|
|
405
|
+
* @constant {Number} OPEN
|
|
406
|
+
* @memberof WebSocket
|
|
407
|
+
*/
|
|
408
|
+
Object.defineProperty(WebSocket, "OPEN", {
|
|
409
|
+
enumerable: true,
|
|
410
|
+
value: readyStates.indexOf("OPEN")
|
|
411
|
+
});
|
|
412
|
+
/**
|
|
413
|
+
* @constant {Number} OPEN
|
|
414
|
+
* @memberof WebSocket.prototype
|
|
415
|
+
*/
|
|
416
|
+
Object.defineProperty(WebSocket.prototype, "OPEN", {
|
|
417
|
+
enumerable: true,
|
|
418
|
+
value: readyStates.indexOf("OPEN")
|
|
419
|
+
});
|
|
420
|
+
/**
|
|
421
|
+
* @constant {Number} CLOSING
|
|
422
|
+
* @memberof WebSocket
|
|
423
|
+
*/
|
|
424
|
+
Object.defineProperty(WebSocket, "CLOSING", {
|
|
425
|
+
enumerable: true,
|
|
426
|
+
value: readyStates.indexOf("CLOSING")
|
|
427
|
+
});
|
|
428
|
+
/**
|
|
429
|
+
* @constant {Number} CLOSING
|
|
430
|
+
* @memberof WebSocket.prototype
|
|
431
|
+
*/
|
|
432
|
+
Object.defineProperty(WebSocket.prototype, "CLOSING", {
|
|
433
|
+
enumerable: true,
|
|
434
|
+
value: readyStates.indexOf("CLOSING")
|
|
435
|
+
});
|
|
436
|
+
/**
|
|
437
|
+
* @constant {Number} CLOSED
|
|
438
|
+
* @memberof WebSocket
|
|
439
|
+
*/
|
|
440
|
+
Object.defineProperty(WebSocket, "CLOSED", {
|
|
441
|
+
enumerable: true,
|
|
442
|
+
value: readyStates.indexOf("CLOSED")
|
|
443
|
+
});
|
|
444
|
+
/**
|
|
445
|
+
* @constant {Number} CLOSED
|
|
446
|
+
* @memberof WebSocket.prototype
|
|
447
|
+
*/
|
|
448
|
+
Object.defineProperty(WebSocket.prototype, "CLOSED", {
|
|
449
|
+
enumerable: true,
|
|
450
|
+
value: readyStates.indexOf("CLOSED")
|
|
451
|
+
});
|
|
452
|
+
[
|
|
453
|
+
"binaryType",
|
|
454
|
+
"bufferedAmount",
|
|
455
|
+
"extensions",
|
|
456
|
+
"isPaused",
|
|
457
|
+
"protocol",
|
|
458
|
+
"readyState",
|
|
459
|
+
"url"
|
|
460
|
+
].forEach((property) => {
|
|
461
|
+
Object.defineProperty(WebSocket.prototype, property, { enumerable: true });
|
|
462
|
+
});
|
|
463
|
+
[
|
|
464
|
+
"open",
|
|
465
|
+
"error",
|
|
466
|
+
"close",
|
|
467
|
+
"message"
|
|
468
|
+
].forEach((method) => {
|
|
469
|
+
Object.defineProperty(WebSocket.prototype, `on${method}`, {
|
|
470
|
+
enumerable: true,
|
|
471
|
+
get() {
|
|
472
|
+
for (const listener of this.listeners(method)) if (listener[kForOnEventAttribute]) return listener[kListener];
|
|
473
|
+
return null;
|
|
474
|
+
},
|
|
475
|
+
set(handler) {
|
|
476
|
+
for (const listener of this.listeners(method)) if (listener[kForOnEventAttribute]) {
|
|
477
|
+
this.removeListener(method, listener);
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
if (typeof handler !== "function") return;
|
|
481
|
+
this.addEventListener(method, handler, { [kForOnEventAttribute]: true });
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
WebSocket.prototype.addEventListener = addEventListener;
|
|
486
|
+
WebSocket.prototype.removeEventListener = removeEventListener;
|
|
487
|
+
module.exports = WebSocket;
|
|
488
|
+
/**
|
|
489
|
+
* Initialize a WebSocket client.
|
|
490
|
+
*
|
|
491
|
+
* @param {WebSocket} websocket The client to initialize
|
|
492
|
+
* @param {(String|URL)} address The URL to which to connect
|
|
493
|
+
* @param {Array} protocols The subprotocols
|
|
494
|
+
* @param {Object} [options] Connection options
|
|
495
|
+
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any
|
|
496
|
+
* of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple
|
|
497
|
+
* times in the same tick
|
|
498
|
+
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
|
|
499
|
+
* automatically send a pong in response to a ping
|
|
500
|
+
* @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait
|
|
501
|
+
* for the closing handshake to finish after `websocket.close()` is called
|
|
502
|
+
* @param {Function} [options.finishRequest] A function which can be used to
|
|
503
|
+
* customize the headers of each http request before it is sent
|
|
504
|
+
* @param {Boolean} [options.followRedirects=false] Whether or not to follow
|
|
505
|
+
* redirects
|
|
506
|
+
* @param {Function} [options.generateMask] The function used to generate the
|
|
507
|
+
* masking key
|
|
508
|
+
* @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
|
|
509
|
+
* handshake request
|
|
510
|
+
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
511
|
+
* size
|
|
512
|
+
* @param {Number} [options.maxRedirects=10] The maximum number of redirects
|
|
513
|
+
* allowed
|
|
514
|
+
* @param {String} [options.origin] Value of the `Origin` or
|
|
515
|
+
* `Sec-WebSocket-Origin` header
|
|
516
|
+
* @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
|
|
517
|
+
* permessage-deflate
|
|
518
|
+
* @param {Number} [options.protocolVersion=13] Value of the
|
|
519
|
+
* `Sec-WebSocket-Version` header
|
|
520
|
+
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
521
|
+
* not to skip UTF-8 validation for text and close messages
|
|
522
|
+
* @private
|
|
523
|
+
*/
|
|
524
|
+
function initAsClient(websocket, address, protocols, options) {
|
|
525
|
+
const opts = {
|
|
526
|
+
allowSynchronousEvents: true,
|
|
527
|
+
autoPong: true,
|
|
528
|
+
closeTimeout: CLOSE_TIMEOUT,
|
|
529
|
+
protocolVersion: protocolVersions[1],
|
|
530
|
+
maxPayload: 100 * 1024 * 1024,
|
|
531
|
+
skipUTF8Validation: false,
|
|
532
|
+
perMessageDeflate: true,
|
|
533
|
+
followRedirects: false,
|
|
534
|
+
maxRedirects: 10,
|
|
535
|
+
...options,
|
|
536
|
+
socketPath: void 0,
|
|
537
|
+
hostname: void 0,
|
|
538
|
+
protocol: void 0,
|
|
539
|
+
timeout: void 0,
|
|
540
|
+
method: "GET",
|
|
541
|
+
host: void 0,
|
|
542
|
+
path: void 0,
|
|
543
|
+
port: void 0
|
|
544
|
+
};
|
|
545
|
+
websocket._autoPong = opts.autoPong;
|
|
546
|
+
websocket._closeTimeout = opts.closeTimeout;
|
|
547
|
+
if (!protocolVersions.includes(opts.protocolVersion)) throw new RangeError(`Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})`);
|
|
548
|
+
let parsedUrl;
|
|
549
|
+
if (address instanceof URL) parsedUrl = address;
|
|
550
|
+
else try {
|
|
551
|
+
parsedUrl = new URL(address);
|
|
552
|
+
} catch (e) {
|
|
553
|
+
throw new SyntaxError(`Invalid URL: ${address}`);
|
|
554
|
+
}
|
|
555
|
+
if (parsedUrl.protocol === "http:") parsedUrl.protocol = "ws:";
|
|
556
|
+
else if (parsedUrl.protocol === "https:") parsedUrl.protocol = "wss:";
|
|
557
|
+
websocket._url = parsedUrl.href;
|
|
558
|
+
const isSecure = parsedUrl.protocol === "wss:";
|
|
559
|
+
const isIpcUrl = parsedUrl.protocol === "ws+unix:";
|
|
560
|
+
let invalidUrlMessage;
|
|
561
|
+
if (parsedUrl.protocol !== "ws:" && !isSecure && !isIpcUrl) invalidUrlMessage = "The URL's protocol must be one of \"ws:\", \"wss:\", \"http:\", \"https:\", or \"ws+unix:\"";
|
|
562
|
+
else if (isIpcUrl && !parsedUrl.pathname) invalidUrlMessage = "The URL's pathname is empty";
|
|
563
|
+
else if (parsedUrl.hash) invalidUrlMessage = "The URL contains a fragment identifier";
|
|
564
|
+
if (invalidUrlMessage) {
|
|
565
|
+
const err = new SyntaxError(invalidUrlMessage);
|
|
566
|
+
if (websocket._redirects === 0) throw err;
|
|
567
|
+
else {
|
|
568
|
+
emitErrorAndClose(websocket, err);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
const defaultPort = isSecure ? 443 : 80;
|
|
573
|
+
const key = randomBytes(16).toString("base64");
|
|
574
|
+
const request = isSecure ? https.request : http.request;
|
|
575
|
+
const protocolSet = /* @__PURE__ */ new Set();
|
|
576
|
+
let perMessageDeflate;
|
|
577
|
+
opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
|
|
578
|
+
opts.defaultPort = opts.defaultPort || defaultPort;
|
|
579
|
+
opts.port = parsedUrl.port || defaultPort;
|
|
580
|
+
opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname;
|
|
581
|
+
opts.headers = {
|
|
582
|
+
...opts.headers,
|
|
583
|
+
"Sec-WebSocket-Version": opts.protocolVersion,
|
|
584
|
+
"Sec-WebSocket-Key": key,
|
|
585
|
+
Connection: "Upgrade",
|
|
586
|
+
Upgrade: "websocket"
|
|
587
|
+
};
|
|
588
|
+
opts.path = parsedUrl.pathname + parsedUrl.search;
|
|
589
|
+
opts.timeout = opts.handshakeTimeout;
|
|
590
|
+
if (opts.perMessageDeflate) {
|
|
591
|
+
perMessageDeflate = new PerMessageDeflate(opts.perMessageDeflate !== true ? opts.perMessageDeflate : {}, false, opts.maxPayload);
|
|
592
|
+
opts.headers["Sec-WebSocket-Extensions"] = format({ [PerMessageDeflate.extensionName]: perMessageDeflate.offer() });
|
|
593
|
+
}
|
|
594
|
+
if (protocols.length) {
|
|
595
|
+
for (const protocol of protocols) {
|
|
596
|
+
if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) throw new SyntaxError("An invalid or duplicated subprotocol was specified");
|
|
597
|
+
protocolSet.add(protocol);
|
|
598
|
+
}
|
|
599
|
+
opts.headers["Sec-WebSocket-Protocol"] = protocols.join(",");
|
|
600
|
+
}
|
|
601
|
+
if (opts.origin) if (opts.protocolVersion < 13) opts.headers["Sec-WebSocket-Origin"] = opts.origin;
|
|
602
|
+
else opts.headers.Origin = opts.origin;
|
|
603
|
+
if (parsedUrl.username || parsedUrl.password) opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
|
|
604
|
+
if (isIpcUrl) {
|
|
605
|
+
const parts = opts.path.split(":");
|
|
606
|
+
opts.socketPath = parts[0];
|
|
607
|
+
opts.path = parts[1];
|
|
608
|
+
}
|
|
609
|
+
let req;
|
|
610
|
+
if (opts.followRedirects) {
|
|
611
|
+
if (websocket._redirects === 0) {
|
|
612
|
+
websocket._originalIpc = isIpcUrl;
|
|
613
|
+
websocket._originalSecure = isSecure;
|
|
614
|
+
websocket._originalHostOrSocketPath = isIpcUrl ? opts.socketPath : parsedUrl.host;
|
|
615
|
+
const headers = options && options.headers;
|
|
616
|
+
options = {
|
|
617
|
+
...options,
|
|
618
|
+
headers: {}
|
|
619
|
+
};
|
|
620
|
+
if (headers) for (const [key$1, value] of Object.entries(headers)) options.headers[key$1.toLowerCase()] = value;
|
|
621
|
+
} else if (websocket.listenerCount("redirect") === 0) {
|
|
622
|
+
const isSameHost = isIpcUrl ? websocket._originalIpc ? opts.socketPath === websocket._originalHostOrSocketPath : false : websocket._originalIpc ? false : parsedUrl.host === websocket._originalHostOrSocketPath;
|
|
623
|
+
if (!isSameHost || websocket._originalSecure && !isSecure) {
|
|
624
|
+
delete opts.headers.authorization;
|
|
625
|
+
delete opts.headers.cookie;
|
|
626
|
+
if (!isSameHost) delete opts.headers.host;
|
|
627
|
+
opts.auth = void 0;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (opts.auth && !options.headers.authorization) options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
|
|
631
|
+
req = websocket._req = request(opts);
|
|
632
|
+
if (websocket._redirects) websocket.emit("redirect", websocket.url, req);
|
|
633
|
+
} else req = websocket._req = request(opts);
|
|
634
|
+
if (opts.timeout) req.on("timeout", () => {
|
|
635
|
+
abortHandshake(websocket, req, "Opening handshake has timed out");
|
|
636
|
+
});
|
|
637
|
+
req.on("error", (err) => {
|
|
638
|
+
if (req === null || req[kAborted]) return;
|
|
639
|
+
req = websocket._req = null;
|
|
640
|
+
emitErrorAndClose(websocket, err);
|
|
641
|
+
});
|
|
642
|
+
req.on("response", (res) => {
|
|
643
|
+
const location = res.headers.location;
|
|
644
|
+
const statusCode = res.statusCode;
|
|
645
|
+
if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) {
|
|
646
|
+
if (++websocket._redirects > opts.maxRedirects) {
|
|
647
|
+
abortHandshake(websocket, req, "Maximum redirects exceeded");
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
req.abort();
|
|
651
|
+
let addr;
|
|
652
|
+
try {
|
|
653
|
+
addr = new URL(location, address);
|
|
654
|
+
} catch (e) {
|
|
655
|
+
emitErrorAndClose(websocket, /* @__PURE__ */ new SyntaxError(`Invalid URL: ${location}`));
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
initAsClient(websocket, addr, protocols, options);
|
|
659
|
+
} else if (!websocket.emit("unexpected-response", req, res)) abortHandshake(websocket, req, `Unexpected server response: ${res.statusCode}`);
|
|
660
|
+
});
|
|
661
|
+
req.on("upgrade", (res, socket, head) => {
|
|
662
|
+
websocket.emit("upgrade", res);
|
|
663
|
+
if (websocket.readyState !== WebSocket.CONNECTING) return;
|
|
664
|
+
req = websocket._req = null;
|
|
665
|
+
const upgrade = res.headers.upgrade;
|
|
666
|
+
if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
|
|
667
|
+
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
const digest = createHash("sha1").update(key + GUID).digest("base64");
|
|
671
|
+
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
672
|
+
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
const serverProt = res.headers["sec-websocket-protocol"];
|
|
676
|
+
let protError;
|
|
677
|
+
if (serverProt !== void 0) {
|
|
678
|
+
if (!protocolSet.size) protError = "Server sent a subprotocol but none was requested";
|
|
679
|
+
else if (!protocolSet.has(serverProt)) protError = "Server sent an invalid subprotocol";
|
|
680
|
+
} else if (protocolSet.size) protError = "Server sent no subprotocol";
|
|
681
|
+
if (protError) {
|
|
682
|
+
abortHandshake(websocket, socket, protError);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
if (serverProt) websocket._protocol = serverProt;
|
|
686
|
+
const secWebSocketExtensions = res.headers["sec-websocket-extensions"];
|
|
687
|
+
if (secWebSocketExtensions !== void 0) {
|
|
688
|
+
if (!perMessageDeflate) {
|
|
689
|
+
abortHandshake(websocket, socket, "Server sent a Sec-WebSocket-Extensions header but no extension was requested");
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
let extensions;
|
|
693
|
+
try {
|
|
694
|
+
extensions = parse(secWebSocketExtensions);
|
|
695
|
+
} catch (err) {
|
|
696
|
+
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Extensions header");
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
const extensionNames = Object.keys(extensions);
|
|
700
|
+
if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate.extensionName) {
|
|
701
|
+
abortHandshake(websocket, socket, "Server indicated an extension that was not requested");
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
try {
|
|
705
|
+
perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
|
|
706
|
+
} catch (err) {
|
|
707
|
+
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Extensions header");
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
websocket._extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
|
|
711
|
+
}
|
|
712
|
+
websocket.setSocket(socket, head, {
|
|
713
|
+
allowSynchronousEvents: opts.allowSynchronousEvents,
|
|
714
|
+
generateMask: opts.generateMask,
|
|
715
|
+
maxPayload: opts.maxPayload,
|
|
716
|
+
skipUTF8Validation: opts.skipUTF8Validation
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
if (opts.finishRequest) opts.finishRequest(req, websocket);
|
|
720
|
+
else req.end();
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Emit the `'error'` and `'close'` events.
|
|
724
|
+
*
|
|
725
|
+
* @param {WebSocket} websocket The WebSocket instance
|
|
726
|
+
* @param {Error} The error to emit
|
|
727
|
+
* @private
|
|
728
|
+
*/
|
|
729
|
+
function emitErrorAndClose(websocket, err) {
|
|
730
|
+
websocket._readyState = WebSocket.CLOSING;
|
|
731
|
+
websocket._errorEmitted = true;
|
|
732
|
+
websocket.emit("error", err);
|
|
733
|
+
websocket.emitClose();
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Create a `net.Socket` and initiate a connection.
|
|
737
|
+
*
|
|
738
|
+
* @param {Object} options Connection options
|
|
739
|
+
* @return {net.Socket} The newly created socket used to start the connection
|
|
740
|
+
* @private
|
|
741
|
+
*/
|
|
742
|
+
function netConnect(options) {
|
|
743
|
+
options.path = options.socketPath;
|
|
744
|
+
return net.connect(options);
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Create a `tls.TLSSocket` and initiate a connection.
|
|
748
|
+
*
|
|
749
|
+
* @param {Object} options Connection options
|
|
750
|
+
* @return {tls.TLSSocket} The newly created socket used to start the connection
|
|
751
|
+
* @private
|
|
752
|
+
*/
|
|
753
|
+
function tlsConnect(options) {
|
|
754
|
+
options.path = void 0;
|
|
755
|
+
if (!options.servername && options.servername !== "") options.servername = net.isIP(options.host) ? "" : options.host;
|
|
756
|
+
return tls.connect(options);
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Abort the handshake and emit an error.
|
|
760
|
+
*
|
|
761
|
+
* @param {WebSocket} websocket The WebSocket instance
|
|
762
|
+
* @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to
|
|
763
|
+
* abort or the socket to destroy
|
|
764
|
+
* @param {String} message The error message
|
|
765
|
+
* @private
|
|
766
|
+
*/
|
|
767
|
+
function abortHandshake(websocket, stream, message) {
|
|
768
|
+
websocket._readyState = WebSocket.CLOSING;
|
|
769
|
+
const err = new Error(message);
|
|
770
|
+
Error.captureStackTrace(err, abortHandshake);
|
|
771
|
+
if (stream.setHeader) {
|
|
772
|
+
stream[kAborted] = true;
|
|
773
|
+
stream.abort();
|
|
774
|
+
if (stream.socket && !stream.socket.destroyed) stream.socket.destroy();
|
|
775
|
+
process.nextTick(emitErrorAndClose, websocket, err);
|
|
776
|
+
} else {
|
|
777
|
+
stream.destroy(err);
|
|
778
|
+
stream.once("error", websocket.emit.bind(websocket, "error"));
|
|
779
|
+
stream.once("close", websocket.emitClose.bind(websocket));
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Handle cases where the `ping()`, `pong()`, or `send()` methods are called
|
|
784
|
+
* when the `readyState` attribute is `CLOSING` or `CLOSED`.
|
|
785
|
+
*
|
|
786
|
+
* @param {WebSocket} websocket The WebSocket instance
|
|
787
|
+
* @param {*} [data] The data to send
|
|
788
|
+
* @param {Function} [cb] Callback
|
|
789
|
+
* @private
|
|
790
|
+
*/
|
|
791
|
+
function sendAfterClose(websocket, data, cb) {
|
|
792
|
+
if (data) {
|
|
793
|
+
const length = isBlob(data) ? data.size : toBuffer(data).length;
|
|
794
|
+
if (websocket._socket) websocket._sender._bufferedBytes += length;
|
|
795
|
+
else websocket._bufferedAmount += length;
|
|
796
|
+
}
|
|
797
|
+
if (cb) {
|
|
798
|
+
const err = /* @__PURE__ */ new Error(`WebSocket is not open: readyState ${websocket.readyState} (${readyStates[websocket.readyState]})`);
|
|
799
|
+
process.nextTick(cb, err);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* The listener of the `Receiver` `'conclude'` event.
|
|
804
|
+
*
|
|
805
|
+
* @param {Number} code The status code
|
|
806
|
+
* @param {Buffer} reason The reason for closing
|
|
807
|
+
* @private
|
|
808
|
+
*/
|
|
809
|
+
function receiverOnConclude(code, reason) {
|
|
810
|
+
const websocket = this[kWebSocket];
|
|
811
|
+
websocket._closeFrameReceived = true;
|
|
812
|
+
websocket._closeMessage = reason;
|
|
813
|
+
websocket._closeCode = code;
|
|
814
|
+
if (websocket._socket[kWebSocket] === void 0) return;
|
|
815
|
+
websocket._socket.removeListener("data", socketOnData);
|
|
816
|
+
process.nextTick(resume, websocket._socket);
|
|
817
|
+
if (code === 1005) websocket.close();
|
|
818
|
+
else websocket.close(code, reason);
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* The listener of the `Receiver` `'drain'` event.
|
|
822
|
+
*
|
|
823
|
+
* @private
|
|
824
|
+
*/
|
|
825
|
+
function receiverOnDrain() {
|
|
826
|
+
const websocket = this[kWebSocket];
|
|
827
|
+
if (!websocket.isPaused) websocket._socket.resume();
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* The listener of the `Receiver` `'error'` event.
|
|
831
|
+
*
|
|
832
|
+
* @param {(RangeError|Error)} err The emitted error
|
|
833
|
+
* @private
|
|
834
|
+
*/
|
|
835
|
+
function receiverOnError(err) {
|
|
836
|
+
const websocket = this[kWebSocket];
|
|
837
|
+
if (websocket._socket[kWebSocket] !== void 0) {
|
|
838
|
+
websocket._socket.removeListener("data", socketOnData);
|
|
839
|
+
process.nextTick(resume, websocket._socket);
|
|
840
|
+
websocket.close(err[kStatusCode]);
|
|
841
|
+
}
|
|
842
|
+
if (!websocket._errorEmitted) {
|
|
843
|
+
websocket._errorEmitted = true;
|
|
844
|
+
websocket.emit("error", err);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* The listener of the `Receiver` `'finish'` event.
|
|
849
|
+
*
|
|
850
|
+
* @private
|
|
851
|
+
*/
|
|
852
|
+
function receiverOnFinish() {
|
|
853
|
+
this[kWebSocket].emitClose();
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* The listener of the `Receiver` `'message'` event.
|
|
857
|
+
*
|
|
858
|
+
* @param {Buffer|ArrayBuffer|Buffer[])} data The message
|
|
859
|
+
* @param {Boolean} isBinary Specifies whether the message is binary or not
|
|
860
|
+
* @private
|
|
861
|
+
*/
|
|
862
|
+
function receiverOnMessage(data, isBinary) {
|
|
863
|
+
this[kWebSocket].emit("message", data, isBinary);
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* The listener of the `Receiver` `'ping'` event.
|
|
867
|
+
*
|
|
868
|
+
* @param {Buffer} data The data included in the ping frame
|
|
869
|
+
* @private
|
|
870
|
+
*/
|
|
871
|
+
function receiverOnPing(data) {
|
|
872
|
+
const websocket = this[kWebSocket];
|
|
873
|
+
if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
|
|
874
|
+
websocket.emit("ping", data);
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* The listener of the `Receiver` `'pong'` event.
|
|
878
|
+
*
|
|
879
|
+
* @param {Buffer} data The data included in the pong frame
|
|
880
|
+
* @private
|
|
881
|
+
*/
|
|
882
|
+
function receiverOnPong(data) {
|
|
883
|
+
this[kWebSocket].emit("pong", data);
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Resume a readable stream
|
|
887
|
+
*
|
|
888
|
+
* @param {Readable} stream The readable stream
|
|
889
|
+
* @private
|
|
890
|
+
*/
|
|
891
|
+
function resume(stream) {
|
|
892
|
+
stream.resume();
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* The `Sender` error event handler.
|
|
896
|
+
*
|
|
897
|
+
* @param {Error} The error
|
|
898
|
+
* @private
|
|
899
|
+
*/
|
|
900
|
+
function senderOnError(err) {
|
|
901
|
+
const websocket = this[kWebSocket];
|
|
902
|
+
if (websocket.readyState === WebSocket.CLOSED) return;
|
|
903
|
+
if (websocket.readyState === WebSocket.OPEN) {
|
|
904
|
+
websocket._readyState = WebSocket.CLOSING;
|
|
905
|
+
setCloseTimer(websocket);
|
|
906
|
+
}
|
|
907
|
+
this._socket.end();
|
|
908
|
+
if (!websocket._errorEmitted) {
|
|
909
|
+
websocket._errorEmitted = true;
|
|
910
|
+
websocket.emit("error", err);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Set a timer to destroy the underlying raw socket of a WebSocket.
|
|
915
|
+
*
|
|
916
|
+
* @param {WebSocket} websocket The WebSocket instance
|
|
917
|
+
* @private
|
|
918
|
+
*/
|
|
919
|
+
function setCloseTimer(websocket) {
|
|
920
|
+
websocket._closeTimer = setTimeout(websocket._socket.destroy.bind(websocket._socket), websocket._closeTimeout);
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* The listener of the socket `'close'` event.
|
|
924
|
+
*
|
|
925
|
+
* @private
|
|
926
|
+
*/
|
|
927
|
+
function socketOnClose() {
|
|
928
|
+
const websocket = this[kWebSocket];
|
|
929
|
+
this.removeListener("close", socketOnClose);
|
|
930
|
+
this.removeListener("data", socketOnData);
|
|
931
|
+
this.removeListener("end", socketOnEnd);
|
|
932
|
+
websocket._readyState = WebSocket.CLOSING;
|
|
933
|
+
if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && this._readableState.length !== 0) {
|
|
934
|
+
const chunk = this.read(this._readableState.length);
|
|
935
|
+
websocket._receiver.write(chunk);
|
|
936
|
+
}
|
|
937
|
+
websocket._receiver.end();
|
|
938
|
+
this[kWebSocket] = void 0;
|
|
939
|
+
clearTimeout(websocket._closeTimer);
|
|
940
|
+
if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) websocket.emitClose();
|
|
941
|
+
else {
|
|
942
|
+
websocket._receiver.on("error", receiverOnFinish);
|
|
943
|
+
websocket._receiver.on("finish", receiverOnFinish);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* The listener of the socket `'data'` event.
|
|
948
|
+
*
|
|
949
|
+
* @param {Buffer} chunk A chunk of data
|
|
950
|
+
* @private
|
|
951
|
+
*/
|
|
952
|
+
function socketOnData(chunk) {
|
|
953
|
+
if (!this[kWebSocket]._receiver.write(chunk)) this.pause();
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* The listener of the socket `'end'` event.
|
|
957
|
+
*
|
|
958
|
+
* @private
|
|
959
|
+
*/
|
|
960
|
+
function socketOnEnd() {
|
|
961
|
+
const websocket = this[kWebSocket];
|
|
962
|
+
websocket._readyState = WebSocket.CLOSING;
|
|
963
|
+
websocket._receiver.end();
|
|
964
|
+
this.end();
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* The listener of the socket `'error'` event.
|
|
968
|
+
*
|
|
969
|
+
* @private
|
|
970
|
+
*/
|
|
971
|
+
function socketOnError() {
|
|
972
|
+
const websocket = this[kWebSocket];
|
|
973
|
+
this.removeListener("error", socketOnError);
|
|
974
|
+
this.on("error", NOOP);
|
|
975
|
+
if (websocket) {
|
|
976
|
+
websocket._readyState = WebSocket.CLOSING;
|
|
977
|
+
this.destroy();
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}));
|
|
981
|
+
|
|
982
|
+
//#endregion
|
|
983
|
+
export default require_websocket();
|
|
984
|
+
|
|
985
|
+
export { require_websocket };
|